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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# (c) Copyright 2007 The Board of Trustees of the University of Illinois.
import sys
# A monad for comparing two files. Comparing proceeds until the first
# mismatch occurs, at which point comparison stops and the error is
# reported.
class CompareMonad(object):
def checkType(x):
if not isinstance(x, CompareMonad):
raise TypeError, "Not a CompareMonad instance"
checkType = staticmethod(checkType)
def run(self, ref_file, out_file):
raise NotImplementedError
# The >>= operator. Executes 'fst', then executes 'snd' with the result
# of 'fst'.
class Bind(CompareMonad):
def __init__(self, fst, snd):
CompareMonad.checkType(fst)
self.fst = fst
self.snd = snd
def run(self, ref_file, out_file):
(ok, value) = self.fst.run(ref_file, out_file)
if ok:
sndMonad = self.snd(value)
CompareMonad.checkType(sndMonad)
return sndMonad.run(ref_file, out_file)
return (False, None)
# The >> operator. Executes 'fst', then executes 'snd'.
class Then(CompareMonad):
def __init__(self, fst, snd):
CompareMonad.checkType(fst)
CompareMonad.checkType(snd)
self.fst = fst
self.snd = snd
def run(self, ref_file, out_file):
(ok, value) = self.fst.run(ref_file, out_file)
if ok:
return self.snd.run(ref_file, out_file)
return (False, None)
# The 'return' operator. Returns a value that is accessible
# within the monad.
class Return(CompareMonad):
def __init__(self, value):
self.value = value
def run(self, ref_file, out_file):
return (True, self.value)
# Run a list of monad instances and return their results as
# a list.
class Sequence(CompareMonad):
def __init__(self, ms):
self.ms = ms
def run(self, ref_file, out_file):
values = []
for m in self.ms:
CompareMonad.checkType(m)
(ok, value) = m.run(ref_file, out_file)
if not ok: return (False, None)
values.append(value)
return (True, values)
# Run a list of monad instances, ignoring their results.
class Sequence_(CompareMonad):
def __init__(self, ms):
self.ms = ms
def run(self, ref_file, out_file):
for m in self.ms:
CompareMonad.checkType(m)
(ok, value) = m.run(ref_file, out_file)
if not ok: return (False, None)
return (True, None)
# The basic CompareMonad routine. This reads a value from both input
# files, compares the result, and, if the comparison was successful,
# returns the value.
class Compare(CompareMonad):
"""Read an item from both input files and compare it."""
def __init__(self,
read = file.read,
equal = lambda x, y: x == y,
message = "Output does not match the expected output"):
self.read = read
self.equal = equal
self.message = message
def run(self, ref_file, out_file):
try:
x = self.read(ref_file)
except ValueError, e:
sys.stderr.write("Malformed reference file!\n")
return (False, None)
except EOFError:
sys.stderr.write("Unexpected end of reference file!\n")
return (False, None)
try:
y = self.read(out_file)
except ValueError, e:
sys.stderr.write("Malformed output file;\n")
sys.stderr.write(str(e))
sys.stderr.write('\n')
return (False, None)
except EOFError:
sys.stderr.write("Unexpected end of output file\n")
return (False, None)
# Compare reference data to result data
if self.equal(x, y):
return (True, x)
else:
sys.stderr.write(self.message)
sys.stderr.write('\n')
return (False, None)
def open_or_abort(filename):
try: f = file(filename, "r")
except:
sys.stderr.write("Cannot open file '" + filename + "'\n")
sys.exit(-1)
return f
def default_main(comparison_routine):
"""Default main() routine. Read file names from sys.argv
and compare the files."""
if len(sys.argv) != 3:
sys.stderr.write("Usage: compare-output <from-file> <to-file>\n")
sys.exit(-1)
ref = open_or_abort(sys.argv[1])
out = open_or_abort(sys.argv[2])
(ok, _) = comparison_routine.run(ref, out)
if ok:
sys.stdout.write("Pass\n")
sys.exit(0)
else:
sys.stdout.write("Mismatch\n")
sys.exit(-1)
|