compiler/test: check Main
locals in inline tests
This commit is contained in:
parent
ebff8be20a
commit
c538512e60
2 changed files with 31 additions and 17 deletions
|
@ -11,19 +11,31 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkCallCount(t *testing.T, src string, expectedCall, expectedInitSlot int) {
|
func checkCallCount(t *testing.T, src string, expectedCall, expectedInitSlot, expectedLocalsMain int) {
|
||||||
v := vmAndCompile(t, src)
|
v, sp := vmAndCompileInterop(t, src)
|
||||||
|
|
||||||
|
mainStart := -1
|
||||||
|
for _, m := range sp.info.Methods {
|
||||||
|
if m.Name.Name == "main" {
|
||||||
|
mainStart = int(m.Range.Start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.True(t, mainStart >= 0)
|
||||||
|
|
||||||
ctx := v.Context()
|
ctx := v.Context()
|
||||||
actualCall := 0
|
actualCall := 0
|
||||||
actualInitSlot := 0
|
actualInitSlot := 0
|
||||||
|
|
||||||
for op, _, err := ctx.Next(); ; op, _, err = ctx.Next() {
|
for op, param, err := ctx.Next(); ; op, param, err = ctx.Next() {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
switch op {
|
switch op {
|
||||||
case opcode.CALL, opcode.CALLL:
|
case opcode.CALL, opcode.CALLL:
|
||||||
actualCall++
|
actualCall++
|
||||||
case opcode.INITSLOT:
|
case opcode.INITSLOT:
|
||||||
actualInitSlot++
|
actualInitSlot++
|
||||||
|
if ctx.IP() == mainStart {
|
||||||
|
require.Equal(t, expectedLocalsMain, int(param[0]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ctx.IP() == ctx.LenInstr() {
|
if ctx.IP() == ctx.LenInstr() {
|
||||||
break
|
break
|
||||||
|
@ -47,75 +59,75 @@ func TestInline(t *testing.T) {
|
||||||
t.Run("no return", func(t *testing.T) {
|
t.Run("no return", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `inline.NoArgsNoReturn()
|
src := fmt.Sprintf(srcTmpl, `inline.NoArgsNoReturn()
|
||||||
return 1`)
|
return 1`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(1))
|
eval(t, src, big.NewInt(1))
|
||||||
})
|
})
|
||||||
t.Run("has return, dropped", func(t *testing.T) {
|
t.Run("has return, dropped", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `inline.NoArgsReturn1()
|
src := fmt.Sprintf(srcTmpl, `inline.NoArgsReturn1()
|
||||||
return 2`)
|
return 2`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(2))
|
eval(t, src, big.NewInt(2))
|
||||||
})
|
})
|
||||||
t.Run("drop twice", func(t *testing.T) {
|
t.Run("drop twice", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `inline.DropInsideInline()
|
src := fmt.Sprintf(srcTmpl, `inline.DropInsideInline()
|
||||||
return 42`)
|
return 42`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(42))
|
eval(t, src, big.NewInt(42))
|
||||||
})
|
})
|
||||||
t.Run("no args return 1", func(t *testing.T) {
|
t.Run("no args return 1", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.NoArgsReturn1()`)
|
src := fmt.Sprintf(srcTmpl, `return inline.NoArgsReturn1()`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(1))
|
eval(t, src, big.NewInt(1))
|
||||||
})
|
})
|
||||||
t.Run("sum", func(t *testing.T) {
|
t.Run("sum", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.Sum(1, 2)`)
|
src := fmt.Sprintf(srcTmpl, `return inline.Sum(1, 2)`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(3))
|
eval(t, src, big.NewInt(3))
|
||||||
})
|
})
|
||||||
t.Run("sum squared (nested inline)", func(t *testing.T) {
|
t.Run("sum squared (nested inline)", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.SumSquared(1, 2)`)
|
src := fmt.Sprintf(srcTmpl, `return inline.SumSquared(1, 2)`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(9))
|
eval(t, src, big.NewInt(9))
|
||||||
})
|
})
|
||||||
t.Run("inline function in inline function parameter", func(t *testing.T) {
|
t.Run("inline function in inline function parameter", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.Sum(inline.SumSquared(1, 2), inline.Sum(3, 4))`)
|
src := fmt.Sprintf(srcTmpl, `return inline.Sum(inline.SumSquared(1, 2), inline.Sum(3, 4))`)
|
||||||
checkCallCount(t, src, 0, 1)
|
checkCallCount(t, src, 0, 1, 2)
|
||||||
eval(t, src, big.NewInt(9+3+4))
|
eval(t, src, big.NewInt(9+3+4))
|
||||||
})
|
})
|
||||||
t.Run("global name clash", func(t *testing.T) {
|
t.Run("global name clash", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.GetSumSameName()`)
|
src := fmt.Sprintf(srcTmpl, `return inline.GetSumSameName()`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(42))
|
eval(t, src, big.NewInt(42))
|
||||||
})
|
})
|
||||||
t.Run("local name clash", func(t *testing.T) {
|
t.Run("local name clash", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.Sum(inline.SumSquared(1, 2), sum(3, 4))`)
|
src := fmt.Sprintf(srcTmpl, `return inline.Sum(inline.SumSquared(1, 2), sum(3, 4))`)
|
||||||
checkCallCount(t, src, 1, 2)
|
checkCallCount(t, src, 1, 2, 2)
|
||||||
eval(t, src, big.NewInt(51))
|
eval(t, src, big.NewInt(51))
|
||||||
})
|
})
|
||||||
t.Run("var args, empty", func(t *testing.T) {
|
t.Run("var args, empty", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.VarSum(11)`)
|
src := fmt.Sprintf(srcTmpl, `return inline.VarSum(11)`)
|
||||||
checkCallCount(t, src, 0, 1)
|
checkCallCount(t, src, 0, 1, 3)
|
||||||
eval(t, src, big.NewInt(11))
|
eval(t, src, big.NewInt(11))
|
||||||
})
|
})
|
||||||
t.Run("var args, direct", func(t *testing.T) {
|
t.Run("var args, direct", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.VarSum(11, 14, 17)`)
|
src := fmt.Sprintf(srcTmpl, `return inline.VarSum(11, 14, 17)`)
|
||||||
checkCallCount(t, src, 0, 1)
|
checkCallCount(t, src, 0, 1, 3)
|
||||||
eval(t, src, big.NewInt(42))
|
eval(t, src, big.NewInt(42))
|
||||||
})
|
})
|
||||||
t.Run("var args, array", func(t *testing.T) {
|
t.Run("var args, array", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `arr := []int{14, 17}
|
src := fmt.Sprintf(srcTmpl, `arr := []int{14, 17}
|
||||||
return inline.VarSum(11, arr...)`)
|
return inline.VarSum(11, arr...)`)
|
||||||
checkCallCount(t, src, 0, 1)
|
checkCallCount(t, src, 0, 1, 3)
|
||||||
eval(t, src, big.NewInt(42))
|
eval(t, src, big.NewInt(42))
|
||||||
})
|
})
|
||||||
t.Run("globals", func(t *testing.T) {
|
t.Run("globals", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `return inline.Concat(Num)`)
|
src := fmt.Sprintf(srcTmpl, `return inline.Concat(Num)`)
|
||||||
checkCallCount(t, src, 0, 0)
|
checkCallCount(t, src, 0, 0, 0)
|
||||||
eval(t, src, big.NewInt(221))
|
eval(t, src, big.NewInt(221))
|
||||||
})
|
})
|
||||||
t.Run("locals, alias", func(t *testing.T) {
|
t.Run("locals, alias", func(t *testing.T) {
|
||||||
src := fmt.Sprintf(srcTmpl, `num := 1; return inline.Concat(num)`)
|
src := fmt.Sprintf(srcTmpl, `num := 1; return inline.Concat(num)`)
|
||||||
checkCallCount(t, src, 0, 1)
|
checkCallCount(t, src, 0, 1, 1)
|
||||||
eval(t, src, big.NewInt(221))
|
eval(t, src, big.NewInt(221))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ func vmAndCompileInterop(t *testing.T, src string) (*vm.VM, *storagePlugin) {
|
||||||
b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src))
|
b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
storePlugin.info = di
|
||||||
invokeMethod(t, testMainIdent, b, vm, di)
|
invokeMethod(t, testMainIdent, b, vm, di)
|
||||||
return vm, storePlugin
|
return vm, storePlugin
|
||||||
}
|
}
|
||||||
|
@ -93,6 +94,7 @@ func invokeMethod(t *testing.T, method string, script []byte, v *vm.VM, di *comp
|
||||||
}
|
}
|
||||||
|
|
||||||
type storagePlugin struct {
|
type storagePlugin struct {
|
||||||
|
info *compiler.DebugInfo
|
||||||
mem map[string][]byte
|
mem map[string][]byte
|
||||||
interops map[uint32]func(v *vm.VM) error
|
interops map[uint32]func(v *vm.VM) error
|
||||||
events []state.NotificationEvent
|
events []state.NotificationEvent
|
||||||
|
|
Loading…
Reference in a new issue