X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani-tests.mdc;h=1a36534abf4ba13b6079e4f80ecc22132ecc1b46;hp=d5e60b739236ab9417b19fa11e329d49e1032a22;hb=a90cecd0016cf35d400d6de895f1b2aa6c5ac0dd;hpb=6f3c6db8d0e5c5bf244f9a101e72e5e498b5fb6d diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc index d5e60b7..1a36534 100644 --- a/csrc/oceani-tests.mdc +++ b/csrc/oceani-tests.mdc @@ -35,42 +35,70 @@ arguments separated from the name by commas. For each test, there is a section oceani_tests := ## test list + oceani_valg_tests := $(oceani_tests) + ## combine test lists tests:: oceani_test_suite oceani_test_suite: oceani coverage_oceani + @echo -n Checking grammar ... + @./parsergen --report --LALR --tag Parser oceani.mdc | grep " - no conflicts" > /dev/null || \ + { echo "Grammar contains conflicts, please review" ; exit 1; } + @echo ok @rm -rf coverage; mkdir -p coverage @cp *.gcno coverage @for T in $(oceani_tests); do \ - echo -n "Test $$T ... "; \ + echo -n "Test $$T.. "; \ i="$$IFS"; IFS=,; set $$T; IFS="$$i"; t=$$1; shift; \ ./md2c oceani-tests.mdc "output: $$T" | grep -v '^#' > .tmp.want; \ ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} > .tmp.have; \ if ! cmp -s .tmp.want .tmp.have; then \ echo "FAILED"; diff -u .tmp.want .tmp.have ; exit 1; fi ;\ - echo -n "passed ... "; \ - if ! valgrind ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} \ - > /dev/null 2> .tmp.valg; then \ - echo "valgrind FAILED"; cat .tmp.valg; exit 1; fi ; \ - echo -n "valgrind passed ... "; \ + echo -n "printing.. "; \ echo '``````' > .tmp.code1; echo '``````' > .tmp.code2 ;\ ./oceani --noexec --print --section "test: $$t" oceani-tests.mdc >> .tmp.code1; \ - ./oceani --noexec --print .tmp.code1 >> .tmp.code2 ;\ + ./oceani --noexec --print .tmp.code1 >> .tmp.code2 || exit 1;\ if ! cmp -s .tmp.code1 .tmp.code2; then \ - echo "Printing Failed"; diff -u .tmp.code1 .tmp.code2; exit1 ; fi ; \ - echo "Printing passed"; \ + echo " Failed"; diff -u .tmp.code1 .tmp.code2; exit 1 ; fi ; \ + echo -n "extra-newlines.. "; \ + sed -e 'i\ + ' .tmp.code1 > .tmp.code1a; \ + echo '``````' > .tmp.code2a ;\ + ./oceani --noexec --print .tmp.code1a >> .tmp.code2a || exit 1;\ + if ! cmp -s .tmp.code1 .tmp.code2a; then \ + echo " Failed"; diff -u .tmp.code1 .tmp.code2a; exit 1; fi ; \ + echo -n "exec-after-print.. "; \ + ./oceani .tmp.code1 $${1+"$$@"} > .tmp.have ; \ + if ! cmp -s .tmp.want .tmp.have; then \ + echo " FAILED"; diff -u .tmp.want .tmp.have; exit 1;fi; \ + echo " all passed"; \ ./coverage_oceani --print --section "test: $$t" oceani-tests.mdc $${1+"$$@"} > /dev/null ; \ ./coverage_oceani -tpbn --section "test: $$t" oceani-tests.mdc > /dev/null 2>&1; \ done ## test code + @for i in coverage/#*.gcda; do mv $$i coverage/$${i##*#}; done @gcov -o coverage oceani.mdc > /dev/null 2> /dev/null - @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage - @ awk '/^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \ + @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage || true + @rm -f .tmp* + + @[ -n "$$SKIP_VALGRIND" ] || for T in $(oceani_valg_tests); do \ + echo -n "Valgrind $$T.. "; \ + i="$$IFS"; IFS=,; set $$T; IFS="$$i"; t=$$1; shift; \ + if valgrind --error-exitcode=42 --log-file=.tmp.valg ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} \ + > /dev/null 2>&1 ; [ $$? -eq 42 ] ; then \ + echo "FAILED"; cat .tmp.valg; exit 1; fi ; \ + if grep 'LEAK SUMMARY' .tmp.valg > /dev/null; then \ + echo "valgrind found LEAKS"; cat .tmp.valg ; exit 1 ; fi; \ + if grep 'in use at exit [1-9]' .tmp.valg > /dev/null; then \ + echo "valgrind found memory in use at exit"; cat .tmp.valg ; exit 1 ; fi; \ + echo " passed"; \ + done + ## valgrind test code + @[ -n "$$SKIP_COVERAGE_CHECK" ] || awk '/NOTEST/ { next } /^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \ END {printf "coverage: %6.2f%%\n", ran * 100 / (ran + skip); \ - if (ran < (ran + skip) *0.90) exit(1) }' \ + if (ran < (ran + skip) *0.972) exit(1) }' \ coverage/oceani.mdc.gcov - @rm -f .tmp* coverage_oceani: oceani.c $(CC) $(CFLAGS) --coverage -fprofile-dir=coverage -o coverage_oceani oceani.c $(LDLIBS) @@ -83,10 +111,9 @@ calculations on them. ###### test list oceani_tests += "valvar" - ###### test: valvar - program: + func main(argv:[argc::]string) a := 23; b:=12 ; b1 := -b print a, b, a+b, a-b, a*b, a/b, a%b print ab, a>=b, a 0.000000001 - do: + do guess = (guess + (target / guess) ) / 2 print count, guess count = count + 1 @@ -160,27 +265,48 @@ Now we need to test if/else and some different loops for j:=0; then j = j+3 ; while j < 10: if j != 0 and then 20 / j > 3: print "20 /", j," =", 20 / j - else: + else print "I won't calculate 20 /", j pi ::= 3.1415926535897 if 355/113 == pi or else +(pi - 355/113) < 0.001: print "Close enough" print "lower" if 355/113 < pi else "higher" + if pi > 3 then print "pi exceeds three"; else print "need more pie" + if (pi < 3) { print "not enough pi" } else { print "pi sufficient" } + for { i := 0; sum := 0 } + then { i = i+1 } + while i <= 10: + sum = sum + i + else + pass + print "sum 1..10 is", sum + if + PI1 := 22/7 + use PI1 < pi + then + print "Smaller" + else + print 'larger' + ###### output: cond_loop Success 1 2 4 8 16 32 64 0 1.5 - 1 1.41667 - 2 1.41422 - 3 1.41421 - error is -4.51095e-12 + 1 1.416666667 + 2 1.414215686 + 3 1.414213562 + error is -4.510950445e-12 I won't calculate 20 / 0 - 20 / 3 = 6.66667 - 20 / 6 = 3.33333 + 20 / 3 = 6.666666667 + 20 / 6 = 3.333333333 I won't calculate 20 / 9 Close enough higher + pi exceeds three + pi sufficient + sum 1..10 is 55 + larger ## Say Hello @@ -188,19 +314,22 @@ The demonstration code presented in the interpreted is suitable for the test sui Here I break it into two parts, keeping the array code separate. ###### test list - oceani_tests += "sayhello,55,33" - oceani_tests += "sayhello,12,60" + oceani_tests += "sayhello,55,33,hello,True" + oceani_tests += "sayhello,12,60,there,False" ###### test: sayhello - program A B: + func main(av:[ac::number]string) + A := $av[1]; B := $av[2] + astr := av[3] + bbool := av[ac-1] == "True" print "Hello World, what lovely oceans you have!" /* When a variable is defined in both branches of an 'if', * and used afterwards, the variables are merged. */ if A > B: bigger := "yes" - else: + else bigger := "no" print "Is", A, "bigger than", B,"? ", bigger /* If a variable is not used after the 'if', no @@ -209,26 +338,27 @@ Here I break it into two parts, keeping the array code separate. if A > B * 2: double:string = "yes" print A, "is more than twice", B, "?", double - else: + else double := B*2 print "double", B, "is", double a : number a = A; b:number = B + print "still", bigger // check for regression in scoping if a > 0 and b > 0: while a != b: if a < b: b = b - a - else: + else a = a - b print "GCD of", A, "and", B,"is", a else if a <= 0: print a, "is not positive, cannot calculate GCD" - else: + else print b, "is not positive, cannot calculate GCD" - for: + for togo := 10 f1 := 1; f2 := 1 print "Fibonacci:", f1,f2, @@ -240,50 +370,60 @@ Here I break it into two parts, keeping the array code separate. f2 = f3 print "" + if bbool: + print astr ++ " was the str" + else + print "I found the str over " ++ astr + /* Binary search... */ - for: + for lo:= 0; hi := 100 target := 77 - while: + while mid := (lo + hi) / 2 if mid == target: - use Found + use .Found if mid < target: lo = mid - else: + else hi = mid if hi - lo < 1: - use GiveUp + lo = mid + use .GiveUp use True - do: pass - case Found: + do pass + case .Found: print "Yay, I found", target - case GiveUp: - print "Closest I found was", mid + case .GiveUp: + print "Closest I found was", lo -###### output: sayhello,55,33 +###### output: sayhello,55,33,hello,True Hello World, what lovely oceans you have! Is 55 bigger than 33 ? yes double 33 is 66 + still yes GCD of 55 and 33 is 11 Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144 - Closest I found was 77.3438 + hello was the str + Closest I found was 77.34375 -###### output: sayhello,12,60 +###### output: sayhello,12,60,there,False Hello World, what lovely oceans you have! Is 12 bigger than 60 ? no double 60 is 120 + still no GCD of 12 and 60 is 12 Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144 - Closest I found was 77.3438 + I found the str over there + Closest I found was 77.34375 ###### test list oceani_tests += "insert_sort" ###### test: insert_sort - program: + func main() size::=55 list:[size]number - list[0] = 1234 + list[0] = 1_234 for i:=1; then i = i + 1; while i < size: n := list[i-1] * list[i-1] list[i] = (n / 100) % 10000 @@ -426,7 +566,7 @@ ad-hoc things array related. ###### test: arrays - program: + func main() bools:[5]Boolean strings:[4]string @@ -434,11 +574,202 @@ ad-hoc things array related. bools[1] = strings[2] <= "there" for i:=0; then i=i+1; while i<5: - print '', bools[i], + j ::= i + ra:[j]number + ra[i-1] = i*i + ra[6] = 42 // mustn't crash + print '', bools[i], ra[j-1], print ###### output: arrays - False True False False False + False 0 True 1 False 4 False 9 False 16 + +## Structures + +Time to test if structure declarations and accesses work correctly. + +###### test list + oceani_tests += structs + +###### test: structs + + const three ::= 3 + struct foo + size:[three]number + name:string + thing:baz + active:Boolean = True + + struct baz { a:number; b:Boolean; } + + func main + do + info:[4]foo + + for i:=0; then i=i+1; while i < 4: + switch i + case 2: nm:= "peter" + case 0: nm:= "bob" + case 1: nm:= "jane" + else nm:= "janine" + + info[i].name = nm + info[i].size[0] = i*i + if nm != "jane": + info[i].active = False + + for i:=0; then i=i+1; while i < 4: + print info[i].name, info[i].active, info[i].size[0] + info[0].thing.b = True + +###### output: structs + + bob False 0 + jane True 1 + peter False 4 + janine False 9 + +## Functions + +Test functions. They don't return anything, so we need to get them to print + +###### test list + oceani_tests += functions func_ret_type + +###### test: functions + + func test1 + t: Boolean + do + if t: + print "true" + + func noarg + do + pass + + func twoarg + a:number + b:string + do + while a > 0: + print b + a = a - 1 + + func test(n:number; s:string) + if n >= 1: + print n,s, + test(n-1, "."++s) + else + print "done" + + func to_polar + x:number; y:number + return + rho:number + theta:number + do + rho = x + y + theta = x - y + + func main() + for i:=0; then i = i + 1; while i < 5: + test(i, " ") + angular := to_polar(32, 23) + print angular.rho, angular.theta + +###### output: functions + done + 1 done + 2 1 . done + 3 2 . 1 .. done + 4 3 . 2 .. 1 ... done + 55 9 + +###### test: func_ret_type + + func double(n:number):number + use n+n + + func answer + prefix:string + suffix:string + return string + do + use prefix ++ suffix + + func noarg_returns + return Boolean + do + use 22/7 == 3.14159 + + func main() + for j:=10; then j = j - 3; while j > -5: + print answer("dou","ble"), j, "is", double(j) + +###### output: func_ret_type + double 10 is 20 + double 7 is 14 + double 4 is 8 + double 1 is 2 + double -2 is -4 + +## References + +A simple linked list example + +###### test list + oceani_tests += "linked_list,one,two,three,four" + +###### test: linked_list + + struct node + next: @node + this: string + + func insert(list:@node; new:string):@node + p:=list + prev := @nil + while ?p and then p.this < new: + prev = p + p = p.next + if ?prev: + prev.next = @new() + prev.next.next = p + prev.next.this = new + else + list = @new() + list.next = p + list.this = new + use list + + func printlist(list:@node) + while ?list: + print list@.this + list = list@.next + + func freelist(list:@node) + if list != @nil: + freelist(list.next) + @free = list + + func main(argv:[ac::]string) + list := insert(@nil, "@start") + list = insert(list, "~end") + for i:=1; then i=i+1; while i < ac: + list = insert(list, argv[i]) + list = insert(list, "Hello!") + printlist(list) + freelist(list) + +###### output: linked_list,one,two,three,four + @start + Hello! + four + one + three + two + ~end ## Test code with syntax errors @@ -470,20 +801,23 @@ separate file first, then run from there. ./coverage_oceani --section "test: $$t" oceani-tests.mdc > /dev/null 2>&1 ;\ done || true +###### combine test lists + oceani_valg_tests += $(oceani_failing_tests) + ###### test list oceani_failing_tests := syn1 oceani_failing_tests += tokerr ###### test: syn1 - program: + func main() if then else while do ###### output: syn1 - .tmp.code:3:11: error: unhandled parse error: then + .tmp.code:3:11: Syntax error in statement: then ###### test: tokerr - program: + func main() a := 1i // imaginary numbers aren't understood b:[2i]number // array sizes are handled separately c:[3.14159]Boolean // array sizes must be integers @@ -513,10 +847,10 @@ separate file first, then run from there. This is a multiline string With an unsupportable suffix """Aa - .tmp.code:14:11: error: undefined type: unknown .tmp.code:15:12: error: name undeclared: unknowable .tmp.code:17:12: error: array size must be a constant: zzsize .tmp.code:20:12: error: unrecognised number: 00123 + .tmp.code:14:11: error: type used but not declared: unknown ## Tests for type errors @@ -529,31 +863,34 @@ These programs were generated by looking for the various places that `type_err()` are called. ###### test list - oceani_failing_tests += type_err1 type_err2 type_err3 type_err4 + oceani_failing_tests += type_err1 type_err2 type_err3 type_err4 type_err5 type_err6 ###### test: type_err1 - program: + func main() print "hello" ++ 5, 5 ++ "hello" b ::= 3 b = b + 1 if 3 * 4 and not True: print "Weird" + d:number = .fred + (d + b) = 12 ###### output: type_err1 .tmp.code:3:25: error: expected string found number .tmp.code:3:28: error: expected string found number .tmp.code:6:8: error: Cannot assign to a constant: b .tmp.code:5:8: info: name was defined as a constant here - .tmp.code:6:8: error: Cannot assign to a constant: b - .tmp.code:5:8: info: name was defined as a constant here .tmp.code:8:11: error: Arithmetic returns number but Boolean expected + .tmp.code:9:20: error: expected number found label + .tmp.code:9:8: info: variable 'd' was set as number here. + .tmp.code:10:8: error: cannot assign to an rval oceani: type error in program - not running. ###### test: type_err2 - program: + func main() a := 1 a := 2 a ::= 3 @@ -574,7 +911,11 @@ various places that `type_err()` are called. ###### test: type_err3 - program: + struct foo + a: number + b:string = "hello" + + func main() c := "hello" c = c + 1 c = "hello" ++ (True and False) @@ -582,11 +923,11 @@ various places that `type_err()` are called. print 45 + ( "Hello" ++ "there") c[5] = 1 - while: + while use 1 use True use "Hello" - do: + do print case 1: print "one" case "Hello": print "Hello" @@ -599,44 +940,281 @@ various places that `type_err()` are called. a4[1] = True c = a2[3] + bar:foo + foo.c = 43 + print c.foo + print bar.c + print bar.b + 42 + + // trigger 'labels not permitted' error message + while 1 if True else False: + print + case 2: print "two" + ###### output: type_err3 - .tmp.code:4:12: error: expected number but variable 'c' is string - .tmp.code:3:8: info: this is where 'c' was set to string - .tmp.code:4:12: error: Arithmetic returns number but string expected - .tmp.code:3:8: info: variable 'c' was set as string here. - .tmp.code:5:24: error: Boolean operation found where string expected - .tmp.code:6:12: error: Comparison returns Boolean but string expected - .tmp.code:3:8: info: variable 'c' was set as string here. - .tmp.code:7:21: error: Concat returns string but number expected - .tmp.code:8:8: error: string cannot be indexed - .tmp.code:8:8: error: string cannot be indexed - .tmp.code:17:13: error: expected number found string - .tmp.code:13:16: error: expected number, found string - .tmp.code:20:8: error: cannot assign value of type [5]number - .tmp.code:21:13: error: expected [5]number but variable 'a3' is [10]number - .tmp.code:19:36: info: this is where 'a3' was set to [10]number - .tmp.code:21:8: error: cannot assign value of type [5]number - .tmp.code:22:13: error: expected [5]number but variable 'a4' is [5]string - .tmp.code:19:51: info: this is where 'a4' was set to [5]string - .tmp.code:22:8: error: cannot assign value of type [5]number - .tmp.code:23:16: error: expected number found string - .tmp.code:24:16: error: expected string found Boolean - .tmp.code:25:12: error: have number but need string - .tmp.code:3:8: info: variable 'c' was set as string here. + .tmp.code:8:12: error: expected number but variable 'c' is string + .tmp.code:7:8: info: this is where 'c' was set to string + .tmp.code:8:12: error: Arithmetic returns number but string expected + .tmp.code:7:8: info: variable 'c' was set as string here. + .tmp.code:9:24: error: Boolean operation found where string expected + .tmp.code:10:12: error: Comparison returns Boolean but string expected + .tmp.code:7:8: info: variable 'c' was set as string here. + .tmp.code:11:21: error: Concat returns string but number expected + .tmp.code:12:8: error: string cannot be indexed + .tmp.code:12:8: error: string cannot be indexed + .tmp.code:21:13: error: expected number found string + .tmp.code:17:16: error: expected number, found string + .tmp.code:24:8: error: cannot assign value of type [5]number + .tmp.code:25:13: error: expected [5]number but variable 'a3' is [10]number + .tmp.code:23:36: info: this is where 'a3' was set to [10]number + .tmp.code:23:8: info: variable 'a1' was set as [5]number here. + .tmp.code:25:8: error: cannot assign value of type [5]number + .tmp.code:26:13: error: expected [5]number but variable 'a4' is [5]string + .tmp.code:23:51: info: this is where 'a4' was set to [5]string + .tmp.code:23:8: info: variable 'a1' was set as [5]number here. + .tmp.code:26:8: error: cannot assign value of type [5]number + .tmp.code:27:16: error: expected number found string + .tmp.code:28:16: error: expected string found Boolean + .tmp.code:29:12: error: have number but need string + .tmp.code:7:8: info: variable 'c' was set as string here. + .tmp.code:32:8: error: variable used but not declared: foo + .tmp.code:32:8: error: field reference on none is not supported + .tmp.code:32:16: error: expected none found number + .tmp.code:33:14: error: field reference on string is not supported + .tmp.code:34:14: error: cannot find requested field in foo + .tmp.code:35:17: error: have string but need number + .tmp.code:38:29: error: expected number found Boolean oceani: type error in program - not running. ###### test: type_err4 - program: + func main() a:=1; b=2; c::=3 print a, b, c ###### output: type_err4 - .tmp.code:3:14: error: expected *unknown*type* (labels not permitted) but variable 'b' is label - .tmp.code:3:14: info: this is where 'b' was set to label - .tmp.code:3:16: error: expected label found number - .tmp.code:3:14: info: variable 'b' was set as label here. - .tmp.code:4:17: error: expected *unknown*type* (labels not permitted) but variable 'b' is label - .tmp.code:3:14: info: this is where 'b' was set to label + .tmp.code:3:14: error: variable used but not declared: b + .tmp.code:3:16: error: expected none found number + .tmp.code:3:14: info: variable 'b' was set as none here. + oceani: type error in program - not running. + +###### test: type_err5 + struct foo + bar:baz + a:number + struct baz + bat:foo + b:string + struct foo + c:number + +###### output: type_err5 + .tmp.code:8:7: error: type already declared: foo + .tmp.code:2:7: info: this is location of declartion: foo + .tmp.code:2:7: error: type has recursive definition: foo + .tmp.code:5:7: error: type has recursive definition: baz + +###### test: type_err6 + + func main() + a:= "hello" + if ?a: + print "no" + print a ?? "there" + +###### output: type_err6 + .tmp.code:4:12: error: '?' requires a testable value, not string + .tmp.code:6:14: error: "??" requires a testable value, not string + oceani: type error in program - not running. + + +###### test list + oceani_failing_tests += type_err_const type_err_const1 type_err_const2 missing_program bad_main + +###### test: type_err_const + const + foo :: number = 45 + bar ::= "string" + 56 + const + bar ::= "baz" + func main() + foo := 4 + print foo, bar + + // trigger duplicate-main error + func main() + foo := 6 + print bar, foo + +###### output: type_err_const + .tmp.code:6:8: error: name already declared: bar + .tmp.code:4:8: info: this is where 'bar' was first declared + .tmp.code:8:8: error: variable 'foo' redeclared + .tmp.code:3:8: info: this is where 'foo' was first declared + .tmp.code:12:5: error: function 'main' redeclared + .tmp.code:7:5: info: this is where 'main' was first declared + .tmp.code:13:8: error: variable 'foo' redeclared + .tmp.code:3:8: info: this is where 'foo' was first declared + .tmp.code:4:16: error: expected number found string + +###### test: type_err_const1 + const + foo : number = 45 + bar := "string" + func main() + foo := 4 + print foo, bar + +###### output: type_err_const1 + .tmp.code:3:12: Syntax error in constant: : + .tmp.code:4:12: Syntax error in constant: : + +###### test: type_err_const2 + const + four ::= two + two + two ::= four / 2 + +###### output: type_err_const2 + .tmp.code:3:8: error: const four cannot be resolved. + .tmp.code:4:8: error: const two cannot be resolved. + +###### test: missing_program + const + foo::="bar" + +###### output: missing_program + oceani: no main function found. + +###### test: bad_main + func main(foo:string) + print foo + +###### output: bad_main + .tmp.code:2:10: error: expected []string but variable 'foo' is string + .tmp.code:2:10: info: this is where 'foo' was set to string + oceani: main has wrong type. + +Test for type errors with functions + +###### test list + oceani_failing_tests += func_err_args func_err_redeclare + +###### test: func_err_args + + func test1(a:number; b:string; c:[3]Boolean) + print a, b, c[1] + + func test2(a:number; b:string; c:[3]Boolean) + print a, b, c[1] + + func test3() + # use undefined names + print a, z + + func main() + truth:[3]Boolean + truth[1] = True + test1(1,"hello") + test1("hello",1) + test1(1, "two", truth) + test1(1, 2, truth) + test1(1, "lo", truth, 4) + print test(), test1(1,2,3) + if test1 == test2: + pass + + func test4(a:number):string + use a * a + + func test5(a:number):string + print a + + struct foo + a: number + b:string = "hello" + + func test6(a:number):foo + b:foo + b.a = a + use b + +###### output: func_err_args + .tmp.code:34:5: error: function cannot return value of type foo + .tmp.code:28:8: error: expected string, found none + .tmp.code:25:8: error: expected string, found number + .tmp.code:15:14: error: insufficient arguments to function. + .tmp.code:16:14: error: expected number found string + .tmp.code:16:22: error: expected string found number + .tmp.code:16:14: error: insufficient arguments to function. + .tmp.code:18:17: error: expected string found number + .tmp.code:19:14: error: too many arguments to function. + .tmp.code:20:14: error: attempt to call a non-function. + .tmp.code:20:32: error: expected string found number + .tmp.code:20:28: error: insufficient arguments to function. + .tmp.code:21:20: error: expected "func test1" but variable 'test2' is "func test2" + .tmp.code:5:5: info: this is where 'test2' was set to "func test2" + .tmp.code:10:14: error: variable used but not declared: a + .tmp.code:10:17: error: variable used but not declared: z + oceani: type error in program - not running. + +###### test: func_err_redeclare + + func test1(a:number; b:string; c:[3]Boolean) + print a, b, c[1] + + func test1 + do + pass + + func test1 + b:Boolean + do + pass + +###### output: func_err_redeclare + .tmp.code:5:5: error: function 'test1' redeclared + .tmp.code:2:5: info: this is where 'test1' was first declared + .tmp.code:9:5: error: function 'test1' redeclared + .tmp.code:2:5: info: this is where 'test1' was first declared + +Test for errors with references + +###### test list + oceani_failing_tests += ref_err1 ref_err2 + +###### test: ref_err1 + func main() + ref:@number + @foo = ref + ref = @old() + if ref == @null: + print "null" + +###### output: ref_err1 + .tmp.code:4:9: error: only "@free" makes sense here: foo + .tmp.code:5:15: error: Only reference function is "@new()": old + .tmp.code:6:19: error: Only reference value is "@nil": null + +###### test: ref_err2 + func main() + ref:@number + ref2:@string + num:number = @new() + print num@ + if num == @nil or ref == ref2 or ref == 2 or ref.foo: + @free = num + +###### output: ref_err2 + .tmp.code:5:22: error: @new() can only be used with references, not number + .tmp.code:5:8: info: variable 'num' was set as number here. + .tmp.code:6:14: error: Cannot dereference number + .tmp.code:7:19: error: @nil can only be used with reference, not number + .tmp.code:7:33: error: expected @number but variable 'ref2' is @string + .tmp.code:4:8: info: this is where 'ref2' was set to @string + .tmp.code:7:48: error: expected @number found number + .tmp.code:7:53: error: field reference on number is not supported + .tmp.code:7:56: error: have none but need Boolean + .tmp.code:8:17: error: @free can only be assigned a reference, not number + .tmp.code:8:17: error: @free can only be assigned a reference, not number oceani: type error in program - not running. ## Test erroneous command line args @@ -660,7 +1238,19 @@ command list possible. echo "passed"; \ ./coverage_oceani $${1+"$$@"} > /dev/null 2>&1 ;\ done || true - +###### valgrind test code + @[ -n "$$SKIP_VALGRIND" ] || for t in $(oceani_special_tests); do\ + echo -n "Valgrind $$t.. "; \ + i="$$IFS"; IFS=,; set $$t; IFS="$$i"; shift ;\ + if valgrind --error-exitcode=42 --log-file=.tmp.valg ./oceani $${1+"$$@"} > .tmp.have 2>&1 ;\ + [ $$? -eq 42 ]; then \ + echo "FAILED"; cat .tmp.valg; exit 1; fi ; \ + if grep 'LEAK SUMMARY' .tmp.valg > /dev/null; then \ + echo "valgrind found LEAKS"; cat .tmp.valg ; exit 1 ; fi; \ + if grep 'in use at exit [1-9]' .tmp.valg > /dev/null; then \ + echo "valgrind found memory in use at exit"; cat .tmp.valg ; exit 1 ; fi; \ + echo " passed"; \ + done ###### test list oceani_special_tests += "cmd" @@ -674,7 +1264,7 @@ command list possible. ###### output: cmd,-zyx ./oceani: invalid option -- 'z' - Usage: oceani --trace --print --noexec --brackets--section=SectionName prog.ocn + Usage: oceani --trace --print --noexec --brackets --section=SectionName prog.ocn ###### output: cmd,nofile oceani: cannot open nofile @@ -684,4 +1274,3 @@ command list possible. ###### output: cmd,--section,toast:nothing,oceani-tests.mdc oceani: cannot find section toast:nothing -