Coverage Report

Created: 2025-11-28 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/surrealmx-0.15.0/src/versions.rs
Line
Count
Source
1
use crate::version::Version;
2
use bytes::Bytes;
3
use smallvec::SmallVec;
4
5
pub(crate) enum IndexOrUpdate<'a> {
6
  /// No need to insert the entry or update
7
  Ignore,
8
  /// Insert the entry at the specified index
9
  Index(usize),
10
  /// Update an entry with the specified entry
11
  Update(&'a mut Version),
12
}
13
14
pub struct Versions {
15
  inner: SmallVec<[Version; 4]>,
16
}
17
18
impl From<Version> for Versions {
19
4.24k
  fn from(value: Version) -> Self {
20
4.24k
    let mut inner = SmallVec::new();
21
4.24k
    inner.push(value);
22
4.24k
    Versions {
23
4.24k
      inner,
24
4.24k
    }
25
4.24k
  }
26
}
27
28
impl Versions {
29
  /// Create a new versions object.
30
  #[inline]
31
0
  pub(crate) fn new() -> Self {
32
0
    Versions {
33
0
      inner: SmallVec::new(),
34
0
    }
35
0
  }
36
37
  /// Appends or inserts an element into its sorted position.
38
  #[inline]
39
675
  pub(crate) fn push(&mut self, value: Version) {
40
    // Fast path: check if appending to the end
41
675
    if let Some(last) = self.inner.last_mut() {
42
      // Compare the new value with the last value
43
675
      match value.version.cmp(&last.version) {
44
        std::cmp::Ordering::Greater => {
45
          // Newer version - append if value is different
46
675
          if value.value != last.value {
47
539
            self.inner.push(value);
48
539
          }
49
          // Same value, ignore duplicate
50
675
          return;
51
        }
52
        std::cmp::Ordering::Equal => {
53
          // Same version - update if value is different
54
0
          if value.value != last.value {
55
0
            last.value = value.value;
56
0
          }
57
          // Same value, ignore
58
0
          return;
59
        }
60
0
        std::cmp::Ordering::Less => {
61
0
          // Older version - fall through to slow path
62
0
        }
63
      }
64
    } else {
65
      // Empty list - push if not a delete
66
0
      if value.value.is_some() {
67
0
        self.inner.push(value);
68
0
      }
69
      // Delete on empty list, ignore
70
0
      return;
71
    }
72
    // Otherwise, use the index or update logic
73
0
    match self.fetch_index_or_update(&value) {
74
      // No need to insert or update the entry
75
0
      IndexOrUpdate::Ignore => {
76
0
        // Do nothing
77
0
      }
78
      // Insert the entry at the specified index
79
0
      IndexOrUpdate::Index(idx) => {
80
0
        self.inner.insert(idx, value);
81
0
      }
82
      // Update an existing entry in the list
83
0
      IndexOrUpdate::Update(entry) => {
84
0
        entry.value = value.value;
85
0
      }
86
    }
87
675
  }
88
89
  /// Determine if a new entry should be ignored, inserted, or update an existing entry.
90
  ///
91
  /// This function works in the following way:
92
  /// - Return IndexOrUpdate::Ignore if:
93
  ///   - The latest entry with a version <= value.version has the same value as the new value
94
  ///   - The latest entry with a version <= value.version is a delete and the new value is a delete
95
  /// - Return IndexOrUpdate::Update(version) if:
96
  ///   - The new value version is the same as an existing version and we should update the entry
97
  /// - Return IndexOrUpdate::Index(index) if:
98
  ///   - There is no entry with a version <= value.version
99
  ///   - The new value version is different to the latest entry with a version <= value.version
100
  ///
101
  #[inline]
102
0
  pub(crate) fn fetch_index_or_update(&mut self, value: &Version) -> IndexOrUpdate<'_> {
103
    // Find the index of the item where item.version <= value.version
104
0
    let idx = self.find_index_lte_version(value.version);
105
    // If there is no entry with a version <= value.version
106
0
    if idx == 0 {
107
      // If this is a delete, ignore it (no point storing initial delete)
108
0
      if value.value.is_none() {
109
0
        return IndexOrUpdate::Ignore;
110
0
      }
111
      // Otherwise, insert at the beginning
112
0
      return IndexOrUpdate::Index(0);
113
0
    }
114
    // Get the latest entry with version <= value.version
115
0
    if let Some(existing) = self.inner.get_mut(idx - 1) {
116
      // Check if the version is the same as an existing version
117
0
      if existing.version == value.version {
118
        // Check if the values are the same
119
0
        if existing.value == value.value {
120
          // Same version, same value - ignore
121
0
          return IndexOrUpdate::Ignore;
122
0
        }
123
        // Same version, different value - update
124
0
        return IndexOrUpdate::Update(existing);
125
0
      }
126
      // Different version - check if values are the same
127
0
      if existing.value == value.value {
128
        // Latest entry has the same value - ignore
129
0
        return IndexOrUpdate::Ignore;
130
0
      }
131
      // Different version, different value - insert
132
0
      return IndexOrUpdate::Index(idx);
133
0
    }
134
    // Fallback - should not reach here
135
0
    IndexOrUpdate::Index(idx)
136
0
  }
137
138
  /// An iterator that removes the items and yields them by value.
139
  #[inline]
