package engine import ( "testing" "git.kingecg.top/kingecg/gomog/pkg/types" ) // TestExpr 测试 $expr 操作符 func TestExpr(t *testing.T) { tests := []struct { name string doc map[string]interface{} filter types.Filter expected bool }{ { name: "simple comparison with $expr", doc: map[string]interface{}{"qty": 10, "minQty": 5}, filter: types.Filter{ "$expr": types.Filter{ "$gt": []interface{}{"$qty", "$minQty"}, }, }, expected: true, }, { name: "comparison fails with $expr", doc: map[string]interface{}{"qty": 3, "minQty": 5}, filter: types.Filter{ "$expr": map[string]interface{}{ "$gt": []interface{}{"$qty", "$minQty"}, }, }, expected: false, }, { name: "equality check with $expr", doc: map[string]interface{}{"a": 5, "b": 5}, filter: types.Filter{ "$expr": types.Filter{ "$eq": []interface{}{"$a", "$b"}, }, }, expected: true, }, { name: "arithmetic in $expr", doc: map[string]interface{}{"price": 100, "tax": 10}, filter: types.Filter{ "$expr": types.Filter{ "$gt": []interface{}{ types.Filter{"$add": []interface{}{"$price", "$tax"}}, float64(100), }, }, }, expected: true, }, { name: "conditional in $expr", doc: map[string]interface{}{"score": 85}, filter: types.Filter{ "$expr": types.Filter{ "$gte": []interface{}{"$score", float64(80)}, }, }, expected: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := MatchFilter(tt.doc, tt.filter) if result != tt.expected { t.Errorf("MatchFilter() = %v, want %v", result, tt.expected) } }) } } // TestJSONSchema 测试 $jsonSchema 验证操作符 func TestJSONSchema(t *testing.T) { tests := []struct { name string doc map[string]interface{} schema map[string]interface{} expected bool }{ { name: "bsonType object validation", doc: map[string]interface{}{"name": "Alice", "age": 25}, schema: map[string]interface{}{ "bsonType": "object", }, expected: true, }, { name: "required fields validation", doc: map[string]interface{}{"name": "Alice", "age": 25}, schema: map[string]interface{}{ "bsonType": "object", "required": []interface{}{"name", "age"}, }, expected: true, }, { name: "required fields missing", doc: map[string]interface{}{"name": "Alice"}, schema: map[string]interface{}{ "bsonType": "object", "required": []interface{}{"name", "email"}, }, expected: false, }, { name: "properties validation", doc: map[string]interface{}{"name": "Alice", "age": 25}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "name": map[string]interface{}{"bsonType": "string"}, "age": map[string]interface{}{"bsonType": "int"}, }, }, expected: true, }, { name: "enum validation", doc: map[string]interface{}{"status": "active"}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "status": map[string]interface{}{ "enum": []interface{}{"active", "inactive", "pending"}, }, }, }, expected: true, }, { name: "enum validation fails", doc: map[string]interface{}{"status": "unknown"}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "status": map[string]interface{}{ "enum": []interface{}{"active", "inactive"}, }, }, }, expected: false, }, { name: "minimum validation", doc: map[string]interface{}{"age": 25}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "age": map[string]interface{}{ "bsonType": "int", "minimum": float64(0), "maximum": float64(150), }, }, }, expected: true, }, { name: "minimum validation fails", doc: map[string]interface{}{"age": -5}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "age": map[string]interface{}{ "minimum": float64(0), }, }, }, expected: false, }, { name: "minLength validation", doc: map[string]interface{}{"name": "Alice"}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "name": map[string]interface{}{ "bsonType": "string", "minLength": float64(1), "maxLength": float64(50), }, }, }, expected: true, }, { name: "pattern validation", doc: map[string]interface{}{"email": "test@example.com"}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "email": map[string]interface{}{ "bsonType": "string", "pattern": `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`, }, }, }, expected: true, }, { name: "pattern validation fails", doc: map[string]interface{}{"email": "invalid-email"}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "email": map[string]interface{}{ "pattern": `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`, }, }, }, expected: false, }, { name: "array items validation", doc: map[string]interface{}{"scores": []interface{}{85, 90, 95}}, schema: map[string]interface{}{ "bsonType": "object", "properties": map[string]interface{}{ "scores": map[string]interface{}{ "bsonType": "array", "items": map[string]interface{}{ "bsonType": "int", }, }, }, }, expected: true, }, { name: "anyOf validation", doc: map[string]interface{}{"type": "A", "fieldA": "value"}, schema: map[string]interface{}{ "bsonType": "object", "anyOf": []interface{}{ map[string]interface{}{ "properties": map[string]interface{}{ "type": map[string]interface{}{"enum": []interface{}{"A"}}, "fieldA": map[string]interface{}{"bsonType": "string"}, }, }, map[string]interface{}{ "properties": map[string]interface{}{ "type": map[string]interface{}{"enum": []interface{}{"B"}}, "fieldB": map[string]interface{}{"bsonType": "int"}, }, }, }, }, expected: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { filter := types.Filter{"$jsonSchema": tt.schema} result := MatchFilter(tt.doc, filter) if result != tt.expected { t.Errorf("MatchFilter with $jsonSchema() = %v, want %v", result, tt.expected) } }) } } // TestIsTrueValue 测试 isTrueValue 辅助函数 func TestIsTrueValue(t *testing.T) { tests := []struct { name string value interface{} expected bool }{ {"nil value", nil, false}, {"bool true", true, true}, {"bool false", false, false}, {"int non-zero", 42, true}, {"int zero", 0, false}, {"float64 non-zero", 3.14, true}, {"float64 zero", 0.0, false}, {"string non-empty", "hello", true}, {"string empty", "", false}, {"array non-empty", []interface{}{1, 2}, true}, {"array empty", []interface{}{}, false}, {"map non-empty", map[string]interface{}{"a": 1}, true}, {"map empty", map[string]interface{}{}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := isTrueValue(tt.value) if result != tt.expected { t.Errorf("isTrueValue(%v) = %v, want %v", tt.value, result, tt.expected) } }) } }