Skip to content

Commit 28f77ac

Browse files
refactor(registry): Remove the shards.is_empty condition for asserting the equality of the 2 routing table formats (#5896)
# Why When doing invariants checks, we should always assert the equality of the 2 routing table formats. The `is_empty` pre-condition was added before the initial migration (where shards don't exist yet), which has long been completed. This change also helps us identify and fix tests where shards are not added in test setups. # What * Remove the `shards.is_empty` pre-conditioin for checking equality * Update tests so that they always prepare shards when routing table is needed.
1 parent 27bd3d2 commit 28f77ac

File tree

2 files changed

+113
-112
lines changed

2 files changed

+113
-112
lines changed

rs/registry/canister/src/invariants/checks.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ mod tests {
190190
},
191191
};
192192
use ic_registry_keys::{
193-
make_canister_migrations_record_key, make_node_operator_record_key,
194-
make_routing_table_record_key,
193+
make_canister_migrations_record_key, make_canister_ranges_key,
194+
make_node_operator_record_key, make_routing_table_record_key,
195195
};
196196
use ic_registry_routing_table::{CanisterIdRange, CanisterMigrations, RoutingTable};
197197
use ic_registry_transport::{
@@ -301,21 +301,26 @@ mod tests {
301301
}).unwrap();
302302

303303
let routing_table = PbRoutingTable::from(routing_table);
304-
let key1 = make_routing_table_record_key();
305-
let value1 = routing_table.encode_to_vec();
304+
let routing_table_key = make_routing_table_record_key();
305+
let routing_table_shard_key = make_canister_ranges_key(CanisterId::from(0));
306+
let routing_table_value = routing_table.encode_to_vec();
306307

307308
// The canister ID range {0x200:0x2ff} in `canister_migrations` is not hosted by any subnet in trace according to the routing table.
308309
let canister_migrations = CanisterMigrations::try_from(btreemap! {
309310
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => vec![subnet_test_id(1), subnet_test_id(2)],
310311
}).unwrap();
311312

312313
let canister_migrations = PbCanisterMigrations::from(canister_migrations);
313-
let key2 = make_canister_migrations_record_key();
314-
let value2 = canister_migrations.encode_to_vec();
314+
let canister_migrations_key = make_canister_migrations_record_key();
315+
let canister_migrations_value = canister_migrations.encode_to_vec();
315316

316317
let mutations = vec![
317-
insert(key1.as_bytes(), value1),
318-
insert(key2.as_bytes(), value2),
318+
insert(routing_table_key.as_bytes(), &routing_table_value),
319+
insert(routing_table_shard_key.as_bytes(), &routing_table_value),
320+
insert(
321+
canister_migrations_key.as_bytes(),
322+
&canister_migrations_value,
323+
),
319324
];
320325