140
365
  pub fn drain<R>(&mut self, range: R)
141
365
  where
142
365
    R: std::ops::RangeBounds<usize>,
143
  {
144
    // Drain the versions
145
365
    self.inner.drain(range);
146
    // Shrink the vec inline
147
365
    self.inner.shrink_to_fit();
148
365
  }
Unexecuted instantiation: <surrealmx::versions::Versions>::drain::<core::ops::range::RangeToInclusive<usize>>
<surrealmx::versions::Versions>::drain::<core::ops::range::RangeTo<usize>>
Line
Count
Source
140
365
  pub fn drain<R>(&mut self, range: R)
141
365
  where
142
365
    R: std::ops::RangeBounds<usize>,
143
  {
144
    // Drain the versions
145
365
    self.inner.drain(range);
146
    // Shrink the vec inline
147
365
    self.inner.shrink_to_fit();
148
365
  }
149
150
  /// Check if the item at a specific version is a delete.
151
  #[inline]
152
241
  pub(crate) fn is_delete(&self, version: usize) -> bool {
153
241
    self.inner.get(version).is_some_and(|v| v.value.is_none())
154
241
  }
155
156
  /// Find the index of the entry where item.version < version.
157
  #[inline]
158
675
  pub(crate) fn find_index_lt_version(&self, version: u64) -> usize {
159
    // Check for any existing version
160
675
    if let Some(last) = self.inner.last() {
161
      // Check if the version is newer
162
675
      if version > last.version {
163
        // Return the index of the last version
164
434
        return self.inner.len();
165
241
      }
166
0
    }
167
    // Check the list length for reverse iteration or binary search
168
241
    if self.inner.len() <= 4 {
169
      // Use linear search to find the first element where v.version > version
170
298
      self.inner.iter().rposition(|v| v.version < version).map_or(0, |i| i + 1)
171
    } else {
172
      // Find the index of the item where item.version <= version
173
448
      self.inner.partition_point(|v| v.version < version)
174
    }
175
675
  }
176
177
  /// Find the index of the entry where item.version <= version.
178
  #[inline]
179
17.7k
  pub(crate) fn find_index_lte_version(&self, version: u64) -> usize {
180
    // Check for any existing version
181
17.7k
    if let Some(last) = self.inner.last() {
182
      // Check if the version is newer
183
17.7k
      if version >= last.version {
184
        // Return the index of the last version
185
17.7k
        return self.inner.len();
186
0
      }
187
0
    }
188
    // Check the list length for reverse iteration or binary search
189
0
    if self.inner.len() <= 4 {
190
      // Use linear search to find the first element where v.version > version
191
0
      self.inner.iter().rposition(|v| v.version <= version).map_or(0, |i| i + 1)
192
    } else {
193
      // Use binary search to find the first element where v.version >= version
194
0
      self.inner.partition_point(|v| v.version <= version)
195
    }
196
17.7k
  }
<surrealmx::versions::Versions>::find_index_lte_version
Line
Count
Source
179
14.4k
  pub(crate) fn find_index_lte_version(&self, version: u64) -> usize {
180
    // Check for any existing version
181
14.4k
    if let Some(last) = self.inner.last() {
182
      // Check if the version is newer
183
14.4k
      if version >= last.version {
184
        // Return the index of the last version
185
14.4k
        return self.inner.len();
186
0
      }
187
0
    }
188
    // Check the list length for reverse iteration or binary search
189
0
    if self.inner.len() <= 4 {
190
      // Use linear search to find the first element where v.version > version
191
0
      self.inner.iter().rposition(|v| v.version <= version).map_or(0, |i| i + 1)
192
    } else {
193
      // Use binary search to find the first element where v.version >= version
194
0
      self.inner.partition_point(|v| v.version <= version)
195
    }
196
14.4k
  }
<surrealmx::versions::Versions>::find_index_lte_version
Line
Count
Source
179
3.32k
  pub(crate) fn find_index_lte_version(&self, version: u64) -> usize {
180
    // Check for any existing version
181
3.32k
    if let Some(last) = self.inner.last() {
182
      // Check if the version is newer
183
3.32k
      if version >= last.version {
184
        // Return the index of the last version
185
3.32k
        return self.inner.len();
186
0
      }
187
0
    }
188
    // Check the list length for reverse iteration or binary search
189
0
    if self.inner.len() <= 4 {
190
      // Use linear search to find the first element where v.version > version
191
0
      self.inner.iter().rposition(|v| v.version <= version).map_or(0, |i| i + 1)
192
    } else {
193
      // Use binary search to find the first element where v.version >= version
194
0
      self.inner.partition_point(|v| v.version <= version)
195
    }
196
3.32k
  }
197
198
  /// Fetch the entry at a specific version in the versions list.
199
  #[inline]
200
17.5k
  pub(crate) fn fetch_version(&self, version: u64) -> Option<Bytes> {
201
    // Find the index of the item where item.version <= version
202
17.5k
    let idx = self.find_index_lte_version(version);
203
    // If there is an entry, return the value
204
17.5k
    if idx > 0 {
205
17.5k
      self.inner.get(idx - 1).and_then(|v| v.value.clone())
206
    } else {
207
0
      None
208
    }
209
17.5k
  }
