Skip to content

Commit 9c37a03

Browse files
committed
fix(base): Check the lazy_previous of the first chunk matches the new first chunk.
This patch adds a new check when inserting a new first chunk. It makes some tests to fail but because they were not realistic. This patch then updates these tests.
1 parent 82ef623 commit 9c37a03

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
459459
// A unique chunk.
460460
assert_matches!(rchunks.next(), Some(chunk) => {
461461
assert_eq!(chunk.identifier(), 2);
462+
assert_eq!(chunk.lazy_previous(), Some(CId::new(1)));
462463

463464
assert_matches!(chunk.content(), ChunkContent::Items(events) => {
464465
assert_eq!(events.len(), 3);
@@ -476,19 +477,17 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
476477
// Load the previous chunk: this is a gap.
477478
{
478479
let first_chunk = linked_chunk.chunks().next().unwrap().identifier();
479-
let mut previous_chunk =
480+
let previous_chunk =
480481
self.load_previous_chunk(room_id, first_chunk).await.unwrap().unwrap();
481482

482-
// Pretend it's the first chunk.
483-
previous_chunk.previous = None;
484-
485483
let _ = lazy_loader::insert_new_first_chunk(&mut linked_chunk, previous_chunk).unwrap();
486484

487485
let mut rchunks = linked_chunk.rchunks();
488486

489487
// The last chunk.
490488
assert_matches!(rchunks.next(), Some(chunk) => {
491489
assert_eq!(chunk.identifier(), 2);
490+
assert!(chunk.lazy_previous().is_none());
492491

493492
// Already asserted, but let's be sure nothing breaks.
494493
assert_matches!(chunk.content(), ChunkContent::Items(events) => {
@@ -502,6 +501,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
502501
// The new chunk.
503502
assert_matches!(rchunks.next(), Some(chunk) => {
504503
assert_eq!(chunk.identifier(), 1);
504+
assert_eq!(chunk.lazy_previous(), Some(CId::new(0)));
505505

506506
assert_matches!(chunk.content(), ChunkContent::Gap(gap) => {
507507
assert_eq!(gap.prev_token, "morbier");
@@ -524,6 +524,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
524524
// The last chunk.
525525
assert_matches!(rchunks.next(), Some(chunk) => {
526526
assert_eq!(chunk.identifier(), 2);
527+
assert!(chunk.lazy_previous().is_none());
527528

528529
// Already asserted, but let's be sure nothing breaks.
529530
assert_matches!(chunk.content(), ChunkContent::Items(events) => {
@@ -537,6 +538,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
537538
// Its previous chunk.
538539
assert_matches!(rchunks.next(), Some(chunk) => {
539540
assert_eq!(chunk.identifier(), 1);
541+
assert!(chunk.lazy_previous().is_none());
540542

541543
// Already asserted, but let's be sure nothing breaks.
542544
assert_matches!(chunk.content(), ChunkContent::Gap(gap) => {
@@ -547,6 +549,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
547549
// The new chunk.
548550
assert_matches!(rchunks.next(), Some(chunk) => {
549551
assert_eq!(chunk.identifier(), 0);
552+
assert!(chunk.lazy_previous().is_none());
550553

551554
assert_matches!(chunk.content(), ChunkContent::Items(events) => {
552555
assert_eq!(events.len(), 2);
@@ -574,6 +577,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
574577
// The first chunk.
575578
assert_matches!(chunks.next(), Some(chunk) => {
576579
assert_eq!(chunk.identifier(), 0);
580+
assert!(chunk.lazy_previous().is_none());
577581

578582
assert_matches!(chunk.content(), ChunkContent::Items(events) => {
579583
assert_eq!(events.len(), 2);
@@ -585,6 +589,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
585589
// The second chunk.
586590
assert_matches!(chunks.next(), Some(chunk) => {
587591
assert_eq!(chunk.identifier(), 1);
592+
assert!(chunk.lazy_previous().is_none());
588593

589594
assert_matches!(chunk.content(), ChunkContent::Gap(gap) => {
590595
assert_eq!(gap.prev_token, "morbier");
@@ -594,6 +599,7 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
594599
// The third and last chunk.
595600
assert_matches!(chunks.next(), Some(chunk) => {
596601
assert_eq!(chunk.identifier(), 2);
602+
assert!(chunk.lazy_previous().is_none());
597603

598604
assert_matches!(chunk.content(), ChunkContent::Items(events) => {
599605
assert_eq!(events.len(), 3);

crates/matrix-sdk-common/src/linked_chunk/lazy_loader.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ where
9696
}
9797
}
9898

99-
let expected_next_chunk = linked_chunk.links.first_chunk().identifier();
99+
let first_chunk = linked_chunk.links.first_chunk();
100+
let expected_next_chunk = first_chunk.identifier();
100101

101102
// New chunk has a next chunk.
102103
let Some(next_chunk) = new_first_chunk.next else {
@@ -111,6 +112,15 @@ where
111112
});
112113
}
113114

115+
// Same check as before, but in reverse: the first chunk has a `lazy_previous`
116+
// to the new first chunk.
117+
if first_chunk.lazy_previous() != Some(new_first_chunk.identifier) {
118+
return Err(LazyLoaderError::CannotConnectTwoChunks {
119+
new_chunk: first_chunk.identifier,
120+
with_chunk: new_first_chunk.identifier,
121+
});
122+
}
123+
114124
// Alright. All checks are made.
115125
}
116126

@@ -524,6 +534,26 @@ mod tests {
524534
});
525535
}
526536

537+
#[test]
538+
fn test_insert_new_first_chunk_err_cannot_connect_two_chunks_before_no_lazy_previous() {
539+
let new_first_chunk = RawChunk {
540+
previous: None,
541+
identifier: ChunkIdentifier::new(1),
542+
next: Some(ChunkIdentifier::new(0)),
543+
content: ChunkContent::Gap(()),
544+
};
545+
546+
let mut linked_chunk = LinkedChunk::<2, char, ()>::new();
547+
linked_chunk.push_gap_back(());
548+
549+
let result = insert_new_first_chunk(&mut linked_chunk, new_first_chunk);
550+
551+
assert_matches!(result, Err(LazyLoaderError::CannotConnectTwoChunks { new_chunk, with_chunk }) => {
552+
assert_eq!(new_chunk, 0);
553+
assert_eq!(with_chunk, 1);
554+
});
555+
}
556+
527557
#[test]
528558
fn test_insert_new_first_chunk_gap() {
529559
let new_first_chunk = RawChunk {
@@ -535,6 +565,7 @@ mod tests {
535565

536566
let mut linked_chunk = LinkedChunk::<5, char, ()>::new_with_update_history();
537567
linked_chunk.push_items_back(vec!['a', 'b']);
568+
linked_chunk.links.first_chunk_mut().lazy_previous = Some(ChunkIdentifier::new(1));
538569

539570
// Drain initial updates.
540571
let _ = linked_chunk.updates().unwrap().take();
@@ -593,6 +624,7 @@ mod tests {
593624

594625
let mut linked_chunk = LinkedChunk::<5, char, ()>::new_with_update_history();
595626
linked_chunk.push_items_back(vec!['a', 'b']);
627+
linked_chunk.links.first_chunk_mut().lazy_previous = Some(ChunkIdentifier::new(1));
596628

597629
// Drain initial updates.
598630
let _ = linked_chunk.updates().unwrap().take();

0 commit comments

Comments
 (0)