mirror of
https://github.com/chaisql/chai.git
synced 2025-11-01 11:22:42 +08:00
419 lines
11 KiB
Go
419 lines
11 KiB
Go
package document_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/genjidb/genji/document"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var numericFuncs = []struct {
|
|
name string
|
|
fn func(x interface{}) document.Value
|
|
}{
|
|
{"integer", func(x interface{}) document.Value { return document.NewIntegerValue(int64(x.(int))) }},
|
|
{"double", func(x interface{}) document.Value { return document.NewDoubleValue(float64(x.(int))) }},
|
|
}
|
|
|
|
var textFuncs = []struct {
|
|
name string
|
|
fn func(x interface{}) document.Value
|
|
}{
|
|
{"text", func(x interface{}) document.Value { return document.NewTextValue(x.(string)) }},
|
|
{"bytes", func(x interface{}) document.Value { return document.NewBlobValue([]byte(x.(string))) }},
|
|
}
|
|
|
|
func TestComparisonNumbers(t *testing.T) {
|
|
tests := []struct {
|
|
op string
|
|
a, b int
|
|
ok bool
|
|
}{
|
|
{"=", 2, 1, false},
|
|
{"=", 2, 2, true},
|
|
{"!=", 2, 1, true},
|
|
{"!=", 2, 2, false},
|
|
{">", 2, 1, true},
|
|
{">", 1, 2, false},
|
|
{">", 2, 2, false},
|
|
{">=", 2, 1, true},
|
|
{">=", 1, 2, false},
|
|
{">=", 2, 2, true},
|
|
{"<", 2, 1, false},
|
|
{"<", 1, 2, true},
|
|
{"<", 2, 2, false},
|
|
{"<=", 2, 1, false},
|
|
{"<=", 1, 2, true},
|
|
{"<=", 2, 2, true},
|
|
}
|
|
|
|
for i := 0; i < len(numericFuncs); i++ {
|
|
for j := 0; j < len(numericFuncs); j++ {
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%s(%d)%s%s(%d)", numericFuncs[i].name, test.a, test.op, numericFuncs[j].name, test.b), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsEqual(numericFuncs[j].fn(test.b))
|
|
case "!=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsNotEqual(numericFuncs[j].fn(test.b))
|
|
case ">":
|
|
ok, err = numericFuncs[i].fn(test.a).IsGreaterThan(numericFuncs[j].fn(test.b))
|
|
case ">=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsGreaterThanOrEqual(numericFuncs[j].fn(test.b))
|
|
case "<":
|
|
ok, err = numericFuncs[i].fn(test.a).IsLesserThan(numericFuncs[j].fn(test.b))
|
|
case "<=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsLesserThanOrEqual(numericFuncs[j].fn(test.b))
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.ok, ok)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComparisonNumbersWithNull(t *testing.T) {
|
|
tests := []struct {
|
|
op string
|
|
a int
|
|
ok bool
|
|
}{
|
|
{"=", 1, false},
|
|
{"=", 0, false},
|
|
{"!=", 0, true},
|
|
{"!=", 1, true},
|
|
{">", 1, false},
|
|
{">", 0, false},
|
|
{">=", 1, false},
|
|
{">=", 0, false},
|
|
{"<", 1, false},
|
|
{"<", 0, false},
|
|
{"<=", 1, false},
|
|
{"<=", 0, false},
|
|
}
|
|
|
|
for i := 0; i < len(numericFuncs); i++ {
|
|
for j := 0; j < len(numericFuncs); j++ {
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%s(%q)%sNULL", numericFuncs[i].name, test.a, test.op), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsEqual(document.NewNullValue())
|
|
case "!=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsNotEqual(document.NewNullValue())
|
|
case ">":
|
|
ok, err = numericFuncs[i].fn(test.a).IsGreaterThan(document.NewNullValue())
|
|
case ">=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsGreaterThanOrEqual(document.NewNullValue())
|
|
case "<":
|
|
ok, err = numericFuncs[i].fn(test.a).IsLesserThan(document.NewNullValue())
|
|
case "<=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsLesserThanOrEqual(document.NewNullValue())
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.ok, ok)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComparisonText(t *testing.T) {
|
|
tests := []struct {
|
|
op string
|
|
a, b string
|
|
ok bool
|
|
}{
|
|
{"=", "b", "a", false},
|
|
{"=", "b", "b", true},
|
|
{"!=", "b", "a", true},
|
|
{"!=", "b", "b", false},
|
|
{">", "b", "a", true},
|
|
{">", "a", "b", false},
|
|
{">", "b", "b", false},
|
|
{">=", "b", "a", true},
|
|
{">=", "a", "b", false},
|
|
{">=", "b", "b", true},
|
|
{"<", "b", "a", false},
|
|
{"<", "a", "b", true},
|
|
{"<", "b", "b", false},
|
|
{"<=", "b", "a", false},
|
|
{"<=", "a", "b", true},
|
|
{"<=", "b", "b", true},
|
|
}
|
|
|
|
for i := 0; i < len(textFuncs); i++ {
|
|
for j := 0; j < len(textFuncs); j++ {
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%s(%q)%s%s(%q)", textFuncs[i].name, test.a, test.op, textFuncs[j].name, test.b), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = textFuncs[i].fn(test.a).IsEqual(textFuncs[j].fn(test.b))
|
|
case "!=":
|
|
ok, err = textFuncs[i].fn(test.a).IsNotEqual(textFuncs[j].fn(test.b))
|
|
case ">":
|
|
ok, err = textFuncs[i].fn(test.a).IsGreaterThan(textFuncs[j].fn(test.b))
|
|
case ">=":
|
|
ok, err = textFuncs[i].fn(test.a).IsGreaterThanOrEqual(textFuncs[j].fn(test.b))
|
|
case "<":
|
|
ok, err = textFuncs[i].fn(test.a).IsLesserThan(textFuncs[j].fn(test.b))
|
|
case "<=":
|
|
ok, err = textFuncs[i].fn(test.a).IsLesserThanOrEqual(textFuncs[j].fn(test.b))
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.ok, ok)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestComparisonTextWithNull(t *testing.T) {
|
|
nullTextTests := []struct {
|
|
op string
|
|
a string
|
|
ok bool
|
|
}{
|
|
{"=", "a", false},
|
|
{"=", "", false},
|
|
{"!=", "a", true},
|
|
{"!=", "", true},
|
|
{">", "a", false},
|
|
{">", "", false},
|
|
{">=", "a", false},
|
|
{">=", "", false},
|
|
{"<", "a", false},
|
|
{"<", "", false},
|
|
{"<=", "a", false},
|
|
{"<=", "", false},
|
|
}
|
|
|
|
for i := 0; i < len(textFuncs); i++ {
|
|
for j := 0; j < len(textFuncs); j++ {
|
|
for _, test := range nullTextTests {
|
|
t.Run(fmt.Sprintf("%s(%q)%sNULL", textFuncs[i].name, test.a, test.op), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = textFuncs[i].fn(test.a).IsEqual(document.NewNullValue())
|
|
case "!=":
|
|
ok, err = textFuncs[i].fn(test.a).IsNotEqual(document.NewNullValue())
|
|
case ">":
|
|
ok, err = textFuncs[i].fn(test.a).IsGreaterThan(document.NewNullValue())
|
|
case ">=":
|
|
ok, err = textFuncs[i].fn(test.a).IsGreaterThanOrEqual(document.NewNullValue())
|
|
case "<":
|
|
ok, err = textFuncs[i].fn(test.a).IsLesserThan(document.NewNullValue())
|
|
case "<=":
|
|
ok, err = textFuncs[i].fn(test.a).IsLesserThanOrEqual(document.NewNullValue())
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.ok, ok)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComparisonDocuments(t *testing.T) {
|
|
tests := []struct {
|
|
op string
|
|
a string
|
|
b string
|
|
}{
|
|
{"=", `{}`, `{}`},
|
|
{"=", `{"a": 1}`, `{"a": 1}`},
|
|
{
|
|
"=",
|
|
`{"a": 1, "b": 2}`,
|
|
`{"b": 2, "a": 1}`,
|
|
},
|
|
{">", `{"a": 2}`, `{"a": 1}`},
|
|
{"<", `{"a": 1}`, `{"a": 2}`},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%v %s %v", test.a, test.op, test.b), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
var d1, d2 document.FieldBuffer
|
|
require.NoError(t, json.Unmarshal([]byte(test.a), &d1))
|
|
require.NoError(t, json.Unmarshal([]byte(test.b), &d2))
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = document.NewDocumentValue(d1).IsEqual(document.NewDocumentValue(d2))
|
|
require.NoError(t, err)
|
|
require.True(t, ok)
|
|
case ">":
|
|
ok, err = document.NewDocumentValue(d1).IsGreaterThan(document.NewDocumentValue(d2))
|
|
require.NoError(t, err)
|
|
require.False(t, ok)
|
|
case ">=":
|
|
ok, err = document.NewDocumentValue(d1).IsGreaterThanOrEqual(document.NewDocumentValue(d2))
|
|
require.NoError(t, err)
|
|
require.False(t, ok)
|
|
case "<":
|
|
ok, err = document.NewDocumentValue(d1).IsLesserThan(document.NewDocumentValue(d2))
|
|
require.NoError(t, err)
|
|
require.False(t, ok)
|
|
case "<=":
|
|
ok, err = document.NewDocumentValue(d1).IsLesserThanOrEqual(document.NewDocumentValue(d2))
|
|
require.NoError(t, err)
|
|
require.False(t, ok)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestComparisonArrays(t *testing.T) {
|
|
tests := []struct {
|
|
op string
|
|
a string
|
|
b string
|
|
expected bool
|
|
}{
|
|
{"=", `[]`, `[]`, true},
|
|
{"=", `[1]`, `[1]`, true},
|
|
{"=", `[1]`, `[]`, false},
|
|
{"=", `[1.0, 2]`, `[1, 2]`, true},
|
|
{"=", `[1,2,3]`, `[1,2,3]`, true},
|
|
{"!=", `[1]`, `[5]`, true},
|
|
{"!=", `[1]`, `[1, 1]`, true},
|
|
{"!=", `[1,2,3]`, `[1,2,3]`, false},
|
|
{"!=", `[1]`, `[]`, true},
|
|
{">", `[2]`, `[1]`, true},
|
|
{">", `[2]`, `[1, 1000]`, true},
|
|
{">", `[1]`, `[1, 1000]`, false},
|
|
{">", `[1, 2]`, `[1, 1000]`, false},
|
|
{">", `[2, 1000]`, `[1]`, true},
|
|
{">", `[2, 1000]`, `[2]`, true},
|
|
{">", `[1,2,3]`, `[1,2,3]`, false},
|
|
{">", `[1,2,3]`, `[]`, true},
|
|
{">=", `[2]`, `[1]`, true},
|
|
{">=", `[2]`, `[2]`, true},
|
|
{">=", `[2]`, `[1, 1000]`, true},
|
|
{">=", `[1]`, `[1, 1000]`, false},
|
|
{">=", `[1, 2]`, `[1, 2]`, true},
|
|
{">=", `[1, 2]`, `[1, 1000]`, false},
|
|
{">=", `[2, 1000]`, `[1]`, true},
|
|
{">=", `[2, 1000]`, `[2]`, true},
|
|
{">=", `[1,2,3]`, `[1,2,3]`, true},
|
|
{">=", `[1,2,3]`, `[]`, true},
|
|
{"<", `[1]`, `[2]`, true},
|
|
{"<", `[1,2,3]`, `[1,2]`, false},
|
|
{"<", `[1,2,3]`, `[1,2,3]`, false},
|
|
{"<", `[1,2]`, `[1,2,3]`, true},
|
|
{"<", `[1, 1000]`, `[2]`, true},
|
|
{"<", `[2]`, `[2, 1000]`, true},
|
|
{"<", `[1,2,3]`, `[]`, false},
|
|
{"<", `[]`, `[1,2,3]`, true},
|
|
{"<=", `[1]`, `[2]`, true},
|
|
{"<=", `[1, 1000]`, `[2]`, true},
|
|
{"<=", `[1,2,3]`, `[1,2]`, false},
|
|
{">=", `[2]`, `[1]`, true},
|
|
{">=", `[2]`, `[2]`, true},
|
|
{">=", `[2]`, `[1, 1000]`, true},
|
|
{">=", `[2, 1000]`, `[1]`, true},
|
|
{"<=", `[1,2,3]`, `[1,2,3]`, true},
|
|
{"<=", `[]`, `[]`, true},
|
|
{"<=", `[]`, `[1,2,3]`, true},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%v %s %v", test.a, test.op, test.b), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
var a1, a2 document.ValueBuffer
|
|
require.NoError(t, json.Unmarshal([]byte(test.a), &a1))
|
|
require.NoError(t, json.Unmarshal([]byte(test.b), &a2))
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = document.NewArrayValue(a1).IsEqual(document.NewArrayValue(a2))
|
|
case ">":
|
|
ok, err = document.NewArrayValue(a1).IsGreaterThan(document.NewArrayValue(a2))
|
|
case ">=":
|
|
ok, err = document.NewArrayValue(a1).IsGreaterThanOrEqual(document.NewArrayValue(a2))
|
|
case "<":
|
|
ok, err = document.NewArrayValue(a1).IsLesserThan(document.NewArrayValue(a2))
|
|
case "<=":
|
|
ok, err = document.NewArrayValue(a1).IsLesserThanOrEqual(document.NewArrayValue(a2))
|
|
case "!=":
|
|
ok, err = document.NewArrayValue(a1).IsNotEqual(document.NewArrayValue(a2))
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.expected, ok)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestComparisonDifferentTypes(t *testing.T) {
|
|
tests := []struct {
|
|
op string
|
|
a int
|
|
b string
|
|
}{
|
|
{"=", 1, "1"},
|
|
{"=", 0, ""},
|
|
{"=", 0, ""},
|
|
{">", 2, "1"},
|
|
{">", 1, ""},
|
|
{">=", 1, "1"},
|
|
{">=", 0, ""},
|
|
{"<", 0, "1"},
|
|
{"<", -1, ""},
|
|
{"<=", 1, "1"},
|
|
{"<=", 0, ""},
|
|
}
|
|
|
|
for i := 0; i < len(numericFuncs); i++ {
|
|
for j := 0; j < len(textFuncs); j++ {
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%s(%d)%s%s(%q)", numericFuncs[i].name, test.a, test.op, textFuncs[j].name, test.b), func(t *testing.T) {
|
|
var ok bool
|
|
var err error
|
|
|
|
switch test.op {
|
|
case "=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsEqual(textFuncs[j].fn(test.b))
|
|
case ">":
|
|
ok, err = numericFuncs[i].fn(test.a).IsGreaterThan(textFuncs[j].fn(test.b))
|
|
case ">=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsGreaterThanOrEqual(textFuncs[j].fn(test.b))
|
|
case "<":
|
|
ok, err = numericFuncs[i].fn(test.a).IsLesserThan(textFuncs[j].fn(test.b))
|
|
case "<=":
|
|
ok, err = numericFuncs[i].fn(test.a).IsLesserThanOrEqual(textFuncs[j].fn(test.b))
|
|
}
|
|
require.NoError(t, err)
|
|
require.False(t, ok)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
t.Run("not equal with different types", func(t *testing.T) {
|
|
ok, err := document.NewIntegerValue(1).IsNotEqual(document.NewTextValue("foo"))
|
|
require.NoError(t, err)
|
|
require.True(t, ok)
|
|
})
|
|
}
|