1
+ use std:: collections:: BTreeMap ;
2
+
1
3
use auto_compressor:: {
2
- manager:: { run_compressor_on_room_chunk} ,
4
+ manager:: { compress_largest_rooms , run_compressor_on_room_chunk} ,
3
5
state_saving:: { connect_to_database, create_tables_if_needed} ,
4
6
} ;
5
7
use compressor_integration_tests:: {
6
8
add_contents_to_database, clear_compressor_state, database_collapsed_states_match_map,
7
9
database_structure_matches_map, empty_database,
8
10
map_builder:: {
9
11
compressed_3_3_from_0_to_13_with_state, line_segments_with_state,
12
+ structure_from_edges_with_state,
10
13
} ,
11
14
setup_logger, DB_URL ,
12
15
} ;
13
16
use serial_test:: serial;
14
- use synapse_compress_state:: { Level } ;
17
+ use state_map:: StateMap ;
18
+ use synapse_compress_state:: { Level , StateGroupEntry } ;
15
19
16
20
#[ test]
17
21
#[ serial( db) ]
@@ -33,7 +37,7 @@ fn run_compressor_on_room_chunk_works() {
33
37
clear_compressor_state ( ) ;
34
38
35
39
// compress in 3,3 level sizes by default
36
- let default_levels = vec ! [ Level :: restore ( 3 , 0 , None ) , Level :: restore ( 3 , 0 , None ) ] ;
40
+ let default_levels = vec ! [ Level :: new ( 3 ) , Level :: new ( 3 ) ] ;
37
41
38
42
// compress the first 7 groups in the room
39
43
// structure should be the following afterwards
@@ -65,3 +69,290 @@ fn run_compressor_on_room_chunk_works() {
65
69
// Check that the structure of the database matches the expected structure
66
70
assert ! ( database_structure_matches_map( & expected) ) ;
67
71
}
72
+
73
+ #[ test]
74
+ #[ serial( db) ]
75
+ fn compress_largest_rooms_compresses_multiple_rooms ( ) {
76
+ setup_logger ( ) ;
77
+ // This creates 2 with the following structure
78
+ //
79
+ // 0-1-2 3-4-5 6-7-8 9-10-11 12-13
80
+ // (with room2's numbers shifted up 14)
81
+ //
82
+ // Each group i has state:
83
+ // ('node','is', i)
84
+ // ('group', j, 'seen') - for all j less than i in that room
85
+ let initial1 = line_segments_with_state ( 0 , 13 ) ;
86
+ let initial2 = line_segments_with_state ( 14 , 27 ) ;
87
+
88
+ empty_database ( ) ;
89
+ add_contents_to_database ( "room1" , & initial1) ;
90
+ add_contents_to_database ( "room2" , & initial2) ;
91
+
92
+ let mut client = connect_to_database ( DB_URL ) . unwrap ( ) ;
93
+ create_tables_if_needed ( & mut client) . unwrap ( ) ;
94
+ clear_compressor_state ( ) ;
95
+
96
+ // compress in 3,3 level sizes by default
97
+ let default_levels = vec ! [ Level :: new( 3 ) , Level :: new( 3 ) ] ;
98
+
99
+ // compress the largest 10 rooms in chunks of size 7
100
+ // (Note only 2 rooms should exist in the database, but this should not panic)
101
+ compress_largest_rooms ( DB_URL , 7 , & default_levels, 10 ) . unwrap ( ) ;
102
+
103
+ // We are aiming for the following structure in the database for room1
104
+ // i.e. groups 6 and 9 should have changed from initial map
105
+ // N.B. this saves 11 rows
106
+ //
107
+ // 0 3\ 12
108
+ // 1 4 6\ 13
109
+ // 2 5 7 9
110
+ // 8 10
111
+ // 11
112
+ //
113
+ // Where each group i has state:
114
+ // ('node','is', i)
115
+ // ('group', j, 'seen') - for all j less than i
116
+ let expected1 = compressed_3_3_from_0_to_13_with_state ( ) ;
117
+
118
+ // Check that the database still gives correct states for each group in room1
119
+ assert ! ( database_collapsed_states_match_map( & initial1) ) ;
120
+
121
+ // Check that the structure of the database matches the expected structure for room1
122
+ assert ! ( database_structure_matches_map( & expected1) ) ;
123
+
124
+ // room 2 should have the same structure but will all numbers shifted up by 14
125
+ let expected_edges: BTreeMap < i64 , i64 > = vec ! [
126
+ ( 15 , 14 ) ,
127
+ ( 16 , 15 ) ,
128
+ ( 18 , 17 ) ,
129
+ ( 19 , 18 ) ,
130
+ ( 20 , 17 ) ,
131
+ ( 21 , 20 ) ,
132
+ ( 22 , 21 ) ,
133
+ ( 23 , 20 ) ,
134
+ ( 24 , 23 ) ,
135
+ ( 25 , 24 ) ,
136
+ ( 27 , 26 ) ,
137
+ ]
138
+ . into_iter ( )
139
+ . collect ( ) ;
140
+
141
+ let expected2 = structure_from_edges_with_state ( expected_edges, 14 , 27 ) ;
142
+
143
+ // Check that the database still gives correct states for each group in room2
144
+ assert ! ( database_collapsed_states_match_map( & initial2) ) ;
145
+
146
+ // Check that the structure of the database matches the expected structure for room2
147
+ assert ! ( database_structure_matches_map( & expected2) ) ;
148
+ }
149
+
150
+ #[ test]
151
+ #[ serial( db) ]
152
+ fn compress_largest_rooms_does_largest_rooms ( ) {
153
+ setup_logger ( ) ;
154
+ // This creates 2 with the following structure
155
+ //
156
+ // 0-1-2 3-4-5 (room1)
157
+ // 14-15-16 17-18-19 20-21-22 23-24-25 26-27 (room2)
158
+ //
159
+ // Each group i has state:
160
+ // ('node','is', i)
161
+ // ('group', j, 'seen') - for all j less than i in that room
162
+
163
+ // NOTE the second room has more state
164
+
165
+ let initial1 = line_segments_with_state ( 0 , 5 ) ;
166
+ let initial2 = line_segments_with_state ( 14 , 27 ) ;
167
+
168
+ empty_database ( ) ;
169
+ add_contents_to_database ( "room1" , & initial1) ;
170
+ add_contents_to_database ( "room2" , & initial2) ;
171
+
172
+ let mut client = connect_to_database ( DB_URL ) . unwrap ( ) ;
173
+ create_tables_if_needed ( & mut client) . unwrap ( ) ;
174
+ clear_compressor_state ( ) ;
175
+
176
+ // compress in 3,3 level sizes by default
177
+ let default_levels = vec ! [ Level :: new( 3 ) , Level :: new( 3 ) ] ;
178
+
179
+ // compress the largest 1 rooms in chunks of size 7
180
+ // (Note this should ONLY compress room2 since it has more state)
181
+ compress_largest_rooms ( DB_URL , 7 , & default_levels, 1 ) . unwrap ( ) ;
182
+
183
+ // We are aiming for the following structure in the database for room2
184
+ // i.e. groups 20 and 23 should have changed from initial map
185
+ // N.B. this saves 11 rows
186
+ //
187
+ // 14 17\ 26
188
+ // 15 18 20\ 27
189
+ // 16 19 21 23
190
+ // 22 24
191
+ // 25
192
+ //
193
+ // Where each group i has state:
194
+ // ('node','is', i)
195
+ // ('group', j, 'seen') - for all j less than i in that room
196
+ let expected_edges: BTreeMap < i64 , i64 > = vec ! [
197
+ ( 15 , 14 ) ,
198
+ ( 16 , 15 ) ,
199
+ ( 18 , 17 ) ,
200
+ ( 19 , 18 ) ,
201
+ ( 20 , 17 ) ,
202
+ ( 21 , 20 ) ,
203
+ ( 22 , 21 ) ,
204
+ ( 23 , 20 ) ,
205
+ ( 24 , 23 ) ,
206
+ ( 25 , 24 ) ,
207
+ ( 27 , 26 ) ,
208
+ ]
209
+ . into_iter ( )
210
+ . collect ( ) ;
211
+
212
+ let expected2 = structure_from_edges_with_state ( expected_edges, 14 , 27 ) ;
213
+
214
+ // Check that the database still gives correct states for each group in room1
215
+ assert ! ( database_collapsed_states_match_map( & initial1) ) ;
216
+
217
+ // Check that the structure of the database is still what it was initially
218
+ assert ! ( database_structure_matches_map( & initial1) ) ;
219
+
220
+ // Check that the database still gives correct states for each group in room2
221
+ assert ! ( database_collapsed_states_match_map( & initial2) ) ;
222
+
223
+ // Check that the structure of the database is the expected compressed one
224
+ assert ! ( database_structure_matches_map( & expected2) ) ;
225
+ }
226
+
227
+ #[ test]
228
+ #[ serial( db) ]
229
+ fn compress_largest_rooms_skips_already_compressed_when_rerun ( ) {
230
+ setup_logger ( ) ;
231
+ // This test builds two rooms in the database and then calls compress_largest_rooms
232
+ // with a number argument of 1 (i.e. only the larger of the two rooms should be
233
+ // compressed)
234
+ //
235
+ // It then adds another state group to the larger of the two rooms and calls the
236
+ // compress_largest_rooms function again. However there is more UNCOMPRESSED state
237
+ // in the smaller room, so the new state added to the larger room should remain
238
+ // untouched
239
+ //
240
+ // This is meant to simulate events happening in rooms between calls to the function
241
+
242
+ // Initially create 2 rooms with the following structure
243
+ //
244
+ // 0-1-2 3-4-5 6-7-8 9-10-11 12-13(room1)
245
+ // 14-15-16 17-18-19 20 (room2)
246
+ //
247
+ // Each group i has state:
248
+ // ('node','is', i)
249
+ // ('group', j, 'seen') - for all j less than i in that room
250
+ // NOTE the first room is the larger one
251
+ let initial1 = line_segments_with_state ( 0 , 13 ) ;
252
+ let initial2 = line_segments_with_state ( 14 , 20 ) ;
253
+
254
+ empty_database ( ) ;
255
+ add_contents_to_database ( "room1" , & initial1) ;
256
+ add_contents_to_database ( "room2" , & initial2) ;
257
+
258
+ let mut client = connect_to_database ( DB_URL ) . unwrap ( ) ;
259
+ create_tables_if_needed ( & mut client) . unwrap ( ) ;
260
+ clear_compressor_state ( ) ;
261
+
262
+ // compress in 3,3 level sizes by default
263
+ let default_levels = vec ! [ Level :: restore( 3 , 0 , None ) , Level :: restore( 3 , 0 , None ) ] ;
264
+
265
+ // compress the largest 1 rooms in chunks of size 7
266
+ // (Note this should ONLY compress room1 since it has more state)
267
+ compress_largest_rooms ( DB_URL , 7 , & default_levels, 1 ) . unwrap ( ) ;
268
+
269
+ // This should have created the following structure in the database
270
+ // i.e. groups 6 and 9 should have changed from before
271
+ // N.B. this saves 11 rows
272
+ //
273
+ // 0 3\ 12
274
+ // 1 4 6\ 13
275
+ // 2 5 7 9
276
+ // 8 10
277
+ // 11
278
+ // room 2 should be unchanged
279
+ let expected1 = compressed_3_3_from_0_to_13_with_state ( ) ;
280
+
281
+ // room1 is new structure, room2 is as it was initially
282
+ assert ! ( database_structure_matches_map( & expected1) ) ;
283
+ assert ! ( database_structure_matches_map( & initial2) ) ;
284
+
285
+ // Now add another state group to room1 with predecessor 12
286
+ //
287
+ // If the compressor is run on room1 again then the prev_state_group for 21
288
+ // will be set to 13
289
+ //
290
+ // i.e the compressor would try and build the following:
291
+ //
292
+ // 0 3\ 12
293
+ // 1 4 6\ 13
294
+ // 2 5 7 9 21
295
+ // 8 10
296
+ // 11
297
+
298
+ let mut initial1_with_new_group = expected1. clone ( ) ;
299
+
300
+ let mut group21 = StateGroupEntry {
301
+ in_range : true ,
302
+ prev_state_group : Some ( 12 ) ,
303
+ state_map : StateMap :: new ( ) ,
304
+ } ;
305
+
306
+ // add in the new state for this state group
307
+ group21. state_map . insert ( "group" , "13" , "seen" . into ( ) ) ;
308
+ group21. state_map . insert ( "group" , "21" , "seen" . into ( ) ) ;
309
+ group21. state_map . insert ( "node" , "is" , "21" . into ( ) ) ;
310
+
311
+ initial1_with_new_group. insert ( 21 , group21) ;
312
+
313
+ // Actually send this group to the database
314
+ let sql = r#"
315
+ INSERT INTO state_groups (id, room_id, event_id) VALUES (21,'room1','left_blank');
316
+ INSERT INTO state_group_edges (state_group, prev_state_group) VALUES
317
+ (21,12);
318
+ INSERT INTO state_groups_state (state_group, room_id, type, state_key, event_id) VALUES
319
+ (21,'room1','node', 'is', '21'),
320
+ (21,'room1','group', '13', 'seen'),
321
+ (21,'room1','group', '21', 'seen');
322
+ "# ;
323
+ client. batch_execute ( sql) . unwrap ( ) ;
324
+
325
+ // We are aiming for the following structure in the database for room2
326
+ // i.e. only group 20 hould have changed from initial map
327
+ //
328
+ // 14 17\
329
+ // 15 18 20
330
+ // 16 19
331
+ //
332
+ // Where each group i has state:
333
+ // ('node','is', i)
334
+ // ('group', j, 'seen') - for all j less than i in that room
335
+ let expected_edges: BTreeMap < i64 , i64 > = vec ! [ ( 15 , 14 ) , ( 16 , 15 ) , ( 18 , 17 ) , ( 19 , 18 ) , ( 20 , 17 ) ]
336
+ . into_iter ( )
337
+ . collect ( ) ;
338
+
339
+ let expected2 = structure_from_edges_with_state ( expected_edges, 14 , 20 ) ;
340
+
341
+ // compress the largest 1 rooms in chunks of size 7
342
+ // (Note this should ONLY compress room2 since room1 only has 1 uncompressed state group)
343
+ compress_largest_rooms ( DB_URL , 7 , & default_levels, 1 ) . unwrap ( ) ;
344
+
345
+ // Check that the database still gives correct states for each group in room1
346
+ assert ! ( database_collapsed_states_match_map(
347
+ & initial1_with_new_group
348
+ ) ) ;
349
+
350
+ // Check that the structure of the database is still what it was befeore
351
+ // compress_largest_rooms was called (i.e. that pred of 21 is still 12 not now 13)
352
+ assert ! ( database_structure_matches_map( & initial1_with_new_group) ) ;
353
+
354
+ // Check that the database still gives correct states for each group in room2
355
+ assert ! ( database_collapsed_states_match_map( & initial2) ) ;
356
+ // Check that the structure of the database is the expected compressed one
357
+ assert ! ( database_structure_matches_map( & expected2) ) ;
358
+ }
0 commit comments