derohe-miniblock-mod/dvm/dvm_execution_test.go

1702 lines
47 KiB
Go
Raw Normal View History

2021-11-08 16:39:17 +00:00
// Copyright 2017-2018 DERO Project. All rights reserved.
// Use of this source code in any form is governed by RESEARCH license.
// license can be found in the LICENSE file.
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package dvm
import "fmt"
import "reflect"
import "testing"
//import "github.com/deroproject/derosuite/crypto"
var execution_tests = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"demo 1",
`Function TestRun(s Uint64) Uint64
10 Return s
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
},
{
"invalid return expression",
`Function TestRun(s Uint64) Uint64
10 Return 1s
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function with 2 params",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 + a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "4", "a2": "4"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function with 2 string params",
`Function TestRun(a1 String,a2 String) String
10 dim s1, s2 as Uint64
20
30 return a1 + a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "4", "a2": "4"},
nil,
Variable{Type: String, ValueString: "44"},
},
// test all arithmetic operations
{
"valid function testing substraction ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 - a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "12", "a2": "4"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing multiplication ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 * a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "4"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing division ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 / a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "25", "a2": "3"}, // it is 25 to confirm we are doing integer division
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing modulus ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 % a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "35", "a2": "9"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing SHL ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 << a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "4", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing SHR ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 >> a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "32", "a2": "2"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing OR ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 | a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "8", "a2": "8"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing AND ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 & a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "9", "a2": "10"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"valid function testing NOT ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return !a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "9", "a2": "10"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(18446744073709551606)}, //NOT 9 == 18446744073709551606
}, {
"valid function testing ^XOR ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return ^a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "9", "a2": "10"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(18446744073709551606)}, //NOT 9 == 18446744073709551606
}, {
"valid function testing XOR ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 ^ a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "60", "a2": "13"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(49)},
}, {
"valid function testing || ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 || a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "0", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"valid function testing && 1 ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return a1 && a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "0", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(0)},
}, {
"valid function testing && 2",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return (a1 && a2)
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
{
"valid function testing && 3",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20
30 return 0 || (a1 && a2)
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
{
"valid function testing LET ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"valid function testing IF THEN form1 fallthrough",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"valid function testing IF THEN form1 THEN case",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(0)},
},
{
"valid function testing IF THEN ELSE form1 THEN case",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30 ELSE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(0)},
}, {
"valid function testing IF THEN ELSE form1 ELSE case",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30 ELSE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"valid function testing != success ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 != 3 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
},
{
"valid function testing != failed",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 != 3 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "3", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"valid function testing <> ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 <> 3 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"invalid operator testing = ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 = 3 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(99)},
},
{
"valid function testing > success ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 > 1 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing > failed ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if 1 > a1 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing >= success",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 >= 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing >= failed",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 >= 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing < success ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 < 3 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing < failed ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 < 3 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "5", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing <= success ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 <= 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing <= success ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 <= 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "4", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing string == success",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 == a2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "asdf", "a2": "asdf"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing string == success",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 == "asdf" then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "asdf", "a2": "asdf"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing string == failed",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 == a2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "asdf", "a2": "asdf1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing !string success ",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if !a1 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "", "a2": "asdf1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing !string fail ",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if !a1 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "a1", "a2": "asdf1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing string != ",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 != a2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "asdf", "a2": "asdfz"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(99)},
}, {
"valid function testing LOR ",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 != a2 || a1 != a2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "asdf", "a2": "asdf"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing comparision of uint64 /string ",
`Function TestRun(a1 String,a2 String) Uint64
10 dim s1, s2 as Uint64
13 LET s1 = 99
15 if a1 != s1 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "asdf", "a2": "asdfz"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(99)},
},
{
"valid function arbitrary function evaluation",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 fact_recursive(10)
20 LET s1 = fact_recursive(10)
30 return s1
End Function
Function fact_recursive(s Uint64) Uint64
10 IF s == 1 THEN GOTO 20 ELSE GOTO 30
20 RETURN 1
30 RETURN s * fact_recursive(s -1)
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(3628800)},
},
{
"Invalid function with 2 string params substractions",
`Function TestRun(a1 String,a2 String) String
10 dim s1, s2 as Uint64
20
30 return a1 - a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "4", "a2": "4"},
fmt.Errorf("dummy"),
Variable{Type: String, ValueString: "44"},
},
}
// run the test
func Test_execution(t *testing.T) {
for _, test := range execution_tests {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// ensure 100% coverage of IF
var execution_tests_if = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"valid function testing IF THEN form1 fallthrough",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"valid function testing IF THEN form1 THEN case",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(0)},
},
{
"valid function testing IF THEN ELSE form1 THEN case",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30 ELSE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "2", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(0)},
}, {
"valid function testing IF THEN ELSE form1 ELSE case",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30 ELSE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 malformed if then",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 = != 2 thenn GOTO 30
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 malformed else",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 30 ELSEE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 malformed then line number",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 0 ELSE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 malformed then else number",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 20 ELSE GOTO 0
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 malformed unparseable then line number",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO ewr
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN ELSE form1 malformed unparseable then line number",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO ewr ELSE GOTO 20
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 malformed unparseable else number",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 20 ELSE GOTO ewr
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
{
"invalid function testing IF THEN form1 unknownelse number",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 if a1 == 2 then GOTO 20 ELSE GOTO 43535
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing IF THEN invalid IF expression",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
13 dim x1 as String
15 if x1 then GOTO 20 ELSE GOTO 43535
20 RETURN 2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "77", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
}
// run the test
func Test_IF_execution(t *testing.T) {
for _, test := range execution_tests_if {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// ensure 100% coverage of DIM
var execution_tests_dim = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"valid function testing DIM ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 GOTO 20
17 RETURN 0
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing DIM string",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as String
15 GOTO 30
17 RETURN 0
20
30 return a1 + a2
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid dim expression collision between arguments and local variable",
`Function TestRun(s Uint64) Uint64
10 dim s as Uint64
20
30 return 8
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"invalid dim expression invalid variable name",
`Function TestRun(s Uint64) Uint64
10 dim 1s as Uint64
20
30 return 8
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"invalid dim expression invalid 2nd variable name",
`Function TestRun(s Uint64) Uint64
10 dim s1,2s2 as Uint64
20
30 return 8
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"invalid dim expression invalid dim syntax",
`Function TestRun(s Uint64) Uint64
10 dim tu ajs Uint64
20
30 return 8
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(8)},
}, {
"invalid dim expression invalid dim syntax",
`Function TestRun(s Uint64) Uint64
10 dim tu as UUint64
20
30 return 8
End Function
`,
"TestRun",
map[string]interface{}{"s": "8"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(8)},
},
}
// run the test
func Test_DIM_execution(t *testing.T) {
for _, test := range execution_tests_dim {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// ensure 100% coverage of LET
var execution_tests_let = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"valid function testing LET ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"valid function testing LET String",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
12 dim add1,add2 as String
13 let add1 = add2
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing LET ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20 LET
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing LET undefined local variable",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20 LET s3 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing LET malformed expression",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
20 LET s1 = ((a1) + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing LET putting int into string",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as String
20 LET s1 = (a1) + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
}
// run the test
func Test_LET_execution(t *testing.T) {
for _, test := range execution_tests_let {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// ensure 100% coverage of PRINT
var execution_tests_print = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"valid function testing PRINT ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15
17 PRINT "%d %d" s1 s2
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing PRINT ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15
17 PRINT "%d %d" a1 a2
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
}
// run the test
func Test_PRINT_execution(t *testing.T) {
for _, test := range execution_tests_print {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// generic cases of coding mistakes
var execution_tests_generic = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"invalid function testing Generic case if function does not return ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15
17 PRINT "%d %d" s1 s2
20 LET s1 = a1 + a2
// 30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing Generic case if invalid expression evaluated ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15
17 dummy (s1 s2 s3
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing Generic case if valid expression but not a function call ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15
17 2 +3
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
// these case check callability of unexported functions etc
{
"valid function testing Invalid Rune ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
string([]byte{0x80}), // EntryPoint checking
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"valid function testing executing first non-ascii function ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"☺☻TestRun", // EntryPoint checking
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"valid function testing executing first non-letter function",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"1TestRun", // EntryPoint checking
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"valid function testing executing unexported function ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"testRun", // EntryPoint checking
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"invalid function testing executing non-existing function ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"TestRun1", // no function exists
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
{
"valid function testing parameter missing ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"TestRun",
map[string]interface{}{"a3": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
{
"valid function testing Invalid parameter uint64 ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "-1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
{
"valid function testing use unknown variable ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1*a3
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"valid function testing use uint64 larger than 64 bits ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1* 118446744073709551615
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
{
"valid function testing recursive FACTORIAL ",
`Function fact_recursive(s Uint64) Uint64
10 IF s == 1 THEN GOTO 20 ELSE GOTO 30
20 RETURN 1
30 RETURN s * fact_recursive(s -1)
End Function
Function TestRun(a1 Uint64) Uint64
10 dim result as Uint64
20 LET result = fact_recursive(a1)
60 printf "FACTORIAL of %d = %d" a1 result
70 RETURN result
End Function
`,
"TestRun",
map[string]interface{}{"a1": "10", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(3628800)},
},
{
"invalid function testing paramter skipped ",
`Function fact_recursive(s Uint64) Uint64
10 IF s == 1 THEN GOTO 20 ELSE GOTO 30
20 RETURN 1
30 RETURN s * fact_recursive(s -1)
End Function
Function TestRun(a1 Uint64) Uint64
10 dim result as Uint64
20 LET result = fact_recursive()
60 printf "FACTORIAL of %d = %d" s result
70 RETURN result
End Function
`,
"TestRun",
map[string]interface{}{"a1": "10", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(3628800)},
},
{
"invalid function testing unknown function called ",
`Function fact_recursive(s Uint64) Uint64
10 IF s == 1 THEN GOTO 20 ELSE GOTO 30
20 RETURN 1
30 RETURN s * fact_recursive(s -1)
End Function
Function TestRun(a1 Uint64) Uint64
10 dim result as Uint64
20 LET result = fact_recursive_unknown(a1)
60 printf "FACTORIAL of %d = %d" s result
70 RETURN result
End Function
`,
"TestRun",
map[string]interface{}{"a1": "10", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(3628800)},
},
{
"invalid function testing error withing sub function call",
`Function fact_recursive(s Uint64) Uint64
10 IF s == 1 THEN GOTO 20 ELSE GOTO 30
20 RETURN 1
30 RETURN s * fact_recursive(s -1) * (
End Function
Function TestRun(a1 Uint64) Uint64
10 dim result as Uint64
20 LET result = fact_recursive(a1)
60 printf "FACTORIAL of %d = %d" s result
70 RETURN result
End Function
`,
"TestRun",
map[string]interface{}{"a1": "10", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(3628800)},
},
{
"1valid function testing sub function call without return",
`Function dummy(s Uint64)
20 RETURN
End Function
Function TestRun(a1 Uint64) Uint64
10 dim result as Uint64
20 LET result = a1
60 dummy(a1)
70 RETURN result
End Function
`,
"TestRun",
map[string]interface{}{"a1": "10", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(10)},
},
{
"valid function testing recursive FACTORIAL ",
`Function fact_recursive(s Uint64, a String, b String, str String) Uint64
10 IF s == 1 THEN GOTO 20 ELSE GOTO 30
20 RETURN 1
30 RETURN s * fact_recursive(s -1,a,b,str)
End Function
Function TestRun(a1 Uint64,a String, b String, str String) Uint64
10 dim result as Uint64
20 LET result = fact_recursive(a1,a,b,str)
60 printf "FACTORIAL of %d = %d" a1 result
70 RETURN result
End Function
`,
"TestRun",
map[string]interface{}{"a1": "10", "a2": "1", "a": "address param", "b": "blob param", "str": "str_param"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(3628800)},
},
}
// run the test
func Test_Generic_execution(t *testing.T) {
for _, test := range execution_tests_generic {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// ensure 100% coverage of RETURN
var execution_tests_return = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"valid function testing RETURN uint64 ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"valid function testing RETURN String ",
`Function TestRun(a1 String,a2 Uint64) String
30 return a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: String, ValueString: "1"},
},
{
"valid function testing RETURN String ",
`Function TestRun(a1 String,a2 Uint64) String
30 return a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: String, ValueString: "1"},
}, {
"valid function testing non returning function returning nothing ",
`Function TestRun(a1 Uint64,a2 Uint64)
30 return
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Invalid},
},
{
"valid function testing non returning function returning something ",
`Function TestRun(a1 Uint64,a2 Uint64)
30 return a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueString: "1"},
}, {
"invalid function testing RETURN uint64 ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
}, {
"invalid function testing RETURN contains unparseable function ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
30 return ( a1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(1)},
},
}
// run the test
func Test_RETURN_execution(t *testing.T) {
for _, test := range execution_tests_return {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}
// ensure 100% coverage of GOTO
var execution_tests_goto = []struct {
Name string
Code string
EntryPoint string
Args map[string]interface{}
Eerr error // execute error
result Variable // execution result
}{
{
"valid function testing GOTO ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 GOTO 20
17 RETURN 0
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
nil,
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing GOTO ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 GOTO qeee
17 RETURN 0
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing GOTO ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 GOTO
17 RETURN 0
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
}, {
"invalid function testing GOTO ",
`Function TestRun(a1 Uint64,a2 Uint64) Uint64
10 dim s1, s2 as Uint64
15 GOTO 0
17 RETURN 0
20 LET s1 = a1 + a2
30 return s1
End Function
`,
"TestRun",
map[string]interface{}{"a1": "1", "a2": "1"},
fmt.Errorf("dummy"),
Variable{Type: Uint64, ValueUint64: uint64(2)},
},
}
// run the test
func Test_GOTO_execution(t *testing.T) {
for _, test := range execution_tests_goto {
sc, _, err := ParseSmartContract(test.Code)
if err != nil {
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected nil\nActual %s\n", test.Name, err)
}
state := &Shared_State{Chain_inputs: &Blockchain_Input{}}
result, err := RunSmartContract(&sc, test.EntryPoint, state, test.Args)
switch {
case test.Eerr == nil && err == nil:
if !reflect.DeepEqual(result, test.result) {
t.Fatalf("Error while executing smart contract \"%s\"\nExpected result %v\nActual result %v\n", test.Name, test.result, result)
}
case test.Eerr != nil && err != nil: // pass
case test.Eerr == nil && err != nil:
fallthrough
case test.Eerr != nil && err == nil:
t.Fatalf("Error while parsing smart contract \"%s\"\nExpected %s\nActual %s\n", test.Name, test.Eerr, err)
}
}
}