forked from cirosantilli/cpp-cheat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest
executable file
·136 lines (119 loc) · 3.8 KB
/
test
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python
"""
Test an executable IO behaviour.
Inputs: stdin, comand line arguments.
Outputs: stdout, stderr, and exit status.
Use as:
./test directory_of_executable basename_of_executable
"""
import imp
import subprocess
import sys
import os
class Input:
"""
TODO environment variables.
"""
def __init__(self, stdin, args = []):
self.stdin = stdin
self.args = args
def __eq__(self, other):
if type(other) is type(self):
return self.__dict__ == other.__dict__
return False
def __repr__(self):
output = ""
previous = False
if self.args:
output += 'args:\n' + repr(self.args)
previous = True
if self.stdin:
if previous:
output += '\n'
output += 'stdin:\n' + self.stdin
previous = True
return output
class Output:
def __init__(self, stdout, stderr = '', exit_status = 0):
self.stdout = stdout
self.stderr = stderr
self.exit_status = exit_status
def __eq__(self, other):
return (type(other) is type(self)
and self.__dict__ == other.__dict__)
def __repr__(self):
output = ""
previous = False
if self.stdout:
output += 'stdout:\n' + self.stdout
if self.stderr:
if previous:
output += '\n'
output += 'stderr:\n' + self.stderr
previous = True
if self.exit_status != 0:
if previous:
output += '\n'
output += 'exit_status: ' + str(self.exit_status)
return output
class IO:
"""
Contains an Input Output pair, and information on how to run the input.
Has many creation default parameters so that the least used parameters do not need to be specified.
"""
def __init__(self, name, stdin="", stdout="", args = [], stderr = "", exit_status = 0):
self.name = name
self.input = Input(stdin, args)
self.output_expected = Output(stdout, stderr, exit_status)
def run(self, program_path):
"""
Run test case using given program.
:returns: empty str it test passed, error message if test failed.
:rtype: str
"""
return_val = ""
command = [program_path]
command.extend(self.input.args)
process = subprocess.Popen(
command,
shell = False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
stdout, stderr = process.communicate(self.input.stdin)
exit_status = process.wait()
output = Output(stdout, stderr, exit_status)
if not output == self.output_expected:
return_val += (
self.name + "\n"
+ (60 * "=") + "\n"
+ "Input\n" + repr(self.input) + "\n"
+ (40 * "-") + "\n"
+ "Output\n" + repr(output) + "\n"
+ (40 * "-") + "\n"
+ "Expected output\n" + repr(self.output_expected))
return return_val
if __name__ == '__main__':
try:
test_io = imp.load_source('test_io', 'test_io.py')
except IOError:
print "No test_io.py file."
sys.exit(1)
if test_io:
os.chdir(sys.argv[1])
program_path = os.path.abspath(sys.argv[2])
errors = []
for inout in test_io.inouts:
error = IO(*inout).run(program_path)
if error:
errors.append(error)
sys.stdout.write('F')
else:
sys.stdout.write('.')
sys.stdout.flush()
print "\n"
if errors:
print "\n\n".join(errors)
else:
print "All tests passed."