Skip to content

Commit 3244bb9

Browse files
AzrenbethAzrenbeth
Azrenbeth
authored and
Azrenbeth
committed
Add test for compress largest rooms
1 parent 21fa1ff commit 3244bb9

File tree

1 file changed

+294
-3
lines changed

1 file changed

+294
-3
lines changed

compressor_integration_tests/tests/auto_compressor_manager_tests.rs

+294-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
use std::collections::BTreeMap;
2+
13
use auto_compressor::{
2-
manager::{run_compressor_on_room_chunk},
4+
manager::{compress_largest_rooms, run_compressor_on_room_chunk},
35
state_saving::{connect_to_database, create_tables_if_needed},
46
};
57
use compressor_integration_tests::{
68
add_contents_to_database, clear_compressor_state, database_collapsed_states_match_map,
79
database_structure_matches_map, empty_database,
810
map_builder::{
911
compressed_3_3_from_0_to_13_with_state, line_segments_with_state,
12+
structure_from_edges_with_state,
1013
},
1114
setup_logger, DB_URL,
1215
};
1316
use serial_test::serial;
14-
use synapse_compress_state::{Level};
17+
use state_map::StateMap;
18+
use synapse_compress_state::{Level, StateGroupEntry};
1519

1620
#[test]
1721
#[serial(db)]
@@ -33,7 +37,7 @@ fn run_compressor_on_room_chunk_works() {
3337
clear_compressor_state();
3438

3539
// 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)];
3741

3842
// compress the first 7 groups in the room
3943
// structure should be the following afterwards
@@ -65,3 +69,290 @@ fn run_compressor_on_room_chunk_works() {
6569
// Check that the structure of the database matches the expected structure
6670
assert!(database_structure_matches_map(&expected));
6771
}
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

Comments
 (0)