<surrealmx::versions::Versions>::fetch_version
Line
Count
Source
200
14.1k
  pub(crate) fn fetch_version(&self, version: u64) -> Option<Bytes> {
201
    // Find the index of the item where item.version <= version
202
14.1k
    let idx = self.find_index_lte_version(version);
203
    // If there is an entry, return the value
204
14.1k
    if idx > 0 {
205
14.1k
      self.inner.get(idx - 1).and_then(|v| v.value.clone())
206
    } else {
207
0
      None
208
    }
209
14.1k
  }
<surrealmx::versions::Versions>::fetch_version
Line
Count
Source
200
3.32k
  pub(crate) fn fetch_version(&self, version: u64) -> Option<Bytes> {
201
    // Find the index of the item where item.version <= version
202
3.32k
    let idx = self.find_index_lte_version(version);
203
    // If there is an entry, return the value
204
3.32k
    if idx > 0 {
205
3.32k
      self.inner.get(idx - 1).and_then(|v| v.value.clone())
206
    } else {
207
0
      None
208
    }
209
3.32k
  }
210
211
  /// Check if an entry at a specific version exists and is not a delete.
212
  #[inline]
213
291
  pub(crate) fn exists_version(&self, version: u64) -> bool {
214
    // Find the index of the item where item.version <= version
215
291
    let idx = self.find_index_lte_version(version);
216
    // If there is an entry, return the value
217
291
    if idx > 0 {
218
291
      self.inner.get(idx - 1).is_some_and(|v| v.value.is_some())
219
    } else {
220
0
      false
221
    }
222
291
  }
<surrealmx::versions::Versions>::exists_version
Line
Count
Source
213
291
  pub(crate) fn exists_version(&self, version: u64) -> bool {
214
    // Find the index of the item where item.version <= version
215
291
    let idx = self.find_index_lte_version(version);
216
    // If there is an entry, return the value
217
291
    if idx > 0 {
218
291
      self.inner.get(idx - 1).is_some_and(|v| v.value.is_some())
219
    } else {
220
0
      false
221
    }
222
291
  }
Unexecuted instantiation: <surrealmx::versions::Versions>::exists_version
223
224
  /// Get all versions as a vector of (version, value) tuples.
225
  #[inline]
226
0
  pub(crate) fn all_versions(&self) -> Vec<(u64, Option<Bytes>)> {
227
0
    self.inner.iter().map(|v| (v.version, v.value.clone())).collect()
228
0
  }
Unexecuted instantiation: <surrealmx::versions::Versions>::all_versions
Unexecuted instantiation: <surrealmx::versions::Versions>::all_versions
229
230
  /// Remove all versions older than the specified version.
231
  #[inline]
232
675
  pub(crate) fn gc_older_versions(&mut self, version: u64) -> usize {
233
    // Find the index of the item where item.version < version
234
675
    let idx = self.find_index_lt_version(version);
235
    // Handle the case where all versions are older than the cutoff
236
675
    if idx >= self.inner.len() {
237
      // Check if the last version is a delete
238
434
      if let Some(last) = self.inner.last() {
239
434
        if last.value.is_none() {
240
0
          // Last version is a delete, remove everything
241
0
          self.inner.clear();
242
434
        } else if idx > 1 {
243
248
          // Last version has data, keep it and remove all others
244
248
          self.drain(..idx - 1);
245
248
        }
246
0
      }
247
241
    } else if self.is_delete(idx) {
248
0
      // Remove all versions up to and including this delete
249
0
      self.drain(..=idx);
250
241
    } else if idx > 0 {
251
117
      // Remove all versions up to this version
252
117
      self.drain(..idx);
253
124
    }
254
    // Return the length
255
675
    self.inner.len()
256
675
  }
