forked from y-crdt/ypy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_y_map.py
284 lines (219 loc) · 7.36 KB
/
test_y_map.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
from copy import deepcopy
import json
import pytest
import y_py as Y
from y_py import YMap, YMapEvent
def test_get():
import y_py as Y
d = Y.YDoc()
m = d.get_map("map")
# Put user info into the map.
with d.begin_transaction() as txn:
m.update(txn, {"username": "John", "online": True})
# Extract the information from the map.
assert m.get("username") == "John"
assert m["online"] == True
# Ensure the default value is returned when key doesn't exist in map.
assert m.get("secretIdentity", "basic") == "basic"
# Ensure that nonexistant keys without default values return None.
assert m.get("SocialSecurityNumber") is None
# Ensure that indexing a non_existant key with bracket notation produces `KeyError`
with pytest.raises(KeyError):
m["doesn't exist"]
def test_set():
d1 = Y.YDoc()
x = d1.get_map("test")
value = x.get("key")
assert value == None
d1.transact(lambda txn: x.set(txn, "key", "value1"))
value = x["key"]
assert value == "value1"
d1.transact(lambda txn: x.set(txn, "key", "value2"))
value = x["key"]
assert value == "value2"
def test_to_json():
contents = {"emojis": [
{"icon":"👍", "description": "thumbs up", "positive":True},
{"icon":"👎", "description": "thumbs down", "positive":False},
]}
doc = Y.YDoc()
prelim = Y.YMap(deepcopy(contents))
integrated = doc.get_map("map")
with doc.begin_transaction() as txn:
integrated.update(txn, contents)
# ensure that it works with python json
assert json.loads(integrated.to_json()) == contents
def test_update():
doc = Y.YDoc()
ymap = doc.get_map("dict")
dict_vals = {"user_id": 1, "username": "Josh", "is_active": True}
tuple_vals = ((k, v) for k, v in dict_vals.items())
# Test updating with a dictionary
with doc.begin_transaction() as txn:
ymap.update(txn, dict_vals)
assert dict(ymap) == dict_vals
# Test updating with an iterator
ymap = doc.get_map("tuples")
with doc.begin_transaction() as txn:
ymap.update(txn, tuple_vals)
assert dict(ymap) == dict_vals
# Test non-string key error
with pytest.raises(Exception) as e:
with doc.begin_transaction() as txn:
ymap.update(txn, [(1, 2)])
# Test non-kv-tuple error
with pytest.raises(Exception) as e:
with doc.begin_transaction() as txn:
ymap.update(txn, [1])
def test_set_nested():
d1 = Y.YDoc()
x = d1.get_map("test")
nested = Y.YMap({"a": "A"})
d1.transact(lambda txn: x.set(txn, "key", nested))
d1.transact(lambda txn: nested.set(txn, "b", "B"))
assert type(x["key"]) == Y.YMap
assert {k : dict(v) for k, v in x.items()} == {"key": {"a": "A", "b": "B"}}
def test_pop():
d1 = Y.YDoc()
x = d1.get_map("test")
d1.transact(lambda txn: x.set(txn, "key", "value1"))
length = len(x)
value = x["key"]
assert length == 1
assert value == "value1"
d1.transact(lambda txn: x.pop(txn, "key"))
with pytest.raises(KeyError):
with d1.begin_transaction() as txn:
x.pop(txn, "does not exist")
assert x.pop(txn, "does not exist", "fallback") == "fallback"
length = len(x)
value = x.get("key")
assert length == 0
assert value == None
d1.transact(lambda txn: x.set(txn, "key", "value2"))
length = len(x)
value = x["key"]
assert length == 1
assert value == "value2"
def test_items_view():
d = Y.YDoc()
m = d.get_map("test")
with d.begin_transaction() as txn:
vals = {"a": 1, "b": 2, "c": 3}
m.update(txn, vals)
items = m.items()
# Ensure that the item view is a multi use iterator
for _ in range(2):
expected = vals.copy()
for (key, val) in items:
v = expected[key]
assert val == v
del expected[key]
assert len(items) == 3
assert ("b", 2) in items
# Ensure that the item view stays up to date with map state
m.set(txn, "d", 4)
assert ("d", 4) in items
def test_keys_values():
d = Y.YDoc()
m = d.get_map("test")
expected_keys = list("abc")
expected_values = list(range(1, 4))
with d.begin_transaction() as txn:
m.update(txn, zip(expected_keys, expected_values))
# Ensure basic iteration works
for key in m:
assert key in expected_keys
assert key in m
# Ensure keys can be iterated over multiple times
keys = m.keys()
for _ in range(2):
for key in keys:
assert key in expected_keys
assert key in keys
values = m.values()
for _ in range(2):
for val in values:
assert val in expected_values
assert val in values
# Ensure keys and values reflect updates to map
with d.begin_transaction() as txn:
m.set(txn, "d", 4)
assert "d" in keys
assert 4 in values
# Ensure key view operations
assert len(keys) == 4
assert len(values) == 4
def test_observer():
d1 = Y.YDoc()
x = d1.get_map("test")
target = None
entries = None
def callback(e: YMapEvent):
nonlocal target
nonlocal entries
target = e.target
entries = e.keys
subscription_id = x.observe(callback)
# insert initial data to an empty YMap
with d1.begin_transaction() as txn:
x.set(txn, "key1", "value1")
x.set(txn, "key2", 2)
assert dict(target) == dict(x)
assert entries == {
"key1": {"action": "add", "newValue": "value1"},
"key2": {"action": "add", "newValue": 2},
}
target = None
entries = None
# remove an entry and update another on
with d1.begin_transaction() as txn:
x.pop(txn, "key1")
x.set(txn, "key2", "value2")
assert dict(target) == dict(x)
assert entries == {
"key1": {"action": "delete", "oldValue": "value1"},
"key2": {"action": "update", "oldValue": 2, "newValue": "value2"},
}
target = None
entries = None
# free the observer and make sure that callback is no longer called
x.unobserve(subscription_id)
with d1.begin_transaction() as txn:
x.set(txn, "key1", [6])
assert target == None
assert entries == None
def test_deep_observe():
"""
Ensure that changes to elements inside the array trigger a callback.
"""
doc = Y.YDoc()
container = doc.get_map("container")
inner_map = Y.YMap({"key": "initial"})
with doc.begin_transaction() as txn:
container.set(txn, "inner", inner_map)
events = None
def callback(e: list):
nonlocal events
events = e
assert len(e[0].path()) == 1
sub = container.observe_deep(callback)
with doc.begin_transaction() as txn:
container["inner"].set(txn, "addition", 1)
events = None
container.unobserve(sub)
with doc.begin_transaction() as txn:
container["inner"].set(txn, "don't show up", 1)
assert events is None
def test_borrow_issue():
doc = Y.YDoc()
wrapper = doc.get_array("wrapper")
inner = Y.YMap({"Foo": "Bar"})
with doc.begin_transaction() as txn:
wrapper.append(txn, inner)
def test_integrate_nested_map():
d1 = Y.YDoc()
array = d1.get_array("test")
nested = Y.YMap({"a": Y.YArray(["A"])})
d1.transact(lambda txn: array.append(txn, nested))
assert array[0]["a"][0] == "A"