1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// in_memory.rs — Mode-specific tests for in-memory Chisel.
//
// Behavior parity with file-backed Chisel is verified by the dual-backing
// integration suite; these tests cover only what is specific to memory mode:
// the open constructors, option validation, and isolation between instances.
mod common;
use chisel::{Chisel, ChiselError, Options};
#[test]
fn open_in_memory_round_trip_commit() {
let mut db = Chisel::open_in_memory().unwrap();
db.begin().unwrap();
let h = db.allocate(b"hello").unwrap();
db.commit().unwrap();
assert_eq!(db.read(h).unwrap(), b"hello".to_vec());
}
#[test]
fn open_in_memory_round_trip_rollback() {
let mut db = Chisel::open_in_memory().unwrap();
db.begin().unwrap();
let h = db.allocate(b"hello").unwrap();
db.rollback().unwrap();
// A fresh transaction must not see rolled-back handles.
db.begin().unwrap();
assert!(
matches!(db.read(h), Err(ChiselError::InvalidHandle(_))),
"rolled-back handle must be InvalidHandle"
);
}
#[test]
fn open_in_memory_with_options_respects_superblock_count() {
// Non-default superblock_count flows through to the memory bootstrap.
// We cannot inspect the superblock count from the public API directly,
// but an invalid value must still be rejected by the same validation
// path used for file-backed open.
let bad = Options::default().superblock_count(1); // below MIN_SUPERBLOCKS (2)
assert!(
matches!(
Chisel::open_in_memory_with_options(bad),
Err(ChiselError::InvalidSuperblockCount { value: 1 })
),
"superblock_count=1 must produce InvalidSuperblockCount {{ value: 1 }}"
);
let good = Options::default().superblock_count(4);
let mut db = Chisel::open_in_memory_with_options(good).unwrap();
db.begin().unwrap();
db.allocate(b"payload").unwrap();
db.commit().unwrap();
}
#[test]
fn open_in_memory_rejects_read_only_option() {
// A read-only, freshly-created memory database cannot bootstrap
// (nothing to read, and the superblock-write step is blocked).
// We surface this early as an explicit InvalidArgument-style error
// rather than letting the bootstrap fail obliquely.
let opts = Options::default().read_only(true);
assert!(
matches!(
Chisel::open_in_memory_with_options(opts),
Err(ChiselError::ReadOnlyMode)
),
"read_only in-memory open must fail with ReadOnlyMode"
);
}
#[test]
fn dropping_in_memory_db_releases_backing() {
// Smoke test: we can create, fill, drop, and recreate many times
// without accumulating state. No fd leaks to check here; this mostly
// guards against "accidentally leaked into a static" regressions.
for _ in 0..8 {
let mut db = Chisel::open_in_memory().unwrap();
db.begin().unwrap();
for i in 0..100u32 {
db.allocate(&i.to_le_bytes()).unwrap();
}
db.commit().unwrap();
}
}