source: trunk/jrun/run-tests.php @ 1184

Revision 993, 4.1 KB checked in by strat.cristian@…, 3 years ago (diff)

Experimental Python Support

This is highly experimental, potentially unsafe. I only enabled it for admins until it's stable.

  • Bash script to compile and link static binaries from Python scripts.
  • Additional unit tests for jrun. (Added several Python test cases.)
  • UI changes for admins only.
  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1#! /usr/bin/env php
2<?php
3
4require_once(dirname($argv[0]) . "/../config.php");
5require_once(IA_ROOT_DIR . 'eval/config.php');
6require_once(IA_ROOT_DIR . 'common/log.php');
7
8// Config options.
9$jail_dir = "jail";
10$exe_name = "prog";
11$extra_args = "--block-syscalls-file=bad_syscalls --verbose";
12//$extra_args = "--nice -5 --block-syscalls-file=bad_syscalls --verbose";
13//$extra_args = "--uid 65534 --gid 65534 --block-syscalls-file=bad_syscalls --chroot";
14//$extra_args = "--uid 65534 --gid 65534 --block-syscalls-file=bad_syscalls";
15
16// In order to run python tests, download a python distribution, configure,
17// make, make install, then specify the top level directory here.
18$py_compiler = IA_ROOT_DIR."scripts/pybin.sh ".IA_JUDGE_PY_DISTRO
19        ." {$jail_dir}";
20
21// Parse a source file
22// Returns the arguments to run the jail with and the expected response.
23// test_exp_res is a posix regex that should match the jail run response.
24function parse_source($filename, &$test_args, &$test_exp_res)
25{
26    $test_args = $test_exp_res = null;
27    foreach (file("$filename") as $line) {
28        if (preg_match("/(?:\/\/|#) JRUN_ARGS =(.*)$/", $line, $matches)) {
29            $test_args = trim($matches[1]);
30        }
31        if (preg_match("/(?:\/\/|#) JRUN_RES =(.*)$/", $line, $matches)) {
32            $test_exp_res = trim($matches[1]);
33        }
34    }
35    if ($test_args === null || $test_exp_res === null) {
36        log_error("$filename doesn't mention JRUN_ARGS and JRUN_RES\n");
37    }
38}
39
40function compile_source($source, $exe)
41{
42    global $py_compiler;
43    if (strpos($source, ".cpp") === strlen($source) - 4) {
44        system("g++ -Wall -lm -O2 $source --static -o $exe", $ret);
45    } else if (strpos($source, ".c") === strlen($source) - 2) {
46        system("gcc -Wall -lm -O2 $source --static -o $exe", $ret);
47    } else if (strpos($source, ".py") === strlen($source) - 3) {
48        system("{$py_compiler} $source $exe", $ret);
49    } else {
50        log_error("Can't compile $source, unknown file extension\n");
51    }
52    if ($ret) {
53        log_error("Compilation error on $source\n");
54    }
55}
56
57// Do a jail run.
58// This will compile $filename in $jail_dir and jrun with the
59// specified args. Returns jail output.
60function jail_run($filename, $args)
61{
62    global $jail_dir, $exe_name;
63
64    system("rm -rf $jail_dir");
65    system("mkdir -p $jail_dir");
66    system("chmod 777 $jail_dir");
67    compile_source($filename, "$jail_dir/$exe_name");
68    $cmd = "./jrun --dir=$jail_dir --prog=$exe_name $args";
69
70    log_print("Running $cmd");
71    $res = shell_exec($cmd);
72    system("rm -rf $jail_dir");
73    return trim($res);
74}
75
76// Run one test.
77// Returns true/false on success/failure.
78function run_test($filename)
79{
80    global $extra_args;
81
82    if (!file_exists($filename)) {
83        log_error("$filename doesn't exists.\n");
84    }
85
86    parse_source($filename, &$test_args, &$test_exp_res);
87    $test_res = jail_run($filename, "$test_args $extra_args");
88
89    if (!preg_match("/^$test_exp_res$/", $test_res)) {
90        $result = false;
91        print("FAIL: $filename\n");
92        print("wanted: $test_exp_res\n");
93        print("got: $test_res\n");
94    } else {
95        $result = true;
96        print("OK: $filename\n");
97        print("got: $test_res\n");
98    }
99
100    return $result;
101}
102
103// Main function.
104function run_all()
105{
106    $tests_total = $tests_failed = 0;
107    $failed_names = array();
108
109    foreach (glob("tests/*") as $filename) {
110        ++$tests_total;
111        if (run_test($filename) == false) {
112            ++$tests_failed;
113            $failed_names[] = $filename;
114        }
115    }
116    if ($tests_failed) {
117        printf("Failed $tests_failed out of $tests_total (%.2lf%%)\n",
118                100.0 * $tests_failed / $tests_total);
119        printf("Tests that failed: ".implode(', ', $failed_names).".\n");
120    } else {
121        print("All $tests_total tests OK.\n");
122    }
123}
124
125// Compile jail.
126system("make", $ret);
127if ($ret) {
128    print("Jailer compilation failed, aborting\n");
129    exit(-1);
130}
131
132do {
133    if ($argc == 1) {
134        run_all();
135    } else if ($argc == 2) {
136        run_test($argv[1]);
137    } else {
138        print("Invalid arguments\n");
139    }
140} while (false);
141
142?>
Note: See TracBrowser for help on using the repository browser.