gomog/internal/engine/bitwise_ops_test.go

302 lines
7.1 KiB
Go

package engine
import (
"testing"
)
func TestBitwiseOps_BitAnd(t *testing.T) {
engine := &AggregationEngine{}
tests := []struct {
name string
data map[string]interface{}
operand interface{}
expected int64
}{
{
name: "basic AND operation",
data: map[string]interface{}{},
operand: []interface{}{float64(12), float64(10)}, // 1100 & 1010 = 1000
expected: 8,
},
{
name: "multiple operands",
data: map[string]interface{}{},
operand: []interface{}{float64(15), float64(7), float64(3)}, // 1111 & 0111 & 0011 = 0011
expected: 3,
},
{
name: "with field references",
data: map[string]interface{}{"a": float64(12), "b": float64(10)},
operand: []interface{}{"$a", "$b"},
expected: 8,
},
{
name: "single operand returns zero",
data: map[string]interface{}{},
operand: []interface{}{float64(5)},
expected: 0,
},
{
name: "empty operand returns zero",
data: map[string]interface{}{},
operand: []interface{}{},
expected: 0,
},
{
name: "AND with zero",
data: map[string]interface{}{},
operand: []interface{}{float64(255), float64(0)},
expected: 0,
},
{
name: "AND same numbers",
data: map[string]interface{}{},
operand: []interface{}{float64(42), float64(42)},
expected: 42,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := engine.bitAnd(tt.operand, tt.data)
if result != tt.expected {
t.Errorf("bitAnd() = %v, want %v", result, tt.expected)
}
})
}
}
func TestBitwiseOps_BitOr(t *testing.T) {
engine := &AggregationEngine{}
tests := []struct {
name string
data map[string]interface{}
operand interface{}
expected int64
}{
{
name: "basic OR operation",
data: map[string]interface{}{},
operand: []interface{}{float64(12), float64(10)}, // 1100 | 1010 = 1110
expected: 14,
},
{
name: "multiple operands",
data: map[string]interface{}{},
operand: []interface{}{float64(1), float64(2), float64(4)}, // 001 | 010 | 100 = 111
expected: 7,
},
{
name: "with field references",
data: map[string]interface{}{"a": float64(5), "b": float64(3)},
operand: []interface{}{"$a", "$b"}, // 101 | 011 = 111
expected: 7,
},
{
name: "single operand returns zero",
data: map[string]interface{}{},
operand: []interface{}{float64(5)},
expected: 0,
},
{
name: "OR with zero",
data: map[string]interface{}{},
operand: []interface{}{float64(42), float64(0)},
expected: 42,
},
{
name: "OR same numbers",
data: map[string]interface{}{},
operand: []interface{}{float64(15), float64(15)},
expected: 15,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := engine.bitOr(tt.operand, tt.data)
if result != tt.expected {
t.Errorf("bitOr() = %v, want %v", result, tt.expected)
}
})
}
}
func TestBitwiseOps_BitXor(t *testing.T) {
engine := &AggregationEngine{}
tests := []struct {
name string
data map[string]interface{}
operand interface{}
expected int64
}{
{
name: "basic XOR operation",
data: map[string]interface{}{},
operand: []interface{}{float64(12), float64(10)}, // 1100 ^ 1010 = 0110
expected: 6,
},
{
name: "multiple operands",
data: map[string]interface{}{},
operand: []interface{}{float64(5), float64(3), float64(1)}, // 101 ^ 011 ^ 001 = 111
expected: 7,
},
{
name: "with field references",
data: map[string]interface{}{"x": float64(7), "y": float64(3)},
operand: []interface{}{"$x", "$y"}, // 111 ^ 011 = 100
expected: 4,
},
{
name: "single operand returns zero",
data: map[string]interface{}{},
operand: []interface{}{float64(5)},
expected: 0,
},
{
name: "XOR with zero",
data: map[string]interface{}{},
operand: []interface{}{float64(42), float64(0)},
expected: 42,
},
{
name: "XOR same numbers",
data: map[string]interface{}{},
operand: []interface{}{float64(25), float64(25)},
expected: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := engine.bitXor(tt.operand, tt.data)
if result != tt.expected {
t.Errorf("bitXor() = %v, want %v", result, tt.expected)
}
})
}
}
func TestBitwiseOps_BitNot(t *testing.T) {
engine := &AggregationEngine{}
tests := []struct {
name string
data map[string]interface{}
operand interface{}
expected int64
}{
{
name: "basic NOT operation",
data: map[string]interface{}{},
operand: float64(5),
expected: ^int64(5),
},
{
name: "NOT zero",
data: map[string]interface{}{},
operand: float64(0),
expected: ^int64(0), // -1
},
{
name: "with field reference",
data: map[string]interface{}{"value": float64(10)},
operand: "$value",
expected: ^int64(10),
},
{
name: "NOT negative number",
data: map[string]interface{}{},
operand: float64(-5),
expected: ^int64(-5),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := engine.bitNot(tt.operand, tt.data)
if result != tt.expected {
t.Errorf("bitNot() = %v, want %v", result, tt.expected)
}
})
}
}
func TestBitwiseOps_Integration(t *testing.T) {
engine := &AggregationEngine{}
// 测试组合使用多个位运算操作符
tests := []struct {
name string
data map[string]interface{}
pipeline []map[string]interface{}
expectedLen int
checkFunc func([]map[string]interface{}) bool
}{
{
name: "combined bitwise operations",
data: map[string]interface{}{
"a": float64(12), // 1100
"b": float64(10), // 1010
"c": float64(6), // 0110
},
pipeline: []map[string]interface{}{
{
"$addFields": map[string]interface{}{
"and_result": map[string]interface{}{
"$bitAnd": []interface{}{"$a", "$b"},
},
"or_result": map[string]interface{}{
"$bitOr": []interface{}{"$a", "$b"},
},
"xor_result": map[string]interface{}{
"$bitXor": []interface{}{"$a", "$b"},
},
"not_result": map[string]interface{}{
"$bitNot": "$c",
},
},
},
},
expectedLen: 1,
checkFunc: func(results []map[string]interface{}) bool {
return results[0]["and_result"] == int64(8) &&
results[0]["or_result"] == int64(14) &&
results[0]["xor_result"] == int64(6)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 简化测试:直接测试表达式评估
doc := tt.data
// 测试 bitAnd
andOperand := []interface{}{"$a", "$b"}
andResult := engine.bitAnd(andOperand, doc)
if andResult != 8 {
t.Errorf("bitAnd integration = %v, want 8", andResult)
}
// 测试 bitOr
orOperand := []interface{}{"$a", "$b"}
orResult := engine.bitOr(orOperand, doc)
if orResult != 14 {
t.Errorf("bitOr integration = %v, want 14", orResult)
}
// 测试 bitXor
xorOperand := []interface{}{"$a", "$b"}
xorResult := engine.bitXor(xorOperand, doc)
if xorResult != 6 {
t.Errorf("bitXor integration = %v, want 6", xorResult)
}
})
}
}