aboutsummaryrefslogtreecommitdiff
path: root/tests/drivers/stack_growth_test.py
diff options
context:
space:
mode:
authorGravatar Moon Flower <moonflower@elhenney.local> 2026-10-12 08:46:23 +0330
committerGravatar Moon Flower <moonflower@elhenney.local> 2026-10-12 08:46:23 +0330
commitecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 (patch)
tree70e0af76a1b13affff7c6cc8aac7b3e6ef960478 /tests/drivers/stack_growth_test.py
a
Diffstat (limited to 'tests/drivers/stack_growth_test.py')
-rw-r--r--tests/drivers/stack_growth_test.py58
1 files changed, 58 insertions, 0 deletions
diff --git a/tests/drivers/stack_growth_test.py b/tests/drivers/stack_growth_test.py
new file mode 100644
index 0000000..d4abe81
--- /dev/null
+++ b/tests/drivers/stack_growth_test.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# operand values and return addresses survive explicit and automatic growth.
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+
+command = sys.argv[1:]
+
+
+def run(source, expected, compile_image=False):
+ if compile_image and command[0] == 'node':
+ # compile the execution stress cases once with stage 0, so a javascript
+ # compiler's speed does not determine the execution-test timeout.
+ with tempfile.TemporaryDirectory(prefix='stack-image-', dir='build') as directory:
+ target = Path(directory)
+ subprocess.run(['bin/genmap', '--preset', 'run', '--grow', '--heap', '1048576', '--genome', '131072', '--frame', '4096', '--return', '256', '--data', '3072', '-o', directory], check=True, capture_output=True)
+ compiler = target / 'zc0'
+ subprocess.run(['cc', '-O1', '-w', '-fwrapv', 'src/tools/zc0.c', '-I' + directory, '-Isrc/core', '-o', str(compiler)], check=True, capture_output=True)
+ full_source = (target / 'rt.zc').read_text() + Path('src/runtime/run.zc').read_text() + source
+ image = subprocess.run([str(compiler)], input=full_source, text=True, capture_output=True, check=True)
+ header = target / 'genome.h'
+ header.write_text(image.stdout)
+ result = subprocess.run(['node', 'tests/drivers/image_run.js', str(header), str(target / 'memmap.h')], text=True, capture_output=True, timeout=45)
+ else:
+ result = subprocess.run(command, input=source, text=True, capture_output=True, timeout=45)
+ assert result.returncode == 0 and result.stdout == expected, (command, result.returncode, result.stdout, result.stderr)
+
+
+run('''fn main() {
+ int old_data = data_top - data_low, old_return = return_top - return_low;
+ put_n(reserve_data(old_data + 1) > old_data); put_c(32);
+ put_n(reserve_returns(old_return + 1) > old_return); put_c(32);
+ gc(); put_n(data_node != 0 && return_node != 0); put_c(10); return 0;
+}
+''', '1 1 1\n')
+
+run('''fn main() {
+ put_n(reserve_data(-1) == -1); put_c(32); put_n(reserve_returns(-1) == -1); put_c(32);
+ put_n(syscall(9, 6, 0, 0) == -1); put_c(32);
+ int current = syscall(9, 0, 0, 0); syscall(9, 5, current, 0);
+ put_n(reserve_data(0x10000000) == -1); put_c(32); gc(); put_n(7); put_c(10); return 0;
+}
+''', '1 1 1 1 7\n')
+
+count = 40000
+source = 'fn main() { int total = asm { ' + ' '.join(str(i + 1) for i in range(count))
+source += ' + ' * (count - 1) + ' }; gc(); put_n(total); put_c(32); '
+source += 'put_n(data_node != 0); put_c(10); return 0; }\n'
+run(source, '800020000 1\n', compile_image=True)
+
+run('''unchecked int descend(int n) {
+ if (!n) { gc(); return 7; }
+ return descend(n - 1) + 1;
+}
+fn main() { put_n(descend(70000)); put_c(32); put_n(return_node != 0); put_c(10); return 0; }
+''', '70007 1\n', compile_image=True)
+print('ok explicit reservation, 40000 operands, and 70000 return addresses: ' + command[0])