257
}
258
259
#[cfg(test)]
260
mod tests {
261
  use super::*;
262
  use bytes::Bytes;
263
264
  /// Helper function to create a Version from a version number and optional value
265
  fn make_version(version: u64, value: Option<&str>) -> Version {
266
    Version {
267
      version,
268
      value: value.map(|s| Bytes::from(s.to_string())),
269
    }
270
  }
271
272
  /// Helper function to create a Versions instance with the given version tuples
273
  fn make_versions(versions: Vec<(u64, Option<&str>)>) -> Versions {
274
    let mut v = Versions::new();
275
    for (version, value) in versions {
276
      v.push(make_version(version, value));
277
    }
278
    v
279
  }
280
281
  // ==================== Tests for find_index_lt_version ====================
282
283
  #[test]
284
  fn test_find_index_lt_version_empty() {
285
    let versions = Versions::new();
286
    assert_eq!(versions.find_index_lt_version(0), 0);
287
    assert_eq!(versions.find_index_lt_version(1), 0);
288
    assert_eq!(versions.find_index_lt_version(100), 0);
289
  }
290
291
  #[test]
292
  fn test_find_index_lt_version_single_version() {
293
    let versions = make_versions(vec![(10, Some("value"))]);
294
    // Query before the version
295
    assert_eq!(versions.find_index_lt_version(5), 0);
296
    assert_eq!(versions.find_index_lt_version(9), 0);
297
    // Query at the version
298
    assert_eq!(versions.find_index_lt_version(10), 0);
299
    // Query after the version
300
    assert_eq!(versions.find_index_lt_version(11), 1);
301
    assert_eq!(versions.find_index_lt_version(100), 1);
302
  }
303
304
  #[test]
305
  fn test_find_index_lt_version_multiple_versions() {
306
    // Create a small list (≤32 elements) to trigger linear search
307
    let versions = make_versions(vec![
308
      (10, Some("v1")),
309
      (20, Some("v2")),
310
      (30, Some("v3")),
311
      (40, Some("v4")),
312
      (50, Some("v5")),
313
    ]);
314
    // Query before the first version
315
    assert_eq!(versions.find_index_lt_version(0), 0);
316
    assert_eq!(versions.find_index_lt_version(5), 0);
317
    // Query at the first version
318
    assert_eq!(versions.find_index_lt_version(10), 0);
319
    // Query after the first version
320
    assert_eq!(versions.find_index_lt_version(15), 1);
321
    // Query at the second version
322
    assert_eq!(versions.find_index_lt_version(20), 1);
323
    // Query after the second version
324
    assert_eq!(versions.find_index_lt_version(25), 2);
325
    assert_eq!(versions.find_index_lt_version(30), 2);
326
    // Query at the third version
327
    assert_eq!(versions.find_index_lt_version(35), 3);
328
    assert_eq!(versions.find_index_lt_version(40), 3);
329
    // Query at the fourth version
330
    assert_eq!(versions.find_index_lt_version(45), 4);
331
    // Query at the fifth version
332
    assert_eq!(versions.find_index_lt_version(50), 4);
333
    // Query after the fifth version
334
    assert_eq!(versions.find_index_lt_version(51), 5);
335
    assert_eq!(versions.find_index_lt_version(100), 5);
336
  }
337
338
  #[test]
339
  fn test_find_index_lt_version_with_deletes() {
340
    let versions = make_versions(vec![
341
      (10, Some("v1")),
342
      (20, None), // Delete
343
      (30, Some("v3")),
344
      (40, None), // Delete
345
    ]);
346
    // Query before the first version
347
    assert_eq!(versions.find_index_lt_version(5), 0);
348
    assert_eq!(versions.find_index_lt_version(9), 0);
349
    // Query at the first version
350
    assert_eq!(versions.find_index_lt_version(10), 0);
351
    // Query after the first version
352
    assert_eq!(versions.find_index_lt_version(15), 1);
353
    // Query at the second version
354
    assert_eq!(versions.find_index_lt_version(20), 1);
355
    // Query after the second version
356
    assert_eq!(versions.find_index_lt_version(25), 2);
357
    assert_eq!(versions.find_index_lt_version(30), 2);
358
    // Query at the third version
359
    assert_eq!(versions.find_index_lt_version(35), 3);
360
    assert_eq!(versions.find_index_lt_version(40), 3);
361
    // Query after the third version
362
    assert_eq!(versions.find_index_lt_version(50), 4);
363
  }
364
365
  // ==================== Tests for find_index_lte_version ====================
366
367
  #[test]
368
  fn test_find_index_lte_version_empty() {
369
    let versions = Versions::new();
370
    assert_eq!(versions.find_index_lte_version(0), 0);
371
    assert_eq!(versions.find_index_lte_version(1), 0);
372
    assert_eq!(versions.find_index_lte_version(100), 0);
373
  }
374
375
  #[test]
376
  fn test_find_index_lte_version_single_version() {
377
    let versions = make_versions(vec![(10, Some("value"))]);
378
    // Query before the version
379
    assert_eq!(versions.find_index_lte_version(5), 0);
380
    assert_eq!(versions.find_index_lte_version(9), 0);
381
    // Query at the version
382
    assert_eq!(versions.find_index_lte_version(10), 1);
383
    // Query after the version
384
    assert_eq!(versions.find_index_lte_version(11), 1);
385
    assert_eq!(versions.find_index_lte_version(100), 1);
386
  }
387
388
  #[test]
389
  fn test_find_index_lte_version_multiple_versions() {
390
    // Create a small list (≤32 elements) to trigger linear search
391
    let versions = make_versions(vec![
392
      (10, Some("v1")),
393
      (20, Some("v2")),
394
      (30, Some("v3")),
395
      (40, Some("v4")),
396
      (50, Some("v5")),
397
    ]);
398
    // Query before the first version
399
    assert_eq!(versions.find_index_lte_version(0), 0);
400
    assert_eq!(versions.find_index_lte_version(5), 0);
401
    // Query at the first version
402
    assert_eq!(versions.find_index_lte_version(10), 1);
403
    // Query after the first version
404
    assert_eq!(versions.find_index_lte_version(15), 1);
405
    // Query at the second version
406
    assert_eq!(versions.find_index_lte_version(20), 2);
407
    // Query after the second version
408
    assert_eq!(versions.find_index_lte_version(25), 2);
409
    // Query at the third version
410
    assert_eq!(versions.find_index_lte_version(30), 3);
411
    // Query after the third version
412
    assert_eq!(versions.find_index_lte_version(35), 3);
413
    // Query at the fourth version
414
    assert_eq!(versions.find_index_lte_version(40), 4);
415
    // Query after the fourth version
416
    assert_eq!(versions.find_index_lte_version(45), 4);
417
    // Query at the fifth version
418
    assert_eq!(versions.find_index_lte_version(50), 5);
419
    // Query after the fifth version
420
    assert_eq!(versions.find_index_lte_version(51), 5);
421
    assert_eq!(versions.find_index_lte_version(100), 5);
422
  }
423
424
  #[test]
425
  fn test_find_index_lte_version_with_deletes() {
426
    let versions = make_versions(vec![
427
      (10, Some("v1")),
428
      (20, None), // Delete
429
      (30, Some("v3")),
430
      (40, None), // Delete
431
    ]);
432
    // Query at the first version
433
    assert_eq!(versions.find_index_lte_version(10), 1);
434
    // Query after the first version
435
    assert_eq!(versions.find_index_lte_version(15), 1);
436
    // Query at the second version
437
    assert_eq!(versions.find_index_lte_version(20), 2);
438
    // Query after the second version
439
    assert_eq!(versions.find_index_lte_version(25), 2);
440
    // Query at the third version
441
    assert_eq!(versions.find_index_lte_version(30), 3);
442
    // Query after the third version
443
    assert_eq!(versions.find_index_lte_version(35), 3);
444
    // Query at the fourth version
445
    assert_eq!(versions.find_index_lte_version(40), 4);
446
    // Query after the fourth version
447
    assert_eq!(versions.find_index_lte_version(50), 4);
448
  }
449
450
  #[test]
451
  fn test_find_index_lt_vs_lte_difference() {
452
    // This test demonstrates the key difference between < and <=
453
    let versions = make_versions(vec![
454
      (10, Some("v1")),
455
      (20, Some("v2")),
456
      (30, Some("v3")),
457
      (40, Some("v4")),
458
      (50, Some("v5")),
459
    ]);
460
    // Query at the first version
461
    assert_eq!(versions.find_index_lt_version(10), 0);
462
    assert_eq!(versions.find_index_lte_version(10), 1);
463
    // Query after the first version
464
    assert_eq!(versions.find_index_lt_version(15), 1);
465
    assert_eq!(versions.find_index_lte_version(15), 1);
466
    // Query at the second version
467
    assert_eq!(versions.find_index_lt_version(20), 1);
468
    assert_eq!(versions.find_index_lte_version(20), 2);
469
    // Query at the third version
470
    assert_eq!(versions.find_index_lt_version(30), 2);
471
    assert_eq!(versions.find_index_lte_version(30), 3);
472
    // Query after the third version
473
    assert_eq!(versions.find_index_lt_version(35), 3);
474
    assert_eq!(versions.find_index_lte_version(35), 3);
475
  }
476
477
  // ==================== Tests for fetch_version ====================
478
479
  #[test]
480
  fn test_fetch_version_empty() {
481
    let versions = Versions::new();
482
    assert_eq!(versions.fetch_version(0), None);
483
    assert_eq!(versions.fetch_version(10), None);
484
    assert_eq!(versions.fetch_version(100), None);
485
  }
486
487
  #[test]
488
  fn test_fetch_version_single_version() {
489
    let versions = make_versions(vec![(10, Some("value"))]);
490
    // Query before the version
491
    assert_eq!(versions.fetch_version(5), None);
492
    assert_eq!(versions.fetch_version(9), None);
493
    // Query at the version
494
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("value".to_string())));
495
    // Query after the version
