Improves read only and secondary test coverage

Adds the missing get method
pull/409/head
Tpt 2 years ago committed by Thomas Tanon
parent 855c39146d
commit b2385509a6
  1. 10
      lib/src/storage/backend/rocksdb.rs
  2. 171
      lib/tests/store.rs

@ -884,9 +884,13 @@ impl Reader {
)); ));
} }
} }
InnerReader::Secondary(_) => { InnerReader::Secondary(inner) => {
return Err(StorageError::Other( ffi_result!(rocksdb_get_pinned_cf_with_status(
"Database is opened as secondary, can not execute Reader.get".into(), secondary_db_handler_or_error(&inner.db)?.db,
self.options,
column_family.0,
key.as_ptr() as *const c_char,
key.len()
)) ))
} }
}?; }?;

@ -292,12 +292,12 @@ fn test_bad_stt_open() -> Result<(), Box<dyn Error>> {
remove_dir_all(&dir.0)?; remove_dir_all(&dir.0)?;
assert!(store assert!(store
.bulk_loader() .bulk_loader()
.load_quads(once(Quad { .load_quads(once(Quad::new(
subject: NamedNode::new_unchecked("http://example.com/s").into(), NamedNode::new_unchecked("http://example.com/s"),
predicate: NamedNode::new_unchecked("http://example.com/p"), NamedNode::new_unchecked("http://example.com/p"),
object: NamedNode::new_unchecked("http://example.com/o").into(), NamedNode::new_unchecked("http://example.com/o"),
graph_name: GraphName::DefaultGraph GraphName::DefaultGraph
})) )))
.is_err()); .is_err());
Ok(()) Ok(())
} }
@ -305,12 +305,12 @@ fn test_bad_stt_open() -> Result<(), Box<dyn Error>> {
#[test] #[test]
#[cfg(not(target_family = "wasm"))] #[cfg(not(target_family = "wasm"))]
fn test_backup() -> Result<(), Box<dyn Error>> { fn test_backup() -> Result<(), Box<dyn Error>> {
let quad = QuadRef { let quad = QuadRef::new(
subject: NamedNodeRef::new_unchecked("http://example.com/s").into(), NamedNodeRef::new_unchecked("http://example.com/s"),
predicate: NamedNodeRef::new_unchecked("http://example.com/p"), NamedNodeRef::new_unchecked("http://example.com/p"),
object: NamedNodeRef::new_unchecked("http://example.com/o").into(), NamedNodeRef::new_unchecked("http://example.com/o"),
graph_name: GraphNameRef::DefaultGraph, GraphNameRef::DefaultGraph,
}; );
let store_dir = TempDir::default(); let store_dir = TempDir::default();
let backup_dir = TempDir::default(); let backup_dir = TempDir::default();
@ -371,76 +371,119 @@ fn test_backward_compatibility() -> Result<(), Box<dyn Error>> {
#[test] #[test]
#[cfg(not(target_family = "wasm"))] #[cfg(not(target_family = "wasm"))]
fn test_secondary_and_readonly() -> Result<(), Box<dyn Error>> { fn test_secondary() -> Result<(), Box<dyn Error>> {
let s = NamedNodeRef::new_unchecked("http://example.com/s"); let quad = QuadRef::new(
let p = NamedNodeRef::new_unchecked("http://example.com/p"); NamedNodeRef::new_unchecked("http://example.com/s"),
let g = NamedNodeRef::new_unchecked("http://example.com/g"); NamedNodeRef::new_unchecked("http://example.com/p"),
let first_quad = QuadRef::new(s, p, NamedNodeRef::new_unchecked("http://example.com/o"), g); NamedNodeRef::new_unchecked("http://example.com/o"),
let second_quad = QuadRef::new( GraphNameRef::DefaultGraph,
s,
p,
NamedNodeRef::new_unchecked("http://example.com/o2"),
g,
);
let second_quad_secondary = QuadRef::new(
s,
p,
NamedNodeRef::new_unchecked("http://example.com/o2secondary"),
g,
);
let second_quad_read_only = QuadRef::new(
s,
p,
NamedNodeRef::new_unchecked("http://example.com/o2read_only"),
g,
); );
let store_dir = TempDir::default(); let primary_dir = TempDir::default();
let secondary_dir = TempDir::default(); let secondary_dir = TempDir::default();
// primary store with read & write access // We open the store
let primary = Store::open(store_dir.0.clone())?; let primary = Store::open(&primary_dir)?;
primary.insert(first_quad)?; let secondary = Store::open_secondary(&primary_dir, &secondary_dir)?;
primary.flush()?;
// TODO: optimize should not be necessary here?
// if removed opening the readonly/secondary database throws an corruption error.
primary.optimize()?;
// create additional stores // We insert a quad
// read_only will not update after creation, so it's important we create it after insertion of primary.insert(quad)?;
// data. primary.flush()?;
let read_only = Store::open_read_only(&store_dir)?;
let secondary = Store::open_secondary(&store_dir, &secondary_dir)?;
// see if we can read the data on all three stores: // It is readable from both stores
for store in &[&primary, &secondary, &read_only] { for store in &[&primary, &secondary] {
assert!(store.contains(quad)?);
assert_eq!( assert_eq!(
store.iter().collect::<Result<Vec<_>, _>>()?, store.iter().collect::<Result<Vec<_>, _>>()?,
vec![first_quad.into_owned()] vec![quad.into_owned()]
); );
} }
// now we add data to the primary store // We validate the states
primary.insert(second_quad)?; primary.validate()?;
// we expect that adding data is not possible with secondary or read_only. secondary.validate()?;
assert!(secondary.insert(second_quad_secondary).is_err());
assert!(read_only.insert(second_quad_read_only).is_err());
// see if we can read the new data from primary and secondary // We close the primary store and remove its content
for store in &[&primary, &secondary] { drop(primary);
assert_eq!( remove_dir_all(&primary_dir)?;
store.iter().collect::<Result<Vec<_>, _>>()?,
vec![first_quad.into_owned(), second_quad.into_owned()] // We secondary store is still readable
); assert!(secondary.contains(quad)?);
secondary.validate()?;
Ok(())
}
#[test]
#[cfg(not(target_family = "wasm"))]
fn test_open_secondary_bad_dir() -> Result<(), Box<dyn Error>> {
let primary_dir = TempDir::default();
let secondary_dir = TempDir::default();
create_dir(&primary_dir.0)?;
{
File::create(primary_dir.0.join("CURRENT"))?.write_all(b"foo")?;
} }
// readonly will not be updated, so here we see just the first document assert!(Store::open_secondary(&primary_dir, &secondary_dir).is_err());
Ok(())
}
#[test]
#[cfg(not(target_family = "wasm"))]
fn test_read_only() -> Result<(), Box<dyn Error>> {
let s = NamedNodeRef::new_unchecked("http://example.com/s");
let p = NamedNodeRef::new_unchecked("http://example.com/p");
let first_quad = QuadRef::new(
s,
p,
NamedNodeRef::new_unchecked("http://example.com/o"),
GraphNameRef::DefaultGraph,
);
let second_quad = QuadRef::new(
s,
p,
NamedNodeRef::new_unchecked("http://example.com/o2"),
GraphNameRef::DefaultGraph,
);
let store_dir = TempDir::default();
// We write to the store and close it
{
let read_write = Store::open(&store_dir)?;
read_write.insert(first_quad)?;
read_write.flush()?;
}
// We open as read-only
let read_only = Store::open_read_only(&store_dir)?;
assert!(read_only.contains(first_quad)?);
assert_eq!( assert_eq!(
read_only.iter().collect::<Result<Vec<_>, _>>()?, read_only.iter().collect::<Result<Vec<_>, _>>()?,
vec![first_quad.into_owned()] vec![first_quad.into_owned()]
); );
read_only.validate()?;
primary.validate()?; // We open as read-write again
secondary.validate()?; let read_write = Store::open(&store_dir)?;
read_write.insert(second_quad)?;
read_write.flush()?;
read_write.optimize()?; // Makes sure it's well flushed
// The new quad is in the read-write instance but not the read-only instance
assert!(read_write.contains(second_quad)?);
assert!(!read_only.contains(second_quad)?);
read_only.validate()?; read_only.validate()?;
Ok(())
}
#[test]
#[cfg(not(target_family = "wasm"))]
fn test_open_read_only_bad_dir() -> Result<(), Box<dyn Error>> {
let dir = TempDir::default();
create_dir(&dir.0)?;
{
File::create(dir.0.join("CURRENT"))?.write_all(b"foo")?;
}
assert!(Store::open_read_only(&dir).is_err());
Ok(()) Ok(())
} }

Loading…
Cancel
Save