321326
let registry = Registry::new();
@@ -324,11 +329,12 @@ mod tests {
324329

325330
#[test]
326331
fn snapshot_reflects_latest_registry_state() {
327-
let key1 = make_routing_table_record_key();
328-
let value1 = PbRoutingTable { entries: vec![] }.encode_to_vec();
332+
let routing_table_key = make_routing_table_record_key();
333+
let routing_table_shard_key = make_canister_ranges_key(CanisterId::from(0));
334+
let routing_table_value = PbRoutingTable { entries: vec![] }.encode_to_vec();
329335

330-
let key2 = make_node_operator_record_key(*TEST_USER1_PRINCIPAL);
331-
let value2 = NodeOperatorRecord {
336+
let node_operator_key = make_node_operator_record_key(*TEST_USER1_PRINCIPAL);
337+
let node_operator_value = NodeOperatorRecord {
332338
node_operator_principal_id: (*TEST_USER1_PRINCIPAL).to_vec(),
333339
node_allowance: 0,
334340
node_provider_principal_id: (*TEST_USER1_PRINCIPAL).to_vec(),
@@ -340,18 +346,19 @@ mod tests {
340346
.encode_to_vec();
341347

342348
let mutations = vec![
343-
insert(key1.as_bytes(), &value1),
344-
insert(key2.as_bytes(), &value2),
349+
insert(routing_table_key.as_bytes(), &routing_table_value),
350+
insert(routing_table_shard_key.as_bytes(), &routing_table_value),
351+
insert(node_operator_key.as_bytes(), &node_operator_value),
345352
];
346353
let snapshot = Registry::new().take_latest_snapshot_with_mutations(&mutations);
347354

348-
let snapshot_data = snapshot.get(key1.as_bytes());
355+
let snapshot_data = snapshot.get(routing_table_key.as_bytes());
349356
assert!(snapshot_data.is_some());
350-
assert_eq!(snapshot_data.unwrap(), &value1);
357+
assert_eq!(snapshot_data.unwrap(), &routing_table_value);
351358

352-
let snapshot_data = snapshot.get(key2.as_bytes());
359+
let snapshot_data = snapshot.get(node_operator_key.as_bytes());
353360
assert!(snapshot_data.is_some());
354-
assert_eq!(snapshot_data.unwrap(), &value2);
361+
assert_eq!(snapshot_data.unwrap(), &node_operator_value);
355362
}
356363

357364
#[test]

rs/registry/canister/src/invariants/routing_table.rs

Lines changed: 88 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,11 @@ fn get_routing_table(snapshot: &RegistrySnapshot) -> RoutingTable {
3535

3636
// If there are shards, they should match the routing table record.
3737
let shards = get_routing_table_shards(snapshot);
38-
if !shards.is_empty() {
39-
let rt_from_shards = RoutingTable::try_from(shards).unwrap();
40-
assert_eq!(
41-
rt_from_shards, rt_from_routing_table_record,
42-
"Routing tables from shards and routing table record do not match."
43-
);
44-
}
38+
let rt_from_shards = RoutingTable::try_from(shards).unwrap();
39+
assert_eq!(
40+
rt_from_shards, rt_from_routing_table_record,
41+
"Routing tables from shards and routing table record do not match."
42+
);
4543

4644
rt_from_routing_table_record
4745
}
@@ -127,20 +125,32 @@ mod tests {
127125
use prost::Message;
128126
use std::convert::TryFrom;
129127

128+
fn insert_routing_table_to_snapshot(
129+
routing_table: RoutingTable,
130+
snapshot: &mut RegistrySnapshot,
131+
) {
132+
let routing_table = PbRoutingTable::from(routing_table);
133+
snapshot.insert(
134+
make_canister_ranges_key(CanisterId::from(0)).into_bytes(),
135+
routing_table.encode_to_vec(),
136+
);
137+
// TODO(NNS1-3781): Remove this once we have sharded table supported by all clients, and
138+
// inline the function after removal.
139+
snapshot.insert(
140+
make_routing_table_record_key().into_bytes(),
141+
routing_table.encode_to_vec(),
142+
);
143+
}
144+
130145
#[test]
131146
fn nonexistent_canister_migrations_can_pass_invariants_check() {
132147
let mut snapshot = RegistrySnapshot::new();
133148

134149
let routing_table = RoutingTable::try_from(btreemap! {
135-
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
136-
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
137-
}).unwrap();
138-
139-
let routing_table = PbRoutingTable::from(routing_table);
140-
let key1 = make_routing_table_record_key();
141-
let value1 = routing_table.encode_to_vec();
142-
143-
snapshot.insert(key1.into_bytes(), value1);
150+
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
151+
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
152+
}).unwrap();
153+
insert_routing_table_to_snapshot(routing_table, &mut snapshot);
144154

145155
assert!(check_routing_table_invariants(&snapshot).is_ok());
146156
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
@@ -151,19 +161,14 @@ mod tests {
151161
let mut snapshot = RegistrySnapshot::new();
152162

153163
let routing_table = RoutingTable::try_from(btreemap! {
154-
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
155-
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
156-
}).unwrap();
157-
158-
let routing_table = PbRoutingTable::from(routing_table);
159-
let key1 = make_routing_table_record_key();
160-
let value1 = routing_table.encode_to_vec();
161-
162-
let key2 = make_canister_migrations_record_key();
163-
let value2 = PbCanisterMigrations { entries: vec![] }.encode_to_vec();
164-
165-
snapshot.insert(key1.into_bytes(), value1);
166-
snapshot.insert(key2.into_bytes(), value2);
164+
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
165+
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
166+
}).unwrap();
167+
insert_routing_table_to_snapshot(routing_table, &mut snapshot);
168+
snapshot.insert(
169+
make_canister_migrations_record_key().into_bytes(),
170+
PbCanisterMigrations { entries: vec![] }.encode_to_vec(),
171+
);
167172

168173
assert!(check_routing_table_invariants(&snapshot).is_ok());
169174
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
@@ -175,15 +180,10 @@ mod tests {
175180

176181
// The routing table before canister migration.
177182
let routing_table = RoutingTable::try_from(btreemap! {
178-
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
179-
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
180-
}).unwrap();
181-
182-
let routing_table = PbRoutingTable::from(routing_table);
183-
let key1 = make_routing_table_record_key();
184-
let value1 = routing_table.encode_to_vec();
185-
186-
snapshot.insert(key1.into_bytes(), value1);
183+
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
184+
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
185+
}).unwrap();
186+
insert_routing_table_to_snapshot(routing_table, &mut snapshot);
187187
assert!(check_routing_table_invariants(&snapshot).is_ok());
188188
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
189189

@@ -193,31 +193,28 @@ mod tests {
193193
}).unwrap();
194194

195195
let canister_migrations = PbCanisterMigrations::from(canister_migrations);
196-
let key2 = make_canister_migrations_record_key();
197-
let value2 = canister_migrations.encode_to_vec();
198-
199-
snapshot.insert(key2.into_bytes(), value2);
196+
snapshot.insert(
197+
make_canister_migrations_record_key().into_bytes(),
198+
canister_migrations.encode_to_vec(),
199+
);
200200
assert!(check_routing_table_invariants(&snapshot).is_ok());
201201
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
202202

203203
// Reassign ranges in routing table.
204204
let routing_table = RoutingTable::try_from(btreemap! {
205205
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xf) } => subnet_test_id(1),
206-
CanisterIdRange{ start: CanisterId::from(0x10), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
207-
}).unwrap();
206+
CanisterIdRange{ start: CanisterId::from(0x10), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
207+
}).unwrap();
208208