496
    assert_eq!(versions.fetch_version(11), Some(Bytes::from("value".to_string())));
497
    assert_eq!(versions.fetch_version(100), Some(Bytes::from("value".to_string())));
498
  }
499
500
  #[test]
501
  fn test_fetch_version_multiple_versions() {
502
    let versions = make_versions(vec![
503
      (10, Some("v1")),
504
      (20, Some("v2")),
505
      (30, Some("v3")),
506
      (40, Some("v4")),
507
      (50, Some("v5")),
508
    ]);
509
    // Query before the first version
510
    assert_eq!(versions.fetch_version(5), None);
511
    // Query at the first version
512
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v1".to_string())));
513
    // Query after the first version
514
    assert_eq!(versions.fetch_version(15), Some(Bytes::from("v1".to_string())));
515
    // Query at the second version
516
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2".to_string())));
517
    // Query after the second version
518
    assert_eq!(versions.fetch_version(25), Some(Bytes::from("v2".to_string())));
519
    // Query at the third version
520
    assert_eq!(versions.fetch_version(30), Some(Bytes::from("v3".to_string())));
521
    // Query after the third version
522
    assert_eq!(versions.fetch_version(35), Some(Bytes::from("v3".to_string())));
523
    // Query at the fourth version
524
    assert_eq!(versions.fetch_version(40), Some(Bytes::from("v4".to_string())));
525
    // Query after the fourth version
526
    assert_eq!(versions.fetch_version(45), Some(Bytes::from("v4".to_string())));
527
    // Query at the fifth version
528
    assert_eq!(versions.fetch_version(50), Some(Bytes::from("v5".to_string())));
529
    // Query after the fifth version
530
    assert_eq!(versions.fetch_version(100), Some(Bytes::from("v5".to_string())));
531
  }
532
533
  #[test]
