/* This file is part of DarkFi (https://dark.fi) * * Copyright (C) 2026-2026 Dyne.org foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ //! Simulate the creation of a [`DatabaseOverlay`] on top of an entire //! [`Database`] instance, and perform writes to verify overlay's cache //! functionality. use kvdb_overlay::{Database, DatabaseOverlay, Result}; const TREE_1: &str = "_tree1"; const TREE_2: &str = "_tree2"; #[test] fn database_overlay() -> Result<()> { // Initialize database let (db, _folder) = Database::open_temp()?; // Initialize overlay let mut overlay = DatabaseOverlay::new(&db, vec![])?; // Open trees in the overlay overlay.open_tree_default(TREE_1, false)?; overlay.open_tree_default(TREE_2, false)?; // Check overlay trees are empty assert!(overlay.is_empty(TREE_1)?); assert!(overlay.is_empty(TREE_2)?); // Check last value is `None` assert_eq!(overlay.last(TREE_1)?, None); assert_eq!(overlay.last(TREE_2)?, None); // We keep seperate trees for validation let tree_1 = db.open_tree_default(TREE_1)?; let tree_2 = db.open_tree_default(TREE_2)?; // Insert some values to the overlay overlay.insert(TREE_1, b"key_a", b"val_a")?; overlay.insert(TREE_1, b"key_b", b"val_b")?; overlay.insert(TREE_1, b"key_c", b"val_c")?; overlay.insert(TREE_2, b"key_d", b"val_d")?; overlay.insert(TREE_2, b"key_e", b"val_e")?; overlay.insert(TREE_2, b"key_f", b"val_f")?; // Verify they are in the overlay assert_eq!(overlay.get(TREE_1, b"key_a")?, Some(b"val_a".into())); assert_eq!(overlay.get(TREE_1, b"key_b")?, Some(b"val_b".into())); assert_eq!(overlay.get(TREE_1, b"key_c")?, Some(b"val_c".into())); assert_eq!(overlay.get(TREE_2, b"key_d")?, Some(b"val_d".into())); assert_eq!(overlay.get(TREE_2, b"key_e")?, Some(b"val_e".into())); assert_eq!(overlay.get(TREE_2, b"key_f")?, Some(b"val_f".into())); // Check overlay trees are not empty assert!(!overlay.is_empty(TREE_1)?); assert!(!overlay.is_empty(TREE_2)?); // Check their last values assert_eq!( overlay.last(TREE_1)?, Some((b"key_c".into(), b"val_c".into())) ); assert_eq!( overlay.last(TREE_2)?, Some((b"key_f".into(), b"val_f".into())) ); // Verify they are not in the database assert_eq!(tree_1.get(b"key_a")?, None); assert_eq!(tree_1.get(b"key_b")?, None); assert_eq!(tree_1.get(b"key_c")?, None); assert_eq!(tree_2.get(b"key_d")?, None); assert_eq!(tree_2.get(b"key_e")?, None); assert_eq!(tree_2.get(b"key_f")?, None); // Now execute all tree batches in the overlay overlay.apply()?; // Don't forget to flush db.flush_default_mode()?; // Verify the database contains keys assert_eq!(tree_1.get(b"key_a")?, Some(b"val_a".into())); assert_eq!(tree_1.get(b"key_b")?, Some(b"val_b".into())); assert_eq!(tree_1.get(b"key_c")?, Some(b"val_c".into())); assert_eq!(tree_2.get(b"key_d")?, Some(b"val_d".into())); assert_eq!(tree_2.get(b"key_e")?, Some(b"val_e".into())); assert_eq!(tree_2.get(b"key_f")?, Some(b"val_f".into())); Ok(()) } #[test] fn database_overlay_iteration() -> Result<()> { // Initialize database let (db, _folder) = Database::open_temp()?; // Initialize tree let tree = db.open_tree_default(TREE_1)?; tree.insert(b"key_a", b"val_a")?; tree.insert(b"key_c", b"val_c")?; tree.insert(b"key_e", b"val_e")?; // Initialize overlay let mut overlay = DatabaseOverlay::new(&db, vec![])?; // Open tree in the overlay overlay.open_tree_default(TREE_1, false)?; // Insert some values to the overlay overlay.insert(TREE_1, b"key_b", b"val_b")?; overlay.insert(TREE_1, b"key_d", b"val_d")?; overlay.insert(TREE_1, b"key_e", b"val_ee")?; overlay.insert(TREE_1, b"key_f", b"val_f")?; // Remove some values from the overlay overlay.remove(TREE_1, b"key_c")?; overlay.remove(TREE_1, b"key_d")?; // Iterate overlay to verify sequence let expected_sequence = [ (b"key_a".to_vec(), b"val_a".to_vec()), (b"key_b".to_vec(), b"val_b".to_vec()), (b"key_e".to_vec(), b"val_ee".to_vec()), (b"key_f".to_vec(), b"val_f".to_vec()), ]; for (index, record) in overlay.iter(TREE_1)?.enumerate() { assert_eq!(record?, expected_sequence[index]); } Ok(()) }