diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/drivers/lsp_test.js | 12 | ||||
| -rw-r--r-- | tests/drivers/runtime_image_test.py | 2 | ||||
| -rw-r--r-- | tests/programs/capture_long.zc | 26 | ||||
| -rw-r--r-- | tests/programs/struct_static_call.zc | 31 | ||||
| -rw-r--r-- | tests/programs/void_main.zc | 8 | ||||
| -rwxr-xr-x | tests/test.sh | 5 |
6 files changed, 84 insertions, 0 deletions
diff --git a/tests/drivers/lsp_test.js b/tests/drivers/lsp_test.js index 0f4abe1..2ad9181 100644 --- a/tests/drivers/lsp_test.js +++ b/tests/drivers/lsp_test.js @@ -199,6 +199,18 @@ const tmsrc = 'struct point {\n\tlet x;\n\t// the sum of the parts\n\tint sum(in hv = hover(tmsrc, 7, at(tmsrc, 7, 'sum')); check(hv && hv.includes('int sum(int k)') && hv.includes('the sum of the parts'), 'a typed method shows its return type and parameters', hv); +// members of the embedded standard library hover like the document's own: the group's static +// function, the group, and a top-level function, each with the comment from std.zc +const stdsrc = 'include rt, std;\nfn main() { char[24] b; rt.put_s(std.Text.itoa(5, b)); return std.array_contains; }\n'; +hv = hover(stdsrc, 1, at(stdsrc, 1, 'itoa')); +check(hv && hv.includes('static int itoa(int n, char* dst)') && hv.includes('writes n in decimal into dst'), 'hover on a std group function shows its signature and doc from std.zc', hv); +hv = hover(stdsrc, 1, at(stdsrc, 1, 'Text')); +check(hv && hv.includes('struct Text') && hv.includes('helpers for char* strings'), 'hover on a std group shows the comment of the group', hv); +hv = hover(stdsrc, 1, at(stdsrc, 1, 'array_contains')); +check(hv && hv.includes('array_contains<T>') && hv.includes('true when an element equals value'), 'hover on a top-level std function shows its doc', hv); +hv = hover(stdsrc, 1, at(stdsrc, 1, 'put_s')); +check(hv && hv.includes('int put_s(char* s)'), 'hover on a runtime function still works beside the std ones', hv); + // externs are declarations, so they draw no "never reassigned" hint const ext = 'extern double sqrt(double);\nextern double pow(double x, double y);\nfn main() {\n\treturn 0;\n}\n'; r = run([init(1), open(A, ext)]); diff --git a/tests/drivers/runtime_image_test.py b/tests/drivers/runtime_image_test.py index d214613..6c44349 100644 --- a/tests/drivers/runtime_image_test.py +++ b/tests/drivers/runtime_image_test.py @@ -18,6 +18,8 @@ cases = [ ('enhancements', 'include rt; fn main() { rt.put_n(17 % 5); rt.put_c(32); rt.put_n(17 / 5); }', b'2 3'), ('array algorithms', Path('examples/learn/31-array-algorithms.zc').read_text(), Path('examples/learn/31-array-algorithms.out').read_bytes()), ('owned pop', 'include rt; int*.u take() { int*[?] a = rt.new(int*[?]); int* p = rt.new(int); *p = 8; a.push(p); return a.pop(); } fn main() { let p = take(); rt.put_n(rt.isobj(p)); rt.put_c(32); rt.put_n(*p); }', b'1 8'), + # main may be void: run.zc's prototype of main must not fix its type (docs/SPEC.md 5.2.5) + ('void main', Path('tests/programs/void_main.zc').read_text(), b'void main\n'), ] prefix = b''.join(Path(f).read_bytes() + b'\n' for f in ['src/runtime/rt.zc', 'src/core/core.zc', 'src/runtime/run.zc']) for name, source, expected in cases: diff --git a/tests/programs/capture_long.zc b/tests/programs/capture_long.zc new file mode 100644 index 0000000..52736a4 --- /dev/null +++ b/tests/programs/capture_long.zc @@ -0,0 +1,26 @@ +namespace; +include rt, std; + +// a capture holds 256 characters and drops the rest. end() must still put its +// 0 inside the buffer, even when the capture was full: the length is 256 and the +// last kept character is the 256th one written (index 255, 'a' + 255 % 26 = 'v'). +// a block allocated right after the buffer is checked afterwards: a 0 written one +// word past the buffer would land in its header and read as a bad or freed block. +memdebug on; // header checks make a write into a neighbouring block visible +fn capture_long() { + let buf = std.capture.start(); + int* next = rt.new(8); + int i = 0; + while (i < 300) { rt.put_c('a' + i % 26); i++; } + std.capture.end(buf); + next[0] = 7; // stops with "bad heap pointer" if its header was overwritten + rt.put_n(next[0]); rt.put_c(10); // 7 + return buf; +} +memdebug off; // the header check only searches 64 words back, so the long buffer is read unchecked +fn main() { + char* buf = capture_long(); + rt.put_n(rt.len_w(buf)); rt.put_c(10); // 256 + rt.put_c(buf[255]); rt.put_c(10); // v + return 0; +} diff --git a/tests/programs/struct_static_call.zc b/tests/programs/struct_static_call.zc new file mode 100644 index 0000000..73fc0fc --- /dev/null +++ b/tests/programs/struct_static_call.zc @@ -0,0 +1,31 @@ +namespace; +include rt; + +// a static function of a struct can be called by its bare name inside the struct's +// methods and static functions, as a struct constant can. the struct's own function +// wins over a top-level one of the same name; outside the struct only S.name reaches it. +int lim() { return 100; } +int base() { return 7; } + +struct S { + int v; + static int lim() { return 3; } + static int twice(int x) { return x * 2; } + static int both() { return lim() + twice(4); } + int get() { return lim() + this.v; } + int scaled() { return twice(this.v) + later(); } + int top() { return base(); } + static int later() { return 1000; } +} + +int main() { + S s; + s.v = 5; + rt.put_n(S.lim()); rt.put_c(32); // 3 + rt.put_n(lim()); rt.put_c(32); // 100, the global one + rt.put_n(S.both()); rt.put_c(32); // 3 + 8 + rt.put_n(s.get()); rt.put_c(32); // 3 + 5 + rt.put_n(s.scaled()); rt.put_c(32); // 10 + 1000, a static function declared later + rt.put_n(s.top()); rt.put_c(10); // 7, a global that the struct has no member of + return 0; +} diff --git a/tests/programs/void_main.zc b/tests/programs/void_main.zc new file mode 100644 index 0000000..b4fde70 --- /dev/null +++ b/tests/programs/void_main.zc @@ -0,0 +1,8 @@ +namespace; +include rt; + +// main may be declared void: the runtime ignores what main returns (docs/SPEC.md 5.2.5, 8.1.3), +// so a run-only image, whose run.zc declares int main();, accepts it as zy does. +void main() { + rt.put_s("void main"); rt.put_c(10); +} diff --git a/tests/test.sh b/tests/test.sh index 298c356..c800e8f 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -128,6 +128,7 @@ run(){ # $1 = vm command, $2 = label chk "$($vm < tests/programs/genmeth.zc | md5sum)" "$(md5sum < tests/programs/genmeth.expected)" "$l methods of generic structs are compiled per type arguments" chk "$($vm < tests/programs/static.zc)" "14 5 9" "$l static functions of a struct are called as Struct.name(args)" chk "$($vm < tests/programs/struct_const.zc)" "24 49 24 23 19 55 12 99" "$l constants declared in a struct are reached as Struct.NAME, and by bare name in its methods" + chk "$($vm < tests/programs/struct_static_call.zc)" "3 100 11 8 1010 7" "$l a static function of a struct is called by its bare name in its methods, and wins over a global of the same name" chk "$($vm < tests/programs/methodown.zc)" "7 9" "$l struct methods and functions return owned objects (.u)" chk "$($vm < tests/programs/typedmethods.zc)" "14 5 13" "$l struct methods declare a return type and typed parameters" chk "$($vm < tests/programs/enumscope.zc)" "0 5 6 blue" "$l enum members are reached as Enum.MEMBER, also in a case" @@ -158,6 +159,9 @@ hello world!42 1 1 0" "$l capture.start() collects output and end() hands back the string" + chk "$($vm < tests/programs/capture_long.zc)" "7 +256 +v" "$l a full capture is still terminated inside its buffer" chk "$($vm < tests/programs/sys.zc)" "2 zy time" "$l syscalls: write, read, time" chk "$($vm < tests/programs/memleak.zc)" $'leak: line 8 3 words\n1' "$l memdebug names a live allocation" chk "$($vm < tests/programs/uaf.zc)" $'zc: line 10: warning: use after free: this storage\'s lifetime ended on line 9\nzy: use after free from line 7' "$l memdebug: use after free" @@ -353,6 +357,7 @@ s_runonly() { runonly wide tests/programs/wide.zc runonly selfpatch examples/selfpatch.zc runonly gc tests/programs/gc.zc + runonly voidmain tests/programs/void_main.zc runonly float tests/programs/float.zc runonly ftruth tests/programs/ftruth.zc runonly ftext tests/programs/ftext.zc |