534
  fn test_fetch_version_with_deletes() {
535
    let versions = make_versions(vec![
536
      (10, Some("v1")),
537
      (20, None), // Delete
538
      (30, Some("v3")),
539
      (40, None), // Delete
540
    ]);
541
    // Query before the first version
542
    assert_eq!(versions.fetch_version(5), None);
543
    // Query at the first version
544
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v1".to_string())));
545
    // Query after the first version
546
    assert_eq!(versions.fetch_version(15), Some(Bytes::from("v1".to_string())));
547
    // Query at the second version (delete)
548
    assert_eq!(versions.fetch_version(20), None);
549
    // Query after the second version (delete)
550
    assert_eq!(versions.fetch_version(25), None);
551
    // Query at the third version
552
    assert_eq!(versions.fetch_version(30), Some(Bytes::from("v3".to_string())));
553
    // Query after the third version
554
    assert_eq!(versions.fetch_version(35), Some(Bytes::from("v3".to_string())));
555
    // Query at the fourth version (delete)
556
    assert_eq!(versions.fetch_version(40), None);
557
    // Query after the fourth version (delete)
558
    assert_eq!(versions.fetch_version(50), None);
559
  }
560
561
  // ==================== Tests for exists_version ====================
562
563
  #[test]
564
  fn test_exists_version_empty() {
565
    let versions = Versions::new();
566
    assert!(!versions.exists_version(0));
567
    assert!(!versions.exists_version(10));
568
    assert!(!versions.exists_version(100));
569
  }
570
571
  #[test]
572
  fn test_exists_version_single_version() {
573
    let versions = make_versions(vec![(10, Some("value"))]);
574
    // Query before the version
575
    assert!(!versions.exists_version(5));
576
    assert!(!versions.exists_version(9));
577
    // Query at the version
578
    assert!(versions.exists_version(10));
579
    // Query after the version
580
    assert!(versions.exists_version(11));
581
    assert!(versions.exists_version(100));
582
  }
583
584
  #[test]
585
  fn test_exists_version_multiple_versions() {
586
    let versions = make_versions(vec![
587
      (10, Some("v1")),
588
      (20, Some("v2")),
589
      (30, Some("v3")),
590
      (40, Some("v4")),
591
      (50, Some("v5")),
592
    ]);
593
    // Query before the first version
594
    assert!(!versions.exists_version(5));
595
    // Query at the first version
596
    assert!(versions.exists_version(10));
597
    // Query after the first version
598
    assert!(versions.exists_version(15));
599
    // Query at the second version
600
    assert!(versions.exists_version(20));
601
    // Query after the second version
602
    assert!(versions.exists_version(25));
603
    // Query at the third version
604
    assert!(versions.exists_version(30));
605
    // Query after the third version
606
    assert!(versions.exists_version(35));
607
    // Query at the fourth version
608
    assert!(versions.exists_version(40));
609
    // Query after the fourth version
610
    assert!(versions.exists_version(45));
611
    // Query at the fifth version
612
    assert!(versions.exists_version(50));
613
    // Query after the fifth version
614
    assert!(versions.exists_version(100));
615
  }
616
617
  #[test]
618
  fn test_exists_version_with_deletes() {
619
    let versions = make_versions(vec![
620
      (10, Some("v1")),
621
      (20, None), // Delete
622
      (30, Some("v3")),
623
      (40, None), // Delete
624
    ]);
625
    // Query before the first version
626
    assert!(!versions.exists_version(5));
627
    // Query at the first version
628
    assert!(versions.exists_version(10));
629
    // Query after the first version
630
    assert!(versions.exists_version(15));
631
    // Query at the second version (delete)
632
    assert!(!versions.exists_version(20));
633
    // Query after the second version (delete)
634
    assert!(!versions.exists_version(25));
635
    // Query at the third version
636
    assert!(versions.exists_version(30));
637
    // Query after the third version
638
    assert!(versions.exists_version(35));
639
    // Query at the fourth version (delete)
640
    assert!(!versions.exists_version(40));
641
    // Query after the fourth version (delete)
642
    assert!(!versions.exists_version(50));
643
  }
644
645
  // ==================== Tests for push ====================
646
647
  #[test]
648
  fn test_push_to_empty_list() {
649
    let mut versions = Versions::new();
650
    // Push a value to empty list
651
    versions.push(make_version(10, Some("v1")));
652
    assert_eq!(versions.inner.len(), 1);
653
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v1".to_string())));
654
  }
655
656
  #[test]
657
  fn test_push_delete_to_empty_list() {
658
    let mut versions = Versions::new();
659
    // Push a delete (None) to empty list - should not add
660
    versions.push(make_version(10, None));
661
    assert_eq!(versions.inner.len(), 0);
662
  }
663
664
  #[test]
665
  fn test_push_in_order() {
666
    let mut versions = Versions::new();
667
    // Push versions in increasing order
668
    versions.push(make_version(10, Some("v1")));
669
    versions.push(make_version(20, Some("v2")));
670
    versions.push(make_version(30, Some("v3")));
671
    assert_eq!(versions.inner.len(), 3);
672
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v1".to_string())));
673
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2".to_string())));
674
    assert_eq!(versions.fetch_version(30), Some(Bytes::from("v3".to_string())));
675
  }
676
677
  #[test]
678
  fn test_push_duplicate_values() {
679
    let mut versions = Versions::new();
680
    // Push first version
681
    versions.push(make_version(10, Some("v1")));
682
    assert_eq!(versions.inner.len(), 1);
683
    // Push same value at newer version - should be skipped
684
    versions.push(make_version(20, Some("v1")));
685
    assert_eq!(versions.inner.len(), 1);
686
    // Push different value - should be added
687
    versions.push(make_version(30, Some("v2")));
688
    assert_eq!(versions.inner.len(), 2);
689
    // Push same value again - should be skipped
690
    versions.push(make_version(40, Some("v2")));
691
    assert_eq!(versions.inner.len(), 2);
692
  }
