Skip to main content

keyvaluedb_shared_tests/
lib.rs

1//! Shared tests for keyvaluedb functionality, to be executed against actual implementations.
2
3#![deny(clippy::all)]
4
5use keyvaluedb::{DBKey, DBKeyRef, DBKeyValue, DBKeyValueRef, IoStatsKind, KeyValueDB};
6use std::io;
7
8/// A test for `KeyValueDB::get`.
9pub async fn test_put_and_get<DB: KeyValueDB>(db: DB) -> io::Result<()> {
10    let key1 = b"key1";
11
12    let mut transaction = db.transaction();
13    transaction.put(0, key1, b"horse");
14    db.write(transaction).await.map_err(|e| e.error)?;
15    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
16    Ok(())
17}
18
19/// A test for `KeyValueDB::num_keys`.
20pub async fn test_num_keys<DB: KeyValueDB>(db: DB) -> io::Result<()> {
21    let key1 = b"key1";
22    let key2 = b"key2";
23
24    let mut transaction = db.transaction();
25    transaction.put(0, key1, b"horse");
26    transaction.put(0, key2, b"horse2");
27    db.write(transaction).await.map_err(|e| e.error)?;
28    assert_eq!(db.num_keys(0).await?, 2);
29    Ok(())
30}
31
32/// A test for `KeyValueDB::get` and delete with transaction.
33pub async fn test_delete_and_get<DB: KeyValueDB>(db: DB) -> io::Result<()> {
34    let key1 = b"key1";
35
36    let mut transaction = db.transaction();
37    transaction.put(0, key1, b"horse");
38    db.write(transaction).await.map_err(|e| e.error)?;
39    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
40
41    let mut transaction = db.transaction();
42    transaction.delete(0, key1);
43    db.write(transaction).await.map_err(|e| e.error)?;
44    assert!(db.get(0, key1).await?.is_none());
45    Ok(())
46}
47
48/// A test for `KeyValueDB::get` and delete without transaction.
49pub async fn test_delete_and_get_single<DB: KeyValueDB>(db: DB) -> io::Result<()> {
50    let key1 = b"key1";
51
52    let mut transaction = db.transaction();
53    transaction.put(0, key1, b"horse");
54    db.write(transaction).await.map_err(|e| e.error)?;
55    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
56
57    assert_eq!(db.delete(0, key1).await?, Some(b"horse".to_vec()));
58    assert!(db.get(0, key1).await?.is_none());
59    assert_eq!(db.delete(0, key1).await?, None);
60
61    Ok(())
62}
63
64/// A test for `KeyValueDB::get`.
65/// Assumes the `db` has only 1 column.
66pub async fn test_get_fails_with_non_existing_column<DB: KeyValueDB>(db: DB) -> io::Result<()> {
67    assert!(db.get(1, b"").await.is_err());
68    Ok(())
69}
70
71/// A test for `KeyValueDB::write`.
72pub async fn test_write_clears_buffered_ops<DB: KeyValueDB>(db: DB) -> io::Result<()> {
73    let mut batch = db.transaction();
74    batch.put(0, b"foo", b"bar");
75    db.write(batch).await.map_err(|e| e.error)?;
76
77    assert_eq!(db.get(0, b"foo").await?.unwrap(), b"bar");
78
79    let mut batch = db.transaction();
80    batch.put(0, b"foo", b"baz");
81    db.write(batch).await.map_err(|e| e.error)?;
82
83    assert_eq!(db.get(0, b"foo").await?.unwrap(), b"baz");
84    Ok(())
85}
86
87/// A test for `KeyValueDB::iter`.
88pub async fn test_iter<DB: KeyValueDB>(db: DB) -> io::Result<()> {
89    let key1 = b"key1";
90    let key2 = b"key2";
91
92    let mut transaction = db.transaction();
93    transaction.put(0, key1, key1);
94    transaction.put(0, key2, key2);
95    db.write(transaction).await.map_err(|e| e.error)?;
96
97    let contents: Vec<DBKeyValue> = Vec::new();
98    let (contents, out) = db
99        .iter(0, None, contents, |contents, kv: DBKeyValueRef| {
100            contents.push((kv.0.clone(), kv.1.clone()));
101            Ok(Option::<()>::None)
102        })
103        .await?;
104    assert!(out.is_none());
105    assert_eq!(contents.len(), 2);
106    assert_eq!(contents[0].0, key1);
107    assert_eq!(contents[0].1, key1);
108    assert_eq!(contents[1].0, key2);
109    assert_eq!(contents[1].1, key2);
110
111    // test iter with early return
112    let contents: Vec<DBKeyValue> = Vec::new();
113    let (contents, out) = db
114        .iter(0, None, contents, |contents, kv: DBKeyValueRef| {
115            contents.push((kv.0.clone(), kv.1.clone()));
116            Ok(Option::<()>::Some(()))
117        })
118        .await?;
119    assert!(out.is_some());
120    assert_eq!(contents.len(), 1);
121    assert_eq!(contents[0].0, key1);
122    assert_eq!(contents[0].1, key1);
123    Ok(())
124}
125
126/// A test for `KeyValueDB::iter_keys`.
127pub async fn test_iter_keys<DB: KeyValueDB>(db: DB) -> io::Result<()> {
128    let key1 = b"key1";
129    let key2 = b"key2";
130
131    let mut transaction = db.transaction();
132    transaction.put(0, key1, key1);
133    transaction.put(0, key2, key2);
134    db.write(transaction).await.map_err(|e| e.error)?;
135
136    let contents: Vec<DBKey> = Vec::new();
137    let (contents, out) = db
138        .iter_keys(0, None, contents, |contents, k: DBKeyRef| {
139            contents.push(k.clone());
140            Ok(Option::<()>::None)
141        })
142        .await?;
143    assert!(out.is_none());
144    assert_eq!(contents.len(), 2);
145    assert_eq!(contents[0], key1);
146    assert_eq!(contents[1], key2);
147
148    // test iter keys with early return
149    let contents: Vec<DBKey> = Vec::new();
150    let (contents, out) = db
151        .iter_keys(0, None, contents, |contents, k: DBKeyRef| {
152            contents.push(k.clone());
153            Ok(Option::<()>::Some(()))
154        })
155        .await?;
156    assert!(out.is_some());
157    assert_eq!(contents.len(), 1);
158    assert_eq!(contents[0], key1);
159
160    Ok(())
161}
162
163/// A test for `KeyValueDB::iter` with a prefix.
164pub async fn test_iter_with_prefix<DB: KeyValueDB>(db: DB) -> io::Result<()> {
165    let key1 = b"0";
166    let key2 = b"ab";
167    let key3 = b"abc";
168    let key4 = b"abcd";
169
170    let mut batch = db.transaction();
171    batch.put(0, key1, key1);
172    batch.put(0, key2, key2);
173    batch.put(0, key3, key3);
174    batch.put(0, key4, key4);
175    db.write(batch).await.map_err(|e| e.error)?;
176
177    // empty prefix
178    let contents: Vec<DBKeyValue> = Vec::new();
179    let (contents, out) = db
180        .iter(0, Some(b""), contents, |contents, kv: DBKeyValueRef| {
181            contents.push((kv.0.clone(), kv.1.clone()));
182            Ok(Option::<()>::None)
183        })
184        .await?;
185    assert!(out.is_none());
186    assert_eq!(contents.len(), 4);
187    assert_eq!(contents[0].0, key1);
188    assert_eq!(contents[1].0, key2);
189    assert_eq!(contents[2].0, key3);
190    assert_eq!(contents[3].0, key4);
191
192    // empty prefix with early return
193    let contents: Vec<DBKeyValue> = Vec::new();
194    let (contents, out) = db
195        .iter(0, Some(b""), contents, |contents, kv: DBKeyValueRef| {
196            contents.push((kv.0.clone(), kv.1.clone()));
197            Ok(Option::<()>::Some(()))
198        })
199        .await?;
200    assert!(out.is_some());
201    assert_eq!(contents.len(), 1);
202    assert_eq!(contents[0].0, key1);
203
204    // prefix a
205    let contents: Vec<DBKeyValue> = Vec::new();
206    let (contents, _) = db
207        .iter(0, Some(b"a"), contents, |contents, kv: DBKeyValueRef| {
208            contents.push((kv.0.clone(), kv.1.clone()));
209            Ok(Option::<()>::None)
210        })
211        .await?;
212    assert_eq!(contents.len(), 3);
213    assert_eq!(contents[0].0, key2);
214    assert_eq!(contents[1].0, key3);
215    assert_eq!(contents[2].0, key4);
216
217    // prefix abc
218    let contents: Vec<DBKeyValue> = Vec::new();
219    let (contents, _) = db
220        .iter(0, Some(b"abc"), contents, |contents, kv: DBKeyValueRef| {
221            contents.push((kv.0.clone(), kv.1.clone()));
222            Ok(Option::<()>::None)
223        })
224        .await?;
225    assert_eq!(contents.len(), 2);
226    assert_eq!(contents[0].0, key3);
227    assert_eq!(contents[1].0, key4);
228
229    // prefix abcde
230    let contents: Vec<DBKeyValue> = Vec::new();
231    let (contents, _) = db
232        .iter(
233            0,
234            Some(b"abcde"),
235            contents,
236            |contents, kv: DBKeyValueRef| {
237                contents.push((kv.0.clone(), kv.1.clone()));
238                Ok(Option::<()>::None)
239            },
240        )
241        .await?;
242    assert_eq!(contents.len(), 0);
243
244    // prefix 0
245    let contents: Vec<DBKeyValue> = Vec::new();
246    let (contents, _) = db
247        .iter(0, Some(b"0"), contents, |contents, kv: DBKeyValueRef| {
248            contents.push((kv.0.clone(), kv.1.clone()));
249            Ok(Option::<()>::None)
250        })
251        .await?;
252    assert_eq!(contents.len(), 1);
253    assert_eq!(contents[0].0, key1);
254    Ok(())
255}
256
257/// The number of columns required to run `test_io_stats`.
258pub const IO_STATS_NUM_COLUMNS: u32 = 3;
259
260/// A test for `KeyValueDB::io_stats`.
261/// Assumes that the `db` has at least 3 columns.
262pub async fn test_io_stats<DB: KeyValueDB>(db: DB) -> io::Result<()> {
263    let key1 = b"kkk";
264    let mut batch = db.transaction();
265    batch.put(0, key1, key1);
266    batch.put(1, key1, key1);
267    batch.put(2, key1, key1);
268
269    for _ in 0..10 {
270        db.get(0, key1).await?;
271    }
272
273    db.write(batch).await.map_err(|e| e.error)?;
274
275    let io_stats = db.io_stats(IoStatsKind::SincePrevious);
276    assert_eq!(io_stats.transactions, 1);
277    assert_eq!(io_stats.writes, 3);
278    assert_eq!(io_stats.bytes_written, 18);
279    assert_eq!(io_stats.reads, 10);
280    assert_eq!(io_stats.bytes_read, 30);
281
282    let new_io_stats = db.io_stats(IoStatsKind::SincePrevious);
283    // Since we taken previous statistic period,
284    // this is expected to be totally empty.
285    assert_eq!(new_io_stats.transactions, 0);
286
287    // but the overall should be there
288    let new_io_stats = db.io_stats(IoStatsKind::Overall);
289    assert_eq!(new_io_stats.bytes_written, 18);
290
291    let mut batch = db.transaction();
292    batch.delete(0, key1);
293    batch.delete(1, key1);
294    batch.delete(2, key1);
295
296    // transaction is not commited yet
297    let stats = db.io_stats(IoStatsKind::SincePrevious);
298    assert_eq!(stats.writes, 0);
299    assert_eq!(stats.deletes, 0);
300
301    db.write(batch).await.map_err(|e| e.error)?;
302    let stats = db.io_stats(IoStatsKind::SincePrevious);
303    assert_eq!(stats.writes, 0);
304    assert_eq!(stats.deletes, 3);
305    Ok(())
306}
307
308/// The number of columns required to run `test_delete_prefix`.
309pub const DELETE_PREFIX_NUM_COLUMNS: u32 = 7;
310
311/// A test for `KeyValueDB::delete_prefix`.
312pub async fn test_delete_prefix<DB: KeyValueDB + 'static>(db: DB) -> io::Result<()> {
313    let keys = [
314        &[][..],
315        &[0u8][..],
316        &[0, 1][..],
317        &[1][..],
318        &[1, 0][..],
319        &[1, 255][..],
320        &[1, 255, 255][..],
321        &[2][..],
322        &[2, 0][..],
323        &[2, 255][..],
324        &[255; 16][..],
325    ];
326    let tests: [_; DELETE_PREFIX_NUM_COLUMNS as usize] = [
327        // standard
328        (
329            &[1u8][..],
330            [
331                true, true, true, false, false, false, false, true, true, true, true,
332            ],
333        ),
334        // edge
335        (
336            &[1u8, 255, 255][..],
337            [
338                true, true, true, true, true, true, false, true, true, true, true,
339            ],
340        ),
341        // none 1
342        (
343            &[1, 2][..],
344            [
345                true, true, true, true, true, true, true, true, true, true, true,
346            ],
347        ),
348        // none 2
349        (
350            &[8][..],
351            [
352                true, true, true, true, true, true, true, true, true, true, true,
353            ],
354        ),
355        // last value
356        (
357            &[255, 255][..],
358            [
359                true, true, true, true, true, true, true, true, true, true, false,
360            ],
361        ),
362        // last value, limit prefix
363        (
364            &[255][..],
365            [
366                true, true, true, true, true, true, true, true, true, true, false,
367            ],
368        ),
369        // all
370        (
371            &[][..],
372            [
373                false, false, false, false, false, false, false, false, false, false, false,
374            ],
375        ),
376    ];
377    for (ix, test) in tests.iter().enumerate() {
378        let ix = ix as u32;
379
380        // Init Transaction
381        let mut batch = db.transaction();
382        for (i, key) in keys.iter().enumerate() {
383            batch.put(ix, key, [i as u8]);
384        }
385        db.write(batch).await.map_err(|e| e.error)?;
386
387        // Delete Transaction
388        let mut batch = db.transaction();
389        batch.delete_prefix(ix, test.0);
390        db.write(batch).await.map_err(|e| e.error)?;
391
392        // Check Test
393        let mut state = [true; 11];
394        for (c, key) in keys.iter().enumerate() {
395            state[c] = db.get(ix, key).await?.is_some();
396        }
397        assert_eq!(state, test.1, "at {}", ix);
398    }
399
400    Ok(())
401}
402
403/// A complex test.
404pub async fn test_complex<DB: KeyValueDB>(db: DB) -> io::Result<()> {
405    let key1 = b"02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
406    let key2 = b"03c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
407    let key3 = b"04c00000000b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
408    let key4 = b"04c01111110b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
409    let key5 = b"04c02222220b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc";
410
411    let mut batch = db.transaction();
412    batch.put(0, key1, b"cat");
413    batch.put(0, key2, b"dog");
414    batch.put(0, key3, b"caterpillar");
415    batch.put(0, key4, b"beef");
416    batch.put(0, key5, b"fish");
417    db.write(batch).await.map_err(|e| e.error)?;
418
419    assert_eq!(db.get(0, key1).await?.unwrap(), b"cat");
420
421    let contents: Vec<DBKeyValue> = Vec::new();
422    let (contents, _) = db
423        .iter(0, None, contents, |contents, kv: DBKeyValueRef| {
424            contents.push((kv.0.clone(), kv.1.clone()));
425            Ok(Option::<()>::None)
426        })
427        .await?;
428    assert_eq!(contents.len(), 5);
429    assert_eq!(contents[0].0, key1.to_vec());
430    assert_eq!(contents[0].1, b"cat");
431    assert_eq!(contents[1].0, key2.to_vec());
432    assert_eq!(contents[1].1, b"dog");
433
434    let contents: Vec<DBKeyValue> = Vec::new();
435    let (contents, _) = db
436        .iter(0, Some(b"04c0"), contents, |contents, kv: DBKeyValueRef| {
437            contents.push((kv.0.clone(), kv.1.clone()));
438            Ok(Option::<()>::None)
439        })
440        .await?;
441    assert_eq!(contents[0].1, b"caterpillar");
442    assert_eq!(contents[1].1, b"beef");
443    assert_eq!(contents[2].1, b"fish");
444
445    let mut batch = db.transaction();
446    batch.delete(0, key1);
447    db.write(batch).await.map_err(|e| e.error)?;
448
449    assert!(db.get(0, key1).await?.is_none());
450
451    let mut batch = db.transaction();
452    batch.put(0, key1, b"cat");
453    db.write(batch).await.map_err(|e| e.error)?;
454
455    let mut transaction = db.transaction();
456    transaction.put(0, key3, b"elephant");
457    transaction.delete(0, key1);
458    db.write(transaction).await.map_err(|e| e.error)?;
459    assert!(db.get(0, key1).await?.is_none());
460    assert_eq!(db.get(0, key3).await?.unwrap(), b"elephant");
461
462    assert_eq!(
463        db.first_with_prefix(0, key3).await?.unwrap(),
464        (key3.to_vec(), b"elephant".to_vec())
465    );
466    assert_eq!(
467        db.first_with_prefix(0, key2).await?.unwrap(),
468        (key2.to_vec(), b"dog".to_vec())
469    );
470
471    let mut transaction = db.transaction();
472    transaction.put(0, key1, b"horse");
473    transaction.delete(0, key3);
474    db.write(transaction).await.map_err(|e| e.error)?;
475    assert!(db.get(0, key3).await?.is_none());
476    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
477
478    assert!(db.get(0, key3).await?.is_none());
479    assert_eq!(db.get(0, key1).await?.unwrap(), b"horse");
480    Ok(())
481}
482
483pub async fn test_cleanup<DB: KeyValueDB>(db: DB) -> io::Result<()> {
484    db.cleanup().await
485}