aboutsummaryrefslogtreecommitdiff
path: root/tests/drivers/stack_growth_test.py
blob: 3c90305fc71d6b643f0db97e5f102219b0f05010 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/usr/bin/env python3
# operand values and return addresses survive explicit and automatic growth.
import subprocess
import sys
import tempfile
from pathlib import Path
sys.dont_write_bytecode = True  # importing imagekit must not leave __pycache__ in the tree
from imagekit import compiler

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.
        Path('build').mkdir(exist_ok=True)
        with tempfile.TemporaryDirectory(prefix='stack-image-', dir='build') as directory:
            target = Path(directory)
            subprocess.run(['build/bin/genmap', '--preset', 'run', '--grow', '--heap', '1048576', '--genome', '131072', '--frame', '4096', '--return', '256', '--data', '3072', '-o', directory], check=True, capture_output=True)
            zc0 = target / 'zc0'
            subprocess.run([compiler(), '-O1', '-w', '-fwrapv', 'src/tools/zc0.c', '-I' + directory, '-Isrc/core', '-o', str(zc0)], check=True, capture_output=True)
            full_source = (target / 'rt.zc').read_text() + Path('src/core/core.zc').read_text() + Path('src/runtime/run.zc').read_text() + source
            image = subprocess.run([str(zc0)], input=full_source.encode(), capture_output=True, check=True)
            (target / 'genome.bin').write_bytes(image.stdout)
            result = subprocess.run(['node', 'tests/drivers/image_run.js', str(target / 'genome.bin'), 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('''namespace;
include rt;
fn main() {
 int old_data = rt.data_top - rt.data_low, old_return = rt.return_top - rt.return_low;
 rt.put_n(rt.reserve_data(old_data + 1) > old_data); rt.put_c(32);
 rt.put_n(rt.reserve_returns(old_return + 1) > old_return); rt.put_c(32);
 rt.gc(); rt.put_n(rt.data_node != 0 && rt.return_node != 0); rt.put_c(10); return 0;
}
''', '1 1 1\n')

run('''namespace;
include rt;
fn main() {
 rt.put_n(rt.reserve_data(-1) == -1); rt.put_c(32); rt.put_n(rt.reserve_returns(-1) == -1); rt.put_c(32);
 rt.put_n(rt.syscall(9, 6, 0, 0) == -1); rt.put_c(32);
 int current = rt.syscall(9, 0, 0, 0); rt.syscall(9, 5, current, 0);
 rt.put_n(rt.reserve_data(0x10000000) == -1); rt.put_c(32); rt.gc(); rt.put_n(7); rt.put_c(10); return 0;
}
''', '1 1 1 1 7\n')

count = 40000
source = 'namespace; include rt; fn main() { int total = asm { ' + ' '.join(str(i + 1) for i in range(count))
source += ' + ' * (count - 1) + ' }; rt.gc(); rt.put_n(total); rt.put_c(32); '
source += 'rt.put_n(rt.data_node != 0); rt.put_c(10); return 0; }\n'
run(source, '800020000 1\n', compile_image=True)

run('''namespace;
include rt;
unchecked int descend(int n) {
 if (!n) { rt.gc(); return 7; }
 return descend(n - 1) + 1;
}
fn main() { rt.put_n(descend(70000)); rt.put_c(32); rt.put_n(rt.return_node != 0); rt.put_c(10); return 0; }
''', '70007 1\n', compile_image=True)
print('ok   explicit reservation, 40000 operands, and 70000 return addresses: ' + command[0])