693
694
  #[test]
695
  fn test_push_out_of_order() {
696
    let mut versions = Versions::new();
697
    // Push versions out of order
698
    versions.push(make_version(30, Some("v3")));
699
    versions.push(make_version(10, Some("v1")));
700
    versions.push(make_version(20, Some("v2")));
701
    // Should be sorted correctly
702
    assert_eq!(versions.inner.len(), 3);
703
    assert_eq!(versions.inner[0].version, 10);
704
    assert_eq!(versions.inner[1].version, 20);
705
    assert_eq!(versions.inner[2].version, 30);
706
  }
707
708
  #[test]
709
  fn test_push_with_deletes() {
710
    let mut versions = Versions::new();
711
    // Push value, then delete, then value again
712
    versions.push(make_version(10, Some("v1")));
713
    assert_eq!(versions.inner.len(), 1);
714
    // Push delete
715
    versions.push(make_version(20, None));
716
    assert_eq!(versions.inner.len(), 2);
717
    assert!(!versions.exists_version(20));
718
    // Push new value
719
    versions.push(make_version(30, Some("v3")));
720
    assert_eq!(versions.inner.len(), 3);
721
    assert!(versions.exists_version(30));
722
  }
723
724
  #[test]
725
  fn test_push_same_version_different_value() {
726
    let mut versions = Versions::new();
727
    // Push a version
728
    versions.push(make_version(10, Some("v1")));
729
    assert_eq!(versions.inner.len(), 1);
730
    // Push same version with different value - should update/replace
731
    versions.push(make_version(10, Some("v2")));
732
    assert_eq!(versions.inner.len(), 1);
733
    // The new value should have replaced the old one
734
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v2".to_string())));
735
  }
736
737
  #[test]
738
  fn test_push_same_version_same_value() {
739
    let mut versions = Versions::new();
740
    // Push a version
741
    versions.push(make_version(10, Some("v1")));
742
    assert_eq!(versions.inner.len(), 1);
743
    // Push same version with same value - should still update (no-op)
744
    versions.push(make_version(10, Some("v1")));
745
    assert_eq!(versions.inner.len(), 1);
746
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v1".to_string())));
747
  }
748
749
  // ==================== Fast Path Tests ====================
750
751
  #[test]
752
  fn test_push_fast_path_append_different_value() {
753
    let mut versions = Versions::new();
754
    versions.push(make_version(10, Some("v1")));
755
    versions.push(make_version(20, Some("v2")));
756
    // Fast path: append with different value
757
    versions.push(make_version(30, Some("v3")));
758
    assert_eq!(versions.inner.len(), 3);
759
    assert_eq!(versions.inner[2].version, 30);
760
    assert_eq!(versions.fetch_version(30), Some(Bytes::from("v3".to_string())));
761
  }
762
763
  #[test]
764
  fn test_push_fast_path_append_same_value() {
765
    let mut versions = Versions::new();
766
    versions.push(make_version(10, Some("v1")));
767
    versions.push(make_version(20, Some("v2")));
768
    // Fast path: append with same value as last - should be ignored
769
    versions.push(make_version(30, Some("v2")));
770
    assert_eq!(versions.inner.len(), 2);
771
    assert_eq!(versions.fetch_version(30), Some(Bytes::from("v2".to_string())));
772
  }
773
774
  #[test]
775
  fn test_push_fast_path_update_last_different_value() {
776
    let mut versions = Versions::new();
777
    versions.push(make_version(10, Some("v1")));
778
    versions.push(make_version(20, Some("v2")));
779
    // Fast path: update last version with different value
780
    versions.push(make_version(20, Some("v2_updated")));
781
    assert_eq!(versions.inner.len(), 2);
782
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2_updated".to_string())));
783
  }
784
785
  #[test]
786
  fn test_push_fast_path_update_last_same_value() {
787
    let mut versions = Versions::new();
788
    versions.push(make_version(10, Some("v1")));
789
    versions.push(make_version(20, Some("v2")));
790
    // Fast path: update last version with same value - no-op
791
    versions.push(make_version(20, Some("v2")));
792
    assert_eq!(versions.inner.len(), 2);
793
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2".to_string())));
794
  }
795
796
  #[test]
797
  fn test_push_fast_path_multiple_updates_to_last() {
798
    let mut versions = Versions::new();
799
    versions.push(make_version(10, Some("v1")));
800
    // Multiple sequential updates to the same version
801
    versions.push(make_version(10, Some("v2")));
802
    versions.push(make_version(10, Some("v3")));
803
    versions.push(make_version(10, Some("v4")));
804
    assert_eq!(versions.inner.len(), 1);
805
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v4".to_string())));
806
  }
807
808
  #[test]
