-
-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add pkg/stdlib/objects Length function * rename lenght.go -> length.go * fix tests according to other tests * add new tests to length tests * delete objects method Length * add objects method Has * add objects function Keys * small fixes in Keys and Has functions * change Has function * unit tests for Keys function * add unit tests for merge. also little change in lib.go * add doc to Keys function * Merge function prototype * add unit tests for KEEP function * added KEEP function * added doc for KEYS function * update lib.go * update lib.go * upd merge prototype * addded isEqualObjects function to objects tests * change object method Compare * added unit tests for Compare method * changed Compare method * fix Compare method * rename method Clone to Copy * added Cloneable interface * added Value to Cloneable interface * implemented Cloneable intefrace by array * added some more unit tests for values.Array * fix values.Array.Compare method * added one more unit test * implemented Cloneable interface by Object * unit tests for Object.Clone * move core.IsCloneable to value.go * change Clone function * move IsClonable to package values * updated MERGE unit tests * added MERGE function * added MERGE to lib * added one more test * changed MERGE function
- Loading branch information
Showing
3 changed files
with
232 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package objects | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/MontFerret/ferret/pkg/runtime/core" | ||
"github.com/MontFerret/ferret/pkg/runtime/values" | ||
) | ||
|
||
/* | ||
* Merge the given objects into a single object. | ||
* @params objs (Array Of Object OR Objects) - objects to merge. | ||
* @returns (Object) - Object created by merging. | ||
*/ | ||
func Merge(_ context.Context, args ...core.Value) (core.Value, error) { | ||
err := core.ValidateArgs(args, 1, core.MaxArgs) | ||
|
||
if err != nil { | ||
return values.None, err | ||
} | ||
|
||
objs := values.NewArrayWith(args...) | ||
|
||
if len(args) == 1 && args[0].Type() == core.ArrayType { | ||
objs = args[0].(*values.Array) | ||
} | ||
|
||
err = validateArrayOf(core.ObjectType, objs) | ||
|
||
if err != nil { | ||
return values.None, err | ||
} | ||
|
||
return mergeArray(objs), nil | ||
} | ||
|
||
func mergeArray(arr *values.Array) *values.Object { | ||
merged, obj := values.NewObject(), values.NewObject() | ||
|
||
arr.ForEach(func(arrValue core.Value, arrIdx int) bool { | ||
obj = arrValue.(*values.Object) | ||
obj.ForEach(func(objValue core.Value, objKey string) bool { | ||
if values.IsCloneable(objValue) { | ||
objValue = objValue.(core.Cloneable).Clone() | ||
} | ||
merged.Set(values.NewString(objKey), objValue) | ||
return true | ||
}) | ||
return true | ||
}) | ||
|
||
return merged | ||
} | ||
|
||
func validateArrayOf(typ core.Type, arr *values.Array) (err error) { | ||
for idx := values.NewInt(0); idx < arr.Length(); idx++ { | ||
if err != nil { | ||
break | ||
} | ||
err = core.ValidateType(arr.Get(idx), typ) | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
package objects_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/MontFerret/ferret/pkg/runtime/values" | ||
"github.com/MontFerret/ferret/pkg/stdlib/objects" | ||
|
||
. "github.com/smartystreets/goconvey/convey" | ||
) | ||
|
||
func TestMerge(t *testing.T) { | ||
Convey("When not enought arguments", t, func() { | ||
obj, err := objects.Merge(context.Background()) | ||
|
||
So(err, ShouldBeError) | ||
So(obj.Compare(values.None), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("When wrong type of arguments", t, func() { | ||
obj, err := objects.Merge(context.Background(), values.NewInt(0)) | ||
|
||
So(err, ShouldBeError) | ||
So(obj.Compare(values.None), ShouldEqual, 0) | ||
|
||
obj, err = objects.Merge(context.Background(), values.NewObject(), values.NewInt(0)) | ||
|
||
So(err, ShouldBeError) | ||
So(obj.Compare(values.None), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("When too many arrays", t, func() { | ||
obj, err := objects.Merge(context.Background(), values.NewArray(0), values.NewArray(0)) | ||
|
||
So(err, ShouldBeError) | ||
So(obj.Compare(values.None), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("Merged object should be independent of source objects", t, func() { | ||
obj1 := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
) | ||
obj2 := values.NewObjectWith( | ||
values.NewObjectProperty("prop3", values.NewInt(3)), | ||
) | ||
|
||
result := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
values.NewObjectProperty("prop3", values.NewInt(3)), | ||
) | ||
|
||
merged, err := objects.Merge(context.Background(), obj1, obj2) | ||
|
||
So(err, ShouldBeNil) | ||
|
||
obj1.Remove(values.NewString("prop1")) | ||
|
||
So(merged.Compare(result), ShouldEqual, 0) | ||
}) | ||
} | ||
|
||
func TestMergeObjects(t *testing.T) { | ||
Convey("Merge single object", t, func() { | ||
obj1 := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
) | ||
result := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
) | ||
|
||
merged, err := objects.Merge(context.Background(), obj1) | ||
|
||
So(err, ShouldBeNil) | ||
So(merged.Compare(result), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("Merge two objects", t, func() { | ||
obj1 := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
) | ||
obj2 := values.NewObjectWith( | ||
values.NewObjectProperty("prop3", values.NewInt(3)), | ||
) | ||
|
||
result := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
values.NewObjectProperty("prop3", values.NewInt(3)), | ||
) | ||
|
||
merged, err := objects.Merge(context.Background(), obj1, obj2) | ||
|
||
So(err, ShouldBeNil) | ||
So(merged.Compare(result), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("When keys are repeated", t, func() { | ||
obj1 := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
) | ||
obj2 := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(3)), | ||
) | ||
result := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(3)), | ||
values.NewObjectProperty("prop2", values.NewString("str")), | ||
) | ||
|
||
merged, err := objects.Merge(context.Background(), obj1, obj2) | ||
|
||
So(err, ShouldBeNil) | ||
So(merged.Compare(result), ShouldEqual, 0) | ||
}) | ||
} | ||
|
||
func TestMergeArray(t *testing.T) { | ||
Convey("Merge array", t, func() { | ||
objArr := values.NewArrayWith( | ||
values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
), | ||
values.NewObjectWith( | ||
values.NewObjectProperty("prop2", values.NewInt(2)), | ||
), | ||
) | ||
result := values.NewObjectWith( | ||
values.NewObjectProperty("prop1", values.NewInt(1)), | ||
values.NewObjectProperty("prop2", values.NewInt(2)), | ||
) | ||
|
||
merged, err := objects.Merge(context.Background(), objArr) | ||
|
||
So(err, ShouldBeNil) | ||
So(merged.Compare(result), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("Merge empty array", t, func() { | ||
objArr := values.NewArray(0) | ||
result := values.NewObject() | ||
|
||
merged, err := objects.Merge(context.Background(), objArr) | ||
|
||
So(err, ShouldBeNil) | ||
So(merged.Compare(result), ShouldEqual, 0) | ||
}) | ||
|
||
Convey("When there is not object element inside the array", t, func() { | ||
objArr := values.NewArrayWith( | ||
values.NewObject(), | ||
values.NewInt(0), | ||
) | ||
|
||
obj, err := objects.Merge(context.Background(), objArr) | ||
|
||
So(err, ShouldBeError) | ||
So(obj.Compare(values.None), ShouldEqual, 0) | ||
}) | ||
} |