blob: a1d52f4da195a657854a0cf792bc99ceae34a4cd [file] [log] [blame]
Gavin Howardfd06ac22018-10-10 16:48:32 -06001#! /usr/bin/python3 -B
2#
3# Copyright 2018 Gavin D. Howard
4#
5# Permission to use, copy, modify, and/or distribute this software for any
6# purpose with or without fee is hereby granted.
7#
8# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14# PERFORMANCE OF THIS SOFTWARE.
15#
16
17import os, errno
18import random
19import sys
20import subprocess
21
22def silentremove(filename):
23 try:
24 os.remove(filename)
25 except OSError as e:
26 if e.errno != errno.ENOENT:
27 raise
28
29def finish():
Gavin Howardfd06ac22018-10-10 16:48:32 -060030 silentremove(math)
Gavin Howardfd06ac22018-10-10 16:48:32 -060031 silentremove(opfile)
32
33def gen(limit=4):
34 return random.randint(0, 2 ** (8 * limit))
35
36def negative():
37 return random.randint(0, 1) == 1
38
39def zero():
40 return random.randint(0, 2 ** (8) - 1) == 0
41
42def num(neg, real, z, limit=4):
43
44 if z:
45 z = zero()
46 else:
47 z = False
48
49 if z:
50 return 0
51
52 if neg:
53 neg = negative()
54
55 g = gen(limit)
56
57 if real and negative():
58 n = gen(25)
59 else:
60 n = 0
61
62 g = str(g)
63 if n != 0:
64 g = g + "." + str(n)
65
66 if neg and g != "0":
67 g = "-" + g
68
69 return g
70
71
Gavin Howarda8f61ed2018-10-10 17:03:42 -060072def add(test, op):
Gavin Howardfd06ac22018-10-10 16:48:32 -060073
74 with open(math, "a") as f:
75 f.write(test + "\n")
76
Gavin Howardfd06ac22018-10-10 16:48:32 -060077 with open(opfile, "a") as f:
78 f.write(str(op) + "\n")
79
80def compare(exe, options, p, test, halt, expected, op, do_add=True):
81
82 if p.returncode != 0:
83
84 print(" {} returned an error ({})".format(exe, p.returncode))
85
86 if do_add:
87 print(" adding {} to checklist...".format(test))
Gavin Howarda8f61ed2018-10-10 17:03:42 -060088 add(test, op)
Gavin Howardfd06ac22018-10-10 16:48:32 -060089
90 return
91
92 actual = p.stdout.decode()
93
94 if actual != expected:
95
96 if op >= exponent:
97
98 indata = "scale += 10; {}; {}".format(test, halt)
99 args = [ exe, options ]
100 p2 = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
101 expected = p2.stdout[:-10].decode()
102
103 if actual == expected:
104 print(" failed because of bug in other {}".format(exe))
105 print(" continuing...")
106 return
107
108 print(" failed \"{}\"".format(test))
109 print(" expected:")
110 print(" {}".format(expected))
111 print(" actual:")
112 print(" {}".format(actual))
113
114 if do_add:
115 print(" adding to checklist...")
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600116 add(test, op)
Gavin Howardfd06ac22018-10-10 16:48:32 -0600117
118
119def gen_test(op):
120
121 scale = num(False, False, True, 5 / 8)
122
123 if op < div:
124 s = fmts[op].format(scale, num(True, True, True), num(True, True, True))
125 elif op == div or op == mod:
126 s = fmts[op].format(scale, num(True, True, True), num(True, True, False))
127 elif op == power:
128 s = fmts[op].format(scale, num(True, True, True, 7 / 8), num(True, False, True, 6 / 8))
129 elif op == modexp:
130 s = fmts[op].format(scale, num(True, False, True), num(True, False, True),
131 num(True, False, False))
132 elif op == sqrt:
133 s = "1"
134 while s == "1":
135 s = num(False, True, True, 1)
136 s = fmts[op].format(scale, s)
137 else:
138
139 if op == exponent:
140 first = num(True, True, True, 6 / 8)
141 elif op == bessel:
142 first = num(False, True, True, 6 / 8)
143 else:
144 first = num(True, True, True)
145
146 if op != bessel:
147 s = fmts[op].format(scale, first)
148 else:
149 s = fmts[op].format(scale, first, 6 / 8)
150
151 return s
152
153def run_test(t):
154
155 op = random.randrange(bessel + 1)
156
157 if op != modexp:
158 exe = "bc"
159 halt = "halt"
160 options = "-lq"
161 else:
162 exe = "dc"
163 halt = "q"
164 options = ""
165
166 test = gen_test(op)
167
168 bcexe = exedir + "/" + exe
169 indata = test + "\n" + halt
170
Gavin Howardfd06ac22018-10-10 16:48:32 -0600171 print("Test {}: {}".format(t, test))
172
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600173 args = [ exe, options ]
174
Gavin Howardfd06ac22018-10-10 16:48:32 -0600175 p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
176
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600177 output1 = p.stdout.decode()
178
179 if p.returncode != 0 or output1 == "":
Gavin Howardfd06ac22018-10-10 16:48:32 -0600180 print(" other {} returned an error ({}); continuing...".format(exe, p.returncode))
181 return
182
Gavin Howardfd06ac22018-10-10 16:48:32 -0600183 args = [ bcexe, options ]
184
185 p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
186 compare(exe, options, p, test, halt, output1, op)
187
188
189if __name__ != "__main__":
190 sys.exit(1)
191
192script = sys.argv[0]
193testdir = os.path.dirname(script)
194
195exedir = testdir + "/.."
Gavin Howardfd06ac22018-10-10 16:48:32 -0600196math = exedir + "/.math.txt"
Gavin Howardfd06ac22018-10-10 16:48:32 -0600197opfile = exedir + "/.ops.txt"
198
199ops = [ '+', '-', '*', '/', '%', '^', '|' ]
200files = [ "add", "subtract", "multiply", "divide", "modulus", "power", "modexp",
201 "sqrt", "exponent", "log", "arctangent", "sine", "cosine", "bessel" ]
202funcs = [ "sqrt", "e", "l", "a", "s", "c", "j" ]
203
204fmts = [ "scale = {}; {} + {}", "scale = {}; {} - {}", "scale = {}; {} * {}",
205 "scale = {}; {} / {}", "scale = {}; {} % {}", "scale = {}; {} ^ {}",
206 "{}k {} {} {}|pR", "scale = {}; sqrt({})", "scale = {}; e({})",
207 "scale = {}; l({})", "scale = {}; a({})", "scale = {}; s({})",
208 "scale = {}; c({})", "scale = {}; j({}, {})" ]
209
210div = 3
211mod = 4
212power = 5
213modexp = 6
214sqrt = 7
215exponent = 8
216bessel = 13
217
218finish()
219
220try:
221 i = 0
222 while True:
223 run_test(i)
224 i = i + 1
225except KeyboardInterrupt:
226 pass
227
228if not os.path.exists(math):
229 print("\nNo items in checklist.")
230 print("Exiting")
231 sys.exit(0)
232
233print("\nGoing through the checklist...\n")
234
235with open(math, "r") as f:
236 tests = f.readlines()
237
Gavin Howardfd06ac22018-10-10 16:48:32 -0600238with open(opfile, "r") as f:
239 ops = f.readlines()
240
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600241if len(tests) != len(ops):
Gavin Howardfd06ac22018-10-10 16:48:32 -0600242 print("Corrupted checklist!")
243 print("Exiting...")
244 sys.exit(1)
245
246for i in range(0, len(tests)):
247
248 #print("Test: {}\nExpected: {}\nOp: {}".format(tests[i], expecteds[i], ops[i]))
249 #continue
250
251 print("\n{}".format(tests[i]))
252
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600253 op = int(ops[i])
254
255 print("op: {}".format(op))
256
257 if op != modexp:
Gavin Howardfd06ac22018-10-10 16:48:32 -0600258 exe = "bc"
259 halt = "halt"
260 options = "-lq"
261 else:
262 exe = "dc"
263 halt = "q"
264 options = ""
265
Gavin Howardfd06ac22018-10-10 16:48:32 -0600266 indata = tests[i] + "\n" + halt
267
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600268 args = [ exe, options ]
269
Gavin Howardfd06ac22018-10-10 16:48:32 -0600270 p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
271
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600272 expected = p.stdout.decode()
273
274 bcexe = exedir + "/" + exe
275
276 args = [ bcexe, options ]
277
278 p = subprocess.run(args, input=indata.encode(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
279
280 compare(exe, options, p, tests[i], halt, expected, op, False)
Gavin Howardfd06ac22018-10-10 16:48:32 -0600281
282 answer = input("\nAdd test to test suite? [y/N]: ")
283
284 if 'Y' in answer or 'y' in answer:
285 print("Yes")
286 continue
287
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600288 name = testdir + "/" + exe + "/" + files[op]
Gavin Howardfd06ac22018-10-10 16:48:32 -0600289
290 with open(name + ".txt", "a") as f:
291 f.write(tests[i])
292
293 with open(name + "_results.txt", "a") as f:
Gavin Howarda8f61ed2018-10-10 17:03:42 -0600294 f.write(expected)
Gavin Howardfd06ac22018-10-10 16:48:32 -0600295
296 else:
297 print("No")
298
299
300finish()