209-
let routing_table = PbRoutingTable::from(routing_table);
210-
let key3 = make_routing_table_record_key();
211-
let value3 = routing_table.encode_to_vec();
212-
snapshot.insert(key3.into_bytes(), value3);
209+
insert_routing_table_to_snapshot(routing_table, &mut snapshot);
213210
assert!(check_routing_table_invariants(&snapshot).is_ok());
214211
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
215212

216213
// Complete canister migrations by removing entries.
217-
let key4 = make_canister_migrations_record_key();
218-
let value4 = PbCanisterMigrations { entries: vec![] }.encode_to_vec();
219-
220-
snapshot.insert(key4.into_bytes(), value4);
214+
snapshot.insert(
215+
make_canister_migrations_record_key().into_bytes(),
216+
PbCanisterMigrations { entries: vec![] }.encode_to_vec(),
217+
);
221218
assert!(check_routing_table_invariants(&snapshot).is_ok());
222219
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
223220
}
@@ -228,16 +225,12 @@ mod tests {
228225

229226
// The routing table before canister migration.
230227
let routing_table = RoutingTable::try_from(btreemap! {
231-
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
232-
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
233-
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => subnet_test_id(3),
234-
}).unwrap();
235-
236-
let routing_table = PbRoutingTable::from(routing_table);
237-
let key1 = make_routing_table_record_key();
238-
let value1 = routing_table.encode_to_vec();
228+
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
229+
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
230+
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => subnet_test_id(3),
231+
}).unwrap();
239232

240-
snapshot.insert(key1.into_bytes(), value1);
233+
insert_routing_table_to_snapshot(routing_table, &mut snapshot);
241234
assert!(check_routing_table_invariants(&snapshot).is_ok());
242235
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
243236

@@ -249,10 +242,10 @@ mod tests {
249242
}).unwrap();
250243

251244
let canister_migrations = PbCanisterMigrations::from(canister_migrations);
252-
let key2 = make_canister_migrations_record_key();
253-
let value2 = canister_migrations.encode_to_vec();
254-
255-
snapshot.insert(key2.into_bytes(), value2);
245+
snapshot.insert(
246+
make_canister_migrations_record_key().into_bytes(),
247+
canister_migrations.encode_to_vec(),
248+
);
256249

257250
assert!(check_routing_table_invariants(&snapshot).is_ok());
258251
assert!(check_canister_migrations_invariants(&snapshot).is_err());
@@ -269,61 +262,60 @@ mod tests {
269262
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => subnet_test_id(3),
270263
}).unwrap();
271264

272-
let routing_table = PbRoutingTable::from(routing_table);
273-
let key1 = make_routing_table_record_key();
274-
let value1 = routing_table.encode_to_vec();
275-
276265
// The canister migrations after preparation.
277266
let canister_migrations = CanisterMigrations::try_from(btreemap! {
278267
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => vec![subnet_test_id(1), subnet_test_id(2)],
279268
}).unwrap();
280269

281270
let canister_migrations = PbCanisterMigrations::from(canister_migrations);
282-
let key2 = make_canister_migrations_record_key();
283-
let value2 = canister_migrations.encode_to_vec();
284271

285-
snapshot.insert(key1.into_bytes(), value1);
286-
snapshot.insert(key2.into_bytes(), value2);
272+
insert_routing_table_to_snapshot(routing_table, &mut snapshot);
273+
snapshot.insert(
274+
make_canister_migrations_record_key().into_bytes(),
275+
canister_migrations.encode_to_vec(),
276+
);
287277
assert!(check_routing_table_invariants(&snapshot).is_ok());
288278
assert!(check_canister_migrations_invariants(&snapshot).is_ok());
289279

