-
Notifications
You must be signed in to change notification settings - Fork 0
/
lww_element_graph_test.py
314 lines (289 loc) · 12.6 KB
/
lww_element_graph_test.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
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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
import unittest
from lww_element_graph import LWW_Element_Graph
import time
class Test_LWW_Element_Graph(unittest.TestCase):
def test_for_vertex_add_operation_idempotence(self):
"""
This method tests idempotence of CRDT for vertex addition in the graph.
This test case is also explained in the table in readme.md file.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
self.assertFalse(graph.add_vertex(1, current_timestamp - 1))
self.assertFalse(graph.add_vertex(1, current_timestamp + 1))
self.assertFalse(graph.add_vertex(1, current_timestamp + 2))
expected_arr: list = [1]
self.assertEqual(graph.get_vertices(), expected_arr)
def test_for_vertex_remove_operation_idempotence(self):
"""
This method tests idempotence of CRDT for vertex removal from the graph.
This test case is also explained in the table in readme.md file.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.remove_vertex(1, current_timestamp)
self.assertFalse(graph.remove_vertex(1, current_timestamp - 1))
self.assertFalse(graph.remove_vertex(1, current_timestamp + 1))
self.assertFalse(graph.remove_vertex(1, current_timestamp + 2))
expected_arr: list = []
self.assertEqual(graph.get_vertices(), expected_arr)
def test_for_vertex_commutativity(self):
"""
This method tests commutativity of CRDT with vertex addition and removal
using different timestamps this test case is also explained in the table
in readme.md file.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
graph.remove_vertex(1, current_timestamp)
expected_arr: list = [1]
self.assertEqual(graph.get_vertices(), expected_arr)
graph = LWW_Element_Graph({})
graph.remove_vertex(1, current_timestamp)
graph.add_vertex(1, current_timestamp)
expected_arr: list = [1]
self.assertEqual(graph.get_vertices(), expected_arr)
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp + 1)
graph.remove_vertex(1, current_timestamp-1)
expected_arr: list = [1]
self.assertEqual(graph.get_vertices(), expected_arr)
graph = LWW_Element_Graph({})
graph.remove_vertex(1, current_timestamp-1)
graph.add_vertex(1, current_timestamp+1)
expected_arr: list = [1]
self.assertEqual(graph.get_vertices(), expected_arr)
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp+1)
graph.remove_vertex(1, current_timestamp+2)
expected_arr: list = []
self.assertEqual(graph.get_vertices(), expected_arr)
graph = LWW_Element_Graph({})
graph.remove_vertex(1, current_timestamp + 2)
graph.add_vertex(1, current_timestamp + 1)
expected_arr: list = []
self.assertEqual(graph.get_vertices(), expected_arr)
def test_add_remove_vertex(self):
"""
This method tests add and remove operation of vertex in the graph.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
self.assertFalse(graph.check_vertex_exists(2))
graph.add_vertex(2, current_timestamp)
graph.remove_vertex(1, current_timestamp + 10)
self.assertTrue(graph.check_vertex_exists(2))
self.assertFalse(graph.check_vertex_exists(1))
expected_arr: list = [2]
self.assertEqual(graph.get_vertices(), expected_arr)
def test_add_remove_edge(self):
"""
This method tests add and remove operation of edge in the graph.
"""
graph = LWW_Element_Graph({})
current_timestamp = time.time()
graph.add_vertex(1, current_timestamp)
graph.add_vertex(2, current_timestamp + 10)
graph.add_vertex(3, current_timestamp + 20)
graph.add_edge((2, 3), current_timestamp)
self.assertTrue(graph.check_edge_exists((2, 3)))
graph.remove_edge((2, 3), current_timestamp + 10)
self.assertFalse(graph.check_edge_exists((2, 3)))
def test_merge_lww_graph(self):
"""
This method tests merge operation of two lww element graphs.
"""
graph_a = LWW_Element_Graph({})
graph_b = LWW_Element_Graph({})
graph_a.add_vertex(6, time.time())
graph_a.add_vertex(2, time.time())
graph_a.add_vertex(3, time.time())
graph_a.add_edge((3, 2), time.time())
graph_b.add_vertex(1, time.time())
graph_b.add_vertex(0, time.time())
graph_b.add_vertex(3, time.time())
graph_b.add_edge((3, 0), time.time())
merged = graph_a.merge(graph_b)
assert {0, 1, 2, 3, 6}.issubset(merged.add_vertex_set.keys())
assert {(3, 2), (3, 0)}.issubset(merged.add_edge_set.keys())
def test_add_remove_add_vertex(self):
"""
This method tests add->remove->add operations of vertex in the graph.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
graph.remove_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
graph.remove_vertex(1, current_timestamp + 100)
self.assertFalse(graph.check_vertex_exists(1))
graph.add_vertex(1, current_timestamp + 120)
self.assertTrue(graph.check_vertex_exists(1))
def test_remove_add_vertex(self):
"""
This method tests remove->add operations of vertex in the graph.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
self.assertFalse(graph.remove_vertex(1, current_timestamp))
graph.add_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
def test_add_edge_remove_vertex_bias(self):
"""
This method tests concurrent operations of add_edge & remove_vertex
this is a deadlock so my implementation is biased towards remove vertex.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
graph.add_vertex(2, current_timestamp)
graph.add_edge((1, 2), current_timestamp + 10)
graph.remove_vertex(2, current_timestamp + 10)
self.assertTrue(graph.check_vertex_exists(1))
self.assertFalse(graph.check_edge_exists((1, 2)))
def test_add_remove_add_edge(self):
"""
This method tests add->remove->edge operations on edge in the graph.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
graph.add_vertex(2, current_timestamp)
graph.add_edge((1, 2), current_timestamp)
self.assertTrue(graph.check_edge_exists((1, 2)))
graph.remove_edge((1, 2), current_timestamp)
self.assertTrue(graph.check_edge_exists((1, 2)))
graph.remove_edge((1, 2), current_timestamp + 100)
self.assertFalse(graph.check_edge_exists((1, 2)))
graph.add_edge((1, 2), current_timestamp + 100)
self.assertTrue(graph.check_edge_exists((1, 2)))
def test_remove_vertex_twice_in_reverse_order(self):
"""
This method tests applying remove operation twice on vertex
in reverse order of timestamps means first bigger timestamp then small.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
graph.remove_vertex(1, current_timestamp + 10)
self.assertFalse(graph.check_vertex_exists(1))
graph.remove_vertex(1, current_timestamp)
self.assertFalse(graph.check_vertex_exists(1))
expected_arr: list = []
self.assertEqual(graph.get_vertices(), expected_arr)
def test_check_vertex_exists(self):
"""
This method tests check_vertex_exists method of the graph.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
self.assertTrue(graph.check_vertex_exists(1))
self.assertFalse(graph.check_vertex_exists(2))
graph.add_vertex(2, current_timestamp)
self.assertTrue(graph.check_vertex_exists(2))
expected_arr: list = [1, 2]
self.assertEqual(graph.get_vertices(), expected_arr)
def test_query_vertices(self):
"""
This method tests query_vertices method of the graph.
It will check whether the return vertices are correct or not for a given vertex.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
graph.add_vertex(2, current_timestamp)
graph.add_vertex(3, current_timestamp)
graph.add_edge((1, 2), current_timestamp)
graph.add_edge((3, 1), current_timestamp)
graph.add_edge((3, 2), current_timestamp)
expected_arr: list = [2, 3]
self.assertEqual(graph.query_vertices(1), expected_arr)
expected_arr: list = [1, 3]
self.assertEqual(graph.query_vertices(2), expected_arr)
expected_arr: list = [1, 2]
self.assertEqual(graph.query_vertices(3), expected_arr)
def test_find_path(self):
"""
This method will test the find_path function of the graph in which
we are finding path between two vertices.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
graph.add_vertex(2, current_timestamp)
graph.add_vertex(3, current_timestamp)
graph.add_edge((1, 2), current_timestamp)
graph.add_edge((3, 2), current_timestamp)
expected_arr: list = [1, 2, 3]
self.assertEqual(graph.find_path(1, 3), expected_arr)
expected_arr: list = [1, 2]
self.assertEqual(graph.find_path(1, 2), expected_arr)
def test_empty_lookup(self):
"""
This method checks empty lookup of the graph.
"""
graph = LWW_Element_Graph({})
expected_arr: list = []
self.assertEqual(graph.get_vertices(), expected_arr)
def test_vertex_already_exists(self):
"""
This method tests if we add already existing
vertex again in the graph is it added or not.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
self.assertEqual(graph.add_vertex(1, current_timestamp + 10), False)
def test_edge_already_exists(self):
"""
This method tests if we add already existing
EDGE again in the graph is it added or not.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
graph.add_vertex(1, current_timestamp)
graph.add_vertex(2, current_timestamp)
graph.add_edge((1, 2), current_timestamp)
self.assertEqual(graph.add_edge((1, 2), current_timestamp + 10), False)
def test_add_vertex_exception(self):
"""
This method tests the exception handling of unhashable type
in add_vertex function.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
self.assertEqual(graph.add_vertex([1, 2, 3], current_timestamp), None)
def test_remove_vertex_exception(self):
"""
This method tests the exception handling of unhashable type
in remove_vertex function.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
self.assertEqual(graph.remove_vertex([1, 2, 3], current_timestamp), None)
def test_add_edge_exception(self):
"""
This method tests the exception handling of unhashable type
in add_edge function.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
self.assertEqual(graph.add_edge([1, 2, 3], current_timestamp), False)
def test_remove_edge_exception(self):
"""
This method tests the exception handling of unhashable type
in remove_edge function.
"""
current_timestamp = time.time()
graph = LWW_Element_Graph({})
self.assertEqual(graph.remove_edge([1, 2, 3], current_timestamp), None)
if __name__ == '__main__':
unittest.main(verbosity=2)