From 2b271e45ac71d94dc8227fd8be73ecfa10224190 Mon Sep 17 00:00:00 2001 From: Benedikt Seidl Date: Fri, 10 Feb 2023 11:43:31 +0100 Subject: [PATCH] Add test for OpenAsReadOnly and OpenAsSecondary --- lib/tests/store.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/lib/tests/store.rs b/lib/tests/store.rs index 7ee2dfd6..7f9fbf46 100644 --- a/lib/tests/store.rs +++ b/lib/tests/store.rs @@ -3,6 +3,8 @@ use oxigraph::model::vocab::{rdf, xsd}; use oxigraph::model::*; use oxigraph::store::Store; #[cfg(not(target_family = "wasm"))] +use oxigraph::store::{ReadOnlyOptions, SecondaryOptions, StoreOpenOptions}; +#[cfg(not(target_family = "wasm"))] use rand::random; #[cfg(not(target_family = "wasm"))] use std::env::temp_dir; @@ -18,7 +20,6 @@ use std::iter::once; use std::path::{Path, PathBuf}; #[cfg(not(target_family = "wasm"))] use std::process::Command; - const DATA: &str = r#" @prefix schema: . @prefix wd: . @@ -370,6 +371,87 @@ fn test_backward_compatibility() -> Result<(), Box> { Ok(()) } +#[test] +#[cfg(not(target_family = "wasm"))] +fn test_secondary_and_readonly() -> Result<(), Box> { + let s = NamedNodeRef::new_unchecked("http://example.com/s"); + let p = NamedNodeRef::new_unchecked("http://example.com/p"); + let g = NamedNodeRef::new_unchecked("http://example.com/g"); + let first_quad = QuadRef::new(s, p, NamedNodeRef::new_unchecked("http://example.com/o"), g); + let second_quad = QuadRef::new( + 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 secondary_dir = TempDir::default(); + + // primary store with read & write access + let primary = Store::open(store_dir.0.clone())?; + primary.insert(first_quad)?; + 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 + // read_only will not update after creation, so it's important we create it after insertion of + // data. + let read_only = Store::open_with_options(StoreOpenOptions::OpenAsReadOnly(ReadOnlyOptions { + path: store_dir.0.clone(), + }))?; + let secondary = + Store::open_with_options(StoreOpenOptions::OpenAsSecondary(SecondaryOptions { + path: store_dir.0.clone(), + secondary_path: secondary_dir.0.clone(), + }))?; + + // see if we can read the data on all three stores: + for store in &[&primary, &secondary, &read_only] { + assert_eq!( + store.iter().collect::, _>>()?, + vec![first_quad.into_owned()] + ); + } + + // now we add data to the primary store + primary.insert(second_quad)?; + // we expect that adding data is not possible with secondary or read_only. + 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 + for store in &[&primary, &secondary] { + assert_eq!( + store.iter().collect::, _>>()?, + vec![first_quad.into_owned(), second_quad.into_owned()] + ); + } + // readonly will not be updated, so here we see just the first document + assert_eq!( + read_only.iter().collect::, _>>()?, + vec![first_quad.into_owned()] + ); + + primary.validate()?; + secondary.validate()?; + read_only.validate()?; + Ok(()) +} + #[cfg(not(target_family = "wasm"))] fn reset_dir(dir: &str) -> Result<(), Box> { assert!(Command::new("git")