]> ocean-lang.org Git - ocean/blob - csrc/oceani-tests.mdc
oceani-tests: add test suite.
[ocean] / csrc / oceani-tests.mdc
1 # Ocean Interpreter test code
2
3 Regular testing is, of course, important for developing any software.
4 The Ocean interpreted is no exception.  This document allows easy
5 testing by providing:
6
7 - a collection of test program
8 - the expected output of these programs when run with various arguments
9 - some "Makefile" code to tie it all together.
10
11 Three different sorts of tests are run.  As soon as any fail, the whole
12 test stops.
13
14 1/ Each program is run and the output is compared against the expected
15     output
16 2/ Each program is then run under valgrind, and an error is reported
17     if valgrind detects an error, or if it reports and lost or unfreed
18     memory.
19 3/ Each program is parsed and printed, then the result is parsed and printed.
20     The two results must match.
21 4/ Each program is run with a version of `oceani` with test-coverage
22     recording enabled.  Once all programs have successfully run and
23     all the coverage data is available, we check that all lines have
24     been tested at least once. A few exceptions are allowed such as
25     lines that call `abort()`.  If any non-exceptional lines have not
26     been run, this final test fails.
27     Until the tests suite is (more) completed, we only throw and error
28     if fewer than 75% of the lines have been tested.
29
30 Each test has a name, which used to identify the section in this file, and optionally some
31 arguments separated from the name by commas.  For each test, there is a section named
32 "output:" followed by the name-and-arguments.
33
34 ###### File: oceani-tests.mk
35
36         oceani_tests :=
37
38         tests:: oceani_test_suite
39         oceani_test_suite: oceani coverage_oceani
40                 @rm -rf coverage; mkdir -p coverage
41                 @cp *.gcno coverage
42                 @for T in $(oceani_tests); do \
43                     echo -n "Test $$T ... "; \
44                     i="$$IFS"; IFS=,; set $$T; IFS="$$i"; t=$$1; shift; \
45                     ./md2c oceani-tests.mdc "output: $$T" | grep -v '^#' > .tmp.want; \
46                     ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} > .tmp.have; \
47                     if ! cmp -s .tmp.want .tmp.have; then \
48                        echo "FAILED"; diff -u .tmp.want .tmp.have ; exit 1; fi ;\
49                     echo -n "passed ... "; \
50                     if ! valgrind ./oceani --section "test: $$t" oceani-tests.mdc $${1+"$$@"} \
51                          > /dev/null 2> .tmp.valg; then \
52                        echo "valgrind FAILED"; cat .tmp.valg; exit 1; fi ; \
53                     echo -n "valgrind passed ... "; \
54                     echo '``````' > .tmp.code1; echo '``````' > .tmp.code2 ;\
55                     ./oceani --noexec --print --section "test: $$t" oceani-tests.mdc >> .tmp.code1; \
56                     ./oceani --noexec --print .tmp.code1 >> .tmp.code2 ;\
57                     if ! cmp -s .tmp.code1 .tmp.code2; then \
58                        echo "Printing Failed"; diff -u .tmp.code1 .tmp.code2; exit1 ; fi ; \
59                     echo "Printing passed"; \
60                     ./coverage_oceani --print --section "test: $$t" oceani-tests.mdc $${1+"$$@"} > /dev/null ; \
61                     ./coverage_oceani -tpbn --section "test: $$t" oceani-tests.mdc > /dev/null 2>&1; \
62                 done
63                 @gcov -o coverage oceani.mdc > /dev/null 2> /dev/null
64                 @mv *.gcov coverage ; [ -f .gcov ] && mv .gcov coverage
65                 @ awk '/^ *[1-9]/ {ran+=1} /^ *###/ {skip+=1} \
66                     END {printf "coverage: %6.2f%%\n", ran * 100 / (ran + skip); \
67                          if (ran < (ran + skip) *0.75) exit(1) }' \
68                         coverage/oceani.mdc.gcov
69                 @rm -f .tmp*
70
71         coverage_oceani: oceani.c
72                 $(CC) $(CFLAGS) --coverage -fprofile-dir=coverage -o coverage_oceani oceani.c $(LDLIBS)
73
74         ## test list
75
76 ## Values and variables
77
78 The first test stores values in variables and performs various
79 calculations on them.
80
81 ###### test list
82        oceani_tests += "valvar"
83
84
85 ###### test: valvar
86
87         program:
88                 a := 23; b:=12
89                 print a, b, a+b, a-b, a*b, a/b, a%b
90                 print a<b, a<=b, a>b, a>=b, a<a, a==b, a==a
91
92                 c ::= "This is a string"
93                 d ::= " field theory"
94                 print c, d, c++d
95
96 ###### output: valvar
97
98         23 12 35 11 276 1.91667 11
99         False False True True False False True
100         This is a string  field theory This is a string field theory
101
102 Next we change the value of variables
103
104 ###### test list
105        oceani_tests += "setvar"
106
107 ###### test: setvar
108
109         program:
110                 a := 4
111                 a = a * a
112                 a = (a + a) * (a + a)
113                 a = a * a * a
114                 print a, a/a
115
116 ###### output: setvar
117         1.07374e+09 1
118
119 ## Conditions and Loops
120
121 Now we need to test if/else and some different loops
122
123 ###### test list
124        oceani_tests += cond_loop
125
126 ###### test: cond_loop
127
128         program:
129                 a := 4
130                 if a < 5:
131                         print "Success"
132                 else:
133                         print "Failure"
134                 for b:=1; then b=b+b; while b < 100:
135                         print '', b,
136                 print
137                 // Newtons method for square root of 2
138                 target ::= 2
139                 guess := target
140                 for:
141                         count: number = 0
142                 while:
143                         current := guess * guess
144                         use +(current - target) > 0.000000001
145                 do:
146                         guess = (guess + (target / guess) ) / 2
147                         print count, guess
148                         count = count + 1
149                 print "error is ", target - guess * guess
150
151 ###### output: cond_loop
152         Success
153          1 2 4 8 16 32 64
154         0 1.5
155         1 1.41667
156         2 1.41422
157         3 1.41421
158         error is  -4.51095e-12
159
160 ## Say Hello
161
162 The demonstration code presented in the interpreted is suitable for the test suite.
163 Here I break it into two parts, keeping the array code separate.
164
165 ###### test list
166         oceani_tests += "sayhello,55,33"
167         oceani_tests += "sayhello,12,60"
168
169 ###### test: sayhello
170
171         program A B:
172                 print "Hello World, what lovely oceans you have!"
173                 /* When a variable is defined in both branches of an 'if',
174                  * and used afterwards, the variables are merged.
175                  */
176                 if A > B:
177                         bigger := "yes"
178                 else:
179                         bigger := "no"
180                 print "Is", A, "bigger than", B,"? ", bigger
181                 /* If a variable is not used after the 'if', no
182                  * merge happens, so types can be different
183                  */
184                 if A > B * 2:
185                         double:string = "yes"
186                         print A, "is more than twice", B, "?", double
187                 else:
188                         double := B*2
189                         print "double", B, "is", double
190
191                 a : number
192                 a = A;
193                 b:number = B
194                 if a > 0 and b > 0:
195                         while a != b:
196                                 if a < b:
197                                         b = b - a
198                                 else:
199                                         a = a - b
200                         print "GCD of", A, "and", B,"is", a
201                 else if a <= 0:
202                         print a, "is not positive, cannot calculate GCD"
203                 else:
204                         print b, "is not positive, cannot calculate GCD"
205
206                 for:
207                         togo := 10
208                         f1 := 1; f2 := 1
209                         print "Fibonacci:", f1,f2,
210                 then togo = togo - 1
211                 while togo > 0:
212                         f3 := f1 + f2
213                         print "", f3,
214                         f1 = f2
215                         f2 = f3
216                 print ""
217
218                 /* Binary search... */
219                 for:
220                         lo:= 0; hi := 100
221                         target := 77
222                 while:
223                         mid := (lo + hi) / 2
224                         if mid == target:
225                                 use Found
226                         if mid < target:
227                                 lo = mid
228                         else:
229                                 hi = mid
230                         if hi - lo < 1:
231                                 use GiveUp
232                         use True
233                 do: pass
234                 case Found:
235                         print "Yay, I found", target
236                 case GiveUp:
237                         print "Closest I found was", mid
238
239 ###### output: sayhello,55,33
240         Hello World, what lovely oceans you have!
241         Is 55 bigger than 33 ?  yes
242         double 33 is 66
243         GCD of 55 and 33 is 11
244         Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144
245         Closest I found was 77.3438
246
247 ###### output: sayhello,12,60
248         Hello World, what lovely oceans you have!
249         Is 12 bigger than 60 ?  no
250         double 60 is 120
251         GCD of 12 and 60 is 12
252         Fibonacci: 1 1 2 3 5 8 13 21 34 55 89 144
253         Closest I found was 77.3438
254
255 ###### test list
256         oceani_tests += "insert_sort"
257 ###### test: insert_sort
258         program:
259                 size::=55
260                 list:[size]number
261                 list[0] = 1234
262                 for i:=1; then i = i + 1; while i < size:
263                         n := list[i-1] * list[i-1]
264                         list[i] = (n / 100) % 10000
265
266                 print "Before sort:"
267                 for i:=0; then i = i + 1; while i < size:
268                         print "list[",i,"]=",list[i]
269
270                 for i := 1; then i=i+1; while i < size:
271                         for j:=i-1; then j=j-1; while j >= 0:
272                                 if list[j] > list[j+1]:
273                                         t:= list[j]
274                                         list[j] = list[j+1]
275                                         list[j+1] = t
276                 print "After sort:"
277                 for i:=0; then i = i + 1; while i < size:
278                         print "list[",i,"]=",list[i]
279
280 ###### output: insert_sort
281         Before sort:
282         list[ 0 ]= 1234
283         list[ 1 ]= 5227
284         list[ 2 ]= 3215
285         list[ 3 ]= 3362
286         list[ 4 ]= 3030
287         list[ 5 ]= 1809
288         list[ 6 ]= 2724
289         list[ 7 ]= 4201
290         list[ 8 ]= 6484
291         list[ 9 ]= 422
292         list[ 10 ]= 1780
293         list[ 11 ]= 1684
294         list[ 12 ]= 8358
295         list[ 13 ]= 8561
296         list[ 14 ]= 2907
297         list[ 15 ]= 4506
298         list[ 16 ]= 3040
299         list[ 17 ]= 2416
300         list[ 18 ]= 8370
301         list[ 19 ]= 569
302         list[ 20 ]= 3237
303         list[ 21 ]= 4781
304         list[ 22 ]= 8579
305         list[ 23 ]= 5992
306         list[ 24 ]= 9040
307         list[ 25 ]= 7216
308         list[ 26 ]= 706
309         list[ 27 ]= 4984
310         list[ 28 ]= 8402
311         list[ 29 ]= 5936
312         list[ 30 ]= 2360
313         list[ 31 ]= 5696
314         list[ 32 ]= 4444
315         list[ 33 ]= 7491
316         list[ 34 ]= 1150
317         list[ 35 ]= 3225
318         list[ 36 ]= 4006
319         list[ 37 ]= 480
320         list[ 38 ]= 2304
321         list[ 39 ]= 3084
322         list[ 40 ]= 5110
323         list[ 41 ]= 1121
324         list[ 42 ]= 2566
325         list[ 43 ]= 5843
326         list[ 44 ]= 1406
327         list[ 45 ]= 9768
328         list[ 46 ]= 4138
329         list[ 47 ]= 1230
330         list[ 48 ]= 5129
331         list[ 49 ]= 3066
332         list[ 50 ]= 4003
333         list[ 51 ]= 240
334         list[ 52 ]= 576
335         list[ 53 ]= 3317
336         list[ 54 ]= 24
337         After sort:
338         list[ 0 ]= 24
339         list[ 1 ]= 240
340         list[ 2 ]= 422
341         list[ 3 ]= 480
342         list[ 4 ]= 569
343         list[ 5 ]= 576
344         list[ 6 ]= 706
345         list[ 7 ]= 1121
346         list[ 8 ]= 1150
347         list[ 9 ]= 1230
348         list[ 10 ]= 1234
349         list[ 11 ]= 1406
350         list[ 12 ]= 1684
351         list[ 13 ]= 1780
352         list[ 14 ]= 1809
353         list[ 15 ]= 2304
354         list[ 16 ]= 2360
355         list[ 17 ]= 2416
356         list[ 18 ]= 2566
357         list[ 19 ]= 2724
358         list[ 20 ]= 2907
359         list[ 21 ]= 3030
360         list[ 22 ]= 3040
361         list[ 23 ]= 3066
362         list[ 24 ]= 3084
363         list[ 25 ]= 3215
364         list[ 26 ]= 3225
365         list[ 27 ]= 3237
366         list[ 28 ]= 3317
367         list[ 29 ]= 3362
368         list[ 30 ]= 4003
369         list[ 31 ]= 4006
370         list[ 32 ]= 4138
371         list[ 33 ]= 4201
372         list[ 34 ]= 4444
373         list[ 35 ]= 4506
374         list[ 36 ]= 4781
375         list[ 37 ]= 4984
376         list[ 38 ]= 5110
377         list[ 39 ]= 5129
378         list[ 40 ]= 5227
379         list[ 41 ]= 5696
380         list[ 42 ]= 5843
381         list[ 43 ]= 5936
382         list[ 44 ]= 5992
383         list[ 45 ]= 6484
384         list[ 46 ]= 7216
385         list[ 47 ]= 7491
386         list[ 48 ]= 8358
387         list[ 49 ]= 8370
388         list[ 50 ]= 8402
389         list[ 51 ]= 8561
390         list[ 52 ]= 8579
391         list[ 53 ]= 9040
392         list[ 54 ]= 9768
393