290280
// The new routing table after reassigning ranges.
291281

292282
// Case 1: cannot find the entry containing `range.start` of canister migrations when looking up entries in the routing table,
293-
let mut new_snapshot = snapshot.clone();
294283
let new_routing_table_1 = RoutingTable::try_from(btreemap! {
295284
CanisterIdRange{ start: CanisterId::from(0x1), end: CanisterId::from(0xff) } => subnet_test_id(1),
296285
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
297286
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => subnet_test_id(3),
298287
}).unwrap();
299288

300-
let routing_table = PbRoutingTable::from(new_routing_table_1);
301-
let key3 = make_routing_table_record_key();
302-
let value3 = routing_table.encode_to_vec();
303-
new_snapshot.insert(key3.into_bytes(), value3);
289+
insert_routing_table_to_snapshot(new_routing_table_1, &mut snapshot);
304290

305-
assert!(check_routing_table_invariants(&new_snapshot).is_ok());
306-
assert!(check_canister_migrations_invariants(&new_snapshot).is_err());
291+
assert!(check_routing_table_invariants(&snapshot).is_ok());
292+
assert!(check_canister_migrations_invariants(&snapshot).is_err());
307293

308294
// Case 2: find the entry containing `range.start` but the entry cannot fully cover the canister migration range {0x0:0xff}.
309295
let new_routing_table_2 = RoutingTable::try_from(btreemap! {
310-
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0x1) } => subnet_test_id(1),
311-
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
312-
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => subnet_test_id(3),
313-
}).unwrap();
296+
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0x1) } => subnet_test_id(1),
297+
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
298+
CanisterIdRange{ start: CanisterId::from(0x200), end: CanisterId::from(0x2ff) } => subnet_test_id(3),
299+
}).unwrap();
314300

315301
let routing_table = PbRoutingTable::from(new_routing_table_2);
316-
let key4 = make_routing_table_record_key();
317-
let value4 = routing_table.encode_to_vec();
318-
snapshot.insert(key4.into_bytes(), value4);
302+
snapshot.insert(
303+
make_routing_table_record_key().into_bytes(),
304+
routing_table.encode_to_vec(),
305+
);
306+
snapshot.insert(
307+
make_canister_ranges_key(CanisterId::from(0)).into_bytes(),
308+
routing_table.encode_to_vec(),
309+
);
319310

320311
assert!(check_routing_table_invariants(&snapshot).is_ok());
321312
assert!(check_canister_migrations_invariants(&snapshot).is_err());
322313
}
323314

315+
// TODO(NNS1-3781): Remove this test once we have sharded table supported by all clients.
324316
#[test]
325317
#[should_panic(expected = "Routing tables from shards and routing table record do not match.")]
326-
fn if_sharded_ranges_they_must_match_original_routing_table() {
318+
fn sharded_ranges_must_match_original_routing_table() {
327319
let mut snapshot = RegistrySnapshot::new();
328320

329321
// The routing table before canister migration.
@@ -334,20 +326,22 @@ mod tests {
334326
}).unwrap();
335327

336328
let routing_table = PbRoutingTable::from(routing_table);
337-
let key1 = make_routing_table_record_key();
338-
let value1 = routing_table.encode_to_vec();
339329

340330
let rt_shard = RoutingTable::try_from(btreemap! {
341331
CanisterIdRange{ start: CanisterId::from(0x0), end: CanisterId::from(0xff) } => subnet_test_id(1),
342332
CanisterIdRange{ start: CanisterId::from(0x100), end: CanisterId::from(0x1ff) } => subnet_test_id(2),
343333
}).unwrap();
344334

345335
let rt_shard = PbRoutingTable::from(rt_shard);
346-
let key2 = make_canister_ranges_key(CanisterId::from_u64(0x0));
347-
let value2 = rt_shard.encode_to_vec();
348336

349-
snapshot.insert(key1.into_bytes(), value1);
350-
snapshot.insert(key2.into_bytes(), value2);
337+
snapshot.insert(
338+
make_routing_table_record_key().into_bytes(),
339+
routing_table.encode_to_vec(),
340+
);
341+
snapshot.insert(
342+
make_canister_ranges_key(CanisterId::from(0)).into_bytes(),
343+
rt_shard.encode_to_vec(),
344+
);
351345

352346
check_routing_table_invariants(&snapshot).unwrap();
353347
}

0 commit comments

Comments
 (0)