11import json
2+ import uuid
23
34import mock
45from django .db .models import Q
5- from django .test import SimpleTestCase
6+ from django .test import SimpleTestCase , TestCase
67
78from morango .models .certificates import Filter
89from morango .models .core import InstanceIDModel , RecordMaxCounter , Store , SyncableModel
@@ -143,6 +144,18 @@ def test_transform(self, mock_bulk, mock_qs):
143144
144145
145146class StoreUpdateTestCase (SimpleTestCase ):
147+ def _build_sync_obj (self , ** overrides ):
148+ obj = mock .Mock ()
149+ obj .id = uuid .uuid4 ().hex
150+ obj .serialize .return_value = {}
151+ obj .morango_model_name = "mymodel"
152+ obj .morango_profile = "profile"
153+ obj ._morango_partition = "partition"
154+ obj ._morango_source_id = "src"
155+ for key , value in overrides .items ():
156+ setattr (obj , key , value )
157+ return obj
158+
146159 @mock .patch ("morango.sync.stream.serialize.StoreUpdate._handle_store_create" )
147160 def test_transform__creates (self , mock_handle_store_create ):
148161 current_id = mock .Mock (id = "inst_1" , counter = 10 )
@@ -176,7 +189,8 @@ def test_transform__updates(self, mock_handle_store_update):
176189 mock_handle_store_update .assert_called_once_with (task )
177190 self .assertEqual (task .counter .counter , 10 )
178191
179- def test_handle_store_update (self ):
192+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = None )
193+ def test_handle_store_update (self , _mock_srf ):
180194 current_id = mock .Mock (id = "inst_1" , counter = 10 )
181195 update = StoreUpdate (current_id )
182196
@@ -193,6 +207,126 @@ def test_handle_store_update(self):
193207 self .assertEqual (ser_data ["old" ], 1 )
194208 self .assertEqual (ser_data ["new" ], 2 )
195209
210+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = None )
211+ def test_handle_store_create__non_self_ref (self , _mock_srf ):
212+ current_id = mock .Mock (id = "inst_1" , counter = 1 )
213+ update = StoreUpdate (current_id )
214+
215+ obj = self ._build_sync_obj ()
216+
217+ task = SerializeTask (mock .Mock (), obj )
218+ update ._handle_store_create (task )
219+
220+ self .assertIsNone (task .store ._self_ref_order )
221+
222+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = "parent_id" )
223+ def test_handle_store_create__self_ref_no_parent (self , _mock_srf ):
224+ current_id = mock .Mock (id = "inst_1" , counter = 1 )
225+ update = StoreUpdate (current_id )
226+
227+ obj = self ._build_sync_obj (parent_id = None ) # no parent
228+
229+ task = SerializeTask (mock .Mock (), obj )
230+ update ._handle_store_create (task )
231+
232+ self .assertEqual (task .store ._self_ref_fk , "" )
233+ self .assertEqual (task .store ._self_ref_order , 0 )
234+
235+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = "parent_id" )
236+ def test_handle_store_update__self_ref_fk_unchanged (self , _mock_srf ):
237+ current_id = mock .Mock (id = "inst_1" , counter = 2 )
238+ update = StoreUpdate (current_id )
239+
240+ parent_id = uuid .uuid4 ().hex
241+ store = Store (
242+ serialized = json .dumps ({}),
243+ dirty_bit = False ,
244+ _self_ref_fk = parent_id ,
245+ _self_ref_order = 5 ,
246+ )
247+ obj = self ._build_sync_obj (parent_id = parent_id ) # same FK — no change
248+
249+ task = SerializeTask (mock .Mock (), obj )
250+ task .set_store (store )
251+ update ._handle_store_update (task )
252+
253+ self .assertEqual (task .store ._self_ref_fk , parent_id )
254+ self .assertEqual (task .store ._self_ref_order , 5 )
255+
256+
257+ def _make_store (** kwargs ):
258+ defaults = dict (
259+ id = uuid .uuid4 ().hex ,
260+ profile = "facilitydata" ,
261+ serialized = "{}" ,
262+ last_saved_instance = uuid .uuid4 ().hex ,
263+ last_saved_counter = 1 ,
264+ partition = "partition" ,
265+ source_id = uuid .uuid4 ().hex ,
266+ model_name = "facility" ,
267+ )
268+ defaults .update (kwargs )
269+ return Store .objects .create (** defaults )
270+
271+
272+ class StoreUpdateSelfRefOrderDbTestCase (TestCase ):
273+ def setUp (self ):
274+ self .current_id = mock .Mock (id = "inst_1" , counter = 1 )
275+ self .update = StoreUpdate (self .current_id )
276+
277+ def _task (self , self_ref_fk_field , fk_value ):
278+ obj = mock .Mock ()
279+ obj .id = uuid .uuid4 ().hex
280+ obj .serialize .return_value = {}
281+ obj .morango_model_name = "facility"
282+ obj .morango_profile = "facilitydata"
283+ obj ._morango_partition = "partition"
284+ obj ._morango_source_id = "src"
285+ setattr (obj , self_ref_fk_field , fk_value )
286+ return SerializeTask (mock .Mock (), obj )
287+
288+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = "parent_id" )
289+ def test_handle_store_create__self_ref_with_parent (self , _mock_srf ):
290+ parent_store = _make_store (_self_ref_order = 3 )
291+
292+ task = self ._task ("parent_id" , parent_store .id )
293+ self .update ._handle_store_create (task )
294+
295+ self .assertEqual (task .store ._self_ref_fk , parent_store .id )
296+ self .assertEqual (task .store ._self_ref_order , 3 )
297+
298+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = "parent_id" )
299+ def test_handle_store_create__self_ref_parent_not_in_store (self , _mock_srf ):
300+ missing_parent_id = uuid .uuid4 ().hex
301+
302+ task = self ._task ("parent_id" , missing_parent_id )
303+ self .update ._handle_store_create (task )
304+
305+ self .assertEqual (task .store ._self_ref_fk , missing_parent_id )
306+ self .assertIsNone (task .store ._self_ref_order )
307+
308+ @mock .patch ("morango.sync.stream.serialize.self_referential_fk" , return_value = "parent_id" )
309+ def test_handle_store_update__self_ref_fk_changed (self , _mock_srf ):
310+ old_parent_store = _make_store (_self_ref_order = 0 )
311+ new_parent_store = _make_store (_self_ref_order = 7 )
312+
313+ store = Store (
314+ serialized = json .dumps ({}),
315+ dirty_bit = False ,
316+ _self_ref_fk = old_parent_store .id ,
317+ _self_ref_order = 0 ,
318+ )
319+ obj = mock .Mock ()
320+ obj .serialize .return_value = {}
321+ obj .parent_id = new_parent_store .id # FK changed
322+
323+ task = SerializeTask (mock .Mock (), obj )
324+ task .set_store (store )
325+ self .update ._handle_store_update (task )
326+
327+ self .assertEqual (task .store ._self_ref_fk , new_parent_store .id )
328+ self .assertEqual (task .store ._self_ref_order , 7 )
329+
196330
197331class ModelPartitionBufferTestCase (SimpleTestCase ):
198332 def test_buffer_splits_on_model_change (self ):
0 commit comments