809
  fn test_push_fast_path_alternating_append_update() {
810
    let mut versions = Versions::new();
811
    // Append version 10
812
    versions.push(make_version(10, Some("v1")));
813
    // Append version 20
814
    versions.push(make_version(20, Some("v2")));
815
    // Update version 20
816
    versions.push(make_version(20, Some("v2_updated")));
817
    // Append version 30
818
    versions.push(make_version(30, Some("v3")));
819
    // Update version 30
820
    versions.push(make_version(30, Some("v3_updated")));
821
822
    assert_eq!(versions.inner.len(), 3);
823
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v1".to_string())));
824
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2_updated".to_string())));
825
    assert_eq!(versions.fetch_version(30), Some(Bytes::from("v3_updated".to_string())));
826
  }
827
828
  #[test]
829
  fn test_push_slow_path_insert_middle() {
830
    let mut versions = Versions::new();
831
    versions.push(make_version(10, Some("v1")));
832
    versions.push(make_version(30, Some("v3")));
833
    // Slow path: insert in the middle (version < last.version)
834
    versions.push(make_version(20, Some("v2")));
835
836
    assert_eq!(versions.inner.len(), 3);
837
    assert_eq!(versions.inner[0].version, 10);
838
    assert_eq!(versions.inner[1].version, 20);
839
    assert_eq!(versions.inner[2].version, 30);
840
  }
841
842
  #[test]
843
  fn test_push_slow_path_insert_beginning() {
844
    let mut versions = Versions::new();
845
    versions.push(make_version(20, Some("v2")));
846
    versions.push(make_version(30, Some("v3")));
847
    // Slow path: insert at the beginning
848
    versions.push(make_version(10, Some("v1")));
849
850
    assert_eq!(versions.inner.len(), 3);
851
    assert_eq!(versions.inner[0].version, 10);
852
    assert_eq!(versions.inner[1].version, 20);
853
    assert_eq!(versions.inner[2].version, 30);
854
  }
855
856
  #[test]
857
  fn test_push_slow_path_update_middle() {
858
    let mut versions = Versions::new();
859
    versions.push(make_version(10, Some("v1")));
860
    versions.push(make_version(20, Some("v2")));
861
    versions.push(make_version(30, Some("v3")));
862
    // Slow path: update a middle version
863
    versions.push(make_version(20, Some("v2_updated")));
864
865
    assert_eq!(versions.inner.len(), 3);
866
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2_updated".to_string())));
867
  }
868
869
  #[test]
870
  fn test_push_with_delete_at_end() {
871
    let mut versions = Versions::new();
872
    versions.push(make_version(10, Some("v1")));
873
    versions.push(make_version(20, Some("v2")));
874
    // Fast path: append delete
875
    versions.push(make_version(30, None));
876
877
    assert_eq!(versions.inner.len(), 3);
878
    assert!(!versions.exists_version(30));
879
    assert_eq!(versions.fetch_version(30), None);
880
  }
881
882
  #[test]
883
  fn test_push_delete_then_value_same_version() {
884
    let mut versions = Versions::new();
885
    versions.push(make_version(10, Some("v1")));
886
    // Push delete
887
    versions.push(make_version(20, None));
888
    assert!(!versions.exists_version(20));
889
    // Update same version with a value
890
    versions.push(make_version(20, Some("v2")));
891
    assert_eq!(versions.inner.len(), 2);
892
    assert!(versions.exists_version(20));
893
    assert_eq!(versions.fetch_version(20), Some(Bytes::from("v2".to_string())));
894
  }
895
896
  #[test]
897
  fn test_push_value_then_delete_same_version() {
898
    let mut versions = Versions::new();
899
    versions.push(make_version(10, Some("v1")));
900
    versions.push(make_version(20, Some("v2")));
901
    // Update last version to delete
902
    versions.push(make_version(20, None));
903
904
    assert_eq!(versions.inner.len(), 2);
905
    assert!(!versions.exists_version(20));
906
    assert_eq!(versions.fetch_version(20), None);
907
  }
908
909
  #[test]
910
  fn test_push_consecutive_deletes() {
911
    let mut versions = Versions::new();
912
    versions.push(make_version(10, Some("v1")));
913
    // Push delete at version 20
914
    versions.push(make_version(20, None));
915
    // Push another delete at version 30 (different from last value which is None)
916
    versions.push(make_version(30, None));
917
918
    // Should only have 2 entries - version 20 and 30 deletes should be separate
919
    assert_eq!(versions.inner.len(), 2);
920
    assert!(!versions.exists_version(20));
921
    assert!(!versions.exists_version(30));
922
  }
923
924
  #[test]
925
  fn test_push_stress_many_appends() {
926
    let mut versions = Versions::new();
927
    // Push many versions in order (all fast path appends)
928
    for i in 0..100 {
929
      let value = format!("v{}", i);
930
      versions.push(make_version(i * 10, Some(&value)));
931
    }
932
    assert_eq!(versions.inner.len(), 100);
933
    assert_eq!(versions.inner[0].version, 0);
934
    assert_eq!(versions.inner[99].version, 990);
935
  }
936
937
  #[test]
938
  fn test_push_stress_many_updates() {
939
    let mut versions = Versions::new();
940
    versions.push(make_version(10, Some("v1")));
941
    // Update the same version many times (all fast path updates)
942
    for i in 0..100 {
943
      let value = format!("v{}", i);
944
      versions.push(make_version(10, Some(&value)));
945
    }
946
    assert_eq!(versions.inner.len(), 1);
947
    assert_eq!(versions.fetch_version(10), Some(Bytes::from("v99".to_string())));
948
  }
949
}