Repository: diegoholiveira/jsonlogic
Pull request #91 (2024-12-09 20:50:58)

Fixes and refactor


Patch:
diff --git a/arrays.go b/arrays.go
index 559c166..7523a29 100644
--- a/arrays.go
+++ b/arrays.go
@@ -1,6 +1,8 @@
 package jsonlogic
 
-import "fmt"
+import (
+	"fmt"
+)
 
 type ErrReduceDataType struct {
 	dataType string
@@ -95,15 +97,21 @@ func reduce(values, data interface{}) interface{} {
 		accumulator interface{}
 		valueType   string
 	)
+
 	{
-		if isBool(parsed[2]) {
-			accumulator = isTrue(parsed[2])
+		initialValue := parsed[2]
+		if isMap(initialValue) {
+			initialValue = apply(initialValue, data)
+		}
+
+		if isBool(initialValue) {
+			accumulator = isTrue(initialValue)
 			valueType = "bool"
-		} else if isNumber(parsed[2]) {
-			accumulator = toNumber(parsed[2])
+		} else if isNumber(initialValue) {
+			accumulator = toNumber(initialValue)
 			valueType = "number"
-		} else if isString(parsed[2]) {
-			accumulator = toString(parsed[2])
+		} else if isString(initialValue) {
+			accumulator = toString(initialValue)
 			valueType = "string"
 		} else {
 			panic(ErrReduceDataType{
diff --git a/comp.go b/comp.go
index ad2343f..84c3d7b 100644
--- a/comp.go
+++ b/comp.go
@@ -75,7 +75,7 @@ func equals(a, b interface{}) bool {
 	}
 
 	if isNumber(a) {
-		return toNumber(a) == toNumber(b)
+		return isPrimitive(b) && toNumber(a) == toNumber(b)
 	}
 
 	if isBool(a) {
@@ -85,5 +85,9 @@ func equals(a, b interface{}) bool {
 		return isTrue(a) == isTrue(b)
 	}
 
+	if !isString(a) || !isString(b) {
+		return false
+	}
+
 	return toString(a) == toString(b)
 }
diff --git a/jsonlogic.go b/jsonlogic.go
index 6968101..edcd9eb 100644
--- a/jsonlogic.go
+++ b/jsonlogic.go
@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"sort"
 	"strings"
 
 	"github.com/barkimedes/go-deepcopy"
@@ -125,40 +124,6 @@ func _inRange(value interface{}, values interface{}) bool {
 	return toString(value) >= toString(i) && toString(j) >= toString(value)
 }
 
-// Expect values to be in alphabetical ascending order
-func _inSorted(value interface{}, values interface{}) bool {
-	valuesSlice := values.([]interface{})
-
-	findElement := func(i int) bool {
-		element := valuesSlice[i]
-
-		if isSlice(valuesSlice[i]) {
-			sliceElement := valuesSlice[i].([]interface{})
-			start := sliceElement[0]
-			end := sliceElement[1]
-
-			return (toString(start) <= toString(value) && toString(end) >= toString(value)) || toString(end) > toString(value)
-		}
-
-		return toString(element) >= toString(value)
-	}
-
-	i := sort.Search(len(valuesSlice), findElement)
-	if i >= len(valuesSlice) {
-		return false
-	}
-
-	if isSlice(valuesSlice[i]) {
-		sliceElement := valuesSlice[i].([]interface{})
-		start := sliceElement[0]
-		end := sliceElement[1]
-
-		return toString(start) <= toString(value) && toString(end) >= toString(value)
-	}
-
-	return toString(valuesSlice[i]) == toString(value)
-}
-
 func _in(value interface{}, values interface{}) bool {
 	if value == nil || values == nil {
 		return false
@@ -168,6 +133,10 @@ func _in(value interface{}, values interface{}) bool {
 		return strings.Contains(values.(string), value.(string))
 	}
 
+	if !isSlice(values) {
+		return false
+	}
+
 	for _, element := range values.([]interface{}) {
 		if isSlice(element) {
 			if _inRange(value, element) {
@@ -522,7 +491,7 @@ func Apply(rule, data io.Reader, result io.Writer) error {
 		return err
 	}
 
-	output, err := ApplyInterface(_rule, _data)
+	output, err := applyInterface(_rule, _data)
 	if err != nil {
 		return err
 	}
@@ -572,7 +541,7 @@ func ApplyRaw(rule, data json.RawMessage) (json.RawMessage, error) {
 		return nil, err
 	}
 
-	result, err := ApplyInterface(_rule, _data)
+	result, err := applyInterface(_rule, _data)
 	if err != nil {
 		return nil, err
 	}
@@ -580,11 +549,9 @@ func ApplyRaw(rule, data json.RawMessage) (json.RawMessage, error) {
 	return json.Marshal(&result)
 }
 
-// ApplyInterface receives a rule and data as interface{} and returns the result
+// applyInterface receives a rule and data as interface{} and returns the result
 // of the rule applied to the data.
-//
-// Deprecated: Use Apply instead because ApplyInterface will be private in the next version.
-func ApplyInterface(rule, data interface{}) (output interface{}, err error) {
+func applyInterface(rule, data interface{}) (output interface{}, err error) {
 	defer func() {
 		if e := recover(); e != nil {
 			// fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
diff --git a/operation.go b/operation.go
index f67c3a2..392a012 100644
--- a/operation.go
+++ b/operation.go
@@ -74,7 +74,7 @@ func operation(operator string, values, data interface{}) interface{} {
 		return _or(parsed)
 	}
 
-	if len(parsed) == 1 {
+	if operator != "in" && len(parsed) == 1 {
 		return unary(operator, parsed[0])
 	}
 
@@ -103,11 +103,10 @@ func operation(operator string, values, data interface{}) interface{} {
 	}
 
 	if operator == "in" {
-		return _in(parsed[0], parsed[1])
-	}
-
-	if operator == "in_sorted" {
-		return _inSorted(parsed[0], parsed[1])
+		if len(parsed) > 1 {
+			return _in(parsed[0], parsed[1])
+		}
+		return _in(parsed[0], nil)
 	}
 
 	if operator == "%" {
diff --git a/validator.go b/validator.go
index 62e97ff..72ae2ae 100644
--- a/validator.go
+++ b/validator.go
@@ -69,7 +69,6 @@ func isOperator(op string) bool {
 		"and",
 		"?:",
 		"in",
-		"in_sorted",
 		"cat",
 		"%",
 		"abs",


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 04284d6..dce5a48 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -5,7 +5,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        go: ['1.14', '1.15', '1.16', '1.18', '1.19', '1.20', '1.21']
+        go: ['1.16', '1.18', '1.19', '1.20', '1.21']
     name: Running with Go ${{ matrix.go }}
     steps:
     - name: Install Go
diff --git a/arrays_test.go b/arrays_test.go
index 6441b40..9500820 100644
--- a/arrays_test.go
+++ b/arrays_test.go
@@ -1,111 +1,79 @@
-package jsonlogic
+package jsonlogic_test
 
 import (
-	"encoding/json"
+	"bytes"
+	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+
+	"github.com/diegoholiveira/jsonlogic/v3"
 )
 
 func TestFilterParseTheSubjectFromFirstPosition(t *testing.T) {
-	var parsed interface{}
-
-	err := json.Unmarshal([]byte(`[
+	rule := strings.NewReader(`{"filter": [
 		[1,2,3,4,5],
 		{"%":[{"var":""},2]}
-	]`), &parsed)
-	if err != nil {
-		panic(err)
-	}
-
-	result := filter(parsed, nil)
-
-	var expected interface{}
+	]}`)
 
-	json.Unmarshal([]byte(`[1,3,5]`), &expected) // nolint:errcheck
+	var result bytes.Buffer
 
-	assert.Equal(t, expected, result)
+	err := jsonlogic.Apply(rule, nil, &result)
+	assert.Nil(t, err)
+	assert.JSONEq(t, `[1,3,5]`, result.String())
 }
 
 func TestFilterParseTheSubjectFromNullValue(t *testing.T) {
-	var parsed interface{}
-
-	err := json.Unmarshal([]byte(`[
+	rule := strings.NewReader(`{"filter": [
 		null,
 		{"%":[{"var":""},2]}
-	]`), &parsed)
-	if err != nil {
-		panic(err)
-	}
-
-	result := filter(parsed, nil)
+	]}`)
 
-	var expected interface{}
+	var result bytes.Buffer
 
-	json.Unmarshal([]byte(`[]`), &expected) // nolint:errcheck
-
-	assert.Equal(t, expected, result)
+	err := jsonlogic.Apply(rule, nil, &result)
+	assert.Nil(t, err)
+	assert.JSONEq(t, `[]`, result.String())
 }
 
 func TestReduceSkipNullValues(t *testing.T) {
-	var parsed interface{}
-
-	err := json.Unmarshal([]byte(`[
+	rule := strings.NewReader(`{"reduce": [
 		[1,2,null,4,5],
 		{"+":[{"var":"current"}, {"var":"accumulator"}]},
 		0
-	]`), &parsed)
-	if err != nil {
-		panic(err)
-	}
+	]}`)
 
-	result := reduce(parsed, nil)
+	var result bytes.Buffer
 
-	var expected interface{}
-
-	json.Unmarshal([]byte(`12`), &expected) // nolint:errcheck
-
-	assert.Equal(t, expected, result)
+	err := jsonlogic.Apply(rule, nil, &result)
+	assert.Nil(t, err)
+	assert.JSONEq(t, `12`, result.String())
 }
 
 func TestReduceBoolValues(t *testing.T) {
-	var parsed interface{}
-
-	err := json.Unmarshal([]byte(`[
+	rule := strings.NewReader(`{"reduce": [
 		[true,false,true,null],
 		{"or":[{"var":"current"}, {"var":"accumulator"}]},
 		false
-	]`), &parsed)
-	if err != nil {
-		panic(err)
-	}
-
-	result := reduce(parsed, nil)
+	]}`)
 
-	var expected interface{}
+	var result bytes.Buffer
 
-	json.Unmarshal([]byte(`true`), &expected) // nolint:errcheck
-
-	assert.Equal(t, expected, result)
+	err := jsonlogic.Apply(rule, nil, &result)
+	assert.Nil(t, err)
+	assert.JSONEq(t, `true`, result.String())
 }
 
 func TestReduceStringValues(t *testing.T) {
-	var parsed interface{}
-
-	err := json.Unmarshal([]byte(`[
+	rule := strings.NewReader(`{"reduce": [
 		["a",null,"b"],
 		{"cat":[{"var":"current"}, {"var":"accumulator"}]},
 		""
-	]`), &parsed)
-	if err != nil {
-		panic(err)
-	}
-
-	result := reduce(parsed, nil)
-
-	var expected interface{}
+	]}`)
 
-	json.Unmarshal([]byte(`"ba"`), &expected) // nolint:errcheck
+	var result bytes.Buffer
 
-	assert.Equal(t, expected, result)
+	err := jsonlogic.Apply(rule, nil, &result)
+	assert.Nil(t, err)
+	assert.JSONEq(t, `"ba"`, result.String())
 }
diff --git a/internal/issues/0083_test.go b/internal/issues/0083_test.go
deleted file mode 100644
index 01fcc1e..0000000
--- a/internal/issues/0083_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package issues_test
-
-import (
-	"bytes"
-	"strings"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/diegoholiveira/jsonlogic/v3"
-)
-
-func TestIssue83(t *testing.T) {
-	rule := `{
-	  "map": [
-	    {"var": "listOfLists"},
-	    {"in": ["item_a", {"var": ""}]}
-	  ]
-	}`
-
-	data := `{
-	  "listOfLists": [
-	    ["item_a", "item_b", "item_c"],
-	    ["item_b", "item_c"],
-	    ["item_a", "item_c"]
-	  ]
-	}`
-
-	var result bytes.Buffer
-
-	err := jsonlogic.Apply(strings.NewReader(rule), strings.NewReader(data), &result)
-
-	if assert.Nil(t, err) {
-		expected := `[true,false,true]`
-		assert.JSONEq(t, expected, result.String())
-	}
-}
diff --git a/internal/testing.go b/internal/testing.go
index d60b29e..7014a87 100644
--- a/internal/testing.go
+++ b/internal/testing.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"encoding/json"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"reflect"
@@ -42,7 +41,7 @@ func GetScenariosFromOfficialTestSuite() Tests {
 		return tests
 	}
 
-	buffer, _ := ioutil.ReadAll(response.Body)
+	buffer, _ := io.ReadAll(response.Body)
 
 	response.Body.Close()
 
diff --git a/issues_test.go b/issues_test.go
new file mode 100644
index 0000000..b61fdcf
--- /dev/null
+++ b/issues_test.go
@@ -0,0 +1,316 @@
+package jsonlogic_test
+
+import (
+	"bytes"
+	"encoding/json"
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/diegoholiveira/jsonlogic/v3"
+)
+
+func TestIssue50(t *testing.T) {
+	logic := strings.NewReader(`{"<": ["abc", 3]}`)
+	data := strings.NewReader(`{}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `false`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue51_example1(t *testing.T) {
+	logic := strings.NewReader(`{"==":[{"var":"test"},true]}`)
+	data := strings.NewReader(`{}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `false`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue51_example2(t *testing.T) {
+	logic := strings.NewReader(`{"==":[{"var":"test"},"true"]}`)
+	data := strings.NewReader(`{"test": true}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `false`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue52_example1(t *testing.T) {
+	data := strings.NewReader(`{}`)
+	logic := strings.NewReader(`{"substr": ["jsonlogic", -10]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `"jsonlogic"`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue52_example2(t *testing.T) {
+	data := strings.NewReader(`{}`)
+	logic := strings.NewReader(`{"substr": ["jsonlogic", 10]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `"jsonlogic"`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue58_example(t *testing.T) {
+	data := strings.NewReader(`{"foo": "bar"}`)
+	logic := strings.NewReader(`{"if":[
+		{"==":[{"var":"foo"},"bar"]},{"foo":"is_bar","path":"foo_is_bar"},
+		{"foo":"not_bar","path":"default_object"}
+	]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `{"foo":"is_bar","path":"foo_is_bar"}`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue70(t *testing.T) {
+	data := strings.NewReader(`{"people": [
+		{"age":18, "name":"John"},
+		{"age":20, "name":"Luke"},
+		{"age":18, "name":"Mark"}
+]}`)
+	logic := strings.NewReader(`{"filter": [
+	{"var": ["people"]},
+	{"==": [{"var": ["age"]}, 18]}
+]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `[
+    {"age": 18, "name": "John"},
+    {"age": 18, "name": "Mark"}
+]`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue71_example_empty_min(t *testing.T) {
+	data := strings.NewReader(`{}`)
+	logic := strings.NewReader(`{"min":[]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `null`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue71_example_empty_max(t *testing.T) {
+	data := strings.NewReader(`{}`)
+	logic := strings.NewReader(`{"max":[]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `null`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue71_example_max(t *testing.T) {
+	data := strings.NewReader(`{}`)
+	logic := strings.NewReader(`{"max":[-3, -2]}`)
+
+	var result bytes.Buffer
+	err := jsonlogic.Apply(logic, data, &result)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `-2`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue74(t *testing.T) {
+	logic := strings.NewReader(`{"if":[ false, {"var":"values.0.categories"}, "else" ]}`)
+	data := strings.NewReader(`{ "values": [] }`)
+
+	var result bytes.Buffer
+	_ = jsonlogic.Apply(logic, data, &result)
+	expected := `"else"`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestJsonLogicWithSolvedVars(t *testing.T) {
+	rule := json.RawMessage(`{
+		"or":[
+		{
+			"and":[
+				{"==": [{ "var":"is_foo" }, true ]},
+				{"==": [{ "var":"is_bar" }, true ]},
+				{">=": [{ "var":"foo" }, 17179869184 ]},
+				{"==": [{ "var":"bar" }, 0 ]}
+			]
+      	},
+      	{
+			"and":[
+				{"==": [{ "var":"is_bar" }, true ]},
+				{"==": [{ "var":"is_foo" }, false ]},
+				{"==": [{ "var":"foo" }, 34359738368 ]},
+				{"==": [{ "var":"bar" }, 0 ]}
+			]
+      	}]
+    }`)
+
+	data := json.RawMessage(`{"foo": 34359738368, "bar": 10, "is_foo": false, "is_bar": true}`)
+
+	output, err := jsonlogic.GetJsonLogicWithSolvedVars(rule, data)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `{
+		"or":[
+		{
+			"and":[
+				{ "==":[ false, true ] },
+				{ "==":[ true, true ] },
+				{ ">=":[ 34359738368, 17179869184 ] },
+				{ "==":[ 10, 0 ] }
+			]
+		},
+		{
+			"and":[
+				{ "==":[ true, true ] },
+				{ "==":[ false, false ] },
+				{ "==":[ 34359738368, 34359738368 ] },
+				{ "==":[ 10, 0 ] }
+			]
+		}]
+	}`
+
+	assert.JSONEq(t, expected, string(output))
+}
+
+func TestIssue79(t *testing.T) {
+	rule := strings.NewReader(
+		`{"and": [
+        {"in": [
+          {"var": "flow"},
+          ["BRAND"]
+        ]},
+        {"or": [
+          {"if": [
+            {"missing": ["gender"]},
+            true,
+            false
+          ]},
+          {"some": [
+            {"var": "gender"},
+            {"==": [
+              {"var": null},
+              "men"
+            ]}
+          ]}
+        ]}
+      ]}`,
+	)
+
+	data := strings.NewReader(`{"category":["sneakers"],"flow":"BRAND","gender":["men"],"market":"US"}`)
+
+	var result bytes.Buffer
+
+	err := jsonlogic.Apply(rule, data, &result)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `true`
+	assert.JSONEq(t, expected, result.String())
+}
+
+func TestIssue83(t *testing.T) {
+	rule := `{
+	  "map": [
+	    {"var": "listOfLists"},
+	    {"in": ["item_a", {"var": ""}]}
+	  ]
+	}`
+
+	data := `{
+	  "listOfLists": [
+	    ["item_a", "item_b", "item_c"],
+	    ["item_b", "item_c"],
+	    ["item_a", "item_c"]
+	  ]
+	}`
+
+	var result bytes.Buffer
+
+	err := jsonlogic.Apply(strings.NewReader(rule), strings.NewReader(data), &result)
+
+	if assert.Nil(t, err) {
+		expected := `[true,false,true]`
+		assert.JSONEq(t, expected, result.String())
+	}
+}
+
+func TestIssue81(t *testing.T) {
+	rule := `{
+      "some": [
+        {"var": "A"},
+        {"!=": [
+          {"var": ".B"},
+          {"var": "B"}
+        ]}
+      ]}
+         `
+
+	data := `{"A":[{"B":1}], "B":2}`
+
+	var result bytes.Buffer
+
+	err := jsonlogic.Apply(strings.NewReader(rule), strings.NewReader(data), &result)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `true`
+	assert.JSONEq(t, expected, result.String())
+}
diff --git a/jsonlogic_test.go b/jsonlogic_test.go
index 5bda383..5e50f59 100644
--- a/jsonlogic_test.go
+++ b/jsonlogic_test.go
@@ -4,12 +4,13 @@ import (
 	"bytes"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"strings"
 	"testing"
 
-	"github.com/diegoholiveira/jsonlogic/v3/internal"
 	"github.com/stretchr/testify/assert"
+
+	"github.com/diegoholiveira/jsonlogic/v3/internal"
 )
 
 func TestRulesFromJsonLogic(t *testing.T) {
@@ -24,7 +25,7 @@ func TestRulesFromJsonLogic(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			if b, err := ioutil.ReadAll(test.Expected); err == nil {
+			if b, err := io.ReadAll(test.Expected); err == nil {
 				assert.JSONEq(t, string(b), result.String())
 			}
 		})
@@ -184,59 +185,6 @@ func TestListOfRanges(t *testing.T) {
 	assert.JSONEq(t, expected, result.String())
 }
 
-func TestInSortedOperator(t *testing.T) {
-	rule := strings.NewReader(`{
-		"filter": [
-			{"var": "people"},
-			{"in_sorted": [
-				{"var": ".age"},
-				[
-					11.00,
-					[12, 14],
-					[13, 18],
-					2,
-					"20",
-					[32, 38],
-					"a",
-					["b", "d"]
-				]
-			]}
-		]
-	}`)
-
-	data := strings.NewReader(`{
-		"people": [
-			{"age":"18", "name":"John"},
-			{"age":20, "name":"Luke"},
-			{"age":18, "name":"Mark"},
-			{"age":40, "name":"Donald"},
-			{"age":11, "name":"Mickey"},
-			{"age":"1", "name":"Minnie"},
-			{"age":2, "name":"Mario"},
-			{"age":"a", "name":"Mario"},
-			{"age":"c", "name":"Princess"}
-		]
-	}`)
-
-	var result bytes.Buffer
-	err := Apply(rule, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `[
-		{"age":"18", "name": "John"},
-		{"age":20, "name":"Luke"},
-		{"age":18, "name": "Mark"},
-		{"age":11, "name":"Mickey"},
-		{"age":2, "name":"Mario"},
-		{"age":"a", "name":"Mario"},
-		{"age":"c", "name":"Princess"}
-	]`
-
-	assert.JSONEq(t, expected, result.String())
-}
-
 func TestSomeWithLists(t *testing.T) {
 	rule := strings.NewReader(`{
 		"some": [
@@ -440,7 +388,7 @@ func TestDataWithDefaultValueWithApplyInterface(t *testing.T) {
 	}
 
 	expected := float64(3)
-	output, err := ApplyInterface(rule, nil)
+	output, err := applyInterface(rule, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -456,7 +404,7 @@ func TestMissingOperators(t *testing.T) {
 		},
 	}
 
-	_, err := ApplyInterface(rule, nil)
+	_, err := applyInterface(rule, nil)
 
 	assert.EqualError(t, err, "The operator \"sum\" is not supported")
 }
@@ -628,7 +576,7 @@ func TestReduceWithUnsupportedValue(t *testing.T) {
 		"data": []interface{}{"str"},
 	}
 
-	_, err := ApplyInterface(rule, data)
+	_, err := applyInterface(rule, data)
 	assert.EqualError(t, err, "The type \"<nil>\" is not supported")
 }
 
@@ -655,280 +603,30 @@ func TestAddOperator(t *testing.T) {
 	assert.JSONEq(t, expected, result.String())
 }
 
-func TestIssue50(t *testing.T) {
-	logic := strings.NewReader(`{"<": ["abc", 3]}`)
-	data := strings.NewReader(`{}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `false`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue51_example1(t *testing.T) {
-	logic := strings.NewReader(`{"==":[{"var":"test"},true]}`)
-	data := strings.NewReader(`{}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `false`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue51_example2(t *testing.T) {
-	logic := strings.NewReader(`{"==":[{"var":"test"},"true"]}`)
-	data := strings.NewReader(`{"test": true}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `false`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue52_example1(t *testing.T) {
-	data := strings.NewReader(`{}`)
-	logic := strings.NewReader(`{"substr": ["jsonlogic", -10]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `"jsonlogic"`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue52_example2(t *testing.T) {
-	data := strings.NewReader(`{}`)
-	logic := strings.NewReader(`{"substr": ["jsonlogic", 10]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `"jsonlogic"`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue58_example(t *testing.T) {
-	data := strings.NewReader(`{"foo": "bar"}`)
-	logic := strings.NewReader(`{"if":[
-		{"==":[{"var":"foo"},"bar"]},{"foo":"is_bar","path":"foo_is_bar"},
-		{"foo":"not_bar","path":"default_object"}
-	]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `{"foo":"is_bar","path":"foo_is_bar"}`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue70(t *testing.T) {
-	data := strings.NewReader(`{"people": [
-		{"age":18, "name":"John"},
-		{"age":20, "name":"Luke"},
-		{"age":18, "name":"Mark"}
-]}`)
-	logic := strings.NewReader(`{"filter": [
-	{"var": ["people"]},
-	{"==": [{"var": ["age"]}, 18]}
-]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `[
-    {"age": 18, "name": "John"},
-    {"age": 18, "name": "Mark"}
-]`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue71_example_empty_min(t *testing.T) {
-	data := strings.NewReader(`{}`)
-	logic := strings.NewReader(`{"min":[]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `null`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue71_example_empty_max(t *testing.T) {
-	data := strings.NewReader(`{}`)
-	logic := strings.NewReader(`{"max":[]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `null`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue71_example_max(t *testing.T) {
-	data := strings.NewReader(`{}`)
-	logic := strings.NewReader(`{"max":[-3, -2]}`)
-
-	var result bytes.Buffer
-	err := Apply(logic, data, &result)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `-2`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestIssue74(t *testing.T) {
-	logic := strings.NewReader(`{"if":[ false, {"var":"values.0.categories"}, "else" ]}`)
-	data := strings.NewReader(`{ "values": [] }`)
-
-	var result bytes.Buffer
-	_ = Apply(logic, data, &result)
-	expected := `"else"`
-	assert.JSONEq(t, expected, result.String())
-}
-
-func TestJsonLogicWithSolvedVars(t *testing.T) {
-	rule := json.RawMessage(`{
-		"or":[
-		{
-			"and":[
-				{"==": [{ "var":"is_foo" }, true ]},
-				{"==": [{ "var":"is_bar" }, true ]},
-				{">=": [{ "var":"foo" }, 17179869184 ]},
-				{"==": [{ "var":"bar" }, 0 ]}
-			]
-      	},
-      	{
-			"and":[
-				{"==": [{ "var":"is_bar" }, true ]},
-				{"==": [{ "var":"is_foo" }, false ]},
-				{"==": [{ "var":"foo" }, 34359738368 ]},
-				{"==": [{ "var":"bar" }, 0 ]}
-			]
-      	}]
-    }`)
-
-	data := json.RawMessage(`{"foo": 34359738368, "bar": 10, "is_foo": false, "is_bar": true}`)
-
-	output, err := GetJsonLogicWithSolvedVars(rule, data)
-
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	expected := `{
-		"or":[
-		{
-			"and":[
-				{ "==":[ false, true ] },
-				{ "==":[ true, true ] },
-				{ ">=":[ 34359738368, 17179869184 ] },
-				{ "==":[ 10, 0 ] }
-			]
-		},
-		{
-			"and":[
-				{ "==":[ true, true ] },
-				{ "==":[ false, false ] },
-				{ "==":[ 34359738368, 34359738368 ] },
-				{ "==":[ 10, 0 ] }
-			]
-		}]
-	}`
-
-	assert.JSONEq(t, expected, string(output))
-}
-
-func TestIssue79(t *testing.T) {
-	rule := strings.NewReader(
-		`{"and": [
-        {"in": [
-          {"var": "flow"},
-          ["BRAND"]
-        ]},
-        {"or": [
-          {"if": [
-            {"missing": ["gender"]},
-            true,
-            false
-          ]},
-          {"some": [
-            {"var": "gender"},
-            {"==": [
-              {"var": null},
-              "men"
-            ]}
-          ]}
-        ]}
-      ]}`,
-	)
-
-	data := strings.NewReader(`{"category":["sneakers"],"flow":"BRAND","gender":["men"],"market":"US"}`)
+func TestInWithOneParam(t *testing.T) {
+	rule := strings.NewReader(`{"in": [ "Ringo" ]}`)
+	data := strings.NewReader(`null`)
 
 	var result bytes.Buffer
 
 	err := Apply(rule, data, &result)
-
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	expected := `true`
-	assert.JSONEq(t, expected, result.String())
+	assert.JSONEq(t, `false`, result.String())
 }
 
-func TestIssue81(t *testing.T) {
-	rule := `{
-      "some": [
-        {"var": "A"},
-        {"!=": [
-          {"var": ".B"},
-          {"var": "B"}
-        ]}
-      ]}
-         `
-
-	data := `{"A":[{"B":1}], "B":2}`
+func TestEqualWithList(t *testing.T) {
+	rule := strings.NewReader(`{"==": [ 2, [3, 2, 1] ]}`)
+	data := strings.NewReader(`null`)
 
 	var result bytes.Buffer
 
-	err := Apply(strings.NewReader(rule), strings.NewReader(data), &result)
-
+	err := Apply(rule, data, &result)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	expected := `true`
-	assert.JSONEq(t, expected, result.String())
+	assert.JSONEq(t, `false`, result.String())
 }
diff --git a/math_test.go b/math_test.go
index 27ccb65..b6dd3cf 100644
--- a/math_test.go
+++ b/math_test.go
@@ -7,20 +7,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestMinusWithOneNumber(t *testing.T) {
-	json_parsed := []interface{}{"-10.0"}
-	input := interface{}(json_parsed)
-	expected := -10.0
-	assert.Equal(t, expected, minus(input))
-}
-
-func TestDivWithOneNumber(t *testing.T) {
-	json_parsed := []interface{}{"2.0"}
-	input := interface{}(json_parsed)
-	expected := 2.0
-	assert.Equal(t, expected, minus(input))
-}
-
 func TestSubOperation(t *testing.T) {
 	var rule json.RawMessage = json.RawMessage(`{
 		"-": [