-
Notifications
You must be signed in to change notification settings - Fork 0
/
tests.py
139 lines (103 loc) · 3.73 KB
/
tests.py
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
import time
import io
import itertools
import random
import unittest
from hypothesis import given
import hypothesis.strategies as st
from serialization import read_content, write_content
from sort import merge_sort_stupid, merge_sort_k_blocks, merge_sort_k_blocks_two_passes
from util import tmp_file
class TestSort(unittest.TestCase):
_memory_size = 2**18
def setUp(self):
self._start = time.time()
def tearDown(self):
print('{}: {:.2f} seconds'.format(self.__class__.__name__, time.time() - self._start), flush=True)
def _predefined_values(self):
yield []
yield [-10]
yield [
1.6,
2.5,
1,
-1,
]
yield [
-100.,
-350.,
-200.,
]
yield itertools.chain.from_iterable(itertools.repeat([
1.6,
3.5,
99,
4,
-5,
6.6,
3,
-9000,
], 2**19))
def _random_values(self, n=2**22):
for i in range(n):
yield random.random()
def _launch_predefined_tests(self, sort_f):
for values in self._predefined_values():
self._test_simple(values, sort_f)
def _test_simple(self, values, sort_f, memory_size=None):
with tmp_file() as input_file, tmp_file() as output_file:
write_content(input_file, values)
input_file.seek(0)
sort_f(input_file, output_file, memory_size=self._memory_size if memory_size is None else memory_size)
self._check_sorted(input_file, output_file)
def _check_sorted(self, source: io.BufferedIOBase, res: io.BufferedIOBase):
hashes_size = 2**20
def h(value):
return hash(value) % hashes_size
source.seek(0)
source_content = list(itertools.repeat(0, hashes_size))
for v in read_content(source):
source_content[h(v)] += 1
res.seek(0)
res_content = list(itertools.repeat(0, hashes_size))
prev = None
for cur in read_content(res):
res_content[h(cur)] += 1
self.assertTrue(prev is None or prev <= cur)
prev = cur
self.assertTrue(source_content == res_content, 'Content differs')
class TestStupidSort(TestSort):
def test_predefined(self):
self._launch_predefined_tests(self._sort)
def test_random_big(self):
self._test_simple(self._random_values(), self._sort)
@given(st.lists(st.floats(allow_nan=False), average_size=2**10))
def test_random(self, values):
self._test_simple(values, self._sort, memory_size=2**7)
@staticmethod
def _sort(*args, **kwargs):
return merge_sort_stupid(*args, **kwargs)
class TestBlocksSort(TestSort):
def test_predefined(self):
self._launch_predefined_tests(self._sort)
def test_random_big(self):
self._test_simple(self._random_values(), self._sort)
@given(st.lists(st.floats(allow_nan=False), average_size=2**10))
def test_random(self, values):
self._test_simple(values, self._sort, memory_size=2**7)
@staticmethod
def _sort(*args, **kwargs):
return merge_sort_k_blocks(*args, **kwargs)
class Test2PassesBlocksSort(TestSort):
def test_predefined(self):
self._launch_predefined_tests(self._sort)
def test_random_big(self):
self._test_simple(self._random_values(), self._sort)
@given(st.lists(st.floats(allow_nan=False), average_size=2**10))
def test_random(self, values):
self._test_simple(values, self._sort, memory_size=2**7)
@staticmethod
def _sort(*args, **kwargs):
return merge_sort_k_blocks_two_passes(*args, **kwargs)
if __name__ == '__main__':
unittest.main()