1- """Tests for delta compression (arena.delta.deep_diff )."""
1+ """Tests for delta compression (arena.delta.shallow_diff )."""
22
33import json
44import unittest
55
6- from arena .delta import deep_diff
6+ from arena .delta import shallow_diff
77
88
9- class TestDeepDiff (unittest .TestCase ):
10- """Unit tests for deep_diff function."""
9+ class TestShallowDiff (unittest .TestCase ):
10+ """Unit tests for shallow_diff function (top-level keys only) ."""
1111
1212 def test_identical_objects (self ):
1313 """Identical dicts should produce empty diff."""
1414 d = {"position" : {"x" : 1 , "y" : 2 , "z" : 3 }, "color" : "#ff0000" }
15- self .assertEqual (deep_diff (d , d .copy ()), {})
15+ self .assertEqual (shallow_diff (d , d .copy ()), {})
1616
1717 def test_position_change (self ):
18- """Only changed position fields should appear in diff ."""
18+ """Changed position dict (even partial) should be included completely ."""
1919 prev = {"position" : {"x" : 2.965 , "y" : 1.6 , "z" : 8.877 }, "rotation" : {"w" : 1 , "x" : 0 , "y" : 0 , "z" : 0 }}
2020 next_val = {"position" : {"x" : 2.852 , "y" : 1.6 , "z" : 8.88 }, "rotation" : {"w" : 1 , "x" : 0 , "y" : 0 , "z" : 0 }}
21- diff = deep_diff (prev , next_val )
22- self .assertEqual (diff , {"position" : {"x" : 2.852 , "z" : 8.88 }})
21+ diff = shallow_diff (prev , next_val )
22+ # Position changed, so full position is included (no recursion)
23+ self .assertEqual (diff , {"position" : {"x" : 2.852 , "y" : 1.6 , "z" : 8.88 }})
2324 self .assertNotIn ("rotation" , diff )
2425
2526 def test_camera_sequence (self ):
26- """Full camera message delta from spec — only position.x and position.z changed ."""
27+ """Camera message with position change — sends full position (no recursion) ."""
2728 prev_data = {
2829 "arena-user" : {
2930 "color" : "#eca7ef" ,
@@ -52,10 +53,11 @@ def test_camera_sequence(self):
5253 "position" : {"x" : 2.852 , "y" : 1.6 , "z" : 8.88 },
5354 "rotation" : {"w" : 1 , "x" : - 0.019 , "y" : 0.013 , "z" : 0 },
5455 }
55- diff = deep_diff (prev_data , next_data )
56- self .assertEqual (diff , {"position" : {"x" : 2.852 , "z" : 8.88 }})
56+ diff = shallow_diff (prev_data , next_data )
57+ # Position and arena-user dicts changed, so both are sent completely
58+ self .assertEqual (diff , {"position" : {"x" : 2.852 , "y" : 1.6 , "z" : 8.88 }})
5759
58- # Verify the delta is much smaller than the full payload
60+ # Verify the delta is still much smaller than the full payload
5961 full_size = len (json .dumps (next_data ))
6062 delta_size = len (json .dumps (diff ))
6163 self .assertLess (delta_size , full_size / 2 )
@@ -64,103 +66,105 @@ def test_null_component_delete(self):
6466 """None value (semantic delete) must flow through the diff."""
6567 prev = {"object_type" : "box" , "material" : {"color" : "#ff0000" }}
6668 next_val = {"object_type" : "box" , "material" : None }
67- diff = deep_diff (prev , next_val )
69+ diff = shallow_diff (prev , next_val )
6870 self .assertEqual (diff , {"material" : None })
6971
7072 def test_null_to_null_noop (self ):
7173 """Both prev and next have None for same key → omitted from diff."""
7274 prev = {"object_type" : "box" , "material" : None }
7375 next_val = {"object_type" : "box" , "material" : None }
74- diff = deep_diff (prev , next_val )
76+ diff = shallow_diff (prev , next_val )
7577 self .assertEqual (diff , {})
7678
7779 def test_new_field_added (self ):
7880 """Field in next but not prev should be included."""
7981 prev = {"object_type" : "box" }
8082 next_val = {"object_type" : "box" , "material" : {"color" : "#00ff00" }}
81- diff = deep_diff (prev , next_val )
83+ diff = shallow_diff (prev , next_val )
8284 self .assertEqual (diff , {"material" : {"color" : "#00ff00" }})
8385
8486 def test_field_removed (self ):
8587 """Field in prev but not next → emitted as None (semantic delete)."""
8688 prev = {"object_type" : "box" , "material" : {"color" : "#ff0000" }}
8789 next_val = {"object_type" : "box" }
88- diff = deep_diff (prev , next_val )
90+ diff = shallow_diff (prev , next_val )
8991 self .assertEqual (diff , {"material" : None })
9092
9193 def test_nested_partial_change (self ):
92- """Only changed fields in nested dicts should appear ."""
94+ """Changed nested dict is sent completely (no recursion) ."""
9395 prev = {"material" : {"color" : "#ff0000" , "opacity" : 0.5 , "transparent" : True }}
9496 next_val = {"material" : {"color" : "#00ff00" , "opacity" : 0.5 , "transparent" : True }}
95- diff = deep_diff (prev , next_val )
96- self .assertEqual (diff , {"material" : {"color" : "#00ff00" }})
97+ diff = shallow_diff (prev , next_val )
98+ # Material changed, so full material dict is sent
99+ self .assertEqual (diff , {"material" : {"color" : "#00ff00" , "opacity" : 0.5 , "transparent" : True }})
97100
98101 def test_array_unchanged (self ):
99102 """Identical arrays should be omitted from diff."""
100103 prev = {"path" : [[0 , 0 , 0 ], [1 , 1 , 1 ]], "object_type" : "line" }
101104 next_val = {"path" : [[0 , 0 , 0 ], [1 , 1 , 1 ]], "object_type" : "line" }
102- diff = deep_diff (prev , next_val )
105+ diff = shallow_diff (prev , next_val )
103106 self .assertEqual (diff , {})
104107
105108 def test_array_changed (self ):
106109 """Changed arrays should be included in diff."""
107110 prev = {"path" : [[0 , 0 , 0 ], [1 , 1 , 1 ]]}
108111 next_val = {"path" : [[0 , 0 , 0 ], [2 , 2 , 2 ]]}
109- diff = deep_diff (prev , next_val )
112+ diff = shallow_diff (prev , next_val )
110113 self .assertEqual (diff , {"path" : [[0 , 0 , 0 ], [2 , 2 , 2 ]]})
111114
112115 def test_deep_nested_diff (self ):
113- """3+ levels of nesting should be handled correctly ."""
116+ """Deeply nested dicts are sent completely if any change (no recursion) ."""
114117 prev = {"a" : {"b" : {"c" : {"d" : 1 , "e" : 2 }}, "f" : 3 }}
115118 next_val = {"a" : {"b" : {"c" : {"d" : 1 , "e" : 99 }}, "f" : 3 }}
116- diff = deep_diff (prev , next_val )
117- self .assertEqual (diff , {"a" : {"b" : {"c" : {"e" : 99 }}}})
119+ diff = shallow_diff (prev , next_val )
120+ # "a" dict changed, so full "a" dict is sent
121+ self .assertEqual (diff , {"a" : {"b" : {"c" : {"d" : 1 , "e" : 99 }}, "f" : 3 }})
118122
119123 def test_empty_dicts (self ):
120124 """Two empty dicts should produce empty diff."""
121- self .assertEqual (deep_diff ({}, {}), {})
125+ self .assertEqual (shallow_diff ({}, {}), {})
122126
123127 def test_prev_empty (self ):
124128 """Empty prev means everything in next is new."""
125129 next_val = {"position" : {"x" : 1 , "y" : 2 , "z" : 3 }}
126- diff = deep_diff ({}, next_val )
130+ diff = shallow_diff ({}, next_val )
127131 self .assertEqual (diff , next_val )
128132
129133 def test_next_empty (self ):
130134 """Empty next means everything in prev is deleted."""
131135 prev = {"position" : {"x" : 1 }, "color" : "red" }
132- diff = deep_diff (prev , {})
136+ diff = shallow_diff (prev , {})
133137 self .assertEqual (diff , {"position" : None , "color" : None })
134138
135139 def test_type_change_dict_to_primitive (self ):
136140 """Dict replaced by primitive should include the new value."""
137141 prev = {"material" : {"color" : "#ff0000" }}
138142 next_val = {"material" : "basic" }
139- diff = deep_diff (prev , next_val )
143+ diff = shallow_diff (prev , next_val )
140144 self .assertEqual (diff , {"material" : "basic" })
141145
142146 def test_type_change_primitive_to_dict (self ):
143147 """Primitive replaced by dict should include the new dict."""
144148 prev = {"material" : "basic" }
145149 next_val = {"material" : {"color" : "#ff0000" }}
146- diff = deep_diff (prev , next_val )
150+ diff = shallow_diff (prev , next_val )
147151 self .assertEqual (diff , {"material" : {"color" : "#ff0000" }})
148152
149153 def test_bool_change (self ):
150154 """Boolean changes should be detected."""
151155 prev = {"hasAudio" : False , "hasVideo" : False }
152156 next_val = {"hasAudio" : True , "hasVideo" : False }
153- diff = deep_diff (prev , next_val )
157+ diff = shallow_diff (prev , next_val )
154158 self .assertEqual (diff , {"hasAudio" : True })
155159
156160 def test_float_precision (self ):
157161 """Float values should be compared with ==."""
158162 prev = {"x" : 1.0 }
159163 next_val = {"x" : 1.0 }
160- self .assertEqual (deep_diff (prev , next_val ), {})
164+ self .assertEqual (shallow_diff (prev , next_val ), {})
161165
162166 next_val2 = {"x" : 1.0000001 }
163- diff = deep_diff (prev , next_val2 )
167+ diff = shallow_diff (prev , next_val2 )
164168 self .assertEqual (diff , {"x" : 1.0000001 })
165169
166170
@@ -246,8 +250,8 @@ def test_update_with_delta(self):
246250 result = scene ._apply_delta (json .dumps (update_msg ), "update" )
247251 result_msg = json .loads (result )
248252
249- # data should only have position delta
250- self .assertEqual (result_msg ["data" ], {"position" : {"x" : 2.852 , "z" : 8.88 }})
253+ # data should have full position (shallow diff sends complete changed dicts)
254+ self .assertEqual (result_msg ["data" ], {"position" : {"x" : 2.852 , "y" : 1.6 , " z" : 8.88 }})
251255 # top-level fields preserved
252256 self .assertEqual (result_msg ["object_id" ], "cam1" )
253257 self .assertEqual (result_msg ["action" ], "update" )
0 commit comments