github.com/informationsea/shellflow@v0.1.3/flowscript/flowscript_evaluate_test.go (about) 1 package flowscript 2 3 import ( 4 "reflect" 5 "strings" 6 "testing" 7 ) 8 9 func createTestGlobalEnvironment() Environment { 10 ge := NewGlobalEnvironment() 11 12 ge.Assign("hoge", StringValue{"hoge"}) 13 ge.Assign("foo", StringValue{"foo"}) 14 ge.Assign("bar", IntValue{1}) 15 ge.Assign("v1", StringValue{"1"}) 16 17 var a1 []Value = make([]Value, 3) 18 a1[0] = IntValue{10} 19 a1[1] = IntValue{11} 20 a1[2] = StringValue{"12"} 21 ge.Assign("array", ArrayValue{a1}) 22 23 var m1 map[string]Value = make(map[string]Value) 24 m1["1"] = IntValue{1} 25 m1["2"] = IntValue{2} 26 m1["3"] = StringValue{"3!"} 27 ge.Assign("map", MapValue{m1}) 28 29 return ge 30 } 31 32 func TestConstantValueAccess(t *testing.T) { 33 env := createTestGlobalEnvironment() 34 var x1 Evaluable = ValueEvaluable{IntValue{1}} 35 if v, e := x1.Evaluate(env); e != nil || v != (IntValue{1}) { 36 t.Fatalf("Invalid value %s or error %s", v, e) 37 } 38 if len(x1.SubEvaluable()) != 0 { 39 t.Fatalf("too many sub-evaluable: %s", x1.SubEvaluable()) 40 } 41 42 var x2 Evaluable = ValueEvaluable{StringValue{"hoge"}} 43 if v, e := x2.Evaluate(env); e != nil || v != (StringValue{"hoge"}) { 44 t.Fatalf("Invalid value %s or error %s", v, e) 45 } 46 47 { 48 array := [...]Value{IntValue{1}, IntValue{2}, IntValue{3}} 49 var x3 Evaluable = ValueEvaluable{ArrayValue{array[:]}} 50 v, e := x3.Evaluate(env) 51 if e != nil { 52 t.Fatalf("Invalid value %s or error %s", v, e) 53 } 54 55 if rv, ok := v.(ArrayValue); !ok || !reflect.DeepEqual(array[:], rv.value) { 56 t.Fatalf("Invalid value %s or error %s", v, e) 57 } 58 } 59 60 var badAccess Evaluable = BadEvaluable{} 61 if v, e := badAccess.Evaluate(env); e.Error() != "bad access" || v != nil { 62 t.Fatalf("Invalid value %s or error %s", v, e) 63 } 64 } 65 66 func TestVariableAccess(t *testing.T) { 67 68 var ge Environment = createTestGlobalEnvironment() 69 70 var evaluable Evaluable = &Variable{"hoge"} 71 var v Value 72 var e error 73 74 v, e = evaluable.Evaluate(ge) 75 if e != nil { 76 t.Fatal("Cannot access hoge variable") 77 } 78 if v != (StringValue{"hoge"}) { 79 t.Fatalf("Invalid value %s", v) 80 } 81 if len(evaluable.SubEvaluable()) != 0 { 82 t.Fatalf("too many sub-evaluable: %s", evaluable.SubEvaluable()) 83 } 84 85 evaluable = &Variable{"hoge"} 86 v, e = evaluable.Evaluate(ge) 87 if e != nil { 88 t.Fatal("Cannot access hoge variable") 89 } 90 if v != (StringValue{"hoge"}) { 91 t.Fatalf("Invalid value %s", v) 92 } 93 94 evaluable = &Variable{"unknown"} 95 v, e = evaluable.Evaluate(ge) 96 if e == nil { 97 t.Fatal("unknown variable should not exits in global environment #1") 98 } 99 if v != nil { 100 t.Fatal("unknown variable should not exits in global environment #2") 101 } 102 103 ge.Assign("unknown", StringValue{"yes"}) 104 v, e = evaluable.Evaluate(ge) 105 if e != nil { 106 t.Fatal("Cannot access hoge variable") 107 } 108 if v != (StringValue{"yes"}) { 109 t.Fatalf("Invalid value %s", v) 110 } 111 } 112 113 func TestArrayAccess(t *testing.T) { 114 ge := createTestGlobalEnvironment() 115 116 originalArray := make([]Value, 3) 117 originalArray[0] = IntValue{1} 118 originalArray[1] = StringValue{"hoge"} 119 originalArray[2] = StringValue{"foo"} 120 121 // check normal access path 122 var arrayAccess1 Evaluable = &ArrayAccess{Array: ValueEvaluable{ArrayValue{originalArray}}, ArrayIndex: ValueEvaluable{IntValue{1}}} 123 if v, e := arrayAccess1.Evaluate(ge); v != (StringValue{"hoge"}) || e != nil { 124 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 125 } 126 127 if s := arrayAccess1.String(); s != "[1, \"hoge\", \"foo\"][1]" { 128 t.Fatalf("Bad string representation: %s", s) 129 } 130 131 subEvaluable := arrayAccess1.SubEvaluable() 132 if len(subEvaluable) != 2 || subEvaluable[1] != (ValueEvaluable{IntValue{1}}) { 133 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 134 } 135 subEvaluable1, ok := subEvaluable[0].(ValueEvaluable).value.(ArrayValue) 136 if !ok { 137 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 138 } 139 if !reflect.DeepEqual(subEvaluable1.value, originalArray) { 140 t.Fatalf("bad sub-evaluable: %s", subEvaluable1.value) 141 } 142 143 ge.Assign("foo", ArrayValue{originalArray}) 144 ge.Assign("bar", IntValue{0}) 145 var arrayAccess2 Evaluable = &ArrayAccess{Array: &Variable{"foo"}, ArrayIndex: &Variable{"bar"}} 146 if v, e := arrayAccess2.Evaluate(ge); v != (IntValue{1}) || e != nil { 147 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 148 } 149 150 if s := arrayAccess2.String(); s != "foo[bar]" { 151 t.Fatalf("Bad string representation: %s", s) 152 } 153 154 // check out of index path 155 { 156 arrayAccess := ArrayAccess{Array: ValueEvaluable{ArrayValue{originalArray}}, ArrayIndex: ValueEvaluable{IntValue{3}}} 157 if v, e := arrayAccess.Evaluate(ge); v != (nil) || 158 !strings.HasPrefix(e.Error(), "out of index error") { 159 160 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 161 } 162 } 163 164 { 165 arrayAccess := ArrayAccess{Array: ValueEvaluable{ArrayValue{originalArray}}, ArrayIndex: ValueEvaluable{IntValue{-1}}} 166 if v, e := arrayAccess.Evaluate(ge); v != (nil) || 167 !strings.HasPrefix(e.Error(), "out of index error") { 168 169 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 170 } 171 } 172 173 // check invalid type path 174 { 175 arrayAccess := ArrayAccess{Array: ValueEvaluable{StringValue{"hoge"}}, ArrayIndex: ValueEvaluable{IntValue{0}}} 176 if v, e := arrayAccess.Evaluate(ge); v != (nil) || e == nil || 177 e.Error() != "\"hoge\" is not array or map" { 178 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 179 } 180 } 181 182 { 183 arrayAccess := ArrayAccess{Array: ValueEvaluable{IntValue{123}}, ArrayIndex: ValueEvaluable{IntValue{0}}} 184 if v, e := arrayAccess.Evaluate(ge); v != (nil) || e == nil || 185 e.Error() != "123 is not array or map" { 186 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 187 } 188 } 189 190 { 191 arrayAccess := ArrayAccess{Array: ValueEvaluable{ArrayValue{originalArray}}, ArrayIndex: ValueEvaluable{StringValue{"hoge"}}} 192 if v, e := arrayAccess.Evaluate(ge); v != (nil) || e == nil || 193 e.Error() != "\"hoge\" is not int" { 194 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 195 } 196 } 197 198 // check evaluation fail path 199 { 200 arrayAccess := ArrayAccess{Array: ValueEvaluable{ArrayValue{originalArray}}, ArrayIndex: BadEvaluable{}} 201 if v, e := arrayAccess.Evaluate(ge); v != (nil) || e == nil || 202 e.Error() != "bad access" { 203 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 204 } 205 } 206 207 { 208 arrayAccess := ArrayAccess{Array: BadEvaluable{}, ArrayIndex: ValueEvaluable{IntValue{0}}} 209 if v, e := arrayAccess.Evaluate(ge); v != (nil) || e == nil || 210 e.Error() != "bad access" { 211 212 t.Fatalf("Invalid array access result:%s / error:%s", v, e) 213 } 214 } 215 } 216 217 func TestMapAccess(t *testing.T) { 218 ge := createTestGlobalEnvironment() 219 { 220 var mapAccess Evaluable = &ArrayAccess{Array: &Variable{"map"}, ArrayIndex: ValueEvaluable{StringValue{"3"}}} 221 if v, e := mapAccess.Evaluate(ge); v != (StringValue{"3!"}) || e != nil { 222 t.Fatalf("Invalid map access result:%s / error:%s", v, e) 223 } 224 225 subEvaluable := mapAccess.SubEvaluable() 226 if len(subEvaluable) != 2 || subEvaluable[1] != (ValueEvaluable{StringValue{"3"}}) { 227 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 228 } 229 subEvaluable1, ok := subEvaluable[0].(*Variable) 230 if !ok || subEvaluable1.Name != "map" { 231 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 232 } 233 } 234 { 235 var mapAccess Evaluable = &ArrayAccess{Array: &Variable{"map"}, ArrayIndex: &Variable{"v1"}} 236 if v, e := mapAccess.Evaluate(ge); v != (IntValue{1}) || e != nil { 237 t.Fatalf("Invalid map access result:%s / error:%s", v, e) 238 } 239 } 240 241 { 242 var mapAccess Evaluable = &ArrayAccess{Array: &Variable{"map"}, ArrayIndex: ValueEvaluable{StringValue{"bad"}}} 243 if v, e := mapAccess.Evaluate(ge); v != nil || e.Error() != "bad is not found in map" { 244 t.Fatalf("Invalid map access result:%s / error:%s", v, e) 245 } 246 } 247 248 // check invalid type path 249 { 250 var mapAccess Evaluable = &ArrayAccess{Array: &Variable{"map"}, ArrayIndex: ValueEvaluable{BadValue{}}} 251 if v, e := mapAccess.Evaluate(ge); v != nil || e.Error() != "bad value is not string" { 252 t.Fatalf("Invalid map access result:%s / error:%s", v, e) 253 } 254 } 255 256 // check evaluation fail path 257 { 258 var mapAccess Evaluable = &ArrayAccess{Array: &Variable{"map"}, ArrayIndex: BadEvaluable{}} 259 if v, e := mapAccess.Evaluate(ge); v != nil || e.Error() != "bad access" { 260 t.Fatalf("Invalid map access result:%s / error:%s", v, e) 261 } 262 } 263 } 264 265 func TestPlusExpression(t *testing.T) { 266 ge := createTestGlobalEnvironment() 267 { 268 var plusExpression Evaluable = &PlusExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{IntValue{2}}} 269 if v, e := plusExpression.Evaluate(ge); e != nil || v != (IntValue{3}) { 270 t.Fatalf("Invalid plus operation value: %s / error: %s", v, e) 271 } 272 if v := plusExpression.String(); v != "1 + 2" { 273 t.Fatalf("bad string representation: %s", v) 274 } 275 subEvaluable := plusExpression.SubEvaluable() 276 if len(subEvaluable) != 2 || subEvaluable[0] != (ValueEvaluable{IntValue{1}}) || subEvaluable[1] != (ValueEvaluable{IntValue{2}}) { 277 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 278 } 279 } 280 281 { 282 var plusExpression Evaluable = &PlusExpression{exp1: ValueEvaluable{StringValue{"hoge"}}, exp2: ValueEvaluable{IntValue{2}}} 283 if v, e := plusExpression.Evaluate(ge); e != nil || v != (StringValue{"hoge2"}) { 284 t.Fatalf("Invalid plus operation value: %s / error: %s", v, e) 285 } 286 if v := plusExpression.String(); v != "\"hoge\" + 2" { 287 t.Fatalf("bad string representation: %s", v) 288 } 289 } 290 291 { 292 var plusExpression Evaluable = &PlusExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{StringValue{"foo"}}} 293 if v, e := plusExpression.Evaluate(ge); e != nil || v != (StringValue{"1foo"}) { 294 t.Fatalf("Invalid plus operation value: %s / error: %s", v, e) 295 } 296 if v := plusExpression.String(); v != "1 + \"foo\"" { 297 t.Fatalf("bad string representation: %s", v) 298 } 299 } 300 301 { 302 var plusExpression Evaluable = &PlusExpression{exp1: ValueEvaluable{StringValue{"foo"}}, exp2: ValueEvaluable{StringValue{"bar"}}} 303 if v, e := plusExpression.Evaluate(ge); e != nil || v != (StringValue{"foobar"}) { 304 t.Fatalf("Invalid plus operation value: %s / error: %s", v, e) 305 } 306 } 307 308 { 309 var numericOperation Evaluable = &PlusExpression{exp1: BadEvaluable{}, exp2: ValueEvaluable{IntValue{2}}} 310 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || e.Error() != "bad access" { 311 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 312 } 313 } 314 315 { 316 var numericOperation Evaluable = &PlusExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: BadEvaluable{}} 317 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || e.Error() != "bad access" { 318 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 319 } 320 } 321 322 { 323 var numericOperation Evaluable = &PlusExpression{exp1: ValueEvaluable{BadValue{}}, exp2: ValueEvaluable{IntValue{2}}} 324 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || !strings.HasPrefix(e.Error(), "cannot combine") { 325 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 326 } 327 } 328 329 { 330 var numericOperation Evaluable = &PlusExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{BadValue{}}} 331 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || !strings.HasPrefix(e.Error(), "cannot combine") { 332 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 333 } 334 } 335 336 } 337 338 func TestNumericOperationExpression(t *testing.T) { 339 ge := createTestGlobalEnvironment() 340 { 341 var numericOperation = &NumericOperationExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{IntValue{2}}, operator: "+"} 342 if v, e := numericOperation.Evaluate(ge); e != nil || v != (IntValue{3}) { 343 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 344 } 345 if v := numericOperation.String(); v != "1 + 2" { 346 t.Fatalf("bad string representation: %s", v) 347 } 348 subEvaluable := numericOperation.SubEvaluable() 349 if len(subEvaluable) != 2 || subEvaluable[0] != (ValueEvaluable{IntValue{1}}) || subEvaluable[1] != (ValueEvaluable{IntValue{2}}) { 350 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 351 } 352 } 353 354 { 355 var numericOperation = &NumericOperationExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{IntValue{2}}, operator: "-"} 356 if v, e := numericOperation.Evaluate(ge); e != nil || v != (IntValue{-1}) { 357 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 358 } 359 if v := numericOperation.String(); v != "1 - 2" { 360 t.Fatalf("bad string representation: %s", v) 361 } 362 } 363 364 { 365 var numericOperation = &NumericOperationExpression{exp1: ValueEvaluable{IntValue{2}}, exp2: ValueEvaluable{IntValue{2}}, operator: "*"} 366 if v, e := numericOperation.Evaluate(ge); e != nil || v != (IntValue{4}) { 367 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 368 } 369 if v := numericOperation.String(); v != "2 * 2" { 370 t.Fatalf("bad string representation: %s", v) 371 } 372 } 373 374 { 375 var numericOperation = &NumericOperationExpression{exp1: ValueEvaluable{IntValue{4}}, exp2: ValueEvaluable{IntValue{2}}, operator: "/"} 376 if v, e := numericOperation.Evaluate(ge); e != nil || v != (IntValue{2}) { 377 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 378 } 379 if v := numericOperation.String(); v != "4 / 2" { 380 t.Fatalf("bad string representation: %s", v) 381 } 382 } 383 384 { 385 var numericOperation = &NumericOperationExpression{exp1: BadEvaluable{}, exp2: ValueEvaluable{IntValue{2}}, operator: "/"} 386 if v, e := numericOperation.Evaluate(ge); e == nil || v != nil || e.Error() != "bad access" { 387 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 388 } 389 } 390 391 { 392 var numericOperation = &NumericOperationExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: BadEvaluable{}, operator: "/"} 393 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || e.Error() != "bad access" { 394 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 395 } 396 } 397 398 { 399 var numericOperation = &NumericOperationExpression{exp1: ValueEvaluable{StringValue{"foo"}}, exp2: ValueEvaluable{IntValue{2}}, operator: "/"} 400 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || !strings.HasPrefix(e.Error(), "cannot calculate") { 401 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 402 } 403 } 404 405 { 406 var numericOperation Evaluable = &NumericOperationExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{StringValue{"foo"}}, operator: "/"} 407 if v, e := numericOperation.Evaluate(ge); e == nil || v != (nil) || !strings.HasPrefix(e.Error(), "cannot calculate") { 408 t.Fatalf("Invalid numeric operation value: %s / error: %s", v, e) 409 } 410 } 411 } 412 413 func TestJoinedExpression(t *testing.T) { 414 ge := createTestGlobalEnvironment() 415 416 { 417 var joinedExpression Evaluable = &JoinedExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: ValueEvaluable{IntValue{2}}} 418 if v, e := joinedExpression.Evaluate(ge); e != nil || v != (IntValue{2}) { 419 t.Fatalf("Invalid joined expression value: %s / error: %s", v, e) 420 } 421 if s := joinedExpression.String(); s != "1; 2" { 422 t.Fatalf("bad string representation: %s", s) 423 } 424 subEvaluable := joinedExpression.SubEvaluable() 425 if len(subEvaluable) != 2 || subEvaluable[0] != (ValueEvaluable{IntValue{1}}) || subEvaluable[1] != (ValueEvaluable{IntValue{2}}) { 426 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 427 } 428 } 429 430 { 431 var joinedExpression Evaluable = &JoinedExpression{exp1: BadEvaluable{}, exp2: ValueEvaluable{IntValue{2}}} 432 if v, e := joinedExpression.Evaluate(ge); e == nil || v != (nil) || e.Error() != "bad access" { 433 t.Fatalf("Invalid joined expression value: %s / error: %s", v, e) 434 } 435 if s := joinedExpression.String(); s != "bad access; 2" { 436 t.Fatalf("bad string representation: %s", s) 437 } 438 } 439 440 { 441 var joinedExpression Evaluable = &JoinedExpression{exp1: ValueEvaluable{IntValue{1}}, exp2: BadEvaluable{}} 442 if v, e := joinedExpression.Evaluate(ge); e == nil || v != (nil) || e.Error() != "bad access" { 443 t.Fatalf("Invalid joined expression value: %s / error: %s", v, e) 444 } 445 } 446 } 447 448 func TestAssignExpression(t *testing.T) { 449 ge := createTestGlobalEnvironment() 450 451 { 452 var assignExpression Evaluable = &AssignExpression{variable: &Variable{"x"}, exp: ValueEvaluable{IntValue{2}}} 453 v, e := assignExpression.Evaluate(ge) 454 av, ae := ge.Value("x") 455 if e != nil || ae != nil || v != (IntValue{2}) || av != (IntValue{2}) { 456 t.Fatalf("Invalid joined expression value: %s / error: %s / assigned: %s / env error: %s", v, e, av, ae) 457 } 458 if s := assignExpression.String(); s != "x = 2" { 459 t.Fatalf("bad string representation: %s", s) 460 } 461 subEvaluable := assignExpression.SubEvaluable() 462 if len(subEvaluable) != 2 || subEvaluable[0].(*Variable).Name != "x" || subEvaluable[1] != (ValueEvaluable{IntValue{2}}) { 463 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 464 } 465 } 466 467 { 468 var assignExpression Evaluable = &AssignExpression{variable: &Variable{"y"}, exp: ValueEvaluable{StringValue{"hoge"}}} 469 v, e := assignExpression.Evaluate(ge) 470 av, ae := ge.Value("y") 471 if e != nil || ae != nil || v != (StringValue{"hoge"}) || av != (StringValue{"hoge"}) { 472 t.Fatalf("Invalid joined expression value: %s / error: %s / assigned: %s / env error: %s", v, e, av, ae) 473 } 474 if s := assignExpression.String(); s != "y = \"hoge\"" { 475 t.Fatalf("bad string representation: %s", s) 476 } 477 } 478 479 { 480 var assignExpression Evaluable = &AssignExpression{variable: &Variable{"hoge"}, exp: BadEvaluable{}} 481 v, e := assignExpression.Evaluate(ge) 482 av, ae := ge.Value("hoge") // check overwriting 483 if e == nil || e.Error() != "bad access" || ae != nil || v != (nil) || av != (StringValue{"hoge"}) { 484 t.Fatalf("Invalid joined expression value: %s / error: %s / assigned: %s / env error: %s", v, e, av, ae) 485 } 486 487 } 488 489 { 490 var assignExpression Evaluable = &AssignExpression{variable: ValueEvaluable{IntValue{1}}, exp: ValueEvaluable{IntValue{2}}} 491 v, e := assignExpression.Evaluate(ge) 492 if e == nil || e.Error() != "1 is not variable" || v != (nil) { 493 t.Fatalf("Invalid joined expression value: %s / error: %s", v, e) 494 } 495 } 496 } 497 498 func TestFunctionCall(t *testing.T) { 499 ge := createTestGlobalEnvironment() 500 501 { 502 args := [...]Evaluable{ValueEvaluable{StringValue{"hoge/foo"}}} 503 dirname := BuiltinFunctions["dirname"] 504 var function Evaluable = &FunctionCall{function: ValueEvaluable{FunctionValue{dirname}}, args: args[:]} 505 506 if subEvaluable := function.SubEvaluable(); len(subEvaluable) != 2 || subEvaluable[0].(ValueEvaluable).value != (StringValue{"hoge/foo"}) || subEvaluable[1] != (ValueEvaluable{FunctionValue{dirname}}) { 507 t.Fatalf("bad sub-evaluable: %s", subEvaluable) 508 } 509 510 if r, e := function.Evaluate(ge); e != nil || r != (StringValue{"hoge"}) { 511 t.Fatalf("Invalid result: %s / error: %s", r, e) 512 } 513 if r := function.String(); r != "dirname(\"hoge/foo\")" { 514 t.Fatalf("Invalid result: %s", r) 515 } 516 } 517 518 { 519 args := [...]Evaluable{ValueEvaluable{StringValue{"hoge/foo.c"}}, ValueEvaluable{StringValue{".c"}}} 520 basename := BuiltinFunctions["basename"] 521 var function Evaluable = &FunctionCall{function: ValueEvaluable{FunctionValue{basename}}, args: args[:]} 522 523 if subEvaluable := function.SubEvaluable(); len(subEvaluable) != 3 || subEvaluable[0].(ValueEvaluable).value != (StringValue{"hoge/foo.c"}) || subEvaluable[1].(ValueEvaluable).value != (StringValue{".c"}) || subEvaluable[2] != (ValueEvaluable{FunctionValue{basename}}) { 524 t.Fatalf("bad sub-evaluable: %s / condition %t %t %t", subEvaluable, subEvaluable[0].(ValueEvaluable).value != (StringValue{"hoge/foo.c"}), subEvaluable[1].(ValueEvaluable).value != (StringValue{".c"}), subEvaluable[2] != (ValueEvaluable{FunctionValue{basename}})) 525 } 526 if r, e := function.Evaluate(ge); e != nil || r != (StringValue{"foo"}) { 527 t.Fatalf("Invalid result: %s / error: %s", r, e) 528 } 529 if r := function.String(); r != "basename(\"hoge/foo.c\", \".c\")" { 530 t.Fatalf("Invalid result: %s", r) 531 } 532 } 533 534 { 535 args := [...]Evaluable{BadEvaluable{}} 536 dirname := BuiltinFunctions["dirname"] 537 var function Evaluable = &FunctionCall{function: ValueEvaluable{FunctionValue{dirname}}, args: args[:]} 538 if r, e := function.Evaluate(ge); e == nil || e.Error() != "bad access" || r != (nil) { 539 t.Fatalf("Invalid result: %s / error: %s", r, e) 540 } 541 } 542 543 { 544 args := [...]Evaluable{ValueEvaluable{IntValue{1}}} 545 var function Evaluable = &FunctionCall{function: BadEvaluable{}, args: args[:]} 546 if r, e := function.Evaluate(ge); e == nil || e.Error() != "bad access" || r != (nil) { 547 t.Fatalf("Invalid result: %s / error: %s", r, e) 548 } 549 } 550 551 { 552 args := [...]Evaluable{ValueEvaluable{IntValue{1}}} 553 var function Evaluable = &FunctionCall{function: ValueEvaluable{IntValue{1}}, args: args[:]} 554 if r, e := function.Evaluate(ge); e == nil || e.Error() != "1 is not function" || r != (nil) { 555 t.Fatalf("Invalid result: %s / error: %s", r, e) 556 } 557 } 558 } 559 560 func TestArrayExpression(t *testing.T) { 561 ge := createTestGlobalEnvironment() 562 { 563 values := [...]Evaluable{ValueEvaluable{IntValue{1}}, ValueEvaluable{IntValue{2}}, ValueEvaluable{IntValue{3}}} 564 expected := [...]Value{IntValue{1}, IntValue{2}, IntValue{3}} 565 var arrayExpression Evaluable = &ArrayExpression{values[:]} 566 r, e := arrayExpression.Evaluate(ge) 567 if e != nil { 568 t.Fatalf("Invalid result: %s / error: %s", r, e) 569 } 570 array, ok := r.(ArrayValue) 571 if !ok { 572 t.Fatalf("Invalid result: %s / error: %s", r, e) 573 } 574 575 if !reflect.DeepEqual(array.value, expected[:]) { 576 t.Fatalf("Invalid result: %s / error: %s", r, e) 577 } 578 579 if s := arrayExpression.String(); s != "[1, 2, 3]" { 580 t.Fatalf("Invalid string result: %s", s) 581 } 582 583 if !reflect.DeepEqual(arrayExpression.SubEvaluable(), values[:]) { 584 t.Fatalf("Invalid result: %s / error: %s", r, e) 585 } 586 } 587 588 { 589 values := [...]Evaluable{ValueEvaluable{IntValue{1}}, BadEvaluable{}, ValueEvaluable{IntValue{3}}} 590 var arrayExpression Evaluable = &ArrayExpression{values[:]} 591 if r, e := arrayExpression.Evaluate(ge); e == nil || r != (nil) || e.Error() != "bad access" { 592 t.Fatalf("Invalid result: %s / error: %s", r, e) 593 } 594 } 595 } 596 597 func TestSearchDependentVariables(t *testing.T) { 598 tokenizer := createInitializedTokenizer("a = b + c + d; k = x / y + basename(\"foo/bar\", z) + b; l = m") 599 evaluable, err := ParseAsExp(tokenizer) 600 if err != nil { 601 t.Fatalf("Failed to parse: %s", err) 602 } 603 dependentVariables := SearchDependentVariables(evaluable).Array() 604 605 expected := []string{"b", "basename", "c", "d", "m", "x", "y", "z"} 606 if !reflect.DeepEqual(expected, dependentVariables) { 607 t.Fatalf("bad dependent variables: %s", dependentVariables) 608 } 609 } 610 611 func TestSearchCreatedVariables(t *testing.T) { 612 tokenizer := createInitializedTokenizer("a = b + c + d; k = x / y + basename(\"foo/bar\", z) + b; l = m") 613 evaluable, err := ParseAsExp(tokenizer) 614 if err != nil { 615 t.Fatalf("Failed to parse: %s", err) 616 } 617 dependentVariables := SearchCreatedVariables(evaluable).Array() 618 619 expected := []string{"a", "k", "l"} 620 if !reflect.DeepEqual(expected, dependentVariables) { 621 t.Fatalf("bad created variables: %s", dependentVariables) 622 } 623 }