@@ -56,19 +56,25 @@ def test_diffsync_sync_self_with_no_data_is_noop(generic_diffsync):
56
56
assert not generic_diffsync .sync_complete .called
57
57
58
58
59
- def test_diffsync_get_with_no_data_is_none (generic_diffsync ):
60
- assert generic_diffsync .get ("anything" , "myname" ) is None
61
- assert generic_diffsync .get (DiffSyncModel , "" ) is None
59
+ def test_diffsync_get_with_no_data_fails (generic_diffsync ):
60
+ with pytest .raises (ObjectNotFound ):
61
+ generic_diffsync .get ("anything" , "myname" )
62
+ with pytest .raises (ObjectNotFound ):
63
+ generic_diffsync .get (DiffSyncModel , "" )
62
64
63
65
64
66
def test_diffsync_get_all_with_no_data_is_empty_list (generic_diffsync ):
65
67
assert list (generic_diffsync .get_all ("anything" )) == []
66
68
assert list (generic_diffsync .get_all (DiffSyncModel )) == []
67
69
68
70
69
- def test_diffsync_get_by_uids_with_no_data_is_empty_list (generic_diffsync ):
70
- assert generic_diffsync .get_by_uids (["any" , "another" ], "anything" ) == []
71
- assert generic_diffsync .get_by_uids (["any" , "another" ], DiffSyncModel ) == []
71
+ def test_diffsync_get_by_uids_with_no_data (generic_diffsync ):
72
+ assert generic_diffsync .get_by_uids ([], "anything" ) == []
73
+ assert generic_diffsync .get_by_uids ([], DiffSyncModel ) == []
74
+ with pytest .raises (ObjectNotFound ):
75
+ generic_diffsync .get_by_uids (["any" , "another" ], "anything" )
76
+ with pytest .raises (ObjectNotFound ):
77
+ generic_diffsync .get_by_uids (["any" , "another" ], DiffSyncModel )
72
78
73
79
74
80
def test_diffsync_add (generic_diffsync , generic_diffsync_model ):
@@ -83,12 +89,15 @@ def test_diffsync_get_with_generic_model(generic_diffsync, generic_diffsync_mode
83
89
# The generic_diffsync_model has an empty identifier/unique-id
84
90
assert generic_diffsync .get (DiffSyncModel , "" ) == generic_diffsync_model
85
91
assert generic_diffsync .get (DiffSyncModel .get_type (), "" ) == generic_diffsync_model
86
- # DiffSync doesn't know how to construct a uid str for a "diffsyncmodel"
87
- assert generic_diffsync .get (DiffSyncModel .get_type (), {}) is None
92
+ # DiffSync doesn't know how to construct a uid str for a "diffsyncmodel" (it needs the class or instance, not a str)
93
+ with pytest .raises (ValueError ):
94
+ generic_diffsync .get (DiffSyncModel .get_type (), {})
88
95
# Wrong object-type - no match
89
- assert generic_diffsync .get ("" , "" ) is None
96
+ with pytest .raises (ObjectNotFound ):
97
+ generic_diffsync .get ("" , "" )
90
98
# Wrong unique-id - no match
91
- assert generic_diffsync .get (DiffSyncModel , "myname" ) is None
99
+ with pytest .raises (ObjectNotFound ):
100
+ generic_diffsync .get (DiffSyncModel , "myname" )
92
101
93
102
94
103
def test_diffsync_get_all_with_generic_model (generic_diffsync , generic_diffsync_model ):
@@ -104,9 +113,11 @@ def test_diffsync_get_by_uids_with_generic_model(generic_diffsync, generic_diffs
104
113
assert generic_diffsync .get_by_uids (["" ], DiffSyncModel ) == [generic_diffsync_model ]
105
114
assert generic_diffsync .get_by_uids (["" ], DiffSyncModel .get_type ()) == [generic_diffsync_model ]
106
115
# Wrong unique-id - no match
107
- assert generic_diffsync .get_by_uids (["myname" ], DiffSyncModel ) == []
108
- # Valid unique-id mixed in with unknown ones - return the successful matches?
109
- assert generic_diffsync .get_by_uids (["aname" , "" , "anothername" ], DiffSyncModel ) == [generic_diffsync_model ]
116
+ with pytest .raises (ObjectNotFound ):
117
+ generic_diffsync .get_by_uids (["myname" ], DiffSyncModel )
118
+ # Valid unique-id mixed in with unknown ones
119
+ with pytest .raises (ObjectNotFound ):
120
+ generic_diffsync .get_by_uids (["aname" , "" , "anothername" ], DiffSyncModel )
110
121
111
122
112
123
def test_diffsync_remove_with_generic_model (generic_diffsync , generic_diffsync_model ):
@@ -115,18 +126,19 @@ def test_diffsync_remove_with_generic_model(generic_diffsync, generic_diffsync_m
115
126
with pytest .raises (ObjectNotFound ):
116
127
generic_diffsync .remove (generic_diffsync_model )
117
128
118
- assert generic_diffsync .get (DiffSyncModel , "" ) is None
129
+ with pytest .raises (ObjectNotFound ):
130
+ generic_diffsync .get (DiffSyncModel , "" )
119
131
assert list (generic_diffsync .get_all (DiffSyncModel )) == []
120
- assert generic_diffsync .get_by_uids (["" ], DiffSyncModel ) == []
132
+ with pytest .raises (ObjectNotFound ):
133
+ generic_diffsync .get_by_uids (["" ], DiffSyncModel )
121
134
122
135
123
- def test_diffsync_subclass_validation ():
124
- """Test the declaration-time checks on a DiffSync subclass."""
136
+ def test_diffsync_subclass_validation_name_mismatch ():
125
137
# pylint: disable=unused-variable
126
138
with pytest .raises (AttributeError ) as excinfo :
127
139
128
140
class BadElementName (DiffSync ):
129
- """Model with a DiffSyncModel attribute whose name does not match the modelname."""
141
+ """DiffSync with a DiffSyncModel attribute whose name does not match the modelname."""
130
142
131
143
dev_class = Device # should be device = Device
132
144
@@ -135,6 +147,35 @@ class BadElementName(DiffSync):
135
147
assert "dev_class" in str (excinfo .value )
136
148
137
149
150
+ def test_diffsync_subclass_validation_missing_top_level ():
151
+ # pylint: disable=unused-variable
152
+ with pytest .raises (AttributeError ) as excinfo :
153
+
154
+ class MissingTopLevel (DiffSync ):
155
+ """DiffSync whose top_level references an attribute that does not exist on the class."""
156
+
157
+ top_level = ["missing" ]
158
+
159
+ assert "top_level" in str (excinfo .value )
160
+ assert "missing" in str (excinfo .value )
161
+ assert "is not a class attribute" in str (excinfo .value )
162
+
163
+
164
+ def test_diffsync_subclass_validation_top_level_not_diffsyncmodel ():
165
+ # pylint: disable=unused-variable
166
+ with pytest .raises (AttributeError ) as excinfo :
167
+
168
+ class TopLevelNotDiffSyncModel (DiffSync ):
169
+ """DiffSync whose top_level references an attribute that is not a DiffSyncModel subclass."""
170
+
171
+ age = 0
172
+ top_level = ["age" ]
173
+
174
+ assert "top_level" in str (excinfo .value )
175
+ assert "age" in str (excinfo .value )
176
+ assert "is not a DiffSyncModel" in str (excinfo .value )
177
+
178
+
138
179
def test_diffsync_dict_with_data (backend_a ):
139
180
assert backend_a .dict () == {
140
181
"device" : {
@@ -238,7 +279,9 @@ def test_diffsync_str_with_data(backend_a):
238
279
interface: rdu-spine2__eth0: {'interface_type': 'ethernet', 'description': 'Interface 0'}
239
280
interface: rdu-spine2__eth1: {'interface_type': 'ethernet', 'description': 'Interface 1'}
240
281
people
241
- person: Glenn Matthews: {}"""
282
+ person: Glenn Matthews: {}
283
+ unused: []\
284
+ """
242
285
)
243
286
244
287
@@ -308,17 +351,21 @@ def test_diffsync_sync_from(backend_a, backend_b):
308
351
site_atl_a = backend_a .get ("site" , "atl" )
309
352
assert isinstance (site_atl_a , Site )
310
353
assert site_atl_a .name == "atl"
311
- assert backend_a .get (Site , "rdu" ) is None
312
- assert backend_a .get ("nothing" , "" ) is None
354
+ with pytest .raises (ObjectNotFound ):
355
+ backend_a .get (Site , "rdu" )
356
+ with pytest .raises (ObjectNotFound ):
357
+ backend_a .get ("nothing" , "" )
313
358
314
359
assert list (backend_a .get_all (Site )) == [site_nyc_a , site_sfo_a , site_atl_a ]
315
360
assert list (backend_a .get_all ("site" )) == [site_nyc_a , site_sfo_a , site_atl_a ]
316
361
assert list (backend_a .get_all ("nothing" )) == []
317
362
318
363
assert backend_a .get_by_uids (["nyc" , "sfo" ], Site ) == [site_nyc_a , site_sfo_a ]
319
364
assert backend_a .get_by_uids (["sfo" , "nyc" ], "site" ) == [site_sfo_a , site_nyc_a ]
320
- assert backend_a .get_by_uids (["nyc" , "sfo" ], Device ) == []
321
- assert backend_a .get_by_uids (["nyc" , "sfo" ], "device" ) == []
365
+ with pytest .raises (ObjectNotFound ):
366
+ backend_a .get_by_uids (["nyc" , "sfo" ], Device )
367
+ with pytest .raises (ObjectNotFound ):
368
+ backend_a .get_by_uids (["nyc" , "sfo" ], "device" )
322
369
323
370
324
371
def test_diffsync_subclass_default_name_type (backend_a ):
@@ -354,6 +401,18 @@ def test_diffsync_add_get_remove_with_subclass_and_data(backend_a):
354
401
backend_a .remove (site_atl_a )
355
402
356
403
404
+ def test_diffsync_remove_missing_child (log , backend_a ):
405
+ rdu_spine1 = backend_a .get (Device , "rdu-spine1" )
406
+ rdu_spine1_eth0 = backend_a .get (Interface , "rdu-spine1__eth0" )
407
+ # Usage error - remove rdu_spine1_eth0 from backend_a, but rdu_spine1 still has a reference to it
408
+ backend_a .remove (rdu_spine1_eth0 )
409
+ # Should log an error but continue removing other child objects
410
+ backend_a .remove (rdu_spine1 , remove_children = True )
411
+ assert log .has ("Unable to remove child rdu-spine1__eth0 of device rdu-spine1 - not found!" , diffsync = backend_a )
412
+ with pytest .raises (ObjectNotFound ):
413
+ backend_a .get (Interface , "rdu-spine1__eth1" )
414
+
415
+
357
416
def test_diffsync_sync_from_exceptions_are_not_caught_by_default (error_prone_backend_a , backend_b ):
358
417
with pytest .raises (ObjectCrudException ):
359
418
error_prone_backend_a .sync_from (backend_b )
@@ -430,8 +489,10 @@ def test_diffsync_diff_with_skip_unmatched_both_flag(
430
489
def test_diffsync_sync_with_skip_unmatched_src_flag (backend_a , backend_a_with_extra_models ):
431
490
backend_a .sync_from (backend_a_with_extra_models , flags = DiffSyncFlags .SKIP_UNMATCHED_SRC )
432
491
# New objects should not have been created
433
- assert backend_a .get (backend_a .site , "lax" ) is None
434
- assert backend_a .get (backend_a .device , "nyc-spine3" ) is None
492
+ with pytest .raises (ObjectNotFound ):
493
+ backend_a .get (backend_a .site , "lax" )
494
+ with pytest .raises (ObjectNotFound ):
495
+ backend_a .get (backend_a .device , "nyc-spine3" )
435
496
assert "nyc-spine3" not in backend_a .get (backend_a .site , "nyc" ).devices
436
497
437
498
@@ -491,7 +552,8 @@ class NoDeleteInterfaceDiffSync(BackendA):
491
552
# NoDeleteInterface.delete() should not be called since we're deleting its parent only
492
553
extra_models .sync_from (backend_a )
493
554
# The extra interface should have been removed from the DiffSync without calling its delete() method
494
- assert extra_models .get (extra_models .interface , extra_interface .get_unique_id ()) is None
555
+ with pytest .raises (ObjectNotFound ):
556
+ extra_models .get (extra_models .interface , extra_interface .get_unique_id ())
495
557
# The sync should be complete, regardless
496
558
diff = extra_models .diff_from (backend_a )
497
559
print (diff .str ()) # for debugging of any failure
0 commit comments