]> mj.ucw.cz Git - eval.git/blob - t/moe/testcase.py
Added a paranoid test for evaluation order
[eval.git] / t / moe / testcase.py
1 #!/usr/bin/env python
2
3 import os.path
4 import moe
5 import moe.config
6 import moe.eval
7 import moe.log
8 import shutil
9 import traceback
10
11 def configure_test(e, test):
12     e.cfgs = moe.config.MoeConfigStack(e.cfgs)
13     e.test_builtins = moe.config.MoeConfig(type="test-builtins")
14     e.test_builtins.set("TEST", test)
15     e.cfgs.push(e.test_builtins)
16
17     test_cf = os.path.join(e["PDIR"], test + ".config")
18     if os.path.exists(test_cf):
19         cfg = moe.config.MoeConfig(name=test_cf, type="test")
20         e.cfgs.push(cfg)
21
22     e.cfgs.apply_overrides("TEST_" + test + "_")
23     ext = e["EXT"]
24     if ext != "":
25         e.cfgs.apply_overrides("EXT_" + ext + "_")
26
27     log = moe.log.MoeLog()
28     log.verbosity = e.log.verbosity
29     log.open(os.path.join(e["TDIR"], test + ".log"))
30     log.say("Test case %s\n\n" % test)
31     e.log = log
32     moe.log.default = log
33
34     e.log_config(2, "for the test")
35
36     e.test_stat = moe.status.MoeStatus()
37     e.test_stat["id"] = test
38     e.stat.get_list("tests").append(e.test_stat)
39
40 def collect_status(e):
41     sf = os.path.join(e["TDIR"], e["TESTCASE_STATUS"])
42     if os.path.exists(sf):
43         e.log.verbose("Reading status from %s\n" % sf)
44         stat = moe.status.MoeStatus()
45         stat.read(name=sf)
46         if e.log.verbosity > 1:
47             stat.write_nested(e.log.log_file, 1)
48         for k in stat.keys():
49             e.test_stat[k] = stat[k]
50         os.unlink(sf)
51     else:
52         e.log.verbose("No status file present\n")
53
54 def tmpname(e):
55     return os.path.join(e["TDIR"], e["TEST"] + ".tmp")
56
57 def collect_tmp_line(tmp_file):
58     if os.path.exists(tmp_file):
59         f = open(tmp_file, "r")
60         v = f.readline().rstrip("\n")
61         f.close()
62         os.unlink(tmp_file)
63     else:
64         v = ""
65     return v
66
67 def collect_verdict(e, verdict_file):
68     v = collect_tmp_line(verdict_file)
69     if len(v) >= 4 and v[0].isalnum and v[1].isalnum and v[2] == ":" and v[3] == " ":
70         e.test_stat["status"] = v[0:2]
71         e.log.verbose("Judge's status: %s\n" % v[0:2])
72         v = v[4:]
73     v.strip()
74     if v != "":
75         e.test_stat["message"] = v
76         e.log.verbose("Judge's verdict: %s\n" % v)
77
78 def collect_points(e):
79     p = collect_tmp_line(os.path.join(e["TDIR"], e["TESTCASE_PTS"]))
80     if p != "":
81         e.log.verbose("Judge has supplied points: %s\n" % p)
82         e.test_stat["points"] = p
83
84 def setup(e):
85     pdir = e["PDIR"]
86     tdir = e["TDIR"]
87     inn = e["TESTCASE_IN"]
88     out = e["TESTCASE_OUT"]
89     ok = e["TESTCASE_OK"]
90
91     if os.path.exists(os.path.join(pdir, inn)):
92         moe.util.link_or_copy(os.path.join(pdir, inn), os.path.join(tdir, inn))
93     if os.path.exists(os.path.join(pdir, out)):
94         moe.util.link_or_copy(os.path.join(pdir, out), os.path.join(tdir, ok))
95
96 def judge(e):
97     cmd = e["OUTPUT_CHECK"]
98     if cmd == "":
99         return
100     verdict_file = tmpname(e)
101     cmd = "exec 2>%s ; %s" % (verdict_file,cmd)
102
103     e.log.progress("<check> ")
104     e.log.verbose("Checking output: %s\n" % cmd)
105     e.log.flush()
106     rc = os.system(cmd)
107     collect_verdict(e, verdict_file)
108     collect_points(e)
109     collect_status(e)
110     if os.WIFEXITED(rc):
111         if os.WEXITSTATUS(rc) == 0:
112             return
113         elif os.WEXITSTATUS(rc) == 1:
114             raise moe.TestError("Wrong answer", "WA")
115     raise moe.MoeError("Judge failure")
116
117 def points(e):
118     if e.test_stat["points"] is None:
119         e.test_stat["points"] = e["POINTS_PER_TEST"]
120
121 def filter(e):
122     cmd = e["OUTPUT_FILTER"]
123     if cmd == "":
124         return
125
126     os.rename(os.path.join(e["TDIR"], e["TESTCASE_OUT"]), os.path.join(e["TDIR"], e["TESTCASE_RAW"]))
127     e.log.progress("<filter> ")
128     e.log.verbose("Filtering output: %s\n" % cmd)
129     e.log.flush()
130     rc = os.system(cmd)
131     if os.WIFEXITED(rc) and os.WEXITSTATUS(rc) == 0:
132         if not os.path.exists(os.path.join(e["TDIR"], e["TESTCASE_OUT"])):
133             raise moe.MoeError("Filter has generated no output")
134     else:
135         raise moe.MoeError("Filter failure")
136
137 def syntax(e):
138     cmd = e["SYNTAX_CHECK"]
139     if cmd == "":
140         return
141     verdict_file = tmpname(e)
142     cmd = "exec 2>%s ; %s" % (verdict_file,cmd)
143
144     e.log.progress("<syntax> ")
145     e.log.verbose("Checking syntax: %s\n" % cmd)
146     e.log.flush()
147     rc = os.system(cmd)
148     collect_verdict(e, verdict_file)
149     collect_status(e)
150     if os.WIFEXITED(rc):
151         if os.WEXITSTATUS(rc) == 0:
152             return
153         elif os.WEXITSTATUS(rc) == 1:
154             raise moe.TestError("Wrong syntax", "SY")
155     raise moe.MoeError("Syntax checker failure")
156
157 def run_test(e, test):
158     configure_test(e, test)
159
160     ## FIXME: interactive tasks
161     e.test_pipe.configure(e["TESTCASE_HOOKS"])
162     if e.log.verbosity >= 2:
163         e.test_pipe.dump(e.log.log_file, prefix="\t")
164     e.test_pipe.run(e)
165
166 def wrap_run_test(e, test):
167     try:
168         run_test(e, test)
169     except moe.MoeError, err:
170         raise moe.TestError(err, "XX")
171     except Exception:
172         if e["DEBUG"]:
173             moe.log.fatal_exception()
174         traceback.print_exc(file = e.log.log_file)
175         raise moe.TestError("Internal exception", "XX")
176
177 def conclude_test(e):
178     stat = e.test_stat
179     if not stat["points"]:
180         stat["points"] = 0
181
182     if e.log.verbosity > 1:
183         e.log.verbose("Final status:\n")
184         stat.write_nested(e.log.log_file, 1)
185
186     if stat["status"]:
187         msg = "%s: %s" % (stat["status"], e.test_stat["message"])
188     else:
189         msg = "OK"
190     msg += " (%s points" % stat["points"]
191     if stat["time"]:
192         msg += ", %s s" % stat["time"]
193     if stat["mem"]:
194         msg += ", %d MB" % ((int(stat["mem"]) + 524288) // 1048576)
195     msg += ")\n"
196     e.log.progress(msg)
197     e.log.say(msg)
198
199 def run_tests(e):
200     e.test_pipe.insert(0, "setup", setup)
201     e.test_pipe.insert(400, "filter", filter)
202     e.test_pipe.insert(500, "syntax", syntax)
203     e.test_pipe.insert(600, "judge", judge)
204     e.test_pipe.insert(700, "points", points)
205
206     for test in e["TESTS"].split():
207         e.log.progress("Test %s: " % test)
208         old_cfgs = e.cfgs
209         old_log = e.log
210
211         try:
212             wrap_run_test(e, test)
213         except moe.TestError, err:
214             if not e.test_stat["status"]:
215                 e.test_stat["status"] = err.stat_code
216             if not e.test_stat["message"]:
217                 e.test_stat["message"] = err.message
218
219         conclude_test(e)
220         
221         e.cfgs = old_cfgs
222         e.log = old_log
223         moe.log.default = old_log