Coverage Report

Created: 2026-03-23 07:13

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