github.com/mattn/anko@v0.1.10/vm/vm_test.go (about) 1 package vm 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "os" 8 "reflect" 9 "sync" 10 "testing" 11 "time" 12 13 "github.com/mattn/anko/ast" 14 "github.com/mattn/anko/ast/astutil" 15 "github.com/mattn/anko/env" 16 "github.com/mattn/anko/parser" 17 ) 18 19 func TestNumbers(t *testing.T) { 20 t.Parallel() 21 22 tests := []Test{ 23 {Script: ``}, 24 {Script: `;`}, 25 {Script: ` 26 `}, 27 {Script: ` 28 1 29 `, RunOutput: int64(1)}, 30 31 {Script: `1..1`, ParseError: fmt.Errorf("invalid number: 1..1")}, 32 {Script: `1e.1`, ParseError: fmt.Errorf("invalid number: 1e.1")}, 33 {Script: `1ee1`, ParseError: fmt.Errorf("syntax error")}, 34 {Script: `1e+e1`, ParseError: fmt.Errorf("syntax error")}, 35 {Script: `0x1g`, ParseError: fmt.Errorf("syntax error")}, 36 {Script: `9223372036854775808`, ParseError: fmt.Errorf("invalid number: 9223372036854775808")}, 37 {Script: `-9223372036854775809`, ParseError: fmt.Errorf("invalid number: -9223372036854775809")}, 38 39 {Script: `1`, RunOutput: int64(1)}, 40 {Script: `-1`, RunOutput: int64(-1)}, 41 {Script: `9223372036854775807`, RunOutput: int64(9223372036854775807)}, 42 {Script: `-9223372036854775808`, RunOutput: int64(-9223372036854775808)}, 43 {Script: `-9223372036854775807-1`, RunOutput: int64(-9223372036854775808)}, 44 {Script: `-9223372036854775807 -1`, RunOutput: int64(-9223372036854775808)}, 45 {Script: `-9223372036854775807 - 1`, RunOutput: int64(-9223372036854775808)}, 46 {Script: `1.1`, RunOutput: float64(1.1)}, 47 {Script: `-1.1`, RunOutput: float64(-1.1)}, 48 49 {Script: `1e1`, RunOutput: float64(10)}, 50 {Script: `1.5e1`, RunOutput: float64(15)}, 51 {Script: `1e-1`, RunOutput: float64(0.1)}, 52 53 {Script: `-1e1`, RunOutput: float64(-10)}, 54 {Script: `-1.5e1`, RunOutput: float64(-15)}, 55 {Script: `-1e-1`, RunOutput: float64(-0.1)}, 56 57 {Script: `0x1`, RunOutput: int64(1)}, 58 {Script: `0xa`, RunOutput: int64(10)}, 59 {Script: `0xb`, RunOutput: int64(11)}, 60 {Script: `0xc`, RunOutput: int64(12)}, 61 {Script: `0xe`, RunOutput: int64(14)}, 62 {Script: `0xf`, RunOutput: int64(15)}, 63 {Script: `0Xf`, RunOutput: int64(15)}, 64 {Script: `0XF`, RunOutput: int64(15)}, 65 {Script: `0x7FFFFFFFFFFFFFFF`, RunOutput: int64(9223372036854775807)}, 66 67 {Script: `-0x1`, RunOutput: int64(-1)}, 68 {Script: `-0xc`, RunOutput: int64(-12)}, 69 {Script: `-0xe`, RunOutput: int64(-14)}, 70 {Script: `-0xf`, RunOutput: int64(-15)}, 71 {Script: `-0Xf`, RunOutput: int64(-15)}, 72 {Script: `-0x7FFFFFFFFFFFFFFF`, RunOutput: int64(-9223372036854775807)}, 73 } 74 runTests(t, tests, nil, &Options{Debug: true}) 75 } 76 77 func TestStrings(t *testing.T) { 78 t.Parallel() 79 80 tests := []Test{ 81 {Script: `a`, Input: map[string]interface{}{"a": 'a'}, RunOutput: 'a', Output: map[string]interface{}{"a": 'a'}}, 82 {Script: `a.b`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support member operation"), Output: map[string]interface{}{"a": 'a'}}, 83 {Script: `a[0]`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support index operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}}, 84 {Script: `a[0:1]`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support slice operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}}, 85 86 {Script: `a.b = "a"`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support member operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}}, 87 {Script: `a[0] = "a"`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support index operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}}, 88 {Script: `a[0:1] = "a"`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support slice operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}}, 89 90 {Script: `a.b = "a"`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("type string does not support member operation"), Output: map[string]interface{}{"a": "test"}}, 91 {Script: `a[0:1] = "a"`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("type string does not support slice operation for assignment"), Output: map[string]interface{}{"a": "test"}}, 92 93 {Script: `a`, Input: map[string]interface{}{"a": "test"}, RunOutput: "test", Output: map[string]interface{}{"a": "test"}}, 94 {Script: `a["a"]`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("index must be a number"), Output: map[string]interface{}{"a": "test"}}, 95 {Script: `a[0]`, Input: map[string]interface{}{"a": ""}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}}, 96 {Script: `a[-1]`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test"}}, 97 {Script: `a[0]`, Input: map[string]interface{}{"a": "test"}, RunOutput: "t", Output: map[string]interface{}{"a": "test"}}, 98 {Script: `a[1]`, Input: map[string]interface{}{"a": "test"}, RunOutput: "e", Output: map[string]interface{}{"a": "test"}}, 99 {Script: `a[3]`, Input: map[string]interface{}{"a": "test"}, RunOutput: "t", Output: map[string]interface{}{"a": "test"}}, 100 {Script: `a[4]`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test"}}, 101 102 {Script: `a`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: `"a"`, Output: map[string]interface{}{"a": `"a"`}}, 103 {Script: `a[0]`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: `"`, Output: map[string]interface{}{"a": `"a"`}}, 104 {Script: `a[1]`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: "a", Output: map[string]interface{}{"a": `"a"`}}, 105 106 {Script: `a = "\"a\""`, RunOutput: `"a"`, Output: map[string]interface{}{"a": `"a"`}}, 107 {Script: `a = "\"a\""; a`, RunOutput: `"a"`, Output: map[string]interface{}{"a": `"a"`}}, 108 {Script: `a = "\"a\""; a[0]`, RunOutput: `"`, Output: map[string]interface{}{"a": `"a"`}}, 109 {Script: `a = "\"a\""; a[1]`, RunOutput: "a", Output: map[string]interface{}{"a": `"a"`}}, 110 111 {Script: `a`, Input: map[string]interface{}{"a": "a\\b"}, RunOutput: "a\\b", Output: map[string]interface{}{"a": "a\\b"}}, 112 {Script: `a`, Input: map[string]interface{}{"a": "a\\\\b"}, RunOutput: "a\\\\b", Output: map[string]interface{}{"a": "a\\\\b"}}, 113 {Script: `a = "a\b"`, RunOutput: "a\b", Output: map[string]interface{}{"a": "a\b"}}, 114 {Script: `a = "a\\b"`, RunOutput: "a\\b", Output: map[string]interface{}{"a": "a\\b"}}, 115 116 {Script: `a[:]`, Input: map[string]interface{}{"a": "test data"}, ParseError: fmt.Errorf("syntax error"), Output: map[string]interface{}{"a": "test data"}}, 117 118 {Script: `a[0:]`, Input: map[string]interface{}{"a": ""}, RunOutput: "", Output: map[string]interface{}{"a": ""}}, 119 {Script: `a[1:]`, Input: map[string]interface{}{"a": ""}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}}, 120 {Script: `a[:0]`, Input: map[string]interface{}{"a": ""}, RunOutput: "", Output: map[string]interface{}{"a": ""}}, 121 {Script: `a[:1]`, Input: map[string]interface{}{"a": ""}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}}, 122 {Script: `a[0:0]`, Input: map[string]interface{}{"a": ""}, RunOutput: "", Output: map[string]interface{}{"a": ""}}, 123 124 {Script: `a[1:0]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 125 {Script: `a[-1:2]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 126 {Script: `a[1:-2]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 127 {Script: `a[-1:]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 128 {Script: `a[:-2]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 129 130 {Script: `a[0:0]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}}, 131 {Script: `a[0:1]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t", Output: map[string]interface{}{"a": "test data"}}, 132 {Script: `a[0:2]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "te", Output: map[string]interface{}{"a": "test data"}}, 133 {Script: `a[0:3]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "tes", Output: map[string]interface{}{"a": "test data"}}, 134 {Script: `a[0:7]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test da", Output: map[string]interface{}{"a": "test data"}}, 135 {Script: `a[0:8]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test dat", Output: map[string]interface{}{"a": "test data"}}, 136 {Script: `a[0:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}}, 137 {Script: `a[0:10]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 138 139 {Script: `a[1:1]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}}, 140 {Script: `a[1:2]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "e", Output: map[string]interface{}{"a": "test data"}}, 141 {Script: `a[1:3]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "es", Output: map[string]interface{}{"a": "test data"}}, 142 {Script: `a[1:7]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est da", Output: map[string]interface{}{"a": "test data"}}, 143 {Script: `a[1:8]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est dat", Output: map[string]interface{}{"a": "test data"}}, 144 {Script: `a[1:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est data", Output: map[string]interface{}{"a": "test data"}}, 145 {Script: `a[1:10]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 146 147 {Script: `a[0:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}}, 148 {Script: `a[1:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est data", Output: map[string]interface{}{"a": "test data"}}, 149 {Script: `a[2:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "st data", Output: map[string]interface{}{"a": "test data"}}, 150 {Script: `a[3:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t data", Output: map[string]interface{}{"a": "test data"}}, 151 {Script: `a[7:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "ta", Output: map[string]interface{}{"a": "test data"}}, 152 {Script: `a[8:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "a", Output: map[string]interface{}{"a": "test data"}}, 153 {Script: `a[9:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}}, 154 155 {Script: `a[:0]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}}, 156 {Script: `a[:1]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t", Output: map[string]interface{}{"a": "test data"}}, 157 {Script: `a[:2]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "te", Output: map[string]interface{}{"a": "test data"}}, 158 {Script: `a[:3]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "tes", Output: map[string]interface{}{"a": "test data"}}, 159 {Script: `a[:7]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test da", Output: map[string]interface{}{"a": "test data"}}, 160 {Script: `a[:8]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test dat", Output: map[string]interface{}{"a": "test data"}}, 161 {Script: `a[:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}}, 162 {Script: `a[:10]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 163 164 {Script: `a[0:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}}, 165 {Script: `a[1:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est data", Output: map[string]interface{}{"a": "test data"}}, 166 {Script: `a[2:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "st data", Output: map[string]interface{}{"a": "test data"}}, 167 {Script: `a[3:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t data", Output: map[string]interface{}{"a": "test data"}}, 168 {Script: `a[7:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "ta", Output: map[string]interface{}{"a": "test data"}}, 169 {Script: `a[8:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "a", Output: map[string]interface{}{"a": "test data"}}, 170 {Script: `a[9:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}}, 171 {Script: `a[10:]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}}, 172 173 // index assignment - len 0 174 {Script: `a = ""; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "x"}}, 175 {Script: `a = ""; a[1] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}}, 176 177 // index assignment - len 1 178 {Script: `a = "a"; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "x"}}, 179 {Script: `a = "a"; a[1] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "ax"}}, 180 {Script: `a = "a"; a[2] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "a"}}, 181 182 // index assignment - len 2 183 {Script: `a = "ab"; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "xb"}}, 184 {Script: `a = "ab"; a[1] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "ax"}}, 185 {Script: `a = "ab"; a[2] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "abx"}}, 186 {Script: `a = "ab"; a[3] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "ab"}}, 187 188 // index assignment - len 3 189 {Script: `a = "abc"; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "xbc"}}, 190 {Script: `a = "abc"; a[1] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "axc"}}, 191 {Script: `a = "abc"; a[2] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "abx"}}, 192 {Script: `a = "abc"; a[3] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "abcx"}}, 193 {Script: `a = "abc"; a[4] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "abc"}}, 194 195 // index assignment - vm types 196 {Script: `a = "abc"; a[1] = nil`, RunOutput: nil, Output: map[string]interface{}{"a": "ac"}}, 197 {Script: `a = "abc"; a[1] = true`, RunError: fmt.Errorf("type bool cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 198 {Script: `a = "abc"; a[1] = 120`, RunOutput: int64(120), Output: map[string]interface{}{"a": "axc"}}, 199 {Script: `a = "abc"; a[1] = 2.2`, RunError: fmt.Errorf("type float64 cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 200 {Script: `a = "abc"; a[1] = ["a"]`, RunError: fmt.Errorf("type []interface {} cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 201 202 // index assignment - Go types 203 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": reflect.Value{}}, RunError: fmt.Errorf("type reflect.Value cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 204 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": nil}, RunOutput: nil, Output: map[string]interface{}{"a": "ac"}}, 205 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": true}, RunError: fmt.Errorf("type bool cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 206 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": int32(120)}, RunOutput: int32(120), Output: map[string]interface{}{"a": "axc"}}, 207 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": int64(120)}, RunOutput: int64(120), Output: map[string]interface{}{"a": "axc"}}, 208 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": float32(1.1)}, RunError: fmt.Errorf("type float32 cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 209 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": float64(2.2)}, RunError: fmt.Errorf("type float64 cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 210 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": "x"}, RunOutput: "x", Output: map[string]interface{}{"a": "axc"}}, 211 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": 'x'}, RunOutput: 'x', Output: map[string]interface{}{"a": "axc"}}, 212 {Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": struct{}{}}, RunError: fmt.Errorf("type struct {} cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}}, 213 } 214 runTests(t, tests, nil, &Options{Debug: true}) 215 } 216 217 func TestVar(t *testing.T) { 218 t.Parallel() 219 220 testInput1 := map[string]interface{}{"b": func() {}} 221 tests := []Test{ 222 // simple one variable 223 {Script: `1 = 2`, RunError: fmt.Errorf("invalid operation")}, 224 {Script: `var 1 = 2`, ParseError: fmt.Errorf("syntax error")}, 225 {Script: `a = 1++`, RunError: fmt.Errorf("invalid operation")}, 226 {Script: `var a = 1++`, RunError: fmt.Errorf("invalid operation")}, 227 {Script: `a := 1`, ParseError: fmt.Errorf("syntax error")}, 228 {Script: `var a := 1`, ParseError: fmt.Errorf("syntax error")}, 229 {Script: `y = z`, RunError: fmt.Errorf("undefined symbol 'z'")}, 230 231 {Script: `a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}}, 232 {Script: `a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}}, 233 {Script: `a = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 234 {Script: `a = 1.1`, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1)}}, 235 {Script: `a = "a"`, RunOutput: "a", Output: map[string]interface{}{"a": "a"}}, 236 237 {Script: `var a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}}, 238 {Script: `var a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}}, 239 {Script: `var a = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 240 {Script: `var a = 1.1`, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1)}}, 241 {Script: `var a = "a"`, RunOutput: "a", Output: map[string]interface{}{"a": "a"}}, 242 243 {Script: `a = b`, Input: map[string]interface{}{"b": reflect.Value{}}, RunOutput: reflect.Value{}, Output: map[string]interface{}{"a": reflect.Value{}, "b": reflect.Value{}}}, 244 {Script: `a = b`, Input: map[string]interface{}{"b": nil}, RunOutput: nil, Output: map[string]interface{}{"a": nil, "b": nil}}, 245 {Script: `a = b`, Input: map[string]interface{}{"b": true}, RunOutput: true, Output: map[string]interface{}{"a": true, "b": true}}, 246 {Script: `a = b`, Input: map[string]interface{}{"b": int32(1)}, RunOutput: int32(1), Output: map[string]interface{}{"a": int32(1), "b": int32(1)}}, 247 {Script: `a = b`, Input: map[string]interface{}{"b": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1), "b": int64(1)}}, 248 {Script: `a = b`, Input: map[string]interface{}{"b": float32(1.1)}, RunOutput: float32(1.1), Output: map[string]interface{}{"a": float32(1.1), "b": float32(1.1)}}, 249 {Script: `a = b`, Input: map[string]interface{}{"b": float64(1.1)}, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1), "b": float64(1.1)}}, 250 {Script: `a = b`, Input: map[string]interface{}{"b": "a"}, RunOutput: "a", Output: map[string]interface{}{"a": "a", "b": "a"}}, 251 {Script: `a = b`, Input: map[string]interface{}{"b": 'a'}, RunOutput: 'a', Output: map[string]interface{}{"a": 'a', "b": 'a'}}, 252 {Script: `a = b`, Input: map[string]interface{}{"b": struct{}{}}, RunOutput: struct{}{}, Output: map[string]interface{}{"a": struct{}{}, "b": struct{}{}}}, 253 254 {Script: `var a = b`, Input: map[string]interface{}{"b": reflect.Value{}}, RunOutput: reflect.Value{}, Output: map[string]interface{}{"a": reflect.Value{}, "b": reflect.Value{}}}, 255 {Script: `var a = b`, Input: map[string]interface{}{"b": nil}, RunOutput: nil, Output: map[string]interface{}{"a": nil, "b": nil}}, 256 {Script: `var a = b`, Input: map[string]interface{}{"b": true}, RunOutput: true, Output: map[string]interface{}{"a": true, "b": true}}, 257 {Script: `var a = b`, Input: map[string]interface{}{"b": int32(1)}, RunOutput: int32(1), Output: map[string]interface{}{"a": int32(1), "b": int32(1)}}, 258 {Script: `var a = b`, Input: map[string]interface{}{"b": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1), "b": int64(1)}}, 259 {Script: `var a = b`, Input: map[string]interface{}{"b": float32(1.1)}, RunOutput: float32(1.1), Output: map[string]interface{}{"a": float32(1.1), "b": float32(1.1)}}, 260 {Script: `var a = b`, Input: map[string]interface{}{"b": float64(1.1)}, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1), "b": float64(1.1)}}, 261 {Script: `var a = b`, Input: map[string]interface{}{"b": "a"}, RunOutput: "a", Output: map[string]interface{}{"a": "a", "b": "a"}}, 262 {Script: `var a = b`, Input: map[string]interface{}{"b": 'a'}, RunOutput: 'a', Output: map[string]interface{}{"a": 'a', "b": 'a'}}, 263 {Script: `var a = b`, Input: map[string]interface{}{"b": struct{}{}}, RunOutput: struct{}{}, Output: map[string]interface{}{"a": struct{}{}, "b": struct{}{}}}, 264 265 // simple one variable overwrite 266 {Script: `a = true; a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}}, 267 {Script: `a = nil; a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}}, 268 {Script: `a = 1; a = 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 269 {Script: `a = 1.1; a = 2.2`, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}}, 270 {Script: `a = "a"; a = "b"`, RunOutput: "b", Output: map[string]interface{}{"a": "b"}}, 271 272 {Script: `var a = true; var a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}}, 273 {Script: `var a = nil; var a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}}, 274 {Script: `var a = 1; var a = 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 275 {Script: `var a = 1.1; var a = 2.2`, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}}, 276 {Script: `var a = "a"; var a = "b"`, RunOutput: "b", Output: map[string]interface{}{"a": "b"}}, 277 278 {Script: `a = nil`, Input: map[string]interface{}{"a": true}, RunOutput: nil, Output: map[string]interface{}{"a": nil}}, 279 {Script: `a = true`, Input: map[string]interface{}{"a": nil}, RunOutput: true, Output: map[string]interface{}{"a": true}}, 280 {Script: `a = 2`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 281 {Script: `a = 2`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 282 {Script: `a = 2.2`, Input: map[string]interface{}{"a": float32(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}}, 283 {Script: `a = 2.2`, Input: map[string]interface{}{"a": float64(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}}, 284 {Script: `a = "b"`, Input: map[string]interface{}{"a": "a"}, RunOutput: "b", Output: map[string]interface{}{"a": "b"}}, 285 286 {Script: `var a = nil`, Input: map[string]interface{}{"a": true}, RunOutput: nil, Output: map[string]interface{}{"a": nil}}, 287 {Script: `var a = true`, Input: map[string]interface{}{"a": nil}, RunOutput: true, Output: map[string]interface{}{"a": true}}, 288 {Script: `var a = 2`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 289 {Script: `var a = 2`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 290 {Script: `var a = 2.2`, Input: map[string]interface{}{"a": float32(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}}, 291 {Script: `var a = 2.2`, Input: map[string]interface{}{"a": float64(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}}, 292 {Script: `var a = "b"`, Input: map[string]interface{}{"a": "a"}, RunOutput: "b", Output: map[string]interface{}{"a": "b"}}, 293 294 // Go variable copy 295 {Script: `a = b`, Input: testInput1, RunOutput: testInput1["b"], Output: map[string]interface{}{"a": testInput1["b"], "b": testInput1["b"]}}, 296 {Script: `var a = b`, Input: testInput1, RunOutput: testInput1["b"], Output: map[string]interface{}{"a": testInput1["b"], "b": testInput1["b"]}}, 297 298 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValue}, RunOutput: testVarValue, Output: map[string]interface{}{"a": testVarValue, "b": testVarValue}}, 299 {Script: `a = b`, Input: map[string]interface{}{"b": testVarBoolP}, RunOutput: testVarBoolP, Output: map[string]interface{}{"a": testVarBoolP, "b": testVarBoolP}}, 300 {Script: `a = b`, Input: map[string]interface{}{"b": testVarInt32P}, RunOutput: testVarInt32P, Output: map[string]interface{}{"a": testVarInt32P, "b": testVarInt32P}}, 301 {Script: `a = b`, Input: map[string]interface{}{"b": testVarInt64P}, RunOutput: testVarInt64P, Output: map[string]interface{}{"a": testVarInt64P, "b": testVarInt64P}}, 302 {Script: `a = b`, Input: map[string]interface{}{"b": testVarFloat32P}, RunOutput: testVarFloat32P, Output: map[string]interface{}{"a": testVarFloat32P, "b": testVarFloat32P}}, 303 {Script: `a = b`, Input: map[string]interface{}{"b": testVarFloat64P}, RunOutput: testVarFloat64P, Output: map[string]interface{}{"a": testVarFloat64P, "b": testVarFloat64P}}, 304 {Script: `a = b`, Input: map[string]interface{}{"b": testVarStringP}, RunOutput: testVarStringP, Output: map[string]interface{}{"a": testVarStringP, "b": testVarStringP}}, 305 {Script: `a = b`, Input: map[string]interface{}{"b": testVarFuncP}, RunOutput: testVarFuncP, Output: map[string]interface{}{"a": testVarFuncP, "b": testVarFuncP}}, 306 307 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValue}, RunOutput: testVarValue, Output: map[string]interface{}{"a": testVarValue, "b": testVarValue}}, 308 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarBoolP}, RunOutput: testVarBoolP, Output: map[string]interface{}{"a": testVarBoolP, "b": testVarBoolP}}, 309 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarInt32P}, RunOutput: testVarInt32P, Output: map[string]interface{}{"a": testVarInt32P, "b": testVarInt32P}}, 310 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarInt64P}, RunOutput: testVarInt64P, Output: map[string]interface{}{"a": testVarInt64P, "b": testVarInt64P}}, 311 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarFloat32P}, RunOutput: testVarFloat32P, Output: map[string]interface{}{"a": testVarFloat32P, "b": testVarFloat32P}}, 312 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarFloat64P}, RunOutput: testVarFloat64P, Output: map[string]interface{}{"a": testVarFloat64P, "b": testVarFloat64P}}, 313 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarStringP}, RunOutput: testVarStringP, Output: map[string]interface{}{"a": testVarStringP, "b": testVarStringP}}, 314 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarFuncP}, RunOutput: testVarFuncP, Output: map[string]interface{}{"a": testVarFuncP, "b": testVarFuncP}}, 315 316 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValueBool}, RunOutput: testVarValueBool, Output: map[string]interface{}{"a": testVarValueBool, "b": testVarValueBool}}, 317 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValueInt32}, RunOutput: testVarValueInt32, Output: map[string]interface{}{"a": testVarValueInt32, "b": testVarValueInt32}}, 318 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValueInt64}, RunOutput: testVarValueInt64, Output: map[string]interface{}{"a": testVarValueInt64, "b": testVarValueInt64}}, 319 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValueFloat32}, RunOutput: testVarValueFloat32, Output: map[string]interface{}{"a": testVarValueFloat32, "b": testVarValueFloat32}}, 320 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValueFloat64}, RunOutput: testVarValueFloat64, Output: map[string]interface{}{"a": testVarValueFloat64, "b": testVarValueFloat64}}, 321 {Script: `a = b`, Input: map[string]interface{}{"b": testVarValueString}, RunOutput: testVarValueString, Output: map[string]interface{}{"a": testVarValueString, "b": testVarValueString}}, 322 323 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueBool}, RunOutput: testVarValueBool, Output: map[string]interface{}{"a": testVarValueBool, "b": testVarValueBool}}, 324 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueInt32}, RunOutput: testVarValueInt32, Output: map[string]interface{}{"a": testVarValueInt32, "b": testVarValueInt32}}, 325 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueInt64}, RunOutput: testVarValueInt64, Output: map[string]interface{}{"a": testVarValueInt64, "b": testVarValueInt64}}, 326 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueFloat32}, RunOutput: testVarValueFloat32, Output: map[string]interface{}{"a": testVarValueFloat32, "b": testVarValueFloat32}}, 327 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueFloat64}, RunOutput: testVarValueFloat64, Output: map[string]interface{}{"a": testVarValueFloat64, "b": testVarValueFloat64}}, 328 {Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueString}, RunOutput: testVarValueString, Output: map[string]interface{}{"a": testVarValueString, "b": testVarValueString}}, 329 330 // one variable spacing 331 {Script: ` 332 a = 1 333 `, RunOutput: int64(1)}, 334 {Script: ` 335 a = 1; 336 `, RunOutput: int64(1)}, 337 338 // one variable many values 339 {Script: `, b = 1, 2`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(2), Output: map[string]interface{}{"b": int64(1)}}, 340 {Script: `var , b = 1, 2`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(2), Output: map[string]interface{}{"b": int64(1)}}, 341 {Script: `a, = 1, 2`, ParseError: fmt.Errorf("syntax error")}, 342 {Script: `var a, = 1, 2`, ParseError: fmt.Errorf("syntax error")}, 343 344 // TOFIX: should not error? 345 {Script: `a = 1, 2`, ParseError: fmt.Errorf("syntax error")}, 346 {Script: `var a = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}}, 347 // TOFIX: should not error? 348 {Script: `a = 1, 2, 3`, ParseError: fmt.Errorf("syntax error")}, 349 {Script: `var a = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1)}}, 350 351 // two variables many values 352 {Script: `a, b = 1,`, ParseError: fmt.Errorf("syntax error")}, 353 {Script: `var a, b = 1,`, ParseError: fmt.Errorf("syntax error")}, 354 {Script: `a, b = ,1`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(1)}, 355 {Script: `var a, b = ,1`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(1)}, 356 {Script: `a, b = 1,,`, ParseError: fmt.Errorf("syntax error")}, 357 {Script: `var a, b = 1,,`, ParseError: fmt.Errorf("syntax error")}, 358 {Script: `a, b = ,1,`, ParseError: fmt.Errorf("syntax error")}, 359 {Script: `var a, b = ,1,`, ParseError: fmt.Errorf("syntax error")}, 360 {Script: `a, b = ,,1`, ParseError: fmt.Errorf("syntax error")}, 361 {Script: `var a, b = ,,1`, ParseError: fmt.Errorf("syntax error")}, 362 363 {Script: `a.c, b = 1, 2`, RunError: fmt.Errorf("undefined symbol 'a'")}, 364 {Script: `a, b.c = 1, 2`, RunError: fmt.Errorf("undefined symbol 'b'")}, 365 366 {Script: `a, b = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 367 {Script: `var a, b = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 368 {Script: `a, b = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 369 {Script: `var a, b = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 370 {Script: `a, b = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 371 {Script: `var a, b = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 372 373 // three variables many values 374 {Script: `a, b, c = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 375 {Script: `var a, b, c = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 376 {Script: `a, b, c = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 377 {Script: `var a, b, c = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 378 {Script: `a, b, c = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}}, 379 {Script: `var a, b, c = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}}, 380 {Script: `a, b, c = 1, 2, 3, 4`, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}}, 381 {Script: `var a, b, c = 1, 2, 3, 4`, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}}, 382 383 // scope 384 {Script: `func(){ a = 1 }(); a`, RunError: fmt.Errorf("undefined symbol 'a'")}, 385 {Script: `func(){ var a = 1 }(); a`, RunError: fmt.Errorf("undefined symbol 'a'")}, 386 387 {Script: `a = 1; func(){ a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 388 {Script: `var a = 1; func(){ a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 389 {Script: `a = 1; func(){ var a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}}, 390 {Script: `var a = 1; func(){ var a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}}, 391 392 // function return 393 {Script: `a, 1++ = func(){ return 1, 2 }()`, RunError: fmt.Errorf("invalid operation"), Output: map[string]interface{}{"a": int64(1)}}, 394 395 {Script: `a = func(){ return 1 }()`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 396 {Script: `var a = func(){ return 1 }()`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}}, 397 {Script: `a, b = func(){ return 1, 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 398 {Script: `var a, b = func(){ return 1, 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}}, 399 } 400 runTests(t, tests, nil, &Options{Debug: true}) 401 } 402 403 func TestModule(t *testing.T) { 404 t.Parallel() 405 406 tests := []Test{ 407 {Script: `module a.b { }`, ParseError: fmt.Errorf("syntax error")}, 408 {Script: `module a { 1++ }`, RunError: fmt.Errorf("invalid operation")}, 409 {Script: `module a { }; a.b`, RunError: fmt.Errorf("undefined symbol 'b'")}, 410 411 {Script: `module a { b = 1 }`, RunOutput: nil}, 412 413 {Script: `module a { b = nil }; a.b`, RunOutput: nil}, 414 {Script: `module a { b = true }; a.b`, RunOutput: true}, 415 {Script: `module a { b = 1 }; a.b`, RunOutput: int64(1)}, 416 {Script: `module a { b = 1.5 }; a.b`, RunOutput: float64(1.5)}, 417 {Script: `module a { b = "a" }; a.b`, RunOutput: "a"}, 418 {Script: `module a { func b() { return "b"} }; a.b()`, RunOutput: "b"}, 419 420 {Script: `module a { _b = "b"; func c() { return _b} }`, RunOutput: nil}, 421 {Script: `module a { _b = "b"; func c() { return _b} }; a.c()`, RunOutput: "b"}, 422 423 {Script: `module a { b = 1 }; var c = a; c.b = 2; c.b`, RunOutput: int64(2)}, 424 425 // test module copy 426 {Script: `module a { b = 1 }; c = a; d = a; a.b = 2; a.b`, RunOutput: int64(2)}, 427 {Script: `module a { b = 1 }; c = a; d = a; a.b = 2; c.b`, RunOutput: int64(1)}, 428 {Script: `module a { b = 1 }; c = a; d = a; a.b = 2; d.b`, RunOutput: int64(1)}, 429 {Script: `module a { b = 1 }; c = a; d = a; c.b = 2; a.b`, RunOutput: int64(1)}, 430 {Script: `module a { b = 1 }; c = a; d = a; c.b = 2; c.b`, RunOutput: int64(2)}, 431 {Script: `module a { b = 1 }; c = a; d = a; c.b = 2; d.b`, RunOutput: int64(1)}, 432 {Script: `module a { b = 1 }; c = a; d = a; d.b = 2; a.b`, RunOutput: int64(1)}, 433 {Script: `module a { b = 1 }; c = a; d = a; d.b = 2; c.b`, RunOutput: int64(1)}, 434 {Script: `module a { b = 1 }; c = a; d = a; d.b = 2; d.b`, RunOutput: int64(2)}, 435 436 {Script: `module a { b = 1 }; var c = a; var d = a; a.b = 2; a.b`, RunOutput: int64(2)}, 437 {Script: `module a { b = 1 }; var c = a; var d = a; a.b = 2; c.b`, RunOutput: int64(1)}, 438 {Script: `module a { b = 1 }; var c = a; var d = a; a.b = 2; d.b`, RunOutput: int64(1)}, 439 {Script: `module a { b = 1 }; var c = a; var d = a; c.b = 2; a.b`, RunOutput: int64(1)}, 440 {Script: `module a { b = 1 }; var c = a; var d = a; c.b = 2; c.b`, RunOutput: int64(2)}, 441 {Script: `module a { b = 1 }; var c = a; var d = a; c.b = 2; d.b`, RunOutput: int64(1)}, 442 {Script: `module a { b = 1 }; var c = a; var d = a; d.b = 2; a.b`, RunOutput: int64(1)}, 443 {Script: `module a { b = 1 }; var c = a; var d = a; d.b = 2; c.b`, RunOutput: int64(1)}, 444 {Script: `module a { b = 1 }; var c = a; var d = a; d.b = 2; d.b`, RunOutput: int64(2)}, 445 446 // test type scope 447 {Script: `module b { make(type Duration, a) }; func c() { d = new(time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunError: fmt.Errorf("no namespace called: time")}, 448 {Script: `module time { make(type Duration, a) }; func c() { d = new(time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunOutput: time.Duration(0)}, 449 {Script: `module x { module time { make(type Duration, a) } }; func c() { d = new(x.time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunOutput: time.Duration(0)}, 450 {Script: `module x { module time { make(type Duration, a) } }; func c() { d = new(y.time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunError: fmt.Errorf("no namespace called: y")}, 451 {Script: `module x { module time { make(type Duration, a) } }; func c() { d = new(x.y.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunError: fmt.Errorf("no namespace called: y")}, 452 } 453 runTests(t, tests, nil, &Options{Debug: true}) 454 } 455 456 func TestNew(t *testing.T) { 457 t.Parallel() 458 459 tests := []Test{ 460 {Script: `new(foo)`, RunError: fmt.Errorf("undefined type 'foo'")}, 461 {Script: `new(nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 462 463 // default 464 {Script: `a = new(bool); *a`, RunOutput: false}, 465 {Script: `a = new(int32); *a`, RunOutput: int32(0)}, 466 {Script: `a = new(int64); *a`, RunOutput: int64(0)}, 467 {Script: `a = new(float32); *a`, RunOutput: float32(0)}, 468 {Script: `a = new(float64); *a`, RunOutput: float64(0)}, 469 {Script: `a = new(string); *a`, RunOutput: ""}, 470 471 // ptr 472 {Script: `a = new(*string); b = *a; *b`, RunOutput: ""}, 473 {Script: `a = new(*string); **a`, RunOutput: ""}, 474 475 // slice 476 {Script: `a = new([]int64); *a`, RunOutput: []int64{}}, 477 478 // map 479 {Script: `a = new(map[string]int64); *a`, RunOutput: map[string]int64{}}, 480 481 // chan 482 {Script: `a = new(chan int64); go func(){ (*a) <- 1 }(); <- *a`, RunOutput: int64(1)}, 483 {Script: `a = new(chan int64); go func(){ *a <- 1 }(); <- *a`, RunOutput: int64(1)}, 484 485 // struct 486 {Script: `a = new(struct{ A int64 }); *a`, RunOutput: struct{ A int64 }{}}, 487 } 488 runTests(t, tests, nil, &Options{Debug: true}) 489 } 490 491 func TestMake(t *testing.T) { 492 t.Parallel() 493 494 tests := []Test{ 495 {Script: `make(map[[]string]int64)`, RunError: fmt.Errorf("reflect.MapOf: invalid key type []string")}, 496 } 497 runTests(t, tests, nil, &Options{Debug: false}) 498 499 tests = []Test{ 500 {Script: `make(struct {})`, ParseError: fmt.Errorf("syntax error")}, 501 {Script: `make(struct { , })`, ParseError: fmt.Errorf("syntax error")}, 502 {Script: `make(struct { A map })`, ParseError: fmt.Errorf("syntax error")}, 503 {Script: `make(struct { , A int64})`, ParseError: fmt.Errorf("syntax error")}, 504 {Script: `make(struct { A int64, })`, ParseError: fmt.Errorf("syntax error")}, 505 506 {Script: `make(foo)`, RunError: fmt.Errorf("undefined type 'foo'")}, 507 {Script: `make(a.b)`, Types: map[string]interface{}{"a": true}, RunError: fmt.Errorf("no namespace called: a")}, 508 {Script: `make(a.b)`, Types: map[string]interface{}{"b": true}, RunError: fmt.Errorf("no namespace called: a")}, 509 {Script: `make([]int64, 1++)`, RunError: fmt.Errorf("invalid operation")}, 510 {Script: `make([]int64, 1, 1++)`, RunError: fmt.Errorf("invalid operation")}, 511 {Script: `make([]int64, 2, 1)`, RunError: fmt.Errorf("make slice len > cap")}, 512 {Script: `make(map[foo]int64)`, RunError: fmt.Errorf("undefined type 'foo'")}, 513 {Script: `make(map[int64]foo)`, RunError: fmt.Errorf("undefined type 'foo'")}, 514 {Script: `make(chan foo)`, RunError: fmt.Errorf("undefined type 'foo'")}, 515 {Script: `make(chan int64, 1++)`, RunError: fmt.Errorf("invalid operation")}, 516 {Script: `make(struct { A foo })`, RunError: fmt.Errorf("undefined type 'foo'")}, 517 518 // nill type 519 {Script: `make(nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 520 {Script: `make(*nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 521 {Script: `make([]nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 522 {Script: `make(map[nilT]string)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 523 {Script: `make(map[string]nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 524 {Script: `make(chan nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 525 {Script: `make(struct { A nilT })`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")}, 526 527 // default 528 {Script: `make(bool)`, RunOutput: false}, 529 {Script: `make(int32)`, RunOutput: int32(0)}, 530 {Script: `make(int64)`, RunOutput: int64(0)}, 531 {Script: `make(float32)`, RunOutput: float32(0)}, 532 {Script: `make(float64)`, RunOutput: float64(0)}, 533 {Script: `make(string)`, RunOutput: ""}, 534 535 // ptr 536 {Script: `a = make(*int64); *a`, RunOutput: int64(0)}, 537 {Script: `a = make(**int64); **a`, RunOutput: int64(0)}, 538 {Script: `a = make(***int64); ***a`, RunOutput: int64(0)}, 539 {Script: `a = make(*[]int64); *a`, RunOutput: []int64{}}, 540 {Script: `a = make(*map[string]int64); *a`, RunOutput: map[string]int64{}}, 541 {Script: `a = make(*chan int64); go func(){ (*a) <- 1 }(); <- *a`, RunOutput: int64(1)}, 542 {Script: `a = make(*chan int64); go func(){ *a <- 1 }(); <- *a`, RunOutput: int64(1)}, 543 544 // slice 545 {Script: `make([]int64)`, RunOutput: []int64{}}, 546 {Script: `a = make([]int64, 1); a[0]`, RunOutput: int64(0)}, 547 {Script: `a = make([]int64, 1, 2); a[0]`, RunOutput: int64(0)}, 548 {Script: `make([]*int64)`, RunOutput: []*int64{}}, 549 {Script: `make([][]int64)`, RunOutput: [][]int64{}}, 550 {Script: `make([]map[string]int64)`, RunOutput: []map[string]int64{}}, 551 552 // map 553 {Script: `make(map[string]int64)`, RunOutput: map[string]int64{}}, 554 {Script: `make(map[string]*int64)`, RunOutput: map[string]*int64{}}, 555 {Script: `make(map[*string]int64)`, RunOutput: map[*string]int64{}}, 556 {Script: `make(map[*string]*int64)`, RunOutput: map[*string]*int64{}}, 557 {Script: `make(map[string][]int64)`, RunOutput: map[string][]int64{}}, 558 {Script: `make(map[string]chan int64)`, RunOutput: map[string]chan int64{}}, 559 {Script: `make(map[chan string]int64)`, RunOutput: map[chan string]int64{}}, 560 561 // chan 562 {Script: `a = make(chan int64); go func(){ a <- 1 }(); <- a`, RunOutput: int64(1)}, 563 {Script: `a = make(chan int64, 1); a <- 1; <- a`, RunOutput: int64(1)}, 564 {Script: `a = make(chan *int64, 1); b = 1; a <- &b; c = <- a; *c`, RunOutput: int64(1)}, 565 {Script: `a = make(chan []int64, 1); a <- [1]; <- a`, RunOutput: []int64{1}}, 566 {Script: `a = make(chan map[string]int64, 1); b = make(map[string]int64); a <- b; <- a`, RunOutput: map[string]int64{}}, 567 {Script: `a = make(chan int64, 1); b = &a; *b <- 1; <- *b`, RunOutput: int64(1)}, 568 569 // struct 570 {Script: `make(struct { A int64 })`, RunOutput: struct{ A int64 }{}}, 571 {Script: `make(struct { A *int64 })`, RunOutput: struct{ A *int64 }{}}, 572 {Script: `make(struct { A []int64 })`, RunOutput: struct{ A []int64 }{A: []int64{}}}, 573 {Script: `make(struct { A map[string]int64 })`, RunOutput: struct{ A map[string]int64 }{A: map[string]int64{}}}, 574 {Script: `a = make(struct { A chan int64 }); go func(){ a.A <- 1 }(); <- a.A`, RunOutput: int64(1)}, 575 } 576 runTests(t, tests, nil, &Options{Debug: true}) 577 } 578 579 func TestMakeType(t *testing.T) { 580 t.Parallel() 581 582 tests := []Test{ 583 {Script: `make(type a, 1++)`, RunError: fmt.Errorf("invalid operation")}, 584 585 {Script: `make(type a, true)`, RunOutput: reflect.TypeOf(true)}, 586 {Script: `a = make(type a, true)`, RunOutput: reflect.TypeOf(true), Output: map[string]interface{}{"a": reflect.TypeOf(true)}}, 587 {Script: `make(type a, true); a = make([]a)`, RunOutput: []bool{}, Output: map[string]interface{}{"a": []bool{}}}, 588 {Script: `make(type a, make([]bool))`, RunOutput: reflect.TypeOf([]bool{})}, 589 {Script: `make(type a, make([]bool)); a = make(a)`, RunOutput: []bool{}, Output: map[string]interface{}{"a": []bool{}}}, 590 } 591 runTests(t, tests, nil, &Options{Debug: true}) 592 } 593 594 func TestReferencingAndDereference(t *testing.T) { 595 t.Parallel() 596 597 tests := []Test{ 598 // TOFIX: 599 // {Script: `a = 1; b = &a; *b = 2; *b`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}}, 600 } 601 runTests(t, tests, nil, &Options{Debug: true}) 602 } 603 604 func TestChan(t *testing.T) { 605 t.Parallel() 606 607 tests := []Test{ 608 // send on closed channel 609 {Script: `a = make(chan int64, 2); close(a); a <- 1`, RunError: fmt.Errorf("send on closed channel")}, 610 } 611 runTests(t, tests, nil, &Options{Debug: false}) 612 613 tests = []Test{ 614 {Script: `a = make(chan int64, 2); a <- 1; = <- a`, ParseError: fmt.Errorf("missing expressions on left side of channel operator"), RunError: fmt.Errorf("invalid operation")}, 615 616 {Script: `<- 1++`, RunError: fmt.Errorf("invalid operation")}, 617 {Script: `1++ <- 1`, RunError: fmt.Errorf("invalid operation")}, 618 {Script: `1 <- 1++`, RunError: fmt.Errorf("invalid operation")}, 619 {Script: `a = make(chan int64, 2); a <- 1++`, RunError: fmt.Errorf("invalid operation")}, 620 {Script: `<- 1`, RunError: fmt.Errorf("receive from non-chan type int64")}, 621 {Script: `1 <- 1`, RunError: fmt.Errorf("send to non-chan type int64")}, 622 {Script: `a = make(chan int64, 2); 1 <- a`, RunError: fmt.Errorf("send to non-chan type int64")}, 623 {Script: `a = make(chan bool, 2); a <- 1`, RunError: fmt.Errorf("cannot use type int64 as type bool to send to chan")}, 624 {Script: `close(1++)`, RunError: fmt.Errorf("invalid operation")}, 625 {Script: `close(1)`, RunError: fmt.Errorf("type cannot be int64 for close")}, 626 627 // let channel errors 628 {Script: `a = <- c`, RunError: fmt.Errorf("undefined symbol 'c'")}, 629 {Script: `a, b = <- c`, RunError: fmt.Errorf("undefined symbol 'c'")}, 630 {Script: `a = <- 1++`, RunError: fmt.Errorf("invalid operation")}, 631 {Script: `a, b = <- 1++`, RunError: fmt.Errorf("invalid operation")}, 632 {Script: `c = 1; a = <- c`, RunError: fmt.Errorf("receive from non-chan type int64")}, 633 {Script: `c = 1; a, b = <- c`, RunError: fmt.Errorf("receive from non-chan type int64")}, 634 {Script: `a = make(chan int64, 2); a <- 1; 1++ = <- a`, RunError: fmt.Errorf("invalid operation")}, 635 {Script: `a = make(chan int64, 2); a <- 1; 1++, b = <- a`, RunError: fmt.Errorf("invalid operation")}, 636 637 // send to channel 638 {Script: `a <- nil`, Input: map[string]interface{}{"a": make(chan interface{}, 2)}}, 639 {Script: `a <- true`, Input: map[string]interface{}{"a": make(chan bool, 2)}}, 640 {Script: `a <- 1`, Input: map[string]interface{}{"a": make(chan int32, 2)}}, 641 {Script: `a <- 2`, Input: map[string]interface{}{"a": make(chan int64, 2)}}, 642 {Script: `a <- 1.5`, Input: map[string]interface{}{"a": make(chan float32, 2)}}, 643 {Script: `a <- 2.5`, Input: map[string]interface{}{"a": make(chan float64, 2)}}, 644 {Script: `a <- "b"`, Input: map[string]interface{}{"a": make(chan string, 2)}}, 645 646 {Script: `a = make(chan interface, 2); a <- nil`}, 647 {Script: `a = make(chan bool, 2); a <- true`}, 648 {Script: `a = make(chan int32, 2); a <- 1`}, 649 {Script: `a = make(chan int64, 2); a <- 2`}, 650 {Script: `a = make(chan float32, 2); a <- 1.5`}, 651 {Script: `a = make(chan float64, 2); a <- 2.5`}, 652 {Script: `a = make(chan string, 2); a <- "b"`}, 653 654 // send to channel then receive from channel 655 {Script: `a <- nil; <- a`, Input: map[string]interface{}{"a": make(chan interface{}, 2)}, RunOutput: nil}, 656 {Script: `a <- true; <- a`, Input: map[string]interface{}{"a": make(chan bool, 2)}, RunOutput: true}, 657 {Script: `a <- 1; <- a`, Input: map[string]interface{}{"a": make(chan int32, 2)}, RunOutput: int32(1)}, 658 {Script: `a <- 2; <- a`, Input: map[string]interface{}{"a": make(chan int64, 2)}, RunOutput: int64(2)}, 659 {Script: `a <- 1.5; <- a`, Input: map[string]interface{}{"a": make(chan float32, 2)}, RunOutput: float32(1.5)}, 660 {Script: `a <- 2.5; <- a`, Input: map[string]interface{}{"a": make(chan float64, 2)}, RunOutput: float64(2.5)}, 661 {Script: `a <- "b"; <- a`, Input: map[string]interface{}{"a": make(chan string, 2)}, RunOutput: "b"}, 662 663 {Script: `a = make(chan interface, 2); a <- nil; <- a`, RunOutput: nil}, 664 {Script: `a = make(chan bool, 2); a <- true; <- a`, RunOutput: true}, 665 {Script: `a = make(chan int32, 2); a <- 1; <- a`, RunOutput: int32(1)}, 666 {Script: `a = make(chan int64, 2); a <- 2; <- a`, RunOutput: int64(2)}, 667 {Script: `a = make(chan float32, 2); a <- 1.5; <- a`, RunOutput: float32(1.5)}, 668 {Script: `a = make(chan float64, 2); a <- 2.5; <- a`, RunOutput: float64(2.5)}, 669 {Script: `a = make(chan string, 2); a <- "b"; <- a`, RunOutput: "b"}, 670 671 // send to channel, receive from channel, then assign to variable 672 {Script: `a <- nil; b = <- a`, Input: map[string]interface{}{"a": make(chan interface{}, 2)}, RunOutput: nil, Output: map[string]interface{}{"b": nil}}, 673 {Script: `a <- true; b = <- a`, Input: map[string]interface{}{"a": make(chan bool, 2)}, RunOutput: true, Output: map[string]interface{}{"b": true}}, 674 {Script: `a <- 1; b = <- a`, Input: map[string]interface{}{"a": make(chan int32, 2)}, RunOutput: int32(1), Output: map[string]interface{}{"b": int32(1)}}, 675 {Script: `a <- 2; b = <- a`, Input: map[string]interface{}{"a": make(chan int64, 2)}, RunOutput: int64(2), Output: map[string]interface{}{"b": int64(2)}}, 676 {Script: `a <- 1.5; b = <- a`, Input: map[string]interface{}{"a": make(chan float32, 2)}, RunOutput: float32(1.5), Output: map[string]interface{}{"b": float32(1.5)}}, 677 {Script: `a <- 2.5; b = <- a`, Input: map[string]interface{}{"a": make(chan float64, 2)}, RunOutput: float64(2.5), Output: map[string]interface{}{"b": float64(2.5)}}, 678 {Script: `a <- "b"; b = <- a`, Input: map[string]interface{}{"a": make(chan string, 2)}, RunOutput: "b", Output: map[string]interface{}{"b": "b"}}, 679 680 {Script: `a = make(chan interface, 2); a <- nil; b = <- a`, RunOutput: nil, Output: map[string]interface{}{"b": nil}}, 681 {Script: `a = make(chan bool, 2); a <- true; b = <- a`, RunOutput: true, Output: map[string]interface{}{"b": true}}, 682 {Script: `a = make(chan int32, 2); a <- 1; b = <- a`, RunOutput: int32(1), Output: map[string]interface{}{"b": int32(1)}}, 683 {Script: `a = make(chan int64, 2); a <- 2; b = <- a`, RunOutput: int64(2), Output: map[string]interface{}{"b": int64(2)}}, 684 {Script: `a = make(chan float32, 2); a <- 1.5; b = <- a`, RunOutput: float32(1.5), Output: map[string]interface{}{"b": float32(1.5)}}, 685 {Script: `a = make(chan float64, 2); a <- 2.5; b = <- a`, RunOutput: float64(2.5), Output: map[string]interface{}{"b": float64(2.5)}}, 686 {Script: `a = make(chan string, 2); a <- "b"; b = <- a`, RunOutput: "b", Output: map[string]interface{}{"b": "b"}}, 687 688 // receive from closed channel 689 {Script: `a = make(chan int64, 2); a <- 1; close(a); <- a`, RunOutput: int64(1)}, 690 {Script: `a = make(chan int64, 2); a <- 1; close(a); <- a; <- a`, RunOutput: nil}, 691 692 // receive & send from same channel 693 {Script: `a = make(chan int64, 2); a <- 1; a <- <- a`, RunOutput: nil}, 694 {Script: `a = make(chan int64, 2); a <- 1; a <- <- a; <- a`, RunOutput: int64(1)}, 695 {Script: `a = make(chan int64, 2); a <- 1; a <- <- a; b = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1)}}, 696 {Script: `a = make(chan int64, 2); a <- 1; a <- (<- a)`, RunOutput: nil}, 697 {Script: `a = make(chan int64, 2); a <- 1; a <- (<- a); <- a`, RunOutput: int64(1)}, 698 {Script: `a = make(chan int64, 2); a <- 1; a <- (<- a); b = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1)}}, 699 700 // 1 then null into a 701 {Script: `a = make(chan int64, 2); a <- a <- 1`, RunOutput: nil}, 702 {Script: `a = make(chan int64, 2); a <- a <- 1; <- a`, RunOutput: int64(1)}, 703 {Script: `a = make(chan int64, 2); a <- a <- 1; <- a; <- a`, RunOutput: int64(0)}, 704 705 // receive & send different channel 706 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- <- a`, RunOutput: nil}, 707 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- <- a; <- b`, RunOutput: int64(1)}, 708 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- <- a; c = <- b`, RunOutput: int64(1), Output: map[string]interface{}{"c": int64(1)}}, 709 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- (<- a)`, RunOutput: nil}, 710 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- (<- a); <- b`, RunOutput: int64(1)}, 711 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- (<- a); c = <- b`, RunOutput: int64(1), Output: map[string]interface{}{"c": int64(1)}}, 712 713 // 1 into a then null into b 714 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); b <- a <- 1`, RunOutput: nil}, 715 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); b <- a <- 1; <- a`, RunOutput: int64(1)}, 716 {Script: `a = make(chan int64, 2); b = make(chan int64, 2); b <- a <- 1; <- a; <- b`, RunOutput: int64(0)}, 717 718 // test ok 719 {Script: `a = make(chan int64, 2); a <- 1; b, ok = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1), "ok": true}}, 720 {Script: `a = make(chan int64, 2); a <- 1; b, 1++ = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1)}}, 721 {Script: `a = make(chan int64, 2); a <- 1; close(a); b, ok = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1), "ok": true}}, 722 {Script: `a = make(chan int64, 2); a <- 1; close(a); b = <- a; b, ok = <- a`, RunOutput: nil, Output: map[string]interface{}{"b": int64(1), "ok": false}}, 723 724 // test let ++ 725 {Script: `a = make(chan int64, 2); b = [1, 2, 3, 4]; c = 0; a <- 11; b[c++] = <- a; b[1]`, RunOutput: int64(11)}, 726 } 727 runTests(t, tests, nil, &Options{Debug: true}) 728 } 729 730 func TestVMDelete(t *testing.T) { 731 t.Parallel() 732 733 tests := []Test{ 734 {Script: `delete(1++)`, RunError: fmt.Errorf("invalid operation")}, 735 {Script: `delete(1)`, RunError: fmt.Errorf("first argument to delete cannot be type int64")}, 736 {Script: `a = 1; delete("a"); a`, RunError: fmt.Errorf("undefined symbol 'a'")}, 737 {Script: `a = {"b": "b"}; delete(a)`, RunError: fmt.Errorf("second argument to delete cannot be nil for map")}, 738 739 {Script: `delete("a", 1++)`, RunError: fmt.Errorf("invalid operation")}, 740 {Script: `b = []; delete(a, b)`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}, RunError: fmt.Errorf("cannot use type int32 as type []interface {} in delete"), Output: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}}, 741 742 // test no variable 743 {Script: `delete("a")`}, 744 {Script: `delete("a", false)`}, 745 {Script: `delete("a", true)`}, 746 {Script: `delete("a", nil)`}, 747 748 // test DeleteGlobal 749 {Script: `a = 1; func b() { delete("a") }; b()`, Output: map[string]interface{}{"a": int64(1)}}, 750 {Script: `a = 1; func b() { delete("a", false) }; b()`, Output: map[string]interface{}{"a": int64(1)}}, 751 {Script: `a = 1; func b() { delete("a", true) }; b(); a`, RunError: fmt.Errorf("undefined symbol 'a'")}, 752 {Script: `a = 2; func b() { a = 3; delete("a"); return a }; b()`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}}, 753 {Script: `a = 2; func b() { a = 3; delete("a", false); return a }; b()`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}}, 754 {Script: `a = 2; func b() { a = 3; delete("a", true); return a }; b()`, RunError: fmt.Errorf("undefined symbol 'a'")}, 755 {Script: `a = 2; func b() { a = 3; delete("a") }; b(); a`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}}, 756 {Script: `a = 2; func b() { a = 3; delete("a", false) }; b(); a`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}}, 757 {Script: `a = 2; func b() { a = 3; delete("a", true) }; b(); a`, RunError: fmt.Errorf("undefined symbol 'a'")}, 758 759 // test empty map 760 {Script: `delete(a, "a")`, Input: map[string]interface{}{"a": testMapEmpty}, Output: map[string]interface{}{"a": testMapEmpty}}, 761 762 // test map 763 {Script: `a = {"b": "b"}; delete(a, "b")`, Output: map[string]interface{}{"a": map[interface{}]interface{}{}}}, 764 {Script: `a = {"b": "b"}; delete(a, "b"); a.b`, Output: map[string]interface{}{"a": map[interface{}]interface{}{}}}, 765 {Script: `a = {"b": "b", "c":"c"}; delete(a, "b")`, Output: map[string]interface{}{"a": map[interface{}]interface{}{"c": "c"}}}, 766 {Script: `a = {"b": "b", "c":"c"}; delete(a, "b"); a.b`, Output: map[string]interface{}{"a": map[interface{}]interface{}{"c": "c"}}}, 767 768 // test key convert 769 {Script: `delete(a, 2)`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}, Output: map[string]interface{}{"a": map[int32]interface{}{}}}, 770 {Script: `delete(a, 2); a[2]`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}, Output: map[string]interface{}{"a": map[int32]interface{}{}}}, 771 {Script: `delete(a, 2)`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2), 3: int32(3)}}, Output: map[string]interface{}{"a": map[int32]interface{}{3: int32(3)}}}, 772 {Script: `delete(a, 2); a[2]`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2), 3: int32(3)}}, Output: map[string]interface{}{"a": map[int32]interface{}{3: int32(3)}}}, 773 } 774 runTests(t, tests, nil, &Options{Debug: true}) 775 } 776 777 func TestComment(t *testing.T) { 778 t.Parallel() 779 780 tests := []Test{ 781 {Script: `# 1`}, 782 {Script: `# 1;`}, 783 {Script: `# 1 // 2`}, 784 {Script: `# 1 \n 2`}, 785 {Script: `# 1 # 2`}, 786 787 {Script: `1# 1`, RunOutput: int64(1)}, 788 {Script: `1# 1;`, RunOutput: int64(1)}, 789 {Script: `1# 1 // 2`, RunOutput: int64(1)}, 790 {Script: `1# 1 \n 2`, RunOutput: int64(1)}, 791 {Script: `1# 1 # 2`, RunOutput: int64(1)}, 792 793 {Script: `1 794 # 1`, RunOutput: int64(1)}, 795 {Script: `1 796 # 1;`, RunOutput: int64(1)}, 797 {Script: `1 798 # 1 // 2`, RunOutput: int64(1)}, 799 {Script: `1 800 # 1 \n 2`, RunOutput: int64(1)}, 801 {Script: `1 802 # 1 # 2`, RunOutput: int64(1)}, 803 804 {Script: `// 1`}, 805 {Script: `// 1;`}, 806 {Script: `// 1 // 2`}, 807 {Script: `// 1 \n 2`}, 808 {Script: `// 1 # 2`}, 809 810 {Script: `1// 1`, RunOutput: int64(1)}, 811 {Script: `1// 1;`, RunOutput: int64(1)}, 812 {Script: `1// 1 // 2`, RunOutput: int64(1)}, 813 {Script: `1// 1 \n 2`, RunOutput: int64(1)}, 814 {Script: `1// 1 # 2`, RunOutput: int64(1)}, 815 816 {Script: `1 817 // 1`, RunOutput: int64(1)}, 818 {Script: `1 819 // 1;`, RunOutput: int64(1)}, 820 {Script: `1 821 // 1 // 2`, RunOutput: int64(1)}, 822 {Script: `1 823 // 1 \n 2`, RunOutput: int64(1)}, 824 {Script: `1 825 // 1 # 2`, RunOutput: int64(1)}, 826 827 {Script: `/* 1 */`}, 828 {Script: `/* * 1 */`}, 829 {Script: `/* 1 * */`}, 830 {Script: `/** 1 */`}, 831 {Script: `/*** 1 */`}, 832 {Script: `/**** 1 */`}, 833 {Script: `/* 1 **/`}, 834 {Script: `/* 1 ***/`}, 835 {Script: `/* 1 ****/`}, 836 {Script: `/** 1 ****/`}, 837 {Script: `/*** 1 ****/`}, 838 {Script: `/**** 1 ****/`}, 839 840 {Script: `1/* 1 */`, RunOutput: int64(1)}, 841 {Script: `1/* * 1 */`, RunOutput: int64(1)}, 842 {Script: `1/* 1 * */`, RunOutput: int64(1)}, 843 {Script: `1/** 1 */`, RunOutput: int64(1)}, 844 {Script: `1/*** 1 */`, RunOutput: int64(1)}, 845 {Script: `1/**** 1 */`, RunOutput: int64(1)}, 846 {Script: `1/* 1 **/`, RunOutput: int64(1)}, 847 {Script: `1/* 1 ***/`, RunOutput: int64(1)}, 848 {Script: `1/* 1 ****/`, RunOutput: int64(1)}, 849 {Script: `1/** 1 ****/`, RunOutput: int64(1)}, 850 {Script: `1/*** 1 ****/`, RunOutput: int64(1)}, 851 {Script: `1/**** 1 ****/`, RunOutput: int64(1)}, 852 853 {Script: `/* 1 */1`, RunOutput: int64(1)}, 854 {Script: `/* * 1 */1`, RunOutput: int64(1)}, 855 {Script: `/* 1 * */1`, RunOutput: int64(1)}, 856 {Script: `/** 1 */1`, RunOutput: int64(1)}, 857 {Script: `/*** 1 */1`, RunOutput: int64(1)}, 858 {Script: `/**** 1 */1`, RunOutput: int64(1)}, 859 {Script: `/* 1 **/1`, RunOutput: int64(1)}, 860 {Script: `/* 1 ***/1`, RunOutput: int64(1)}, 861 {Script: `/* 1 ****/1`, RunOutput: int64(1)}, 862 {Script: `/** 1 ****/1`, RunOutput: int64(1)}, 863 {Script: `/*** 1 ****/1`, RunOutput: int64(1)}, 864 {Script: `/**** 1 ****/1`, RunOutput: int64(1)}, 865 866 {Script: `1 867 /* 1 */`, RunOutput: int64(1)}, 868 {Script: `1 869 /* * 1 */`, RunOutput: int64(1)}, 870 {Script: `1 871 /* 1 * */`, RunOutput: int64(1)}, 872 {Script: `1 873 /** 1 */`, RunOutput: int64(1)}, 874 {Script: `1 875 /*** 1 */`, RunOutput: int64(1)}, 876 {Script: `1 877 /**** 1 */`, RunOutput: int64(1)}, 878 {Script: `1 879 /* 1 **/`, RunOutput: int64(1)}, 880 {Script: `1 881 /* 1 ***/`, RunOutput: int64(1)}, 882 {Script: `1 883 /* 1 ****/`, RunOutput: int64(1)}, 884 {Script: `1 885 /** 1 ****/`, RunOutput: int64(1)}, 886 {Script: `1 887 /*** 1 ****/`, RunOutput: int64(1)}, 888 {Script: `1 889 /**** 1 ****/`, RunOutput: int64(1)}, 890 } 891 runTests(t, tests, nil, &Options{Debug: true}) 892 } 893 894 func TestCancelWithContext(t *testing.T) { 895 scripts := []string{ 896 ` 897 b = 0 898 close(waitChan) 899 for { 900 b = 1 901 } 902 `, 903 ` 904 b = 0 905 close(waitChan) 906 for { 907 for { 908 b = 1 909 } 910 } 911 `, 912 ` 913 a = [] 914 for i = 0; i < 20000; i++ { 915 a += 1 916 } 917 b = 0 918 close(waitChan) 919 for { 920 for i in a { 921 b = i 922 } 923 } 924 `, 925 ` 926 a = [] 927 for i = 0; i < 20000; i++ { 928 a += 1 929 } 930 b = 0 931 close(waitChan) 932 for i in a { 933 for j in a { 934 b = j 935 } 936 } 937 `, 938 ` 939 close(waitChan) 940 b = 0 941 for i = 0; true; nil { 942 } 943 `, 944 ` 945 b = 0 946 close(waitChan) 947 for i = 0; true; nil { 948 for j = 0; true; nil { 949 b = 1 950 } 951 } 952 `, 953 ` 954 a = {} 955 for i = 0; i < 20000; i++ { 956 a[toString(i)] = 1 957 } 958 b = 0 959 close(waitChan) 960 for { 961 for i in a { 962 b = 1 963 } 964 } 965 `, 966 ` 967 a = {} 968 for i = 0; i < 20000; i++ { 969 a[toString(i)] = 1 970 } 971 b = 0 972 close(waitChan) 973 for i in a { 974 for j in a { 975 b = 1 976 } 977 } 978 `, 979 ` 980 close(waitChan) 981 <- make(chan string) 982 `, 983 ` 984 a = "" 985 close(waitChan) 986 a = <- make(chan string) 987 `, 988 ` 989 for { 990 a = "" 991 close(waitChan) 992 a = <- make(chan string) 993 } 994 `, 995 ` 996 a = make(chan int) 997 close(waitChan) 998 a <- 1 999 `, 1000 ` 1001 a = make(chan interface) 1002 close(waitChan) 1003 a <- nil 1004 `, 1005 ` 1006 a = make(chan int64, 1) 1007 close(waitChan) 1008 for v in a { } 1009 `, 1010 ` 1011 close(waitChan) 1012 try { 1013 for { } 1014 } catch { } 1015 `, 1016 } 1017 for _, script := range scripts { 1018 runCancelTestWithContext(t, script) 1019 } 1020 } 1021 1022 func runCancelTestWithContext(t *testing.T, script string) { 1023 waitChan := make(chan struct{}, 1) 1024 toString := func(value interface{}) string { 1025 return fmt.Sprintf("%v", value) 1026 } 1027 e := env.NewEnv() 1028 err := e.Define("waitChan", waitChan) 1029 if err != nil { 1030 t.Errorf("Define error: %v", err) 1031 } 1032 err = e.Define("toString", toString) 1033 if err != nil { 1034 t.Errorf("Define error: %v", err) 1035 } 1036 1037 ctx, cancel := context.WithCancel(context.Background()) 1038 go func() { 1039 <-waitChan 1040 time.Sleep(time.Millisecond) 1041 cancel() 1042 }() 1043 1044 _, err = ExecuteContext(ctx, e, nil, script) 1045 if err == nil || err.Error() != ErrInterrupt.Error() { 1046 t.Errorf("execute error - received %#v - expected: %#v - script: %v", err, ErrInterrupt, script) 1047 } 1048 } 1049 1050 func TestContextConcurrency(t *testing.T) { 1051 var waitGroup sync.WaitGroup 1052 e := env.NewEnv() 1053 1054 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 1055 waitGroup.Add(100) 1056 for i := 0; i < 100; i++ { 1057 go func() { 1058 _, err := ExecuteContext(ctx, e, nil, "for { }") 1059 if err == nil || err.Error() != ErrInterrupt.Error() { 1060 t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt) 1061 } 1062 waitGroup.Done() 1063 }() 1064 } 1065 cancel() 1066 waitGroup.Wait() 1067 cancel() 1068 1069 _, err := ExecuteContext(ctx, e, nil, "for { }") 1070 if err == nil || err.Error() != ErrInterrupt.Error() { 1071 t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt) 1072 } 1073 1074 ctx, cancel = context.WithCancel(context.Background()) 1075 _, err = ExecuteContext(ctx, e, nil, "for i = 0; i < 1000; i++ {}") 1076 if err != nil { 1077 t.Errorf("execute error - received: %v - expected: %v", err, nil) 1078 } 1079 waitGroup.Add(100) 1080 for i := 0; i < 100; i++ { 1081 go func() { 1082 _, err := ExecuteContext(ctx, e, nil, "for i = 0; i < 1000; i++ { }") 1083 if err != nil { 1084 t.Errorf("execute error - received: %v - expected: %v", err, nil) 1085 } 1086 waitGroup.Done() 1087 }() 1088 } 1089 waitGroup.Wait() 1090 1091 waitGroup.Add(100) 1092 for i := 0; i < 100; i++ { 1093 go func() { 1094 _, err := ExecuteContext(ctx, e, nil, "for { }") 1095 if err == nil || err.Error() != ErrInterrupt.Error() { 1096 t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt) 1097 } 1098 waitGroup.Done() 1099 }() 1100 } 1101 time.Sleep(time.Millisecond) 1102 cancel() 1103 waitGroup.Wait() 1104 1105 waitGroup.Add(100) 1106 for i := 0; i < 100; i++ { 1107 go func() { 1108 _, err := Execute(e, nil, "for i = 0; i < 1000; i++ { }") 1109 if err != nil { 1110 t.Errorf("execute error - received: %v - expected: %v", err, nil) 1111 } 1112 waitGroup.Done() 1113 }() 1114 } 1115 waitGroup.Wait() 1116 } 1117 1118 func TestContextFunction(t *testing.T) { 1119 t.Parallel() 1120 1121 e := env.NewEnv() 1122 script := ` 1123 func myFunc(myVar) { 1124 myVar = 3 1125 }` 1126 envModule, err := e.NewModule("a") 1127 if err != nil { 1128 t.Fatal("NewModule error:", err) 1129 } 1130 1131 ctx, cancel := context.WithCancel(context.Background()) 1132 _, err = ExecuteContext(ctx, envModule, nil, script) 1133 if err != nil { 1134 t.Errorf("execute error - received %#v - expected: %#v", err, nil) 1135 } 1136 cancel() 1137 1138 script = "a.myFunc(2)" 1139 1140 ctx, cancel = context.WithCancel(context.Background()) 1141 _, err = ExecuteContext(ctx, e, nil, script) 1142 if err != nil { 1143 t.Errorf("execute error - received %#v - expected: %#v", err, nil) 1144 } 1145 cancel() 1146 } 1147 1148 func TestAssignToInterface(t *testing.T) { 1149 t.Parallel() 1150 1151 e := env.NewEnv() 1152 X := new(struct { 1153 Stdout io.Writer 1154 }) 1155 err := e.Define("X", X) 1156 if err != nil { 1157 t.Errorf("Define error: %v", err) 1158 } 1159 err = e.Define("a", new(os.File)) 1160 if err != nil { 1161 t.Errorf("Define error: %v", err) 1162 } 1163 _, err = Execute(e, nil, "X.Stdout = a") 1164 if err != nil { 1165 t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt) 1166 } 1167 } 1168 1169 // TestValueEqual do some basic ValueEqual tests for coverage 1170 func TestValueEqual(t *testing.T) { 1171 t.Parallel() 1172 1173 result := valueEqual(true, true) 1174 if result != true { 1175 t.Fatal("ValueEqual") 1176 } 1177 result = valueEqual(true, false) 1178 if result != false { 1179 t.Fatal("ValueEqual") 1180 } 1181 result = valueEqual(false, true) 1182 if result != false { 1183 t.Fatal("ValueEqual") 1184 } 1185 } 1186 1187 // TestUnknownCases tests switch cases that are the unknown cases 1188 func TestUnknownCases(t *testing.T) { 1189 t.Parallel() 1190 1191 oneLiteral := &ast.LiteralExpr{Literal: reflect.ValueOf(int64(1))} 1192 type ( 1193 BadStmt struct { 1194 ast.StmtImpl 1195 } 1196 BadExpr struct { 1197 ast.ExprImpl 1198 } 1199 BadOperator struct { 1200 ast.OperatorImpl 1201 } 1202 ) 1203 1204 stmts := []ast.Stmt{ 1205 &BadStmt{}, 1206 &ast.ExprStmt{Expr: &BadExpr{}}, 1207 &ast.ExprStmt{Expr: &ast.OpExpr{Op: &BadOperator{}}}, 1208 &ast.ExprStmt{Expr: &ast.UnaryExpr{Expr: oneLiteral}}, 1209 &ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.BinaryOperator{LHS: oneLiteral}}}, 1210 &ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.ComparisonOperator{LHS: oneLiteral, RHS: oneLiteral}}}, 1211 &ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.AddOperator{LHS: oneLiteral, RHS: oneLiteral}}}, 1212 &ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.MultiplyOperator{LHS: oneLiteral, RHS: oneLiteral}}}, 1213 } 1214 1215 for _, stmt := range stmts { 1216 e := env.NewEnv() 1217 _, err := Run(e, nil, stmt) 1218 if err == nil { 1219 t.Errorf("no error - stmt: %#v", stmt) 1220 } else if len(err.Error()) < 9 || err.Error()[:8] != "unknown " { 1221 t.Errorf("err: %v - stmt: %#v", err, stmt) 1222 } 1223 } 1224 } 1225 1226 type Foo struct { 1227 Value int 1228 } 1229 type Bar struct { 1230 Foo 1231 Ref *int 1232 } 1233 1234 func (f Foo) ValueReceiver() int { 1235 return f.Value 1236 } 1237 func (b *Bar) PointerReceiver() (int, int) { 1238 b.Value = 0 1239 *b.Ref = 0 1240 return b.Value, *b.Ref 1241 } 1242 1243 func TestCallStructMethod(t *testing.T) { 1244 t.Parallel() 1245 1246 ref := 10 1247 ptr := &Bar{ 1248 Foo: Foo{ 1249 Value: 100, 1250 }, 1251 Ref: &ref, 1252 } 1253 val := Bar{ 1254 Foo: Foo{ 1255 Value: 200, 1256 }, 1257 Ref: &ref, 1258 } 1259 1260 // execution in native go 1261 v := ptr.ValueReceiver() 1262 if v != 100 { 1263 t.Fatal("ptr: call value receiver failed, v should equal to 100") 1264 } 1265 v, r := ptr.PointerReceiver() 1266 if v != 0 || r != 0 { 1267 t.Fatal("ptr: call pointer receiver failed, both should be 0") 1268 } 1269 1270 ref = 10 1271 v = val.ValueReceiver() 1272 if v != 200 { 1273 t.Fatal("val: call value receiver failed, v should equal to 200") 1274 } 1275 v, r = val.PointerReceiver() 1276 if v != 0 || r != 0 { 1277 t.Fatal("val: call pointer receiver failed, both should be 0") 1278 } 1279 1280 // reinitialize values before executing script in VM 1281 ptr.Value = 100 1282 val.Value = 200 1283 1284 // Define pointer 'ptr' to struct Bar in VM 1285 ref = 10 1286 tests := []Test{ 1287 {Script: "ptr.ValueReceiver()", Input: map[string]interface{}{"ptr": ptr}, RunOutput: 100}, 1288 {Script: "ptr.PointerReceiver()", Input: map[string]interface{}{"ptr": ptr}, RunOutput: []interface{}{0, 0}}, 1289 } 1290 runTests(t, tests, nil, &Options{Debug: true}) 1291 1292 // Define value 'val' to struct Bar in VM 1293 ref = 10 1294 tests = []Test{ 1295 {Script: "val.ValueReceiver()", Input: map[string]interface{}{"val": val}, RunOutput: 200}, 1296 {Script: "val.PointerReceiver()", Input: map[string]interface{}{"val": val}, RunOutput: []interface{}{0, 0}}, 1297 } 1298 runTests(t, tests, nil, &Options{Debug: true}) 1299 } 1300 1301 func fib(x int) int { 1302 if x < 2 { 1303 return x 1304 } 1305 return fib(x-1) + fib(x-2) 1306 } 1307 1308 func BenchmarkFibGo(b *testing.B) { 1309 for i := 0; i < b.N; i++ { 1310 fib(29) 1311 } 1312 } 1313 1314 func BenchmarkFibVM(b *testing.B) { 1315 b.StopTimer() 1316 1317 e := env.NewEnv() 1318 a, err := e.NewModule("a") 1319 if err != nil { 1320 b.Fatal("NewModule error:", err) 1321 } 1322 1323 script := ` 1324 fib = func(x) { 1325 if x < 2 { 1326 return x 1327 } 1328 return fib(x-1) + fib(x-2) 1329 }` 1330 1331 _, err = Execute(a, nil, script) 1332 if err != nil { 1333 b.Fatal("Execute error:", err) 1334 } 1335 1336 b.ResetTimer() 1337 b.StartTimer() 1338 1339 for i := 0; i < b.N; i++ { 1340 _, err = Execute(e, nil, "a.fib(29)") 1341 if err != nil { 1342 b.Fatal("Execute error:", err) 1343 } 1344 } 1345 } 1346 1347 func TestLetsStatementPosition(t *testing.T) { 1348 src := `a, b = 1, 2 1349 ` 1350 stmts, err := parser.ParseSrc(src) 1351 if err != nil { 1352 t.Fatal(err) 1353 } 1354 1355 var stmtFound bool 1356 err = astutil.Walk(stmts, func(e interface{}) error { 1357 switch e := e.(type) { 1358 case *ast.LetsStmt: 1359 if len(e.LHSS) == 2 { 1360 if is, want := e.Position().Line, 1; is != want { 1361 t.Fatalf("%v != %v", is, want) 1362 } 1363 if is, want := e.Position().Column, 1; is != want { 1364 t.Fatalf("%v != %v", is, want) 1365 } 1366 } 1367 stmtFound = true 1368 } 1369 1370 return nil 1371 }) 1372 1373 if err != nil { 1374 t.Fatal(err) 1375 } 1376 1377 if is, want := stmtFound, true; is != want { 1378 t.Fatalf("%v != %v", is, want) 1379 } 1380 }