| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /* 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 <https://www.gnu.org/licenses/>.
- */
- use std::io::{Cursor, Read};
- use kvdb_overlay::{Database, DatabaseOverlay, Error, Result, TreeOverlay, Value};
- #[test]
- fn tree_value_owns_bytes() -> Result<()> {
- let (db, _folder) = Database::open_temp()?;
- let value = {
- let tree = db.open_tree_default("values")?;
- assert!(tree.get(b"missing")?.is_none());
- tree.insert(b"empty", b"")?;
- assert_eq!(tree.get(b"empty")?.unwrap().as_ref(), b"");
- tree.insert(b"key", &[42; 128])?;
- let value = tree.get(b"key")?.unwrap();
- assert!(matches!(value, Value::Backend(_)));
- tree.insert(b"key", b"replacement")?;
- tree.remove(b"key")?;
- value
- };
- drop(db);
- let mut reader = Cursor::new(value);
- let mut bytes = [0; 128];
- reader.read_exact(&mut bytes)?;
- assert_eq!(bytes, [42; 128]);
- assert_eq!(reader.read(&mut bytes)?, 0);
- Ok(())
- }
- #[test]
- fn overlay_value_borrows_cache() -> Result<()> {
- let (db, _folder) = Database::open_temp()?;
- let tree = db.open_tree_default("values")?;
- tree.insert(b"key", b"backend")?;
- let mut overlay = TreeOverlay::new(&tree);
- assert!(overlay.get(b"missing")?.is_none());
- let value = overlay.get(b"key")?.unwrap();
- assert!(matches!(value, Value::Backend(_)));
- assert_eq!(value.as_ref(), b"backend");
- overlay.insert(b"key", &[7; 128])?;
- let value = overlay.get(b"key")?.unwrap();
- assert!(matches!(value, Value::Cached(_)));
- assert_eq!(
- value.as_ref().as_ptr(),
- overlay.state.cache.get(b"key".as_slice()).unwrap().as_ptr()
- );
- let mut reader = value.as_ref();
- let mut bytes = [0; 128];
- reader.read_exact(&mut bytes)?;
- assert_eq!(bytes, [7; 128]);
- assert_eq!(reader.read(&mut bytes)?, 0);
- overlay.remove(b"key")?;
- assert!(overlay.get(b"key")?.is_none());
- assert!(tree.get(b"key")?.is_some());
- overlay.insert(b"key", b"")?;
- assert_eq!(overlay.get(b"key")?.unwrap().as_ref(), b"");
- // Removals take precedence even if a public cache state contains both.
- overlay.state.removed.insert(b"key".to_vec());
- assert!(overlay.get(b"key")?.is_none());
- Ok(())
- }
- #[test]
- fn database_overlay_value() -> Result<()> {
- let (db, _folder) = Database::open_temp()?;
- let tree = db.open_tree_default("values")?;
- tree.insert(b"key", b"backend")?;
- let mut overlay = DatabaseOverlay::new(&db, vec![])?;
- assert!(matches!(
- overlay.get("values", b"key"),
- Err(Error::CollectionNotFound(_))
- ));
- overlay.open_tree_default("values", false)?;
- assert!(overlay.get("values", b"missing")?.is_none());
- assert_eq!(overlay.get("values", b"key")?.unwrap().as_ref(), b"backend");
- overlay.insert("values", b"key", b"cached")?;
- assert_eq!(overlay.get("values", b"key")?.unwrap().as_ref(), b"cached");
- overlay.remove("values", b"key")?;
- assert!(overlay.get("values", b"key")?.is_none());
- overlay.drop_tree("values")?;
- assert!(matches!(
- overlay.get("values", b"key"),
- Err(Error::CollectionNotFound(_))
- ));
- Ok(())
- }
- #[test]
- fn value_into_vec_copies_bytes() -> Result<()> {
- for cached in [false, true] {
- for original in [b"value".as_slice(), b""] {
- let mut bytes = {
- let (db, _folder) = Database::open_temp()?;
- let tree = db.open_tree_default("values")?;
- tree.insert(b"key", original)?;
- let mut overlay = TreeOverlay::new(&tree);
- if cached {
- overlay.insert(b"key", original)?;
- }
- let value = overlay.get(b"key")?.unwrap();
- if cached {
- assert!(matches!(value, Value::Cached(_)));
- } else {
- assert!(matches!(value, Value::Backend(_)));
- }
- let mut bytes = value.into_vec();
- assert_eq!(bytes, original);
- bytes.reverse();
- bytes.push(b'!');
- assert_eq!(overlay.get(b"key")?.unwrap().as_ref(), original);
- assert_eq!(tree.get(b"key")?.unwrap().as_ref(), original);
- overlay.insert(b"key", b"replacement")?;
- overlay.remove(b"key")?;
- bytes
- };
- assert_eq!(bytes.pop(), Some(b'!'));
- bytes.reverse();
- assert_eq!(bytes, original);
- }
- }
- Ok(())
- }
|