Skip to content

Commit 9a864ea

Browse files
committed
Add M2 test
1 parent 6b408b0 commit 9a864ea

File tree

1 file changed

+385
-0
lines changed

1 file changed

+385
-0
lines changed

testM2.py

Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
from lstore.db import Database
2+
from lstore.query import Query
3+
4+
from random import choice, randint, sample, seed
5+
6+
7+
records = {}
8+
number_of_records = 1000
9+
number_of_aggregates = 100
10+
number_of_updates = 1
11+
keys = {}
12+
13+
def reorganize_result(result):
14+
val = list()
15+
for r in result:
16+
val.append(r.columns)
17+
val.sort()
18+
return val
19+
20+
# 30 points in total
21+
def correctness_tester1():
22+
records = [
23+
[0, 1, 1, 2, 1],
24+
[1, 1, 1, 1, 2],
25+
[2, 0, 3, 5, 1],
26+
[3, 1, 5, 1, 3],
27+
[4, 2, 7, 1, 1],
28+
[5, 1, 1, 1, 1],
29+
[6, 0, 9, 1, 0],
30+
[7, 1, 1, 1, 1],
31+
]
32+
db = Database()
33+
db.open("./CT")
34+
test_table = db.create_table('test', 5, 0)
35+
query = Query(test_table)
36+
for record in records:
37+
query.insert(*record)
38+
try:
39+
# select on columns with index
40+
test_table.index.create_index(2)
41+
result = reorganize_result(query.select(1, 2, [1,1,1,1,1]))
42+
if len(result) == 4:
43+
if records[0] in result and records[1] in result and records[5] in result and records[7] in result:
44+
print("PASS[0]")
45+
else:
46+
print("Error[0]")
47+
else:
48+
print("Error[0]")
49+
except Exception as e:
50+
print("Wrong[0]")
51+
52+
try:
53+
# select on columns without index and return 1 record
54+
test_table.index.drop_index(2)
55+
result = reorganize_result(query.select(3, 2, [1,1,1,1,1]))
56+
if len(result) == 1 and records[2] in result:
57+
print("PASS[1]")
58+
else:
59+
print("Error[1]")
60+
except Exception as e:
61+
print("Wrong[1]")
62+
63+
try:
64+
# select on columns without index and return multiple records
65+
result = reorganize_result(query.select(1, 2, [1,1,1,1,1]))
66+
if len(result) == 4:
67+
if records[0] in result and records[1] in result and records[5] in result and records[7] in result:
68+
print("PASS[2]")
69+
else:
70+
print("Error[2]")
71+
else:
72+
print("Error[2]")
73+
except Exception as e:
74+
print("Wrong[2]")
75+
76+
try:
77+
# select on columns without index and return empty list
78+
result = reorganize_result(query.select(10, 2, [1,1,1,1,1]))
79+
print(result)
80+
if len(result) == 0:
81+
print("PASS[3]")
82+
else:
83+
print("Error[3]")
84+
except Exception as e:
85+
print("Wrong[3]")
86+
87+
try:
88+
# update on a primary key that does not exits
89+
query.update(8, *[None,2,2,2,2])
90+
result = reorganize_result(query.select(8, 0, [1,1,1,1,1]))
91+
if len(result) == 0:
92+
print("PASS[4]")
93+
else:
94+
print("Error[4]")
95+
except Exception as e:
96+
print("Wrong[4]")
97+
98+
try:
99+
# update that changes primary key,
100+
query.update(7, *[8,2,2,2,2])
101+
result = reorganize_result(query.select(7, 0, [1,1,1,1,1]))
102+
if len(result) == 0:
103+
print("PASS[5]")
104+
else:
105+
print("Error[5]")
106+
except Exception as e:
107+
print("Wrong[5]")
108+
109+
try:
110+
# delete a record
111+
query.delete(5)
112+
result = reorganize_result(query.select(5, 0, [1,1,1,1,1]))
113+
if len(result) == 0:
114+
print("PASS[6]")
115+
else:
116+
print("Error[6]")
117+
except Exception as e:
118+
print("Wrong[6]")
119+
120+
try:
121+
# multiple tables
122+
123+
test_table2 = db.create_table("test2", 5, 0)
124+
records2 = [
125+
[1, 1, 1, 2, 1],
126+
[2, 1, 1, 1, 2],
127+
[3, 0, 3, 5, 1],
128+
[4, 1, 5, 1, 3],
129+
[5, 2, 7, 1, 1],
130+
[6, 1, 1, 1, 1],
131+
[7, 0, 9, 1, 0],
132+
[8, 1, 1, 1, 1],
133+
]
134+
query2 = Query(test_table2)
135+
for record in records2:
136+
query2.insert(*record)
137+
result = reorganize_result(query2.select(1, 0, [1,1,1,1,1]))
138+
if len(result) == 1 and records2[0] in result:
139+
print("PASS[7]")
140+
else:
141+
print("Error[7]")
142+
except Exception as e:
143+
print("Wrong[7]")
144+
145+
def correctness_tester2():
146+
# different primary key
147+
try:
148+
db = Database()
149+
test_table3 = db.create_table("test3", 5, 2)
150+
records3 = [
151+
[1, 1, 0, 2, 1],
152+
[2, 1, 1, 1, 2],
153+
[3, 0, 2, 5, 1],
154+
[4, 1, 3, 1, 3],
155+
[5, 2, 4, 1, 1],
156+
[6, 1, 5, 1, 1],
157+
[7, 0, 6, 1, 0],
158+
[8, 1, 7, 1, 1],
159+
]
160+
query3 = Query(test_table3)
161+
for record in records3:
162+
query3.insert(*record)
163+
result = query3.sum(3, 5, 4)
164+
print(result)
165+
if result == 5:
166+
print("PASS[8]")
167+
else:
168+
print("Error[8]")
169+
except Exception as e:
170+
print("Wrong[8]")
171+
172+
173+
def generte_keys():
174+
global records, number_of_records, number_of_aggregates, number_of_updates, keys
175+
176+
if True:
177+
records = {}
178+
seed(3562901)
179+
180+
for i in range(0, number_of_records):
181+
key = 92106429 + i
182+
records[key] = [key, randint(0, 20), randint(0, 20), randint(0, 20), randint(0, 20)]
183+
184+
keys = sorted(records.keys())
185+
186+
for _ in range(number_of_updates):
187+
for key in keys:
188+
updated_columns = [None, None, None, None, None]
189+
# copy record to check
190+
for i in range(1, 5):
191+
# updated value
192+
value = randint(0, 20)
193+
updated_columns[i] = value
194+
# update our test directory
195+
records[key][i] = value
196+
197+
def durability_tester1():
198+
print("Checking exam M2 durability")
199+
global records, number_of_records, number_of_aggregates, number_of_updates, keys
200+
201+
if True:
202+
db = Database()
203+
db.open('./M2')
204+
# Create a table with 5 columns
205+
# Student Id and 4 grades
206+
# The first argument is name of the table
207+
# The second argument is the number of columns
208+
# The third argument is determining the which columns will be primay key
209+
# Here the first column would be student id and primary key
210+
grades_table = db.create_table('Grades', 5, 0)
211+
212+
# create a query class for the grades table
213+
query = Query(grades_table)
214+
215+
# dictionary for records to test the database: test directory
216+
records = {}
217+
218+
seed(3562901)
219+
220+
for i in range(0, number_of_records):
221+
key = 92106429 + i
222+
records[key] = [key, randint(0, 20), randint(0, 20), randint(0, 20), randint(0, 20)]
223+
query.insert(*records[key])
224+
print("Insert finished")
225+
226+
# Check inserted records using select query
227+
for key in keys:
228+
record = query.select(key, 0, [1, 1, 1, 1, 1])[0]
229+
error = False
230+
for i, column in enumerate(record.columns):
231+
if column != records[key][i]:
232+
error = True
233+
if error:
234+
print('select error on', key, ':', record, ', correct:', records[key])
235+
else:
236+
pass
237+
# print('select on', key, ':', record)
238+
print("Select finished")
239+
240+
# x update on every column
241+
for _ in range(number_of_updates):
242+
for key in keys:
243+
updated_columns = [None, None, None, None, None]
244+
# copy record to check
245+
original = records[key].copy()
246+
for i in range(1, grades_table.num_columns):
247+
# updated value
248+
value = randint(0, 20)
249+
updated_columns[i] = value
250+
# update our test directory
251+
records[key][i] = value
252+
query.update(key, *updated_columns)
253+
record = query.select(key, 0, [1, 1, 1, 1, 1])[0]
254+
error = False
255+
for j, column in enumerate(record.columns):
256+
if column != records[key][j]:
257+
error = True
258+
if error:
259+
raise Exception('update error on', original, 'and', updated_columns, ':', record.columns, ', correct:', records[key])
260+
else:
261+
pass
262+
# print('update on', original, 'and', updated_columns, ':', record)
263+
print("Update finished")
264+
265+
for i in range(0, number_of_aggregates):
266+
r = sorted(sample(range(0, len(keys)), 2))
267+
column_sum = sum(map(lambda key: records[key][0], keys[r[0]: r[1] + 1]))
268+
result = query.sum(keys[r[0]], keys[r[1]], 0)
269+
if column_sum != result:
270+
print('sum error on [', keys[r[0]], ',', keys[r[1]], ']: ', result, ', correct: ', column_sum)
271+
else:
272+
pass
273+
# print('sum on [', keys[r[0]], ',', keys[r[1]], ']: ', column_sum)
274+
print("Aggregate finished")
275+
db.close()
276+
print("DB is closed")
277+
278+
def durability_tester2():
279+
# reopen the database
280+
global records, number_of_records, number_of_aggregates, number_of_updates, keys
281+
282+
if True:
283+
db = Database()
284+
db.open('./M2')
285+
286+
# Getting the existing Grades table
287+
grades_table = db.get_table('Grades')
288+
289+
# create a query class for the grades table
290+
query = Query(grades_table)
291+
292+
# dictionary for records to test the database: test directory
293+
294+
# Check inserted records using select query
295+
err = False
296+
for key in keys:
297+
record = query.select(key, 0, [1, 1, 1, 1, 1])[0]
298+
error = False
299+
for i, column in enumerate(record.columns):
300+
if column != records[key][i]:
301+
error = True
302+
if error:
303+
err = True
304+
print('[Durability]select error on', key, ':', record.columns, ', correct:', records[key])
305+
else:
306+
pass
307+
# print('select on', key, ':', record)
308+
if not err:
309+
pass
310+
print("Select finished")
311+
312+
err = False
313+
for i in range(0, number_of_aggregates):
314+
r = sorted(sample(range(0, len(keys)), 2))
315+
correct_result = sum(map(lambda x: records[x][0] if x in records else 0, keys[r[0]: r[1] + 1]))
316+
sum_result = query.sum(keys[r[0]], keys[r[1]], 0)
317+
if correct_result != sum_result:
318+
err = True
319+
raise Exception('[Durability]sum error on [', keys[r[0]], ',', keys[r[1]], ']: ', sum_result, ', correct: ', correct_result)
320+
else:
321+
pass
322+
print("Aggregate finished")
323+
324+
db.close()
325+
326+
327+
328+
329+
def merging_tester():
330+
# Without Merging, the select would be extremely slow.
331+
db = Database()
332+
db.open("./MT")
333+
merge_table = db.create_table('merge', 5, 0)
334+
query = Query(merge_table)
335+
update_nums = [2, 4, 8, 16]
336+
records_num = 10000
337+
sample_count = 200
338+
select_repeat = 200
339+
for i in range(records_num):
340+
query.insert(*[i, (i+100)%records_num, (i+200)%records_num, (i+300)%records_num, (i+400)%records_num])
341+
for index in range(len(update_nums)):
342+
# 10000*4*(5+4*2+3*4+2*8+16*1) = 2280000 Byte = 556 Pages (4KB Page)
343+
update_num = update_nums[index]
344+
for count in range(update_num):
345+
for i in range(records_num):
346+
update_record = [None, (i+101+count)%records_num, (i+201+count)%records_num,\
347+
(i+301+count)%records_num, (i+401+count)%records_num]
348+
for idx in range(index):
349+
update_record[4-idx] = None
350+
query.update(i, *update_record)
351+
keys = sorted(sample(range(0, records_num),sample_count))
352+
time = 0
353+
# 200 * 200 select
354+
while time < select_repeat:
355+
time += 1
356+
for key in keys:
357+
query.select(key, 0, [1,1,1,1,1])
358+
359+
from timeit import default_timer as timer
360+
from decimal import Decimal
361+
362+
import os
363+
import glob
364+
import traceback
365+
import shutil
366+
367+
m2tests = [1,1,1]
368+
if m2tests[0] == 1:
369+
print("==========correctness tester===============")
370+
correctness_tester1()
371+
correctness_tester2()
372+
if m2tests[1] == 1:
373+
print("==========durability tester================")
374+
generte_keys()
375+
durability_tester1()
376+
durability_tester2()
377+
if m2tests[2] == 1:
378+
print("==========merging tester===================")
379+
start = timer()
380+
merging_tester()
381+
end = timer()
382+
print()
383+
print("Total time Taken: ", Decimal(end - start).quantize(Decimal('0.01')), "seconds")
384+
385+

0 commit comments

Comments
 (0)