Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use lockstore_rs::{LockstoreDatastore, LockstoreError, LockstoreKeystore, SecurityLevel};
use std::sync::Arc;
use tempfile::tempdir;
fn make_in_memory_ds(collection: &str) -> LockstoreDatastore {
let keystore = Arc::new(LockstoreKeystore::new_in_memory().expect("Failed to create keystore"));
keystore
.create_dek(collection, SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
LockstoreDatastore::new_in_memory(collection.to_string(), keystore, SecurityLevel::LocalKey)
.expect("Failed to create datastore")
}
#[test]
fn test_new_in_memory() {
let keystore = Arc::new(LockstoreKeystore::new_in_memory().expect("Failed to create keystore"));
keystore
.create_dek("test", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let datastore =
LockstoreDatastore::new_in_memory("test".to_string(), keystore, SecurityLevel::LocalKey)
.expect("Failed to create datastore");
datastore.close();
}
#[test]
fn test_new_in_memory_without_dek() {
let keystore = Arc::new(LockstoreKeystore::new_in_memory().expect("Failed to create keystore"));
let result =
LockstoreDatastore::new_in_memory("missing".to_string(), keystore, SecurityLevel::LocalKey);
assert!(matches!(result, Err(LockstoreError::NotFound(_))));
}
#[test]
fn test_put_get_roundtrip() {
let datastore = make_in_memory_ds("test");
datastore.put("key1", b"value1").expect("Failed to put");
let value = datastore.get("key1").expect("Failed to get");
assert_eq!(value, b"value1");
datastore.close();
}
#[test]
fn test_update_existing_key() {
let datastore = make_in_memory_ds("test");
datastore.put("key1", b"value1").expect("Failed to put");
assert_eq!(datastore.get("key1").expect("Failed to get"), b"value1");
datastore.put("key1", b"value2").expect("Failed to update");
assert_eq!(
datastore.get("key1").expect("Failed to get updated value"),
b"value2"
);
let keys = datastore.keys().expect("Failed to list keys");
assert_eq!(keys.len(), 1);
datastore.close();
}
#[test]
fn test_delete_existing() {
let datastore = make_in_memory_ds("test");
datastore.put("key1", b"value1").expect("Failed to put");
datastore.delete("key1").expect("Failed to delete");
let result = datastore.get("key1");
assert!(matches!(result, Err(LockstoreError::NotFound(_))));
datastore.close();
}
#[test]
fn test_delete_nonexistent() {
let datastore = make_in_memory_ds("test");
let result = datastore.delete("nonexistent");
assert!(matches!(result, Err(LockstoreError::NotFound(_))));
datastore.close();
}
#[test]
fn test_get_nonexistent() {
let datastore = make_in_memory_ds("test");
let result = datastore.get("nonexistent");
assert!(matches!(result, Err(LockstoreError::NotFound(_))));
datastore.close();
}
#[test]
fn test_keys_empty() {
let datastore = make_in_memory_ds("test");
let keys = datastore.keys().expect("Failed to list keys");
assert!(keys.is_empty());
datastore.close();
}
#[test]
fn test_keys_single() {
let datastore = make_in_memory_ds("test");
datastore.put("only", b"data").expect("Failed to put");
let keys = datastore.keys().expect("Failed to list keys");
assert_eq!(keys, vec!["only"]);
datastore.close();
}
#[test]
fn test_keys_multiple() {
let datastore = make_in_memory_ds("test");
datastore.put("key1", b"v1").expect("Failed to put");
datastore.put("key2", b"v2").expect("Failed to put");
datastore.put("key3", b"v3").expect("Failed to put");
let keys = datastore.keys().expect("Failed to list keys");
assert_eq!(keys.len(), 3);
assert!(keys.contains(&"key1".to_string()));
assert!(keys.contains(&"key2".to_string()));
assert!(keys.contains(&"key3".to_string()));
datastore.close();
}
#[test]
fn test_keys_after_delete() {
let datastore = make_in_memory_ds("test");
datastore.put("a", b"1").expect("Failed to put");
datastore.put("b", b"2").expect("Failed to put");
datastore.delete("a").expect("Failed to delete");
let keys = datastore.keys().expect("Failed to list keys");
assert_eq!(keys, vec!["b"]);
datastore.close();
}
#[test]
fn test_binary_data() {
let datastore = make_in_memory_ds("test");
let binary: Vec<u8> = (0..=255).collect();
datastore
.put("binary", &binary)
.expect("Failed to put binary");
let value = datastore.get("binary").expect("Failed to get binary");
assert_eq!(value, binary);
datastore.close();
}
#[test]
fn test_empty_data() {
let datastore = make_in_memory_ds("test");
datastore.put("empty", b"").expect("Failed to put empty");
let value = datastore.get("empty").expect("Failed to get empty");
assert!(value.is_empty());
datastore.close();
}
#[test]
fn test_large_data() {
let datastore = make_in_memory_ds("test");
let large = vec![0xABu8; 1_000_000];
datastore.put("large", &large).expect("Failed to put large");
let value = datastore.get("large").expect("Failed to get large");
assert_eq!(value, large);
datastore.close();
}
#[test]
fn test_multiple_collections_independent() {
let ks1 = Arc::new(LockstoreKeystore::new_in_memory().expect("Failed to create keystore"));
ks1.create_dek("col1", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let ds1 = LockstoreDatastore::new_in_memory("col1".to_string(), ks1, SecurityLevel::LocalKey)
.expect("Failed to create ds1");
let ks2 = Arc::new(LockstoreKeystore::new_in_memory().expect("Failed to create keystore"));
ks2.create_dek("col2", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let ds2 = LockstoreDatastore::new_in_memory("col2".to_string(), ks2, SecurityLevel::LocalKey)
.expect("Failed to create ds2");
ds1.put("key", b"from_col1").expect("Failed to put");
ds2.put("key", b"from_col2").expect("Failed to put");
assert_eq!(ds1.get("key").expect("Failed to get"), b"from_col1");
assert_eq!(ds2.get("key").expect("Failed to get"), b"from_col2");
ds1.close();
ds2.close();
}
#[test]
fn test_close() {
let datastore = make_in_memory_ds("test");
datastore.close();
}
#[test]
fn test_new_on_disk() {
let dir = tempdir().expect("Failed to create temp dir");
let ks_path = dir.path().join("keystore.sqlite");
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to create keystore"));
keystore
.create_dek("col1", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let datastore = LockstoreDatastore::new(
dir.path().to_path_buf(),
"col1".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to create on-disk datastore");
datastore.put("key1", b"value1").expect("Failed to put");
let value = datastore.get("key1").expect("Failed to get");
assert_eq!(value, b"value1");
datastore.close();
}
#[test]
fn test_new_on_disk_without_dek() {
let dir = tempdir().expect("Failed to create temp dir");
let ks_path = dir.path().join("keystore.sqlite");
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to create keystore"));
let result = LockstoreDatastore::new(
dir.path().to_path_buf(),
"missing".to_string(),
keystore,
SecurityLevel::LocalKey,
);
assert!(matches!(result, Err(LockstoreError::NotFound(_))));
}
#[test]
fn test_on_disk_persistence() {
let dir = tempdir().expect("Failed to create temp dir");
let data_path = dir.path().to_path_buf();
let ks_path = dir.path().join("keystore.sqlite");
{
let keystore =
Arc::new(LockstoreKeystore::new(ks_path.clone()).expect("Failed to create keystore"));
keystore
.create_dek("persist", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let datastore = LockstoreDatastore::new(
data_path.clone(),
"persist".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to create on-disk datastore");
datastore.put("key1", b"value1").expect("Failed to put");
datastore.close();
}
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to reopen keystore"));
let datastore = LockstoreDatastore::new(
data_path,
"persist".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to reopen datastore");
let value = datastore.get("key1").expect("Data should persist");
assert_eq!(value, b"value1");
datastore.close();
}
#[test]
fn test_on_disk_keys_persists() {
let dir = tempdir().expect("Failed to create temp dir");
let data_path = dir.path().to_path_buf();
let ks_path = dir.path().join("keystore.sqlite");
{
let keystore =
Arc::new(LockstoreKeystore::new(ks_path.clone()).expect("Failed to create keystore"));
keystore
.create_dek("listcol", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let datastore = LockstoreDatastore::new(
data_path.clone(),
"listcol".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to create on-disk datastore");
datastore.put("a", b"1").expect("Failed to put");
datastore.put("b", b"2").expect("Failed to put");
datastore.put("c", b"3").expect("Failed to put");
datastore.close();
}
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to reopen keystore"));
let datastore = LockstoreDatastore::new(
data_path,
"listcol".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to reopen datastore");
let keys = datastore.keys().expect("Failed to list keys");
assert_eq!(keys.len(), 3);
assert!(keys.contains(&"a".to_string()));
assert!(keys.contains(&"b".to_string()));
assert!(keys.contains(&"c".to_string()));
datastore.close();
}
#[test]
fn test_in_memory_datastore_with_on_disk_keystore() {
let dir = tempdir().expect("Failed to create temp dir");
let ks_path = dir.path().join("keystore.sqlite");
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to create keystore"));
keystore
.create_dek("memcol", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let datastore =
LockstoreDatastore::new_in_memory("memcol".to_string(), keystore, SecurityLevel::LocalKey)
.expect("Failed to create in-memory datastore with on-disk keystore");
datastore.put("key1", b"value1").expect("Failed to put");
let value = datastore.get("key1").expect("Failed to get");
assert_eq!(value, b"value1");
datastore.close();
}
#[test]
fn test_on_disk_datastore_with_in_memory_keystore() {
let dir = tempdir().expect("Failed to create temp dir");
let keystore = Arc::new(LockstoreKeystore::new_in_memory().expect("Failed to create keystore"));
keystore
.create_dek("ondisk", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
let datastore = LockstoreDatastore::new(
dir.path().to_path_buf(),
"ondisk".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to create on-disk datastore with in-memory keystore");
datastore.put("key1", b"value1").expect("Failed to put");
let value = datastore.get("key1").expect("Failed to get");
assert_eq!(value, b"value1");
datastore.close();
}
#[test]
fn test_multiple_collections_shared_on_disk_keystore() {
let dir = tempdir().expect("Failed to create temp dir");
let ks_path = dir.path().join("keystore.sqlite");
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to create keystore"));
keystore
.create_dek("col_a", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK for col_a");
keystore
.create_dek("col_b", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK for col_b");
let ds_a = LockstoreDatastore::new(
dir.path().to_path_buf(),
"col_a".to_string(),
keystore.clone(),
SecurityLevel::LocalKey,
)
.expect("Failed to create datastore A");
let ds_b = LockstoreDatastore::new(
dir.path().to_path_buf(),
"col_b".to_string(),
keystore,
SecurityLevel::LocalKey,
)
.expect("Failed to create datastore B");
ds_a.put("key", b"from_a").expect("Failed to put to A");
ds_b.put("key", b"from_b").expect("Failed to put to B");
assert_eq!(ds_a.get("key").expect("Failed to get from A"), b"from_a");
assert_eq!(ds_b.get("key").expect("Failed to get from B"), b"from_b");
let keys_a = ds_a.keys().expect("Failed to list A");
let keys_b = ds_b.keys().expect("Failed to list B");
assert_eq!(keys_a, vec!["key"]);
assert_eq!(keys_b, vec!["key"]);
ds_a.close();
ds_b.close();
}
#[test]
fn test_cross_security_level_access() {
let dir = tempdir().expect("Failed to create temp dir");
let ks_path = dir.path().join("keystore.sqlite");
let data_path = dir.path().to_path_buf();
let keystore = Arc::new(LockstoreKeystore::new(ks_path).expect("Failed to create keystore"));
keystore
.create_dek("col", SecurityLevel::LocalKey, false)
.expect("Failed to create DEK");
keystore
.add_security_level("col", SecurityLevel::LocalKey, SecurityLevel::TestLevel)
.expect("Failed to add TestLevel");
{
let ds = LockstoreDatastore::new(
data_path.clone(),
"col".to_string(),
keystore.clone(),
SecurityLevel::LocalKey,
)
.expect("Failed to create datastore with LocalKey");
ds.put("entry", b"secret_data").expect("Failed to put");
ds.close();
}
let ds = LockstoreDatastore::new(
data_path,
"col".to_string(),
keystore,
SecurityLevel::TestLevel,
)
.expect("Failed to create datastore with TestLevel");
let value = ds
.get("entry")
.expect("Data should be accessible via TestLevel");
assert_eq!(value, b"secret_data");
ds.close();
}