1use kvdb::{IoStatsKind, KeyValueDB};
12use std::io;
13
14pub fn test_put_and_get(db: &dyn KeyValueDB) -> io::Result<()> {
16 let key1 = b"key1";
17
18 let mut transaction = db.transaction();
19 transaction.put(0, key1, b"horse");
20 db.write(transaction)?;
21 assert_eq!(&*db.get(0, key1)?.unwrap(), b"horse");
22 Ok(())
23}
24
25pub fn test_delete_and_get(db: &dyn KeyValueDB) -> io::Result<()> {
27 let key1 = b"key1";
28
29 let mut transaction = db.transaction();
30 transaction.put(0, key1, b"horse");
31 db.write(transaction)?;
32 assert_eq!(&*db.get(0, key1)?.unwrap(), b"horse");
33
34 let mut transaction = db.transaction();
35 transaction.delete(0, key1);
36 db.write(transaction)?;
37 assert!(db.get(0, key1)?.is_none());
38 Ok(())
39}
40
41pub fn test_get_fails_with_non_existing_column(db: &dyn KeyValueDB) -> io::Result<()> {
44 assert!(db.get(1, &[]).is_err());
45 Ok(())
46}
47
48pub fn test_write_clears_buffered_ops(db: &dyn KeyValueDB) -> io::Result<()> {
50 let mut batch = db.transaction();
51 batch.put(0, b"foo", b"bar");
52 db.write(batch)?;
53
54 assert_eq!(db.get(0, b"foo")?.unwrap(), b"bar");
55
56 let mut batch = db.transaction();
57 batch.put(0, b"foo", b"baz");
58 db.write(batch)?;
59
60 assert_eq!(db.get(0, b"foo")?.unwrap(), b"baz");
61 Ok(())
62}
63
64pub fn test_iter(db: &dyn KeyValueDB) -> io::Result<()> {
66 let key1 = b"key1";
67 let key2 = b"key2";
68
69 let mut transaction = db.transaction();
70 transaction.put(0, key1, key1);
71 transaction.put(0, key2, key2);
72 db.write(transaction)?;
73
74 let contents: Vec<_> = db.iter(0).into_iter().map(Result::unwrap).collect();
75 assert_eq!(contents.len(), 2);
76 assert_eq!(&*contents[0].0, key1);
77 assert_eq!(&*contents[0].1, key1);
78 assert_eq!(&*contents[1].0, key2);
79 assert_eq!(&*contents[1].1, key2);
80 Ok(())
81}
82
83pub fn test_iter_with_prefix(db: &dyn KeyValueDB) -> io::Result<()> {
85 let key1 = b"0";
86 let key2 = b"ab";
87 let key3 = b"abc";
88 let key4 = b"abcd";
89
90 let mut batch = db.transaction();
91 batch.put(0, key1, key1);
92 batch.put(0, key2, key2);
93 batch.put(0, key3, key3);
94 batch.put(0, key4, key4);
95 db.write(batch)?;
96
97 let contents: Vec<_> = db.iter_with_prefix(0, b"").into_iter().map(Result::unwrap).collect();
99 assert_eq!(contents.len(), 4);
100 assert_eq!(&*contents[0].0, key1);
101 assert_eq!(&*contents[1].0, key2);
102 assert_eq!(&*contents[2].0, key3);
103 assert_eq!(&*contents[3].0, key4);
104
105 let contents: Vec<_> = db.iter_with_prefix(0, b"a").into_iter().map(Result::unwrap).collect();
107 assert_eq!(contents.len(), 3);
108 assert_eq!(&*contents[0].0, key2);
109 assert_eq!(&*contents[1].0, key3);
110 assert_eq!(&*contents[2].0, key4);
111
112 let contents: Vec<_> = db.iter_with_prefix(0, b"abc").into_iter().map(Result::unwrap).collect();
114 assert_eq!(contents.len(), 2);
115 assert_eq!(&*contents[0].0, key3);
116 assert_eq!(&*contents[1].0, key4);
117
118 let contents: Vec<_> = db.iter_with_prefix(0, b"abcde").into_iter().map(Result::unwrap).collect();
120 assert_eq!(contents.len(), 0);
121
122 let contents: Vec<_> = db.iter_with_prefix(0, b"0").into_iter().map(Result::unwrap).collect();
124 assert_eq!(contents.len(), 1);
125 assert_eq!(&*contents[0].0, key1);
126 Ok(())
127}
128
129pub const IO_STATS_NUM_COLUMNS: u32 = 3;
131
132pub fn test_io_stats(db: &dyn KeyValueDB) -> io::Result<()> {
135 let key1 = b"kkk";
136 let mut batch = db.transaction();
137 batch.put(0, key1, key1);
138 batch.put(1, key1, key1);
139 batch.put(2, key1, key1);
140
141 for _ in 0..10 {
142 db.get(0, key1)?;
143 }
144
145 db.write(batch)?;
146
147 let io_stats = db.io_stats(IoStatsKind::SincePrevious);
148 assert_eq!(io_stats.transactions, 1);
149 assert_eq!(io_stats.writes, 3);
150 assert_eq!(io_stats.bytes_written, 18);
151 assert_eq!(io_stats.reads, 10);
152 assert_eq!(io_stats.bytes_read, 30);
153
154 let new_io_stats = db.io_stats(IoStatsKind::SincePrevious);
155 assert_eq!(new_io_stats.transactions, 0);
158
159 let new_io_stats = db.io_stats(IoStatsKind::Overall);
161 assert_eq!(new_io_stats.bytes_written, 18);
162
163 let mut batch = db.transaction();
164 batch.delete(0, key1);
165 batch.delete(1, key1);
166 batch.delete(2, key1);
167
168 assert_eq!(db.io_stats(IoStatsKind::SincePrevious).writes, 0);
170
171 db.write(batch)?;
172 assert_eq!(db.io_stats(IoStatsKind::SincePrevious).writes, 3);
174 Ok(())
175}
176
177pub const DELETE_PREFIX_NUM_COLUMNS: u32 = 7;
179
180pub fn test_delete_prefix(db: &dyn KeyValueDB) -> io::Result<()> {
182 let keys = [
183 &[][..],
184 &[0u8][..],
185 &[0, 1][..],
186 &[1][..],
187 &[1, 0][..],
188 &[1, 255][..],
189 &[1, 255, 255][..],
190 &[2][..],
191 &[2, 0][..],
192 &[2, 255][..],
193 &[255; 16][..],
194 ];
195 let init_db = |ix: u32| -> io::Result<()> {
196 let mut batch = db.transaction();
197 for (i, key) in keys.iter().enumerate() {
198 batch.put(ix, key, &[i as u8]);
199 }
200 db.write(batch)?;
201 Ok(())
202 };
203 let check_db = |ix: u32, content: [bool; 11]| -> io::Result<()> {
204 let mut state = [true; 11];
205 for (c, key) in keys.iter().enumerate() {
206 state[c] = db.get(ix, key)?.is_some();
207 }
208 assert_eq!(state, content, "at {}", ix);
209 Ok(())
210 };
211 let tests: [_; DELETE_PREFIX_NUM_COLUMNS as usize] = [
212 (&[1u8][..], [true, true, true, false, false, false, false, true, true, true, true]),
214 (&[1u8, 255, 255][..], [true, true, true, true, true, true, false, true, true, true, true]),
216 (&[1, 2][..], [true, true, true, true, true, true, true, true, true, true, true]),
218 (&[8][..], [true, true, true, true, true, true, true, true, true, true, true]),
220 (&[255, 255][..], [true, true, true, true, true, true, true, true, true, true, false]),
222 (&[255][..], [true, true, true, true, true, true, true, true, true, true, false]),
224 (&[][..], [false, false, false, false, false, false, false, false, false, false, false]),
226 ];
227 for (ix, test) in tests.iter().enumerate() {
228 let ix = ix as u32;
229 init_db(ix)?;
230 let mut batch = db.transaction();
231 batch.delete_prefix(ix, test.0);
232 db.write(batch)?;
233 check_db(ix, test.1)?;
234 }
235
236 Ok(())
237}
238
239pub fn test_complex(db: &dyn KeyValueDB) -> io::Result<()> {
241 let key1 = b"02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
242 let key2 = b"03c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
243 let key3 = b"04c00000000b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
244 let key4 = b"04c01111110b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
245 let key5 = b"04c02222220b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
246
247 let mut batch = db.transaction();
248 batch.put(0, key1, b"cat");
249 batch.put(0, key2, b"dog");
250 batch.put(0, key3, b"caterpillar");
251 batch.put(0, key4, b"beef");
252 batch.put(0, key5, b"fish");
253 db.write(batch)?;
254
255 assert_eq!(&*db.get(0, key1)?.unwrap(), b"cat");
256
257 let contents: Vec<_> = db.iter(0).into_iter().map(Result::unwrap).collect();
258 assert_eq!(contents.len(), 5);
259 assert_eq!(contents[0].0.to_vec(), key1.to_vec());
260 assert_eq!(&*contents[0].1, b"cat");
261 assert_eq!(contents[1].0.to_vec(), key2.to_vec());
262 assert_eq!(&*contents[1].1, b"dog");
263
264 let mut prefix_iter = db.iter_with_prefix(0, b"04c0");
265 assert_eq!(*prefix_iter.next().unwrap().unwrap().1, b"caterpillar"[..]);
266 assert_eq!(*prefix_iter.next().unwrap().unwrap().1, b"beef"[..]);
267 assert_eq!(*prefix_iter.next().unwrap().unwrap().1, b"fish"[..]);
268
269 let mut batch = db.transaction();
270 batch.delete(0, key1);
271 db.write(batch)?;
272
273 assert!(db.get(0, key1)?.is_none());
274
275 let mut batch = db.transaction();
276 batch.put(0, key1, b"cat");
277 db.write(batch)?;
278
279 let mut transaction = db.transaction();
280 transaction.put(0, key3, b"elephant");
281 transaction.delete(0, key1);
282 db.write(transaction)?;
283 assert!(db.get(0, key1)?.is_none());
284 assert_eq!(&*db.get(0, key3)?.unwrap(), b"elephant");
285
286 assert_eq!(&*db.get_by_prefix(0, key3).unwrap().unwrap(), b"elephant");
287 assert_eq!(&*db.get_by_prefix(0, key2).unwrap().unwrap(), b"dog");
288
289 let mut transaction = db.transaction();
290 transaction.put(0, key1, b"horse");
291 transaction.delete(0, key3);
292 db.write(transaction)?;
293 assert!(db.get(0, key3)?.is_none());
294 assert_eq!(&*db.get(0, key1)?.unwrap(), b"horse");
295
296 assert!(db.get(0, key3)?.is_none());
297 assert_eq!(&*db.get(0, key1)?.unwrap(), b"horse");
298 Ok(())
299}