diff --git a/node/expr/binary_op/t_binary_op_test.go b/node/expr/binary_op/t_binary_op_test.go new file mode 100644 index 0000000..46d8a1d --- /dev/null +++ b/node/expr/binary_op/t_binary_op_test.go @@ -0,0 +1,643 @@ +package binary_op_test + +import ( + "bytes" + "reflect" + "testing" + + "github.com/kylelemons/godebug/pretty" + + "github.com/z7zmey/php-parser/node" + "github.com/z7zmey/php-parser/node/expr" + "github.com/z7zmey/php-parser/node/expr/binary_op" + "github.com/z7zmey/php-parser/node/stmt" + "github.com/z7zmey/php-parser/php5" + "github.com/z7zmey/php-parser/php7" +) + +func assertEqual(t *testing.T, expected interface{}, actual interface{}) { + if !reflect.DeepEqual(expected, actual) { + diff := pretty.Compare(expected, actual) + + if diff != "" { + t.Errorf("diff: (-expected +actual)\n%s", diff) + } else { + t.Errorf("expected and actual are not equal\n") + } + } +} + +func TestBitwiseAnd(t *testing.T) { + src := `= $b;` + + expected := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Expression{ + Expr: &binary_op.GreaterOrEqual{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + }, + }, + } + + actual, _, _ := php7.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) + + actual, _, _ = php5.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) +} + +func TestGreater(t *testing.T) { + src := ` $b;` + + expected := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Expression{ + Expr: &binary_op.Greater{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + }, + }, + } + + actual, _, _ := php7.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) + + actual, _, _ = php5.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) +} + +func TestIdentical(t *testing.T) { + src := `> $b;` + + expected := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Expression{ + Expr: &binary_op.ShiftRight{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + }, + }, + } + + actual, _, _ := php7.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) + + actual, _, _ = php5.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) +} + +func TestSmallerOrEqual(t *testing.T) { + src := ` $b;` + + expected := &stmt.StmtList{ + Stmts: []node.Node{ + &stmt.Expression{ + Expr: &binary_op.Spaceship{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + }, + }, + } + + actual, _, _ := php7.Parse(bytes.NewBufferString(src), "test.php") + assertEqual(t, expected, actual) +} diff --git a/node/expr/binary_op/t_visitor_test.go b/node/expr/binary_op/t_visitor_test.go new file mode 100644 index 0000000..dfa084e --- /dev/null +++ b/node/expr/binary_op/t_visitor_test.go @@ -0,0 +1,346 @@ +package binary_op_test + +import ( + "reflect" + "testing" + + "github.com/kylelemons/godebug/pretty" + + "github.com/z7zmey/php-parser/node" + "github.com/z7zmey/php-parser/node/expr" + "github.com/z7zmey/php-parser/node/expr/binary_op" + "github.com/z7zmey/php-parser/walker" +) + +var nodesToTest = []struct { + node node.Node // node + expectedVisitedKeys []string // visited keys + expectedAttributes map[string]interface{} +}{ + { + &binary_op.BitwiseAnd{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.BitwiseOr{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.BitwiseXor{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.BooleanAnd{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.BooleanOr{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Coalesce{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Concat{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Div{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Equal{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.GreaterOrEqual{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Greater{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Identical{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.LogicalAnd{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.LogicalOr{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.LogicalXor{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Minus{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Mod{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Mul{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.NotEqual{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.NotIdentical{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Plus{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Pow{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.ShiftLeft{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.ShiftRight{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.SmallerOrEqual{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Smaller{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, + { + &binary_op.Spaceship{ + BinaryOp: binary_op.BinaryOp{ + Left: &expr.Variable{VarName: &node.Identifier{Value: "$a"}}, + Right: &expr.Variable{VarName: &node.Identifier{Value: "$b"}}, + }, + }, + []string{"Left", "Right"}, + map[string]interface{}{}, + }, +} + +type visitorMock struct { + visitChildren bool + visitedKeys []string +} + +func (v *visitorMock) EnterNode(n walker.Walker) bool { return v.visitChildren } +func (v *visitorMock) GetChildrenVisitor(key string) walker.Visitor { + v.visitedKeys = append(v.visitedKeys, key) + return &visitorMock{v.visitChildren, nil} +} +func (v *visitorMock) LeaveNode(n walker.Walker) {} + +func TestVisitorDisableChildren(t *testing.T) { + for _, tt := range nodesToTest { + v := &visitorMock{false, nil} + tt.node.Walk(v) + + expected := []string{} + actual := v.visitedKeys + + diff := pretty.Compare(expected, actual) + if diff != "" { + t.Errorf("%s diff: (-expected +actual)\n%s", reflect.TypeOf(tt.node), diff) + } + } +} + +func TestVisitor(t *testing.T) { + for _, tt := range nodesToTest { + v := &visitorMock{true, nil} + tt.node.Walk(v) + + expected := tt.expectedVisitedKeys + actual := v.visitedKeys + + diff := pretty.Compare(expected, actual) + if diff != "" { + t.Errorf("%s diff: (-expected +actual)\n%s", reflect.TypeOf(tt.node), diff) + } + } +} + +// test Attributes() + +func TestNameAttributes(t *testing.T) { + for _, tt := range nodesToTest { + expected := tt.expectedAttributes + actual := tt.node.Attributes() + + diff := pretty.Compare(expected, actual) + if diff != "" { + t.Errorf("%s diff: (-expected +actual)\n%s", reflect.TypeOf(tt.node), diff) + } + } +}