mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-19 14:19:06 -04:00
fix(linked chunk): fix order handling of initial chunks in UpdateToVectorDiff::new()
The code would use a chunk iterator that moves forward, but call `push_front()` repetitively on each chunk, semantically storing the lengths in *reverse* order. This could result in subsequent panics, when a new chunk was added, because the links would not match what's expected (e.g. the last chunk must have no successor, etc.).
This commit is contained in:
committed by
Ivan Enderlin
parent
bc582ae101
commit
de568837fb
@@ -99,7 +99,7 @@ impl UpdateToVectorDiff {
|
||||
let mut initial_chunk_lengths = VecDeque::new();
|
||||
|
||||
for chunk in chunk_iterator {
|
||||
initial_chunk_lengths.push_front((
|
||||
initial_chunk_lengths.push_back((
|
||||
chunk.identifier(),
|
||||
match chunk.content() {
|
||||
ChunkContent::Gap(_) => 0,
|
||||
@@ -773,7 +773,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn updates_are_drained_when_constructing_as_vector() {
|
||||
fn test_updates_are_drained_when_constructing_as_vector() {
|
||||
let mut linked_chunk = LinkedChunk::<10, char, ()>::new_with_update_history();
|
||||
|
||||
linked_chunk.push_items_back(['a']);
|
||||
@@ -793,6 +793,40 @@ mod tests {
|
||||
assert_eq!(diffs.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_as_vector_with_initial_content() {
|
||||
// Fill the linked chunk with some initial items.
|
||||
let mut linked_chunk = LinkedChunk::<3, char, ()>::new_with_update_history();
|
||||
linked_chunk.push_items_back(['a', 'b', 'c', 'd']);
|
||||
|
||||
#[rustfmt::skip]
|
||||
assert_items_eq!(linked_chunk, ['a', 'b', 'c'] ['d']);
|
||||
|
||||
// Empty updates first.
|
||||
let _ = linked_chunk.updates().take();
|
||||
|
||||
// Start observing future updates.
|
||||
let mut as_vector = linked_chunk.as_vector().unwrap();
|
||||
|
||||
assert!(as_vector.take().is_empty());
|
||||
|
||||
// It's important to cause a change that will create new chunks, like pushing
|
||||
// enough items.
|
||||
linked_chunk.push_items_back(['e', 'f', 'g']);
|
||||
#[rustfmt::skip]
|
||||
assert_items_eq!(linked_chunk, ['a', 'b', 'c'] ['d', 'e', 'f'] ['g']);
|
||||
|
||||
// And the vector diffs can be computed without crashing.
|
||||
let diffs = as_vector.take();
|
||||
assert_eq!(diffs.len(), 2);
|
||||
assert_matches!(&diffs[0], VectorDiff::Append { values } => {
|
||||
assert_eq!(*values, ['e', 'f'].into());
|
||||
});
|
||||
assert_matches!(&diffs[1], VectorDiff::Append { values } => {
|
||||
assert_eq!(*values, ['g'].into());
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod proptests {
|
||||
use proptest::prelude::*;
|
||||
@@ -824,7 +858,7 @@ mod tests {
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn as_vector_is_correct(
|
||||
fn test_as_vector_is_correct(
|
||||
operations in prop::collection::vec(as_vector_operation_strategy(), 50..=200)
|
||||
) {
|
||||
let mut linked_chunk = LinkedChunk::<10, char, ()>::new_with_update_history();
|
||||
|
||||
Reference in New Issue
Block a user