## Automated HSpeak tests. See documentation in hspeaktest.py ## Run these tests with "scons hspeaktest" ## Including just this is faster than all of plotscr.hsd include, hamsterspeak.hsd define function, begin 1,noop4,4,0,0,0,0 @obsolete, 2,obsoletecmd,0 @obsolete(replacement,"Message"), 3,obsoletecmd2,0 @obsolete(error), 4,removedcmd,0 @obsolete(), 100,__obsolete,0 # OK end script, div, a, b () defineoperator(100, eqstr, stringcompare) defineoperator(100, div, div) globalvariable(1,globalvar) defineconstant(1,constant) ## Check for errors given extra commas, and for operators in illegal positions script, comma and operator tests, begin variable(xx) +, # ERROR + , # ERROR <<, # ERROR << , # ERROR ,<<1 # ERROR , <<2 # ERROR ,<3 # ERROR , <4 # ERROR 1,-2 # WARN ,-2 # WARN -2, # WARN noop4(1,-2) # OK 1,:=2 # ERROR 1,--2 # ERROR 2--1 # WARN ## FIXME: This is major lexer bug 2-1 # ERROR (known failure) 1, div, 2 # OK 1, eqstr, 2 # OK 1, eqstr, 2 + 3 # OK (1) eqstr (2 + 3) # OK (1) div (2 + 3) # OK noop4(1,mod,2) # OK #if,(xx) then() # WARN if(xx), then() # OK #if(xx) then,() # WARN noop4((1), (2)) # OK noop4(-2) # OK noop4((2) -- (1)) # OK ## These error checks aren't implemented; they're hard to catch noop(), # ERROR (known failure) noop,() # ERROR (known failure) noop4(noop,()) # ERROR (known failure) ## This fails because parsed as noop(0), but noop takes no args ## Let's say this should be a warning, because the behaviour would have changed noop4(noop,(0)) # WARN (known failure) noop4( --2) # ERROR noop4(,--2) # ERROR noop4( , , 0) # ERROR noop4( , 0) # ERROR ## These probably don't particularly need to be disallowed noop4(0 ,) # OK variable(,yy) # ERROR (explict check for this) variable(yy,) # OK (??) variable() # OK (??) ## $ is treated as a unary operator $,0="" # ERROR $0,="" # ERROR $0=,"" # ERROR noop4($0="") # OK noop4(1,$0="") # OK noop4(,$0="") # ERROR ## Warnings for logical errors if (xx == 2||3||4) then() # WARN (known failure) end end # ERROR begin # ERROR script, foo, end # ERROR () # ERROR script, string tests, begin $0="", 232 # WARN $0="" 232 # ERROR (known failure) "asdasd" # ERROR end script, number tests, x, begin x := 000 0000 # OK x := - 14 # OK ## tab characters x := - 1 4 # OK x := 14a # ERROR x := - 14a # ERROR x := 0x14a # OK x := - 0x 14a # OK x := - 0x 14a # OK x := 0x # ERROR x := 0o # ERROR x := 0b # ERROR ## Space after the 0 not supported... but we don't care one way or the other ##x := 0 x1 ## - is not a valid token, and identifiers can't start with - x := - # ERROR variable(-) # ERROR variable(-y) # ERROR x := -x # ERROR x := -(1+2) # ERROR ## Numbers which aren't 32 bit x := 0x100000000 # ERROR x := 0o1 # OK x := 0o8 # ERROR x := 0oa # ERROR x := 0b0 # OK x := 0xa # OK x := 0xf # OK x := 0bf # ERROR x := 0XF # OK x := -0x111 # OK ## special rules for non-decimals: silently overflow large unsigned 32bit ints x := 0xffffffff # OK x := -0xffffffff # OK x := -2147483648 # OK x := -2147483649 # ERROR x := 1. # ERROR x := 1.0 # ERROR x := .0 # ERROR end script, math warnings, x, begin x := random () # ERROR x := random (1) # ERROR x := random (1, 0) # WARNING (known failure) x := random (1, 1) # OK ## The following test optimisations x := 1 / 0 # ERROR x := 1, mod, 0 # ERROR x := 1^0 # OK x := 0^-1 # ERROR ## Negative exponents evaluate to 0, but will probably change in future x := 1^-1 # OK x := sqrt(0) # OK x := sqrt(-1) # ERROR end script, flow tests, dummy, begin (dummy) # WARN () # ERROR if(dummy) then() else() else() # ERROR then() # ERROR break # ERROR (known failure) continue # ERROR (known failure) if () then() # ERROR if(dummy,dummy) then() # ERROR if(dummy) if(dummy) then() # ERROR if(dummy) else() # OK if(dummy) else() then() # ERROR dummy := variable(foo) # ERROR (if(dummy) else()) # ERROR (known failure) if(if(1)then(1))then() # ERROR dummy := if(1)then(1) # ERROR if(assert(1))then() # ERROR if($1="")then() # OK if() then # ERROR if(then()) # ERROR if(dummy) variable(x) then() # ERROR if(dummy) then(variable(x)) # OK ## In case of of a missing bracket, ideally hspeak would throw an error here ## instead of complaining the next script/declaration appears inside this script. ## (This test fails because the error gets thrown on a different line.) if (key is pressed(key:M) then (pick hero()) # ERROR (known failure) end ############################### Namespace tests ############################### ## Testing whether various types of names are properly disallowed globalvariable(one,global) # ERROR globalvariable(two,globalvar2) # OK globalvariable(2,globalvar) # ERROR globalvariable(1,globalvar2) # ERROR globalvariable(2,one) # ERROR globalvariable(8,G2,9,G3) # OK globalvariable(8,G2,9,G2) # ERROR globalvariable(8) # ERROR globalvariable(8,G2,9) # ERROR globalvariable(9,begin) # ERROR globalvariable(9,+) # ERROR globalvariable(9,add) # ERROR globalvariable(9,mod) # ERROR globalvariable(9,eqstr) # ERROR globalvariable(9,div) # ERROR globalvariable(-1,ok) # ERROR globalvariable(9,script) # ERROR defineconstant(1,begin) # ERROR script, namespace tests, arg, begin variable(noop) # ERROR variable(script) # ERROR variable(variable) # ERROR variable(globalvariable) # ERROR variable(globalvar) # ERROR variable(constant) # ERROR variable(flow tests) # ERROR variable(arg) # ERROR variable(1) # ERROR variable(a.) # ERROR variable(add) # ERROR variable(mod) # ERROR variable(eqstr) # ERROR variable(div) # ERROR variable(:=) # ERROR variable(x:=y) # ERROR variable($) # ERROR variable($+) # ERROR variable(v) variable(@v) # ERROR (known failure) variable(@obsolete) # ERROR ## subscript args and variables can shadow outer locals, but not globals or other names subscript, sub () # OK subscript, sub, globalvar () # ERROR subscript, sub, constant () # ERROR subscript, sub, NO OP () # ERROR subscript, sub, namespace tests () # ERROR subscript, sub, sub () # ERROR (known failure) subscript, sub, arg () # OK subscript, sub, v () # OK subscript, namespace tests, arg () # ERROR subscript, sub, (subscript, sub2 ()) # OK subscript, sub, (subscript, SUB ()) # ERROR subscript, sub, (subscript, namespace tests ()) # ERROR subscript, sub, v (subscript, sub2, v ()) # OK subscript, sub, W (subscript, sub2, w ()) # OK v := subscript, sub () # ERROR @obsolete("message") subscript, sub () # OK @obsolete, @obsolete(blarg), subscript, sub () # OK ## Should shadowing scripts in an outer scope be allowed? (Currently not.) Seems useful. ## Scripts with both of the following names have been declared, but hspeak ## hasn't parsed anotherscript yet, so fails to report an error. ## (Probably same thing with subscripts which are in scope.) subscript, div () # ERROR (?) subscript, a script () # ERROR (?) (known failure) ## Operators subscript, add () # ERROR subscript, sub, add () # ERROR subscript, mod () # ERROR subscript, sub, mod () # ERROR subscript, eqstr () # ERROR subscript, sub, eqstr () # ERROR subscript, div () # ERROR subscript, sub, div () # ERROR ## Testing @obsolete warnings and errors obsoletecmd # WARN obsoletecmd2 # WARN removedcmd # ERROR obsoletescript # WARN end definescript(1, missing script, 0) # ERROR ## Don't care whether definescript after the script itself is allowed (currently is) #definescript(1, flow tests, 1, 0) # OK ## Even plotscripts can use definescript to fix an ID definescript(1, a plotscript, 0) # OK ## OK to give defaults for more arguments in definescript than in the definition definescript(1, a script, 3, 0, 56, 42) # OK definescript(1, a script, 3, 0, 56, 0) # ERROR (elsewhere) definescript(autonumber, a script, 3, 0, 0, 42) # OK ## Only functions can have variable numbers of args definescript(1, a script, -1) # ERROR plotscript, a plotscript () script, a script, x, y, z = 42 () @obsolete, script, obsolete script ()