database_overlay.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2026-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. //! Simulate the creation of a [`DatabaseOverlay`] on top of an entire
  19. //! [`Database`] instance, and perform writes to verify overlay's cache
  20. //! functionality.
  21. use kvdb_overlay::{Database, DatabaseOverlay, Result};
  22. const TREE_1: &str = "_tree1";
  23. const TREE_2: &str = "_tree2";
  24. #[test]
  25. fn database_overlay() -> Result<()> {
  26. // Initialize database
  27. let (db, _folder) = Database::open_temp()?;
  28. // Initialize overlay
  29. let mut overlay = DatabaseOverlay::new(&db, vec![])?;
  30. // Open trees in the overlay
  31. overlay.open_tree_default(TREE_1, false)?;
  32. overlay.open_tree_default(TREE_2, false)?;
  33. // Check overlay trees are empty
  34. assert!(overlay.is_empty(TREE_1)?);
  35. assert!(overlay.is_empty(TREE_2)?);
  36. // Check last value is `None`
  37. assert_eq!(overlay.last(TREE_1)?, None);
  38. assert_eq!(overlay.last(TREE_2)?, None);
  39. // We keep seperate trees for validation
  40. let tree_1 = db.open_tree_default(TREE_1)?;
  41. let tree_2 = db.open_tree_default(TREE_2)?;
  42. // Insert some values to the overlay
  43. overlay.insert(TREE_1, b"key_a", b"val_a")?;
  44. overlay.insert(TREE_1, b"key_b", b"val_b")?;
  45. overlay.insert(TREE_1, b"key_c", b"val_c")?;
  46. overlay.insert(TREE_2, b"key_d", b"val_d")?;
  47. overlay.insert(TREE_2, b"key_e", b"val_e")?;
  48. overlay.insert(TREE_2, b"key_f", b"val_f")?;
  49. // Verify they are in the overlay
  50. assert_eq!(overlay.get(TREE_1, b"key_a")?, Some(b"val_a".into()));
  51. assert_eq!(overlay.get(TREE_1, b"key_b")?, Some(b"val_b".into()));
  52. assert_eq!(overlay.get(TREE_1, b"key_c")?, Some(b"val_c".into()));
  53. assert_eq!(overlay.get(TREE_2, b"key_d")?, Some(b"val_d".into()));
  54. assert_eq!(overlay.get(TREE_2, b"key_e")?, Some(b"val_e".into()));
  55. assert_eq!(overlay.get(TREE_2, b"key_f")?, Some(b"val_f".into()));
  56. // Check overlay trees are not empty
  57. assert!(!overlay.is_empty(TREE_1)?);
  58. assert!(!overlay.is_empty(TREE_2)?);
  59. // Check their last values
  60. assert_eq!(
  61. overlay.last(TREE_1)?,
  62. Some((b"key_c".into(), b"val_c".into()))
  63. );
  64. assert_eq!(
  65. overlay.last(TREE_2)?,
  66. Some((b"key_f".into(), b"val_f".into()))
  67. );
  68. // Verify they are not in the database
  69. assert_eq!(tree_1.get(b"key_a")?, None);
  70. assert_eq!(tree_1.get(b"key_b")?, None);
  71. assert_eq!(tree_1.get(b"key_c")?, None);
  72. assert_eq!(tree_2.get(b"key_d")?, None);
  73. assert_eq!(tree_2.get(b"key_e")?, None);
  74. assert_eq!(tree_2.get(b"key_f")?, None);
  75. // Now execute all tree batches in the overlay
  76. overlay.apply()?;
  77. // Don't forget to flush
  78. db.flush_default_mode()?;
  79. // Verify the database contains keys
  80. assert_eq!(tree_1.get(b"key_a")?, Some(b"val_a".into()));
  81. assert_eq!(tree_1.get(b"key_b")?, Some(b"val_b".into()));
  82. assert_eq!(tree_1.get(b"key_c")?, Some(b"val_c".into()));
  83. assert_eq!(tree_2.get(b"key_d")?, Some(b"val_d".into()));
  84. assert_eq!(tree_2.get(b"key_e")?, Some(b"val_e".into()));
  85. assert_eq!(tree_2.get(b"key_f")?, Some(b"val_f".into()));
  86. Ok(())
  87. }
  88. #[test]
  89. fn database_overlay_iteration() -> Result<()> {
  90. // Initialize database
  91. let (db, _folder) = Database::open_temp()?;
  92. // Initialize tree
  93. let tree = db.open_tree_default(TREE_1)?;
  94. tree.insert(b"key_a", b"val_a")?;
  95. tree.insert(b"key_c", b"val_c")?;
  96. tree.insert(b"key_e", b"val_e")?;
  97. // Initialize overlay
  98. let mut overlay = DatabaseOverlay::new(&db, vec![])?;
  99. // Open tree in the overlay
  100. overlay.open_tree_default(TREE_1, false)?;
  101. // Insert some values to the overlay
  102. overlay.insert(TREE_1, b"key_b", b"val_b")?;
  103. overlay.insert(TREE_1, b"key_d", b"val_d")?;
  104. overlay.insert(TREE_1, b"key_e", b"val_ee")?;
  105. overlay.insert(TREE_1, b"key_f", b"val_f")?;
  106. // Remove some values from the overlay
  107. overlay.remove(TREE_1, b"key_c")?;
  108. overlay.remove(TREE_1, b"key_d")?;
  109. // Iterate overlay to verify sequence
  110. let expected_sequence = [
  111. (b"key_a".to_vec(), b"val_a".to_vec()),
  112. (b"key_b".to_vec(), b"val_b".to_vec()),
  113. (b"key_e".to_vec(), b"val_ee".to_vec()),
  114. (b"key_f".to_vec(), b"val_f".to_vec()),
  115. ];
  116. for (index, record) in overlay.iter(TREE_1)?.enumerate() {
  117. assert_eq!(record?, expected_sequence[index]);
  118. }
  119. Ok(())
  120. }