package compiler_test import ( "bytes" "fmt" "math/big" "strings" "testing" "github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/stretchr/testify/require" ) var switchTestCases = []testCase{ { "simple switch success", `func F%d() int { a := 5 switch a { case 5: return 2 } return 1 } `, big.NewInt(2), }, { "switch with no tag", `func f() bool { return false } func F%d() int { switch { case f(): return 1 case true: return 2 } return 3 } `, big.NewInt(2), }, { "type conversion in tag", `type state int func F%d() int { a := 1 switch state(a) { case 1: return 42 default: return 11 } } `, big.NewInt(42), }, { "simple switch fail", `func F%d() int { a := 6 switch a { case 5: return 2 } return 1 } `, big.NewInt(1), }, { "multiple cases success", `func F%d() int { a := 6 switch a { case 5: return 2 case 6: return 3 } return 1 } `, big.NewInt(3), }, { "multiple cases fail", `func F%d() int { a := 7 switch a { case 5: return 2 case 6: return 3 } return 1 } `, big.NewInt(1), }, { "default case", `func F%d() int { a := 7 switch a { case 5: return 2 case 6: return 3 default: return 4 } return 1 } `, big.NewInt(4), }, { "empty case before default", `func F%d() int { a := 6 switch a { case 5: return 2 case 6: default: return 4 } return 1 } `, big.NewInt(1), }, { "expression in case clause", `func F%d() int { a := 6 b := 3 switch a { case 5: return 2 case b*3-3: return 3 } return 1 } `, big.NewInt(3), }, { "multiple expressions in case", `func F%d() int { a := 8 b := 3 switch a { case 5: return 2 case b*3-3, 7, 8: return 3 } return 1 } `, big.NewInt(3), }, { "string switch", `func F%d() int { name := "Valera" switch name { case "Misha": return 2 case "Katya", "Dima": return 3 case "Lera", "Valer" + "a": return 4 } return 1 } `, big.NewInt(4), }, { "break from switch", `func F%d() int { i := 3 switch i { case 2: return 2 case 3: i = 1 break return 3 case 4: return 4 } return i } `, big.NewInt(1), }, { "break from outer for", `func F%d() int { i := 3 loop: for i < 10 { i++ switch i { case 5: i = 7 break loop return 3 case 6: return 4 } } return i } `, big.NewInt(7), }, { "continue outer for", `func F%d() int { i := 2 for i < 10 { i++ switch i { case 3: i = 7 continue case 4, 5, 6, 7: return 5 case 8: return 2 } if i == 7 { return 6 } } return i } `, big.NewInt(2), }, { "simple fallthrough", `func F%d() int { n := 2 switch n { case 1: return 5 case 2: fallthrough case 3: return 6 } return 7 } `, big.NewInt(6), }, { "double fallthrough", `func F%d() int { n := 2 k := 5 switch n { case 0: return k case 1: fallthrough case 2: k++ fallthrough case 3: case 4: k++ return k } return k } `, big.NewInt(6), }, } func TestSwitch(t *testing.T) { srcBuilder := bytes.NewBuffer([]byte("package testcase\n")) for i, tc := range switchTestCases { srcBuilder.WriteString(fmt.Sprintf(tc.src, i)) } ne, di, err := compiler.CompileWithOptions("file.go", strings.NewReader(srcBuilder.String()), nil) require.NoError(t, err) for i, tc := range switchTestCases { t.Run(tc.name, func(t *testing.T) { v := vm.New() invokeMethod(t, fmt.Sprintf("F%d", i), ne.Script, v, di) runAndCheck(t, v, tc.result) }) } }