11import unittest
2+ import sys
23from regions import Region , is_local
34from immutable import freeze , isfrozen
45
5- class BaseTestRegionDict (unittest .TestCase ):
6+ class TestRegionDict (unittest .TestCase ):
7+ def check_view_ref (self , create_view ):
8+ # Setup
9+ r = Region ()
10+ r .dict = {}
11+ base_lrc = r ._lrc
12+
13+ # Pre-condition
14+ self .assertGreater (base_lrc , 0 )
15+
16+ # Action: Creating a view
17+ view = create_view (r .dict )
18+ self .assertEqual (r ._lrc , base_lrc + 1 )
19+
20+ # Action: Check mapping of view
21+ mapping = view .mapping
22+ self .assertEqual (r ._lrc , base_lrc + 2 )
23+
24+ # Clearing references could decrease the LRC
25+ mapping = None
26+ self .assertEqual (r ._lrc , base_lrc + 1 )
27+ view = None
28+ self .assertEqual (r ._lrc , base_lrc )
29+
30+ def test_new_dict_refs_from_item_view (self ):
31+ self .check_view_ref (lambda dict : dict .items ())
32+
33+ def test_new_dict_refs_from_keys_view (self ):
34+ self .check_view_ref (lambda dict : dict .keys ())
35+
36+ def test_new_dict_refs_from_values_view (self ):
37+ self .check_view_ref (lambda dict : dict .values ())
38+
39+ class BaseTestRegionDictKeys (unittest .TestCase ):
640 __test__ = False
741
842 def check_dict_assign (self , dict , key ):
@@ -103,8 +137,39 @@ class SomeObject:
103137 # Post-condition
104138 self .assertEqual (r ._lrc , lrc + 1 )
105139
140+ def check_loop_lrc_change (self , region , iter_src , loop_lrc_effect , iter_lrc_cost = 1 ):
141+ # Check loop iterations change the LRC
142+ lrc = region ._lrc
143+ i = 0
144+ for v in iter_src :
145+ self .assertEqual (region ._lrc , lrc + iter_lrc_cost + loop_lrc_effect ,
146+ f"Fail in iteration: { i } base LRC { lrc } + { iter_lrc_cost } for iter" )
147+ # Reassigning v should reset the LRC
148+ v = None
149+ self .assertEqual (region ._lrc , lrc + iter_lrc_cost ,
150+ f"LRC didn't reset in iteration: { i } base LRC { lrc } + { iter_lrc_cost } for iter" )
151+ i += 1
152+
153+ # Check LRC is back to pre-loop levels
154+ self .assertEqual (region ._lrc , lrc )
155+
156+ def check_dict_view (self , key1 , key2 , create_view , loop_lrc_effect , iter_lrc_cost = 1 ):
157+ class SomeObject :
158+ pass
159+ freeze (SomeObject ())
160+
161+ # Setup
162+ r = Region ()
163+ r .dict = {}
164+ r .dict [key1 ] = SomeObject ()
165+ r .dict [key2 ] = SomeObject ()
166+
167+ # Create the view
168+ view = create_view (r .dict )
169+
170+ self .check_loop_lrc_change (r , view , loop_lrc_effect , iter_lrc_cost )
106171
107- class TestRegionDictUnicodeKeys (BaseTestRegionDict ):
172+ class TestRegionDictUnicodeKeys (BaseTestRegionDictKeys ):
108173 def test_wb_insert_empty (self ):
109174 self .check_dict_assign ({}, "some-key" )
110175
@@ -138,7 +203,24 @@ def test_wb_get_default(self):
138203 def test_wb_copy (self ):
139204 self .check_dict_item_access ("another key" , lambda dict , key : dict .copy ())
140205
141- class TestRegionDictObjectKeys (BaseTestRegionDict ):
206+ def test_wb_keys_view (self ):
207+ self .check_dict_view ("K1" , "K2" , lambda d : d .keys (), loop_lrc_effect = 0 )
208+
209+ def test_wb_values_view (self ):
210+ self .check_dict_view ("K1" , "K2" , lambda d : d .values (), loop_lrc_effect = 1 )
211+
212+ @unittest .expectedFailure # FIXME(regions): xFrednet: Broken until WBs in tuples have been added
213+ def test_wb_items_view (self ):
214+ self .check_dict_view ("K1" , "K2" , lambda d : d .items (), loop_lrc_effect = 1 )
215+
216+ def test_wb_iter_dict (self ):
217+ self .check_dict_view ("K1" , "K2" , lambda d : d , loop_lrc_effect = 0 )
218+
219+ def test_wb_iter_dict_reversed (self ):
220+ # The iterator doesn't effect the LRC, since we create it with the `reversed`
221+ self .check_dict_view ("K1" , "K2" , lambda d : reversed (d ), loop_lrc_effect = 0 , iter_lrc_cost = 0 )
222+
223+ class TestRegionDictObjectKeys (BaseTestRegionDictKeys ):
142224 class Key :
143225 pass
144226
@@ -182,11 +264,26 @@ def test_wb_copy(self):
182264 # LRC increase of 2: 1x for the key 1x for the item
183265 self .check_dict_item_access (self .Key (), lambda dict , key : dict .copy (), lrc_offset = 2 )
184266
185- @unittest .expectedFailure # Broken until WBs in lists have been added
267+ @unittest .expectedFailure # FIXME(regions): xFrednet: Broken until WBs in lists have been added
186268 def test_wb_key_list (self ):
187269 self .check_dict_item_access (self .Key (), lambda dict , key : list (dict ))
188270
271+ def test_wb_keys_view (self ):
272+ self .check_dict_view (self .Key (), self .Key (), lambda d : d .keys (), 1 )
273+
274+ def test_wb_values_view (self ):
275+ self .check_dict_view (self .Key (), self .Key (), lambda d : d .values (), 1 )
189276
277+ @unittest .expectedFailure # FIXME(regions): xFrednet: Broken until WBs in tuples have been added
278+ def test_wb_items_view (self ):
279+ self .check_dict_view (self .Key (), self .Key (), lambda d : d .items (), 2 )
280+
281+ def test_wb_iter_dict (self ):
282+ self .check_dict_view (self .Key (), self .Key (), lambda d : d , loop_lrc_effect = 1 )
283+
284+ def test_wb_iter_reversed_dict (self ):
285+ # The iterator doesn't effect the LRC, since we create it with the `reversed`
286+ self .check_dict_view (self .Key (), self .Key (), lambda d : reversed (d ), loop_lrc_effect = 1 , iter_lrc_cost = 0 )
190287
191288# TODO: Construction: dict(one=1, two=2, three=3)
192289# TODO: Construction: {'one': 1, 'two': 2, 'three': 3}
@@ -195,18 +292,16 @@ def test_wb_key_list(self):
195292# TODO: Construction: dict({'three': 3, 'one': 1, 'two': 2})
196293# TODO: Construction: dict({'one': 1, 'three': 3}, two=2)
197294
198-
295+ # FIXME(regions): xFrednet: Set operations on views, like `&`, `^` and `|`
296+ # are currently not tested and probably don't work.
199297
200298# TODO: classmethod fromkeys(iterable, value=None, /)
201- # TODO: dict.items()
202- # TODO: dict.keys()
203299# TODO: dict.pop(key)
204300# TODO: dict.pop(key, default)
205301# TODO: dict.popitem(key)
206302# TODO: reversed(dict)
207303# TODO: dict.setdefault(key)
208304# TODO: dict.setdefault(key, default)
209305# TODO: dict.update(???)
210- # TODO: dict.values()
211306# TODO: dict1 | dict2
212307# TODO: dict1 |= dict2
0 commit comments