mirror of
https://github.com/MontFerret/ferret.git
synced 2024-12-14 11:23:02 +02:00
ebea64da37
* added VALUES function * updated object.Compare
411 lines
12 KiB
Go
411 lines
12 KiB
Go
package values_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
)
|
|
|
|
func TestObject(t *testing.T) {
|
|
Convey("#constructor", t, func() {
|
|
Convey("Should create an empty object", func() {
|
|
obj := values.NewObject()
|
|
|
|
So(obj.Length(), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("Should create an object, from passed values", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("none", values.None),
|
|
values.NewObjectProperty("boolean", values.False),
|
|
values.NewObjectProperty("int", values.NewInt(1)),
|
|
values.NewObjectProperty("float", values.Float(1)),
|
|
values.NewObjectProperty("string", values.NewString("1")),
|
|
values.NewObjectProperty("array", values.NewArray(10)),
|
|
values.NewObjectProperty("object", values.NewObject()),
|
|
)
|
|
|
|
So(obj.Length(), ShouldEqual, 7)
|
|
})
|
|
})
|
|
|
|
Convey(".MarshalJSON", t, func() {
|
|
Convey("Should serialize an empty object", func() {
|
|
obj := values.NewObject()
|
|
marshaled, err := obj.MarshalJSON()
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
So(string(marshaled), ShouldEqual, "{}")
|
|
})
|
|
|
|
Convey("Should serialize full object", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("none", values.None),
|
|
values.NewObjectProperty("boolean", values.False),
|
|
values.NewObjectProperty("int", values.NewInt(1)),
|
|
values.NewObjectProperty("float", values.Float(1)),
|
|
values.NewObjectProperty("string", values.NewString("1")),
|
|
values.NewObjectProperty("array", values.NewArray(10)),
|
|
values.NewObjectProperty("object", values.NewObject()),
|
|
)
|
|
marshaled, err := obj.MarshalJSON()
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
So(string(marshaled), ShouldEqual, "{\"array\":[],\"boolean\":false,\"float\":1,\"int\":1,\"none\":null,\"object\":{},\"string\":\"1\"}")
|
|
})
|
|
})
|
|
|
|
Convey(".Type", t, func() {
|
|
Convey("Should return type", func() {
|
|
obj := values.NewObject()
|
|
|
|
So(obj.Type(), ShouldEqual, core.ObjectType)
|
|
})
|
|
})
|
|
|
|
Convey(".Unwrap", t, func() {
|
|
Convey("Should return an unwrapped value", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.NewString("foo")),
|
|
values.NewObjectProperty("bar", values.NewString("bar")),
|
|
)
|
|
|
|
for _, val := range obj.Unwrap().(map[string]interface{}) {
|
|
So(val, ShouldHaveSameTypeAs, "")
|
|
}
|
|
})
|
|
})
|
|
|
|
Convey(".String", t, func() {
|
|
Convey("Should return a string representation ", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.NewString("bar")),
|
|
)
|
|
|
|
So(obj.String(), ShouldEqual, "{\"foo\":\"bar\"}")
|
|
})
|
|
})
|
|
|
|
Convey(".Compare", t, func() {
|
|
Convey("It should return 1 for all non-object values", func() {
|
|
arr := []core.Value{
|
|
values.None,
|
|
values.False,
|
|
values.NewInt(1),
|
|
values.Float(1),
|
|
values.NewString("1"),
|
|
values.NewArray(10),
|
|
}
|
|
obj := values.NewObject()
|
|
|
|
for _, val := range arr {
|
|
So(obj.Compare(val), ShouldEqual, 1)
|
|
}
|
|
})
|
|
|
|
Convey("It should return -1 for all object values", func() {
|
|
arr := values.NewArrayWith(values.ZeroInt, values.ZeroInt)
|
|
obj := values.NewObject()
|
|
|
|
So(arr.Compare(obj), ShouldEqual, -1)
|
|
})
|
|
|
|
Convey("It should return 0 when both objects are empty", func() {
|
|
obj1 := values.NewObject()
|
|
obj2 := values.NewObject()
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("It should return 0 when both objects are equal (independent of key order)", func() {
|
|
obj1 := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.NewString("foo")),
|
|
values.NewObjectProperty("bar", values.NewString("bar")),
|
|
)
|
|
obj2 := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.NewString("foo")),
|
|
values.NewObjectProperty("bar", values.NewString("bar")),
|
|
)
|
|
|
|
So(obj1.Compare(obj1), ShouldEqual, 0)
|
|
So(obj2.Compare(obj2), ShouldEqual, 0)
|
|
So(obj1.Compare(obj2), ShouldEqual, 0)
|
|
So(obj2.Compare(obj1), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("It should return 1 when other array is empty", func() {
|
|
obj1 := values.NewObjectWith(values.NewObjectProperty("foo", values.NewString("bar")))
|
|
obj2 := values.NewObject()
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 1)
|
|
})
|
|
|
|
Convey("It should return 1 when values are bigger", func() {
|
|
obj1 := values.NewObjectWith(values.NewObjectProperty("foo", values.NewFloat(3)))
|
|
obj2 := values.NewObjectWith(values.NewObjectProperty("foo", values.NewFloat(2)))
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 1)
|
|
})
|
|
|
|
Convey("It should return 1 when values are less", func() {
|
|
obj1 := values.NewObjectWith(values.NewObjectProperty("foo", values.NewFloat(1)))
|
|
obj2 := values.NewObjectWith(values.NewObjectProperty("foo", values.NewFloat(2)))
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, -1)
|
|
})
|
|
|
|
Convey("ArangoDB compatibility", func() {
|
|
Convey("It should return 1 when {a:1} and {b:2}", func() {
|
|
obj1 := values.NewObjectWith(values.NewObjectProperty("a", values.NewInt(1)))
|
|
obj2 := values.NewObjectWith(values.NewObjectProperty("b", values.NewInt(2)))
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 1)
|
|
})
|
|
|
|
Convey("It should return 0 when {a:1} and {a:1}", func() {
|
|
obj1 := values.NewObjectWith(values.NewObjectProperty("a", values.NewInt(1)))
|
|
obj2 := values.NewObjectWith(values.NewObjectProperty("a", values.NewInt(1)))
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("It should return 0 {a:1, c:2} and {c:2, a:1}", func() {
|
|
obj1 := values.NewObjectWith(
|
|
values.NewObjectProperty("a", values.NewInt(1)),
|
|
values.NewObjectProperty("c", values.NewInt(2)),
|
|
)
|
|
obj2 := values.NewObjectWith(
|
|
values.NewObjectProperty("c", values.NewInt(2)),
|
|
values.NewObjectProperty("a", values.NewInt(1)),
|
|
)
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("It should return -1 when {a:1} and {a:2}", func() {
|
|
obj1 := values.NewObjectWith(values.NewObjectProperty("a", values.NewInt(1)))
|
|
obj2 := values.NewObjectWith(values.NewObjectProperty("a", values.NewInt(2)))
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, -1)
|
|
})
|
|
|
|
Convey("It should return 1 when {a:1, c:2} and {c:2, b:2}", func() {
|
|
obj1 := values.NewObjectWith(
|
|
values.NewObjectProperty("a", values.NewInt(1)),
|
|
values.NewObjectProperty("c", values.NewInt(2)),
|
|
)
|
|
obj2 := values.NewObjectWith(
|
|
values.NewObjectProperty("c", values.NewInt(2)),
|
|
values.NewObjectProperty("b", values.NewInt(2)),
|
|
)
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 1)
|
|
})
|
|
|
|
Convey("It should return 1 {a:1, c:3} and {c:2, a:1}", func() {
|
|
obj1 := values.NewObjectWith(
|
|
values.NewObjectProperty("a", values.NewInt(1)),
|
|
values.NewObjectProperty("c", values.NewInt(3)),
|
|
)
|
|
obj2 := values.NewObjectWith(
|
|
values.NewObjectProperty("c", values.NewInt(2)),
|
|
values.NewObjectProperty("a", values.NewInt(1)),
|
|
)
|
|
|
|
So(obj1.Compare(obj2), ShouldEqual, 1)
|
|
})
|
|
})
|
|
})
|
|
|
|
Convey(".Hash", t, func() {
|
|
Convey("It should calculate hash of non-empty object", func() {
|
|
v := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.NewString("bar")),
|
|
values.NewObjectProperty("faz", values.NewInt(1)),
|
|
values.NewObjectProperty("qaz", values.True),
|
|
)
|
|
|
|
h := v.Hash()
|
|
|
|
So(h, ShouldBeGreaterThan, 0)
|
|
})
|
|
|
|
Convey("It should calculate hash of empty object", func() {
|
|
v := values.NewObject()
|
|
|
|
h := v.Hash()
|
|
|
|
So(h, ShouldBeGreaterThan, 0)
|
|
})
|
|
|
|
Convey("Hash sum should be consistent", func() {
|
|
v := values.NewObjectWith(
|
|
values.NewObjectProperty("boolean", values.True),
|
|
values.NewObjectProperty("int", values.NewInt(1)),
|
|
values.NewObjectProperty("float", values.NewFloat(1.1)),
|
|
values.NewObjectProperty("string", values.NewString("foobar")),
|
|
values.NewObjectProperty("datetime", values.NewCurrentDateTime()),
|
|
values.NewObjectProperty("array", values.NewArrayWith(values.NewInt(1), values.True)),
|
|
values.NewObjectProperty("object", values.NewObjectWith(values.NewObjectProperty("foo", values.NewString("bar")))),
|
|
)
|
|
|
|
h1 := v.Hash()
|
|
h2 := v.Hash()
|
|
|
|
So(h1, ShouldEqual, h2)
|
|
})
|
|
})
|
|
|
|
Convey(".Length", t, func() {
|
|
Convey("Should return 0 when empty", func() {
|
|
obj := values.NewObject()
|
|
|
|
So(obj.Length(), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("Should return greater than 0 when not empty", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.ZeroInt),
|
|
values.NewObjectProperty("bar", values.ZeroInt),
|
|
)
|
|
|
|
So(obj.Length(), ShouldEqual, 2)
|
|
})
|
|
})
|
|
|
|
Convey(".ForEach", t, func() {
|
|
Convey("Should iterate over elements", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.ZeroInt),
|
|
values.NewObjectProperty("bar", values.ZeroInt),
|
|
)
|
|
counter := 0
|
|
|
|
obj.ForEach(func(value core.Value, key string) bool {
|
|
counter += 1
|
|
|
|
return true
|
|
})
|
|
|
|
So(counter, ShouldEqual, obj.Length())
|
|
})
|
|
|
|
Convey("Should not iterate when empty", func() {
|
|
obj := values.NewObject()
|
|
counter := 0
|
|
|
|
obj.ForEach(func(value core.Value, key string) bool {
|
|
counter += 1
|
|
|
|
return true
|
|
})
|
|
|
|
So(counter, ShouldEqual, obj.Length())
|
|
})
|
|
|
|
Convey("Should break iteration when false returned", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("1", values.NewInt(1)),
|
|
values.NewObjectProperty("2", values.NewInt(2)),
|
|
values.NewObjectProperty("3", values.NewInt(3)),
|
|
values.NewObjectProperty("4", values.NewInt(4)),
|
|
values.NewObjectProperty("5", values.NewInt(5)),
|
|
)
|
|
threshold := 3
|
|
counter := 0
|
|
|
|
obj.ForEach(func(value core.Value, key string) bool {
|
|
counter += 1
|
|
|
|
return counter < threshold
|
|
})
|
|
|
|
So(counter, ShouldEqual, threshold)
|
|
})
|
|
})
|
|
|
|
Convey(".Get", t, func() {
|
|
Convey("Should return item by key", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("foo", values.NewInt(1)),
|
|
values.NewObjectProperty("bar", values.NewInt(2)),
|
|
values.NewObjectProperty("qaz", values.NewInt(3)),
|
|
)
|
|
|
|
el, _ := obj.Get("foo")
|
|
|
|
So(el.Compare(values.NewInt(1)), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("Should return None when no value", func() {
|
|
obj := values.NewObject()
|
|
|
|
el, _ := obj.Get("foo")
|
|
|
|
So(el.Compare(values.None), ShouldEqual, 0)
|
|
})
|
|
})
|
|
|
|
Convey(".Set", t, func() {
|
|
Convey("Should set item by index", func() {
|
|
obj := values.NewObject()
|
|
|
|
obj.Set("foo", values.NewInt(1))
|
|
|
|
So(obj.Length(), ShouldEqual, 1)
|
|
|
|
v, _ := obj.Get("foo")
|
|
So(v.Compare(values.NewInt(1)), ShouldEqual, 0)
|
|
})
|
|
})
|
|
|
|
Convey(".Clone", t, func() {
|
|
Convey("Cloned object should be equal to source object", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("one", values.NewInt(1)),
|
|
values.NewObjectProperty("two", values.NewInt(2)),
|
|
)
|
|
|
|
clone := obj.Clone().(*values.Object)
|
|
|
|
So(obj.Compare(clone), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("Cloned object should be independent of the source object", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty("one", values.NewInt(1)),
|
|
values.NewObjectProperty("two", values.NewInt(2)),
|
|
)
|
|
|
|
clone := obj.Clone().(*values.Object)
|
|
|
|
obj.Remove(values.NewString("one"))
|
|
|
|
So(obj.Compare(clone), ShouldNotEqual, 0)
|
|
})
|
|
|
|
Convey("Cloned object must contain copies of the nested objects", func() {
|
|
obj := values.NewObjectWith(
|
|
values.NewObjectProperty(
|
|
"arr", values.NewArrayWith(values.NewInt(1)),
|
|
),
|
|
)
|
|
|
|
clone := obj.Clone().(*values.Object)
|
|
|
|
nestedInObj, _ := obj.Get(values.NewString("arr"))
|
|
nestedInObjArr := nestedInObj.(*values.Array)
|
|
nestedInObjArr.Push(values.NewInt(2))
|
|
|
|
nestedInClone, _ := clone.Get(values.NewString("arr"))
|
|
nestedInCloneArr := nestedInClone.(*values.Array)
|
|
|
|
So(nestedInObjArr.Compare(nestedInCloneArr), ShouldNotEqual, 0)
|
|
})
|
|
})
|
|
}
|