-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathsimpletests.py
More file actions
298 lines (257 loc) · 10.3 KB
/
simpletests.py
File metadata and controls
298 lines (257 loc) · 10.3 KB
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# *******************************************************************************************
# *******************************************************************************************
#
# Name : simpletests.py
# Purpose : Test generator
# Date : 22nd September 2022
# Author : Paul Robson ([email protected])
#
# *******************************************************************************************
# *******************************************************************************************
import os,sys,re,random
# *******************************************************************************************
#
# Base test class, provides support functions
#
# *******************************************************************************************
class TestAssertion(object):
def shortInteger(self):
if random.randint(0,1) == 0:
return random.randint(-20,20)
return random.randint(-2000,2000)
def float(self):
return random.randint(-40000000,40000000)/1000
def smallFloat(self):
return random.randint(-9000,9000)/1000
def string(self,maxLen = 9):
return "".join([chr(random.randint(97,117)) for x in range(0,random.randint(0,maxLen))])
def str(self,n):
return str(n) if n == int(n) else "{0:.7f}".format(n)
def make(self,test):
return "assert {0} = {1}".format(test[0],test[1])
def toDisplay(self,v):
return '"'+v+'"' if isinstance(v,str) else self.str(v)
# *******************************************************************************************
#
# Integer mathematic/binary operation
#
# *******************************************************************************************
class IntegerMath(TestAssertion):
def create(self,parent):
n1 = self.shortInteger()
n2 = self.shortInteger()
opList = "+-*/%&|^"
op = opList[random.randint(0,len(opList)-1)]
if op == "%" or op == "|" or op == "&" or op == "^": # -ve makes no sense with these
n1 = abs(n1)
n2 = abs(n2)
if (op == "*" and abs(n1)*abs(n2) > 0x7FFFFFF): # multiply out of range
return None
if (op == "/" or op == "%") and n2 == 0: # divide/modulus with zero
return None
r = int(eval("{0}{1}{2}".format(n1,op,n2)))
return ["({0}{1}{2})".format(n1,"\\" if op == "/" else op,n2),self.str(r)]
# *******************************************************************************************
#
# Float mathematic/binary operation
#
# *******************************************************************************************
class FloatMath(TestAssertion):
def create(self,parent):
n1 = self.float()
n2 = self.float()
opList = "+-*"
op = opList[random.randint(0,len(opList)-1)]
if op == "/" and n2 == 0:
return None
r = eval("{0}{1}{2}".format(n1,op,n2))
return ["({0}{1}{2})".format(n1,op,n2),self.str(r)]
# *******************************************************************************************
#
# Integer Comparison class
#
# *******************************************************************************************
class IntegerCompare(TestAssertion):
def create(self,parent):
n1 = self.shortInteger()
n2 = self.shortInteger()
op = [">","<","==",">=","<=","!="][random.randint(0,5)] # pick a compare
r = -1 if eval("{0}{1}{2}".format(n1,op,n2)) else 0
return ["{0}{1}{2}".format(n1,op.replace("!=","<>").replace("==","="),n2),r] # do translated to BASIC
# *******************************************************************************************
#
# Float Comparison class
#
# *******************************************************************************************
class FloatCompare(TestAssertion):
def create(self,parent):
n1 = self.float()
n2 = self.float()
op = [">","<","==",">=","<=","!="][random.randint(0,5)] # pick a compare
r = -1 if eval("{0}{1}{2}".format(n1,op,n2)) else 0
return ["({0}{1}{2})".format(n1,op.replace("!=","<>").replace("==","="),n2),r] # do translated to BASIC
# *******************************************************************************************
#
# String Comparison/Concat class
#
# *******************************************************************************************
class StringBinary(TestAssertion):
def create(self,parent):
s1 = self.string()
s2 = self.string()
if random.randint(0,2) > 0:
op = [">","<","==",">=","<=","!="][random.randint(0,5)] # pick a compare
ev = '"{0}"{1}"{2}"'.format(s1,op,s2)
r = -1 if eval(ev) else 0
return [ev.replace("!=","<>").replace("==","="),r] # do translated to BASIC
else:
return [ '"{0}"+"{1}"'.format(s1,s2),'"'+s1+s2+'"']
# *******************************************************************************************
#
# Unary functions returning numbers
#
# *******************************************************************************************
class UnaryNumber(TestAssertion):
def create(self,parent):
t1 = random.randint(0,10)
n1 = self.shortInteger() if random.randint(0,1) == 0 else self.float()
s1 = self.string()
if t1 == 0:
return [ "abs({0})".format(str(n1)),str(abs(n1))]
elif t1 == 1:
s = 0 if (n1 == 0) else (-1 if n1 < 0 else 1)
return [ "sgn({0})".format(str(n1)),str(s)]
elif t1 == 2:
return [ "len(\"{0}\")".format(s1),str(len(s1))]
elif t1 == 3:
a = ord(s1[0]) if s1 != "" else 0
return [ "asc(\"{0}\")".format(s1),str(a)]
elif t1 == 4:
s = int(abs(n1)) * (-1 if n1 < 0 else 1)
return [ "int({0})".format(str(n1)),str(s)]
elif t1 == 5:
n1 = self.smallFloat() # Precision is lost if you have 999999.322 say
s = abs(n1)-int(abs(n1))
return [ "frac({0})".format(str(n1)),self.str(s)]
elif t1 == 6:
n = 0 if random.randint(0,3) == 0 else self.shortInteger()
return [ "not({0})".format(str(n)),str(0 if n != 0 else -1)]
elif t1 == 7:
return [ "val(\"{0}\")".format(self.str(n1)),self.str(n1)]
elif t1 == 8:
isString = random.randint(0,1) == 0
isMin = random.randint(0,1) == 0
cList = [s1 if isString else n1]
for i in range(1,random.randint(1,4)):
cList.append(self.string() if isString else self.shortInteger() if random.randint(0,1) == 0 else self.float())
result = self.toDisplay(min(cList) if isMin else max(cList))
return [ "{0}({1})".format("min" if isMin else "max",",".join([self.toDisplay(x) for x in cList])),result ]
else:
return None
# *******************************************************************************************
#
# Unary functions returning strings
#
# *******************************************************************************************
class UnaryString(TestAssertion):
def create(self,parent):
t1 = random.randint(0,10)
s1 = self.string()
if t1 == 0:
n1 = random.randint(35,126)
return [ "chr$({0})".format(n1),'"{0}"'.format(chr(n1)) ]
elif t1 == 1:
n1 = random.randint(0,11)
return [ "spc({0})".format(n1),'"{0}"'.format(" "[:n1]) ]
elif t1 == 2:
n1 = random.randint(0,len(s1)+2)
return [ 'left$(\"{0}\",{1})'.format(s1,n1),'"'+s1[:n1]+'"']
elif t1 == 3:
n1 = random.randint(0,len(s1)+2)
return [ 'right$(\"{0}\",{1})'.format(s1,n1),'"'+s1[max(0,len(s1)-n1):]+'"']
elif t1 == 4:
n1 = random.randint(1,len(s1)+1)
l1 = random.randint(0,3)
s = s1[n1-1:][:l1]
return [ 'mid$(\"{0}\",{1},{2})'.format(s1,n1,l1),'"'+s+'"']
elif t1 == 5:
s = str(random.randint(-1000,1000))
return [ 'str$({0})'.format(s),'"'+s+'"']
elif t1 == 6:
s = str(random.randint(-1000,1000))+"."+str(random.randint(1,9))
return [ 'str$({0})'.format(s),'"'+s+'0000"']
else:
return None
# *******************************************************************************************
#
# Parenthesis check
#
# *******************************************************************************************
class Parenthesis(TestAssertion):
def createExpression(self,level):
if level == 0: # level 0 = single term.
return str(random.randint(-10,10))
elements = []
for i in range(0,random.randint(1,3)): # build a chain at this level.
elements.append(self.createExpression(level-1))
elements.append("+-*"[random.randint(0,2)])
expr = " ".join(elements[:-1])
return "("+expr+")"
def create(self,parent):
try:
expr = self.createExpression(3)
v = eval(expr)
return [expr,v]
except ValueError:
return self.createValidExpression(level)
# *******************************************************************************************
#
# Complete Test Set class
#
# *******************************************************************************************
class TestSet(object):
def __init__(self,seed = None,handle = None):
self.handle = handle if handle is not None else open("storage/load.dat","w")
random.seed() # randomise against clock
self.seed = random.randint(1,99999) if seed is None else seed # pick a seed if not provided
random.seed(self.seed)
self.factories = self.getFactoryList()
self.lineNumber = 1
self.step = 1
self.count = 300
sys.stderr.write("Seed = {0}\n".format(self.seed))
def do(self,count):
self.count = count
return self
def getCount(self):
return self.count
def getFactoryList(self):
return [ # list of test factory classes
FloatCompare(),FloatMath(),
IntegerCompare(),IntegerMath(),
StringBinary(),UnaryNumber(),
UnaryString(),Parenthesis()
]
def nextLineNumber(self):
self.lineNumber += self.step
return self.lineNumber-self.step
def startup(self):
return self
def create(self):
self.handle.write("{0} rem \"Seed {1}\"\n".format(self.lineNumber,self.seed)) # put the seed in the BASIC listing
self.lineNumber += self.step
for i in range(0,self.count): # create tests
factory = random.randint(0,len(self.factories)-1) # pick a factory
test = None
while test is None: # get a legitimate test
test = self.factories[factory].create(self)
self.handle.write("{0} {1}\n".format(self.nextLineNumber(),self.factories[factory].make(test)))
return self
def closedown(self):
return self
def terminate(self):
self.handle.write("{0} call $ffff\n".format(self.nextLineNumber())) # on emulator jmp $FFFF returns to OS
for i in range(0,16): # high byte end line data.
self.handle.write(chr(255))
if __name__ == "__main__":
TestSet().startup().create().closedown().terminate()