diff --git a/raphtory/src/algorithms/centrality/betweenness.rs b/raphtory/src/algorithms/centrality/betweenness.rs index 453461983e..cb7c319d80 100644 --- a/raphtory/src/algorithms/centrality/betweenness.rs +++ b/raphtory/src/algorithms/centrality/betweenness.rs @@ -115,8 +115,7 @@ pub fn betweenness_centrality<'graph, G: GraphViewOps<'graph>>( #[cfg(test)] mod betweenness_centrality_test { use super::*; - use crate::{db::api::view::StaticGraphViewOps, prelude::*}; - use tempfile::TempDir; + use crate::{prelude::*, test_storage}; #[test] fn test_betweenness_centrality() { @@ -139,11 +138,7 @@ mod betweenness_centrality_test { graph.add_edge(0, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let mut expected: HashMap = HashMap::new(); expected.insert("1".to_string(), 0.0); expected.insert("2".to_string(), 1.0); @@ -164,9 +159,6 @@ mod betweenness_centrality_test { expected.insert("6".to_string(), 0.0); let res = betweenness_centrality(graph, None, Some(true)); assert_eq!(res.get_all_with_names(), expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/centrality/degree_centrality.rs b/raphtory/src/algorithms/centrality/degree_centrality.rs index 8a90238f47..c9892d8579 100644 --- a/raphtory/src/algorithms/centrality/degree_centrality.rs +++ b/raphtory/src/algorithms/centrality/degree_centrality.rs @@ -60,14 +60,11 @@ pub fn degree_centrality( mod degree_centrality_test { use crate::{ algorithms::centrality::degree_centrality::degree_centrality, - db::{ - api::{mutation::AdditionOps, view::StaticGraphViewOps}, - graph::graph::Graph, - }, + db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn test_degree_centrality() { @@ -76,11 +73,7 @@ mod degree_centrality_test { for (src, dst) in &vs { graph.add_edge(0, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let mut hash_map_result: HashMap = HashMap::new(); hash_map_result.insert("1".to_string(), 1.0); hash_map_result.insert("2".to_string(), 1.0); @@ -90,9 +83,6 @@ mod degree_centrality_test { let binding = degree_centrality(graph, None); let res = binding.get_all_with_names(); assert_eq!(res, hash_map_result); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/centrality/hits.rs b/raphtory/src/algorithms/centrality/hits.rs index f1498dfad3..15842786f9 100644 --- a/raphtory/src/algorithms/centrality/hits.rs +++ b/raphtory/src/algorithms/centrality/hits.rs @@ -181,8 +181,8 @@ mod hits_tests { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; use super::*; @@ -214,11 +214,7 @@ mod hits_tests { (7, 3), (8, 1), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = hits(graph, 20, None).get_all_with_names(); assert_eq!( @@ -234,9 +230,6 @@ mod hits_tests { ("8".to_string(), (0.030866561, 0.05943252)) ]) ); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/centrality/pagerank.rs b/raphtory/src/algorithms/centrality/pagerank.rs index 97440bb740..8fc3878345 100644 --- a/raphtory/src/algorithms/centrality/pagerank.rs +++ b/raphtory/src/algorithms/centrality/pagerank.rs @@ -184,18 +184,15 @@ pub fn unweighted_page_rank( #[cfg(test)] mod page_rank_tests { - use std::borrow::Borrow; - - use itertools::Itertools; - use pretty_assertions::assert_eq; - use tempfile::TempDir; - + use super::*; use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - - use super::*; + use itertools::Itertools; + use pretty_assertions::assert_eq; + use std::borrow::Borrow; fn load_graph() -> Graph { let graph = Graph::new(); @@ -212,22 +209,14 @@ mod page_rank_tests { fn test_page_rank() { let graph = load_graph(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = unweighted_page_rank(graph, Some(1000), Some(1), None, true, None); assert_eq_f64(results.get("1"), Some(&0.38694), 5); assert_eq_f64(results.get("2"), Some(&0.20195), 5); assert_eq_f64(results.get("4"), Some(&0.20195), 5); assert_eq_f64(results.get("3"), Some(&0.20916), 5); - } - - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -264,11 +253,7 @@ mod page_rank_tests { graph.add_edge(t, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = unweighted_page_rank(graph, Some(1000), Some(4), None, true, None); assert_eq_f64(results.get("10"), Some(&0.072082), 5); @@ -282,10 +267,7 @@ mod page_rank_tests { assert_eq_f64(results.get("7"), Some(&0.01638), 5); assert_eq_f64(results.get("9"), Some(&0.06186), 5); assert_eq_f64(results.get("5"), Some(&0.19658), 5); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -298,19 +280,12 @@ mod page_rank_tests { graph.add_edge(t as i64, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = unweighted_page_rank(graph, Some(1000), Some(4), None, false, None); assert_eq_f64(results.get("1"), Some(&0.5), 3); assert_eq_f64(results.get("2"), Some(&0.5), 3); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -323,20 +298,13 @@ mod page_rank_tests { graph.add_edge(t as i64, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = unweighted_page_rank(graph, Some(10), Some(4), None, false, None); assert_eq_f64(results.get("1"), Some(&0.303), 3); assert_eq_f64(results.get("2"), Some(&0.393), 3); assert_eq_f64(results.get("3"), Some(&0.303), 3); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -367,12 +335,7 @@ mod page_rank_tests { for (src, dst, t) in edges { graph.add_edge(t, src, dst, NO_PROPS, None).unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = unweighted_page_rank(graph, Some(1000), Some(4), None, true, None); assert_eq_f64(results.get("1"), Some(&0.055), 3); @@ -386,10 +349,7 @@ mod page_rank_tests { assert_eq_f64(results.get("9"), Some(&0.110), 3); assert_eq_f64(results.get("10"), Some(&0.117), 3); assert_eq_f64(results.get("11"), Some(&0.122), 3); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } fn assert_eq_f64 + PartialEq + std::fmt::Debug>( diff --git a/raphtory/src/algorithms/community_detection/label_propagation.rs b/raphtory/src/algorithms/community_detection/label_propagation.rs index e69ee0cc7e..298e15a959 100644 --- a/raphtory/src/algorithms/community_detection/label_propagation.rs +++ b/raphtory/src/algorithms/community_detection/label_propagation.rs @@ -77,7 +77,7 @@ fn find_max_label(label_count: &BTreeMap) -> Option { #[cfg(test)] mod lpa_tests { use super::*; - use tempfile::TempDir; + use crate::test_storage; #[test] fn lpa_test() { @@ -98,11 +98,8 @@ mod lpa_tests { for (ts, src, dst) in edges { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let seed = Some([5; 32]); let result = label_propagation(graph, seed).unwrap(); let expected = vec![ @@ -123,9 +120,6 @@ mod lpa_tests { for hashset in expected { assert!(result.contains(&hashset)); } - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/community_detection/louvain.rs b/raphtory/src/algorithms/community_detection/louvain.rs index 121155d9ba..7383f114d9 100644 --- a/raphtory/src/algorithms/community_detection/louvain.rs +++ b/raphtory/src/algorithms/community_detection/louvain.rs @@ -66,11 +66,10 @@ pub fn louvain<'graph, M: ModularityFunction, G: GraphViewOps<'graph>>( mod test { use crate::{ algorithms::community_detection::{louvain::louvain, modularity::ModularityUnDir}, - db::api::view::StaticGraphViewOps, prelude::*, + test_storage, }; use proptest::prelude::*; - use tempfile::TempDir; #[test] fn test_louvain() { @@ -99,17 +98,11 @@ mod test { .add_edge(1, dst, src, [("weight", weight)], None) .unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let result = louvain::(graph, 1.0, Some("weight"), None); assert!(graph.nodes().iter().all(|n| result.get(n).is_some())); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } fn test_all_nodes_assigned_inner_unweighted(edges: Vec<(u64, u64)>) { @@ -119,17 +112,10 @@ mod test { graph.add_edge(1, dst, src, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let result = louvain::(graph, 1.0, None, None); assert!(graph.nodes().iter().all(|n| result.get(n).is_some())); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } proptest! { @@ -168,16 +154,9 @@ mod test { }) .unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let result = louvain::(graph, 1.0, None, None); println!("{result:?}") - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/community_detection/modularity.rs b/raphtory/src/algorithms/community_detection/modularity.rs index b1a64a1f97..0635874463 100644 --- a/raphtory/src/algorithms/community_detection/modularity.rs +++ b/raphtory/src/algorithms/community_detection/modularity.rs @@ -424,10 +424,9 @@ mod test { ComID, ModularityFunction, ModularityUnDir, Partition, }, core::entities::VID, - db::api::view::StaticGraphViewOps, prelude::*, + test_storage, }; - use tempfile::TempDir; #[test] fn test_delta() { @@ -435,11 +434,7 @@ mod test { graph.add_edge(0, 1, 2, NO_PROPS, None).unwrap(); graph.add_edge(0, 2, 1, NO_PROPS, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let mut m = ModularityUnDir::new( graph, None, @@ -453,10 +448,7 @@ mod test { println!("delta: {delta}"); m.move_node(&VID(0), ComID(1)); assert_eq!(m.value(), old_value + delta) - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -469,11 +461,7 @@ mod test { graph.add_edge(0, 0, 3, NO_PROPS, None).unwrap(); graph.add_edge(0, 3, 0, NO_PROPS, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let partition = Partition::from_iter([0usize, 0, 1, 1]); let mut m = ModularityUnDir::new(graph, None, 1.0, partition, 1e-8); let value_before = m.value(); @@ -486,9 +474,6 @@ mod test { let value_merged = m.value(); assert_eq!(value_merged, 0.0); assert!((value_merged - (value_after + delta)).abs() < 1e-8); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/components/connected_components.rs b/raphtory/src/algorithms/components/connected_components.rs index 91cc182ddb..c4e469c8aa 100644 --- a/raphtory/src/algorithms/components/connected_components.rs +++ b/raphtory/src/algorithms/components/connected_components.rs @@ -93,11 +93,10 @@ where #[cfg(test)] mod cc_test { use super::*; - use crate::{db::api::mutation::AdditionOps, prelude::*}; + use crate::{db::api::mutation::AdditionOps, prelude::*, test_storage}; use itertools::*; use quickcheck_macros::quickcheck; use std::{cmp::Reverse, collections::HashMap, iter::once}; - use tempfile::TempDir; #[test] fn run_loop_simple_connected_components() { @@ -117,11 +116,7 @@ mod cc_test { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = weakly_connected_components(graph, usize::MAX, None).get_all_with_names(); assert_eq!( results, @@ -138,10 +133,7 @@ mod cc_test { .into_iter() .collect::>() ); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -178,11 +170,7 @@ mod cc_test { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = weakly_connected_components(graph, usize::MAX, None).get_all_with_names(); assert_eq!( @@ -203,10 +191,7 @@ mod cc_test { .into_iter() .collect::>() ); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } // connected community_detection on a graph with 1 node and a self loop @@ -220,11 +205,7 @@ mod cc_test { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = weakly_connected_components(graph, usize::MAX, None).get_all_with_names(); assert_eq!( @@ -233,10 +214,7 @@ mod cc_test { .into_iter() .collect::>() ); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -247,11 +225,7 @@ mod cc_test { graph.add_edge(9, 3, 4, NO_PROPS, None).expect("add edge"); graph.add_edge(9, 4, 3, NO_PROPS, None).expect("add edge"); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = weakly_connected_components(graph, usize::MAX, None).get_all_with_names(); let expected = vec![ ("1".to_string(), 1), @@ -273,10 +247,7 @@ mod cc_test { .collect::>(); assert_eq!(results, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[quickcheck] @@ -321,11 +292,7 @@ mod cc_test { graph.add_edge(0, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G, smallest: &u64, edges: &[(u64, u64)]) { + test_storage!(&graph, |graph| { // now we do connected community_detection over window 0..1 let res = weakly_connected_components(graph, usize::MAX, None).group_by(); @@ -339,10 +306,7 @@ mod cc_test { .unwrap(); assert_eq!(actual, (*smallest, edges.len())); - } - test(&graph, smallest, &edges); - #[cfg(feature = "storage")] - test(&disk_graph, smallest, &edges); + }); } } } diff --git a/raphtory/src/algorithms/components/in_components.rs b/raphtory/src/algorithms/components/in_components.rs index b4fbc4f0a3..878f561706 100644 --- a/raphtory/src/algorithms/components/in_components.rs +++ b/raphtory/src/algorithms/components/in_components.rs @@ -85,9 +85,8 @@ where #[cfg(test)] mod components_test { use super::*; - use crate::{db::api::mutation::AdditionOps, prelude::*}; + use crate::{db::api::mutation::AdditionOps, prelude::*, test_storage}; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn in_components_test() { @@ -106,11 +105,8 @@ mod components_test { for (ts, src, dst) in edges { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = in_components(graph, None).get_all_with_names(); let mut correct = HashMap::new(); correct.insert("1".to_string(), vec![]); @@ -129,9 +125,6 @@ mod components_test { }) .collect(); assert_eq!(map, correct); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/components/out_components.rs b/raphtory/src/algorithms/components/out_components.rs index 2cfbe72d3a..b0d881c89f 100644 --- a/raphtory/src/algorithms/components/out_components.rs +++ b/raphtory/src/algorithms/components/out_components.rs @@ -88,9 +88,8 @@ where #[cfg(test)] mod components_test { use super::*; - use crate::{db::api::mutation::AdditionOps, prelude::*}; + use crate::{db::api::mutation::AdditionOps, prelude::*, test_storage}; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn out_components_test() { @@ -110,11 +109,7 @@ mod components_test { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = out_components(graph, None).get_all_with_names(); let mut correct = HashMap::new(); correct.insert("1".to_string(), vec![2, 3, 4, 5, 6, 7, 8]); @@ -133,9 +128,6 @@ mod components_test { }) .collect(); assert_eq!(map, correct); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/components/scc.rs b/raphtory/src/algorithms/components/scc.rs index 29eadfa6ff..6d90130b64 100644 --- a/raphtory/src/algorithms/components/scc.rs +++ b/raphtory/src/algorithms/components/scc.rs @@ -174,11 +174,10 @@ where mod strongly_connected_components_tests { use crate::{ algorithms::components::scc::strongly_connected_components, - db::api::view::StaticGraphViewOps, prelude::{AdditionOps, Graph, NO_PROPS}, + test_storage, }; use std::collections::HashSet; - use tempfile::TempDir; #[test] fn scc_test() { @@ -199,11 +198,8 @@ mod strongly_connected_components_tests { for (ts, src, dst) in edges { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let scc_nodes: HashSet<_> = strongly_connected_components(graph, None) .group_by() .into_values() @@ -223,10 +219,7 @@ mod strongly_connected_components_tests { .map(|v| v.into_iter().map(|s| s.to_owned()).collect()) .collect(); assert_eq!(scc_nodes, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -250,11 +243,7 @@ mod strongly_connected_components_tests { graph.add_edge(0, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let scc_nodes: HashSet<_> = strongly_connected_components(graph, None) .group_by() .into_values() @@ -270,10 +259,7 @@ mod strongly_connected_components_tests { .map(|v| v.into_iter().map(|s| s.to_owned()).collect()) .collect(); assert_eq!(scc_nodes, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -284,11 +270,7 @@ mod strongly_connected_components_tests { graph.add_edge(0, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let scc_nodes: HashSet<_> = strongly_connected_components(graph, None) .group_by() .into_values() @@ -303,10 +285,7 @@ mod strongly_connected_components_tests { .map(|v| v.into_iter().map(|s| s.to_owned()).collect()) .collect(); assert_eq!(scc_nodes, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -326,11 +305,7 @@ mod strongly_connected_components_tests { graph.add_edge(0, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let scc_nodes: HashSet<_> = strongly_connected_components(graph, None) .group_by() .into_values() @@ -353,9 +328,6 @@ mod strongly_connected_components_tests { .map(|v| v.into_iter().map(|s| s.to_owned()).collect()) .collect(); assert_eq!(scc_nodes, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/cores/k_core.rs b/raphtory/src/algorithms/cores/k_core.rs index fdc8dc3733..e19e30d96c 100644 --- a/raphtory/src/algorithms/cores/k_core.rs +++ b/raphtory/src/algorithms/cores/k_core.rs @@ -102,12 +102,8 @@ where #[cfg(test)] mod k_core_test { + use crate::{algorithms::cores::k_core::k_core_set, prelude::*, test_storage}; use std::collections::HashSet; - use tempfile::TempDir; - - use crate::{ - algorithms::cores::k_core::k_core_set, db::api::view::StaticGraphViewOps, prelude::*, - }; #[test] fn k_core_2() { @@ -143,11 +139,7 @@ mod k_core_test { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let result = k_core_set(graph, 2, usize::MAX, None); let subgraph = graph.subgraph(result.clone()); let actual = vec!["1", "3", "4", "5", "6", "8", "9", "10", "11"] @@ -156,9 +148,6 @@ mod k_core_test { .collect::>(); assert_eq!(actual, subgraph.nodes().name().collect::>()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/dynamics/temporal/epidemics.rs b/raphtory/src/algorithms/dynamics/temporal/epidemics.rs index 8e462bb783..3611419c47 100644 --- a/raphtory/src/algorithms/dynamics/temporal/epidemics.rs +++ b/raphtory/src/algorithms/dynamics/temporal/epidemics.rs @@ -252,6 +252,7 @@ mod test { use rand_distr::{Distribution, Exp}; use rayon::prelude::*; use stats::{mean, stddev}; + #[cfg(feature = "storage")] use tempfile::TempDir; fn correct_res(x: f64) -> f64 { diff --git a/raphtory/src/algorithms/metrics/balance.rs b/raphtory/src/algorithms/metrics/balance.rs index ae115498d4..1afd0a395b 100644 --- a/raphtory/src/algorithms/metrics/balance.rs +++ b/raphtory/src/algorithms/metrics/balance.rs @@ -132,14 +132,12 @@ mod sum_weight_test { use crate::{ algorithms::metrics::balance::balance, core::{Direction, Prop}, - db::{ - api::{mutation::AdditionOps, view::StaticGraphViewOps}, - graph::graph::Graph, - }, + db::{api::mutation::AdditionOps, graph::graph::Graph}, + prelude::GraphViewOps, + test_storage, }; use pretty_assertions::assert_eq; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn test_sum_float_weights() { @@ -168,11 +166,7 @@ mod sum_weight_test { .expect("Couldnt add edge"); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let res = balance(graph, "value_dec".to_string(), Direction::BOTH, None); let node_one = graph.node("1").unwrap(); let node_two = graph.node("2").unwrap(); @@ -207,9 +201,6 @@ mod sum_weight_test { (node_five, 0.0), ]); assert_eq!(res.get_all(), expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/metrics/clustering_coefficient.rs b/raphtory/src/algorithms/metrics/clustering_coefficient.rs index 1e723e27a6..bc8ec458d6 100644 --- a/raphtory/src/algorithms/metrics/clustering_coefficient.rs +++ b/raphtory/src/algorithms/metrics/clustering_coefficient.rs @@ -52,9 +52,9 @@ mod cc_test { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; use pretty_assertions::assert_eq; - use tempfile::TempDir; /// Test the global clustering coefficient #[test] @@ -89,16 +89,9 @@ mod cc_test { graph.add_edge(0, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = clustering_coefficient(graph); assert_eq!(results, 0.3); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/metrics/degree.rs b/raphtory/src/algorithms/metrics/degree.rs index 9bf9271a63..ce6f3f63d4 100644 --- a/raphtory/src/algorithms/metrics/degree.rs +++ b/raphtory/src/algorithms/metrics/degree.rs @@ -89,19 +89,15 @@ pub fn average_degree<'graph, G: GraphViewOps<'graph>>(graph: &'graph G) -> f64 #[cfg(test)] mod degree_test { + use super::max_out_degree; use crate::{ algorithms::metrics::degree::{ average_degree, max_degree, max_in_degree, min_degree, min_in_degree, min_out_degree, }, - db::{ - api::{mutation::AdditionOps, view::StaticGraphViewOps}, - graph::graph::Graph, - }, + db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; - - use super::max_out_degree; #[test] fn degree_test() { @@ -119,11 +115,7 @@ mod degree_test { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let expected_max_out_degree = 3; let actual_max_out_degree = max_out_degree(graph); @@ -152,9 +144,6 @@ mod degree_test { assert_eq!(expected_average_degree, actual_average_degree); assert_eq!(expected_max_degree, actual_max_degree); assert_eq!(expected_min_degree, actual_min_degree); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/metrics/directed_graph_density.rs b/raphtory/src/algorithms/metrics/directed_graph_density.rs index 8b1f9a461f..65dde18118 100644 --- a/raphtory/src/algorithms/metrics/directed_graph_density.rs +++ b/raphtory/src/algorithms/metrics/directed_graph_density.rs @@ -44,8 +44,8 @@ mod directed_graph_density_tests { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; #[test] fn low_graph_density() { @@ -64,20 +64,13 @@ mod directed_graph_density_tests { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let windowed_graph = graph.window(0, 7); let actual = directed_graph_density(&windowed_graph); let expected = 0.3; assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -90,19 +83,12 @@ mod directed_graph_density_tests { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let windowed_graph = graph.window(0, 3); let actual = directed_graph_density(&windowed_graph); let expected = 1.0; assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/metrics/local_clustering_coefficient.rs b/raphtory/src/algorithms/metrics/local_clustering_coefficient.rs index 49b9aea21f..a010c774e3 100644 --- a/raphtory/src/algorithms/metrics/local_clustering_coefficient.rs +++ b/raphtory/src/algorithms/metrics/local_clustering_coefficient.rs @@ -85,8 +85,8 @@ mod clustering_coefficient_tests { graph::graph::Graph, }, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; #[test] fn clusters_of_triangles() { @@ -104,11 +104,7 @@ mod clustering_coefficient_tests { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let expected = vec![0.33333334, 1.0, 1.0, 0.0, 0.0]; let windowed_graph = graph.window(0, 7); let actual = (1..=5) @@ -116,9 +112,6 @@ mod clustering_coefficient_tests { .collect::>(); assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/metrics/reciprocity.rs b/raphtory/src/algorithms/metrics/reciprocity.rs index 350ff75f9c..041daefcf3 100644 --- a/raphtory/src/algorithms/metrics/reciprocity.rs +++ b/raphtory/src/algorithms/metrics/reciprocity.rs @@ -164,15 +164,12 @@ pub fn all_local_reciprocity( mod reciprocity_test { use crate::{ algorithms::metrics::reciprocity::{all_local_reciprocity, global_reciprocity}, - db::{ - api::{mutation::AdditionOps, view::StaticGraphViewOps}, - graph::graph::Graph, - }, + db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; use pretty_assertions::assert_eq; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn test_global_recip() { @@ -193,11 +190,7 @@ mod reciprocity_test { graph.add_edge(0, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let actual = global_reciprocity(graph, None); assert_eq!(actual, 0.5); @@ -210,9 +203,6 @@ mod reciprocity_test { let res = all_local_reciprocity(graph, None); assert_eq!(res.get("1"), hash_map_result.get("1")); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/motifs/global_temporal_three_node_motifs.rs b/raphtory/src/algorithms/motifs/global_temporal_three_node_motifs.rs index 576b054a69..3a9d95c2f4 100644 --- a/raphtory/src/algorithms/motifs/global_temporal_three_node_motifs.rs +++ b/raphtory/src/algorithms/motifs/global_temporal_three_node_motifs.rs @@ -308,8 +308,8 @@ mod motifs_test { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; fn load_graph(edges: Vec<(i64, u64, u64)>) -> Graph { let graph = Graph::new(); @@ -350,11 +350,7 @@ mod motifs_test { (23, 11, 9), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let global_motifs = &temporal_three_node_motif_multi(graph, vec![10], None); let expected: [usize; 40] = vec![ @@ -367,9 +363,6 @@ mod motifs_test { .try_into() .unwrap(); assert_eq!(global_motifs[0], expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/motifs/local_temporal_three_node_motifs.rs b/raphtory/src/algorithms/motifs/local_temporal_three_node_motifs.rs index d62bc9c76d..369ea215e1 100644 --- a/raphtory/src/algorithms/motifs/local_temporal_three_node_motifs.rs +++ b/raphtory/src/algorithms/motifs/local_temporal_three_node_motifs.rs @@ -388,8 +388,8 @@ mod motifs_test { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; fn load_graph(edges: Vec<(i64, u64, u64)>) -> Graph { let graph = Graph::new(); @@ -509,11 +509,7 @@ mod motifs_test { fn test_local_motif() { let graph = load_sample_graph(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "arrow")] - let arrow_graph = graph.persist_as_arrow(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let binding = temporal_three_node_motif(graph, Vec::from([10]), None); let actual = binding .iter() @@ -607,10 +603,7 @@ mod motifs_test { expected.get(&ind.to_string()).unwrap() ); } - } - #[cfg(feature = "arrow")] - test(&arrow_graph); - test(&graph); + }); } #[test] diff --git a/raphtory/src/algorithms/motifs/local_triangle_count.rs b/raphtory/src/algorithms/motifs/local_triangle_count.rs index fff93fecc1..bb38ff09d5 100644 --- a/raphtory/src/algorithms/motifs/local_triangle_count.rs +++ b/raphtory/src/algorithms/motifs/local_triangle_count.rs @@ -74,8 +74,8 @@ mod triangle_count_tests { graph::graph::Graph, }, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; #[test] fn counts_triangles() { @@ -86,11 +86,7 @@ mod triangle_count_tests { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let windowed_graph = graph.window(0, 5); let expected = vec![1, 1, 1]; @@ -99,9 +95,6 @@ mod triangle_count_tests { .collect::>(); assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/motifs/triangle_count.rs b/raphtory/src/algorithms/motifs/triangle_count.rs index 20bd670f3e..33f1047fa1 100644 --- a/raphtory/src/algorithms/motifs/triangle_count.rs +++ b/raphtory/src/algorithms/motifs/triangle_count.rs @@ -132,8 +132,8 @@ mod triangle_count_tests { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; - use tempfile::TempDir; #[test] fn triangle_count_1() { @@ -160,18 +160,11 @@ mod triangle_count_tests { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let actual_tri_count = triangle_count(graph, Some(2)); assert_eq!(actual_tri_count, 4) - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -208,8 +201,9 @@ mod triangle_count_tests { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let actual_tri_count = triangle_count(&graph, None); - - assert_eq!(actual_tri_count, 8) + test_storage!(&graph, |graph| { + let actual_tri_count = triangle_count(graph, None); + assert_eq!(actual_tri_count, 8) + }); } } diff --git a/raphtory/src/algorithms/motifs/triplet_count.rs b/raphtory/src/algorithms/motifs/triplet_count.rs index 184d87cc37..a7d2b9be5c 100644 --- a/raphtory/src/algorithms/motifs/triplet_count.rs +++ b/raphtory/src/algorithms/motifs/triplet_count.rs @@ -118,9 +118,9 @@ mod triplet_test { use crate::{ db::{api::mutation::AdditionOps, graph::graph::Graph}, prelude::NO_PROPS, + test_storage, }; use pretty_assertions::assert_eq; - use tempfile::TempDir; /// Test the global clustering coefficient #[test] @@ -154,18 +154,12 @@ mod triplet_test { for (src, dst) in edges { graph.add_edge(0, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let exp_triplet_count = 20; let results = triplet_count(graph, None); assert_eq!(results, exp_triplet_count); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/pathing/dijkstra.rs b/raphtory/src/algorithms/pathing/dijkstra.rs index 81f1840d71..ca64c8dd2c 100644 --- a/raphtory/src/algorithms/pathing/dijkstra.rs +++ b/raphtory/src/algorithms/pathing/dijkstra.rs @@ -212,15 +212,13 @@ pub fn dijkstra_single_source_shortest_paths)>) -> Graph { let graph = Graph::new(); @@ -246,11 +244,8 @@ mod dijkstra_tests { #[test] fn test_dijkstra_multiple_targets() { let graph = basic_graph(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let targets: Vec<&str> = vec!["D", "F"]; let results = dijkstra_single_source_shortest_paths( graph, @@ -283,20 +278,14 @@ mod dijkstra_tests { assert_eq!(results.get("D").unwrap().1, vec!["B", "C", "D"]); assert_eq!(results.get("E").unwrap().1, vec!["B", "C", "E"]); assert_eq!(results.get("F").unwrap().1, vec!["B", "C", "E", "F"]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] fn test_dijkstra_no_weight() { let graph = basic_graph(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let targets: Vec<&str> = vec!["C", "E", "F"]; let results = dijkstra_single_source_shortest_paths(graph, "A", targets, None, Direction::OUT) @@ -304,10 +293,7 @@ mod dijkstra_tests { assert_eq!(results.get("C").unwrap().1, vec!["A", "C"]); assert_eq!(results.get("E").unwrap().1, vec!["A", "C", "E"]); assert_eq!(results.get("F").unwrap().1, vec!["A", "C", "F"]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -328,11 +314,7 @@ mod dijkstra_tests { graph.add_edge(t, src, dst, props, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let targets = vec![4, 6]; let results = dijkstra_single_source_shortest_paths( graph, @@ -363,10 +345,7 @@ mod dijkstra_tests { assert_eq!(results.get("4").unwrap().1, vec!["2", "3", "4"]); assert_eq!(results.get("5").unwrap().1, vec!["2", "3", "5"]); assert_eq!(results.get("6").unwrap().1, vec!["2", "3", "5", "6"]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -388,11 +367,7 @@ mod dijkstra_tests { graph.add_edge(t, src, dst, props, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let targets: Vec<&str> = vec!["D", "F"]; let results = dijkstra_single_source_shortest_paths( graph, @@ -423,10 +398,7 @@ mod dijkstra_tests { assert_eq!(results.get("D").unwrap().1, vec!["B", "C", "D"]); assert_eq!(results.get("E").unwrap().1, vec!["B", "C", "E"]); assert_eq!(results.get("F").unwrap().1, vec!["B", "C", "E", "F"]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -443,11 +415,7 @@ mod dijkstra_tests { graph.add_edge(t, src, dst, props, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let targets: Vec<&str> = vec!["D"]; let results = dijkstra_single_source_shortest_paths( graph, @@ -460,10 +428,7 @@ mod dijkstra_tests { let results = results.unwrap(); assert_eq!(results.get("D").unwrap().0, Prop::U64(7u64)); assert_eq!(results.get("D").unwrap().1, vec!["A", "C", "D"]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -480,19 +445,12 @@ mod dijkstra_tests { graph.add_edge(t, src, dst, props, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let targets: Vec<&str> = vec!["D"]; let results = dijkstra_single_source_shortest_paths(graph, "A", targets, None, Direction::BOTH) .unwrap(); assert_eq!(results.get("D").unwrap().1, vec!["A", "C", "D"]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/pathing/single_source_shortest_path.rs b/raphtory/src/algorithms/pathing/single_source_shortest_path.rs index 5b3b6e7590..a9185a80a8 100644 --- a/raphtory/src/algorithms/pathing/single_source_shortest_path.rs +++ b/raphtory/src/algorithms/pathing/single_source_shortest_path.rs @@ -79,11 +79,10 @@ pub fn single_source_shortest_path<'graph, G: GraphViewOps<'graph>, T: AsNodeRef #[cfg(test)] mod sssp_tests { use super::*; - use crate::db::{ - api::{mutation::AdditionOps, view::StaticGraphViewOps}, - graph::graph::Graph, + use crate::{ + db::{api::mutation::AdditionOps, graph::graph::Graph}, + test_storage, }; - use tempfile::TempDir; fn load_graph(edges: Vec<(i64, u64, u64)>) -> Graph { let graph = Graph::new(); @@ -107,11 +106,7 @@ mod sssp_tests { (8, 5, 6), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let binding = single_source_shortest_path(graph, 1, Some(4)); let results = binding.get_all_with_names(); let expected: HashMap> = HashMap::from([ @@ -136,9 +131,6 @@ mod sssp_tests { assert_eq!(results, expected); let binding = single_source_shortest_path(graph, 5, Some(4)); println!("{:?}", binding.get_all_with_names()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/algorithms/pathing/temporal_reachability.rs b/raphtory/src/algorithms/pathing/temporal_reachability.rs index c023f8ee6d..8db7379ed1 100644 --- a/raphtory/src/algorithms/pathing/temporal_reachability.rs +++ b/raphtory/src/algorithms/pathing/temporal_reachability.rs @@ -204,8 +204,10 @@ pub fn temporally_reachable_nodes( #[cfg(test)] mod generic_taint_tests { use super::*; - use crate::db::{api::mutation::AdditionOps, graph::graph::Graph}; - use tempfile::TempDir; + use crate::{ + db::{api::mutation::AdditionOps, graph::graph::Graph}, + test_storage, + }; fn sort_inner_by_string( data: HashMap>, @@ -260,11 +262,7 @@ mod generic_taint_tests { (10, 5, 8), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = sort_inner_by_string(test_generic_taint(graph, 20, 11, vec![2], None)); let expected: Vec<(String, Vec<(i64, String)>)> = Vec::from([ ("1".to_string(), vec![]), @@ -283,10 +281,7 @@ mod generic_taint_tests { ("8".to_string(), vec![]), ]); assert_eq!(results, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -304,11 +299,7 @@ mod generic_taint_tests { (10, 5, 8), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = sort_inner_by_string(test_generic_taint(graph, 20, 11, vec![1, 2], None)); let expected: Vec<(String, Vec<(i64, String)>)> = Vec::from([ ("1".to_string(), vec![(11i64, "start".to_string())]), @@ -330,10 +321,7 @@ mod generic_taint_tests { ("8".to_string(), vec![]), ]); assert_eq!(results, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -351,11 +339,7 @@ mod generic_taint_tests { (10, 5, 8), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = sort_inner_by_string(test_generic_taint( graph, 20, @@ -377,10 +361,7 @@ mod generic_taint_tests { ("8".to_string(), vec![]), ]); assert_eq!(results, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -400,11 +381,7 @@ mod generic_taint_tests { (10, 5, 8), ]); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let results = sort_inner_by_string(test_generic_taint( graph, 20, @@ -430,9 +407,6 @@ mod generic_taint_tests { ("8".to_string(), vec![]), ]); assert_eq!(results, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } diff --git a/raphtory/src/core/entities/nodes/input_node.rs b/raphtory/src/core/entities/nodes/input_node.rs index e320c77e76..17d92f1c38 100644 --- a/raphtory/src/core/entities/nodes/input_node.rs +++ b/raphtory/src/core/entities/nodes/input_node.rs @@ -22,28 +22,33 @@ pub fn parse_u64_strict(input: &str) -> Option { if first == byte_0 { return input_iter.next().is_none().then_some(0); } - if input.len() == 20 && (byte_1..=MAX_U64_BYTES[0]).contains(&first) { - let mut result = (first - byte_0) as u64; - for (next_byte, max_byte) in input_iter.zip(MAX_U64_BYTES[1..].iter().copied()) { + + let mut check_max = input.len() == 20; + if check_max { + if !(byte_1..=MAX_U64_BYTES[0]).contains(&first) { + return None; + } + } else { + if !(byte_1..=byte_9).contains(&first) { + return None; + } + } + + let mut result = (first - byte_0) as u64; + for (next_byte, max_byte) in input_iter.zip(MAX_U64_BYTES[1..].iter().copied()) { + if check_max { if !(byte_0..=max_byte).contains(&next_byte) { return None; } - result = result * 10 + (next_byte - byte_0) as u64; - } - return Some(result); - } - if (byte_1..=byte_9).contains(&first) { - let mut result = (first - byte_0) as u64; - for next_byte in input_iter { + check_max = next_byte == max_byte; + } else { if !(byte_0..=byte_9).contains(&next_byte) { return None; } - result = result * 10 + (next_byte - byte_0) as u64; } - return Some(result); + result = result * 10 + (next_byte - byte_0) as u64; } - - None + return Some(result); } pub trait InputNode: Clone { @@ -84,7 +89,8 @@ impl InputNode for String { #[cfg(test)] mod test { - use crate::core::entities::nodes::input_node::InputNode; + use crate::core::entities::nodes::input_node::{parse_u64_strict, InputNode}; + use proptest::prelude::*; #[test] fn test_weird_num_edge_cases() { @@ -93,4 +99,21 @@ mod test { assert_ne!("00".id(), "0".id()); assert_eq!("0".id(), 0.id()); } + + #[test] + fn test_u64_string_works() { + proptest!(|(n in any::())| { + assert_eq!(n.to_string().id(), n); + }); + } + + #[test] + fn test_if_str_parses_it_is_a_u64() { + proptest!(|(s in any::())| { + let res = parse_u64_strict(&s); + if let Some(n) = res { + assert_eq!(n.to_string(), s) + } + }); + } } diff --git a/raphtory/src/db/api/view/edge.rs b/raphtory/src/db/api/view/edge.rs index 966f74c68e..10fd68a6d3 100644 --- a/raphtory/src/db/api/view/edge.rs +++ b/raphtory/src/db/api/view/edge.rs @@ -295,8 +295,7 @@ impl<'graph, E: BaseEdgeViewOps<'graph>> EdgeViewOps<'graph> for E { #[cfg(test)] mod test_edge_view { - use crate::{db::api::view::StaticGraphViewOps, prelude::*}; - use tempfile::TempDir; + use crate::{prelude::*, test_storage, test_utils::test_graph}; #[test] fn test_exploded_edge_properties() { @@ -306,11 +305,7 @@ mod test_edge_view { graph.add_edge(0, 1, 2, [("test", *v)], None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G, actual_prop_values: &[i32]) { + test_storage!(&graph, |graph| { let prop_values: Vec<_> = graph .edge(1, 2) .unwrap() @@ -319,10 +314,7 @@ mod test_edge_view { .flat_map(|p| p.get("test").into_i32()) .collect(); assert_eq!(prop_values, actual_prop_values) - } - test(&graph, &actual_prop_values); - #[cfg(feature = "storage")] - test(&disk_graph, &actual_prop_values); + }); } #[test] @@ -336,16 +328,7 @@ mod test_edge_view { for v in actual_prop_values_1.iter() { graph.add_edge(1, 1, 2, [("test", *v)], None).unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test( - graph: &G, - actual_prop_values_0: &[i32], - actual_prop_values_1: &[i32], - ) { + test_storage!(&graph, |graph| { let prop_values: Vec<_> = graph .at(0) .edge(1, 2) @@ -364,10 +347,7 @@ mod test_edge_view { .flat_map(|p| p.get("test").into_i32()) .collect(); assert_eq!(prop_values, actual_prop_values_1) - } - test(&graph, &actual_prop_values_0, &actual_prop_values_1); - #[cfg(feature = "storage")] - test(&disk_graph, &actual_prop_values_0, &actual_prop_values_1); + }); } #[test] @@ -379,12 +359,8 @@ mod test_edge_view { .add_edge(0, 1, 2, [("test", *v)], Some((v % 2).to_string().as_str())) .unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G, expected_prop_values: &[i32]) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let prop_values: Vec<_> = graph .edge(1, 2) .unwrap() @@ -443,10 +419,7 @@ mod test_edge_view { .all(|l| l.is_err())); assert!(graph.edges().explode().time().all(|l| l.is_ok())); assert!(graph.edges().explode_layers().time().all(|l| l.is_err())); - } - test(&graph, &expected_prop_values); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph, &expected_prop_values); + }); } #[test] @@ -457,11 +430,8 @@ mod test_edge_view { graph.add_edge(0, 1, 2, [("second", true)], None).unwrap(); graph.add_edge(0, 2, 3, [("second", true)], None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: boolean properties not supported yet (Issue #48) + test_graph(&graph, |graph| { let mut exploded_edges: Vec<_> = graph.edges().explode().iter().collect(); exploded_edges.sort_by_key(|a| a.time_and_index()); @@ -484,9 +454,6 @@ mod test_edge_view { (2, 3, Some(true)) ] ) - } - test(&graph); - // FIXME: boolean properties not supported yet (Issue #48) - // test(&disk_graph); + }); } } diff --git a/raphtory/src/db/api/view/graph.rs b/raphtory/src/db/api/view/graph.rs index 705cb22c9d..8773d2116c 100644 --- a/raphtory/src/db/api/view/graph.rs +++ b/raphtory/src/db/api/view/graph.rs @@ -465,8 +465,7 @@ impl<'graph, G: GraphViewOps<'graph> + 'graph> OneHopFilter<'graph> for G { #[cfg(test)] mod test_exploded_edges { - use crate::{db::api::view::StaticGraphViewOps, prelude::*}; - use tempfile::TempDir; + use crate::{prelude::*, test_storage}; #[test] fn test_exploded_edges() { @@ -475,28 +474,18 @@ mod test_exploded_edges { graph.add_edge(1, 0, 1, NO_PROPS, None).unwrap(); graph.add_edge(2, 0, 1, NO_PROPS, None).unwrap(); graph.add_edge(3, 0, 1, NO_PROPS, None).unwrap(); - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { assert_eq!(graph.count_temporal_edges(), 4) - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } } #[cfg(test)] mod test_materialize { use crate::{ - core::OptionAsStr, - db::api::view::{internal::CoreGraphOps, StaticGraphViewOps}, - prelude::*, + core::OptionAsStr, db::api::view::internal::CoreGraphOps, prelude::*, + test_utils::test_graph, }; - use tempfile::TempDir; #[test] fn test_materialize() { @@ -571,10 +560,9 @@ mod test_materialize { let graph = Graph::new(); graph.add_node(0, "A", NO_PROPS, None).unwrap(); graph.add_node(1, "B", NO_PROPS, Some("H")).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + + // FIXME: Node types not yet supported (Issue #51) + test_graph(&graph, |graph| { let node_a = graph.node("A").unwrap(); let node_b = graph.node("B").unwrap(); let node_a_type = node_a.node_type(); @@ -582,10 +570,7 @@ mod test_materialize { assert_eq!(node_a_type_str, None); assert_eq!(node_b.node_type().as_str(), Some("H")); - } - test(&graph); - // FIXME: Node types not yet supported (Issue #51) - // test(&disk_graph); + }); // Nodes with No type can be overwritten let node_a = graph.add_node(1, "A", NO_PROPS, Some("TYPEA")).unwrap(); diff --git a/raphtory/src/db/api/view/time.rs b/raphtory/src/db/api/view/time.rs index dd110672c2..e1ffa33868 100644 --- a/raphtory/src/db/api/view/time.rs +++ b/raphtory/src/db/api/view/time.rs @@ -301,15 +301,15 @@ mod time_tests { mutation::AdditionOps, view::{ time::{internal::InternalTimeOps, WindowSet}, - StaticGraphViewOps, TimeOps, + TimeOps, }, }, graph::graph::Graph, }, prelude::{GraphViewOps, NO_PROPS}, + test_storage, }; use itertools::Itertools; - use tempfile::TempDir; // start inclusive, end exclusive fn graph_with_timeline(start: i64, end: i64) -> Graph { @@ -334,94 +334,53 @@ mod time_tests { #[test] fn rolling() { let graph = graph_with_timeline(1, 7); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test1(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.rolling(2, None).unwrap(); let expected = vec![(Some(1), Some(3)), (Some(3), Some(5)), (Some(5), Some(7))]; assert_bounds(windows, expected); - } - test1(&graph); - #[cfg(feature = "storage")] - test1(&disk_graph); + }); let graph = graph_with_timeline(1, 6); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test2(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.rolling(3, Some(2)).unwrap(); let expected = vec![(Some(0), Some(3)), (Some(2), Some(5)), (Some(4), Some(7))]; assert_bounds(windows, expected.clone()); - } - test2(&graph); - #[cfg(feature = "storage")] - test2(&disk_graph); + }); let graph = graph_with_timeline(0, 9); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test3(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.window(1, 6).rolling(3, Some(2)).unwrap(); assert_bounds( windows, vec![(Some(1), Some(3)), (Some(2), Some(5)), (Some(4), Some(6))], ); - } - test3(&graph); - #[cfg(feature = "storage")] - test3(&disk_graph); + }); } #[test] fn expanding() { let graph = graph_with_timeline(1, 7); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test1(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.expanding(2).unwrap(); let expected = vec![(None, Some(3)), (None, Some(5)), (None, Some(7))]; assert_bounds(windows, expected); - } - test1(&graph); - #[cfg(feature = "storage")] - test1(&disk_graph); + }); let graph = graph_with_timeline(1, 6); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test2(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.expanding(2).unwrap(); let expected = vec![(None, Some(3)), (None, Some(5)), (None, Some(7))]; assert_bounds(windows, expected.clone()); - } - test2(&graph); - #[cfg(feature = "storage")] - test2(&disk_graph); + }); let graph = graph_with_timeline(0, 9); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test3(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.window(1, 6).expanding(2).unwrap(); assert_bounds( windows, vec![(Some(1), Some(3)), (Some(1), Some(5)), (Some(1), Some(6))], ); - } - test3(&graph); - #[cfg(feature = "storage")] - test3(&disk_graph); + }); } #[test] @@ -429,11 +388,7 @@ mod time_tests { let start = "2020-06-06 00:00:00".try_into_time().unwrap(); let end = "2020-06-07 23:59:59.999".try_into_time().unwrap(); let graph = graph_with_timeline(start, end); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test1(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.rolling("1 day", None).unwrap(); let expected = vec![ ( @@ -446,19 +401,12 @@ mod time_tests { ), ]; assert_bounds(windows, expected); - } - test1(&graph); - #[cfg(feature = "storage")] - test1(&disk_graph); + }); let start = "2020-06-06 00:00:00".try_into_time().unwrap(); let end = "2020-06-08 00:00:00".try_into_time().unwrap(); let graph = graph_with_timeline(start, end); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test2(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.rolling("1 day", None).unwrap(); let expected = vec![ ( @@ -471,10 +419,7 @@ mod time_tests { ), ]; assert_bounds(windows, expected); - } - test2(&graph); - #[cfg(feature = "storage")] - test2(&disk_graph); + }); // TODO: turn this back on if we bring bach epoch alignment for unwindowed graphs // let start = "2020-06-05 23:59:59.999".into_time().unwrap(); @@ -499,39 +444,25 @@ mod time_tests { let start = "2020-06-06 00:00:00".try_into_time().unwrap(); let end = "2020-06-07 23:59:59.999".try_into_time().unwrap(); let graph = graph_with_timeline(start, end); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test1(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.expanding("1 day").unwrap(); let expected = vec![ (None, "2020-06-07 00:00:00".try_into_time().ok()), (None, "2020-06-08 00:00:00".try_into_time().ok()), ]; assert_bounds(windows, expected); - } - test1(&graph); - #[cfg(feature = "storage")] - test1(&disk_graph); + }); let start = "2020-06-06 00:00:00".try_into_time().unwrap(); let end = "2020-06-08 00:00:00".try_into_time().unwrap(); let graph = graph_with_timeline(start, end); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test2(graph: &G) { + test_storage!(&graph, |graph| { let windows = graph.expanding("1 day").unwrap(); let expected = vec![ (None, "2020-06-07 00:00:00".try_into_time().ok()), (None, "2020-06-08 00:00:00".try_into_time().ok()), ]; assert_bounds(windows, expected); - } - test2(&graph); - #[cfg(feature = "storage")] - test2(&disk_graph); + }); } } diff --git a/raphtory/src/db/graph/edge.rs b/raphtory/src/db/graph/edge.rs index fe022665ae..4accc97dcd 100644 --- a/raphtory/src/db/graph/edge.rs +++ b/raphtory/src/db/graph/edge.rs @@ -404,12 +404,12 @@ impl<'graph, G: GraphViewOps<'graph>, GH: GraphViewOps<'graph>> OneHopFilter<'gr mod test_edge { use crate::{ core::{ArcStr, IntoPropMap}, - db::api::view::StaticGraphViewOps, prelude::*, + test_storage, + test_utils::test_graph, }; use itertools::Itertools; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn test_properties() { @@ -417,20 +417,15 @@ mod test_edge { let props = [(ArcStr::from("test"), "test".into_prop())]; graph.add_edge(0, 1, 2, NO_PROPS, None).unwrap(); graph.add_edge(2, 1, 2, props.clone(), None).unwrap(); - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G, props: [(ArcStr, Prop); 1]) { + test_storage!(&graph, |graph| { let e1 = graph.edge(1, 2).unwrap(); let e1_w = graph.window(0, 1).edge(1, 2).unwrap(); - assert_eq!(HashMap::from_iter(e1.properties().as_vec()), props.into()); + assert_eq!( + HashMap::from_iter(e1.properties().as_vec()), + props.clone().into() + ); assert!(e1_w.properties().as_vec().is_empty()) - } - test(&graph, props.clone()); - #[cfg(feature = "storage")] - test(&disk_graph, props); + }); } #[test] @@ -447,11 +442,8 @@ mod test_edge { .add_constant_properties([("test_prop", "test_val")], Some("layer 2")) .unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: multilayer edge views are not supported yet (Issue #47) + test_graph(&graph, |graph| { assert_eq!( graph .edge(1, 2) @@ -478,10 +470,7 @@ mod test_edge { ) } } - } - test(&graph); - // FIXME: multilayer edge views are not supported yet (Issue #47) - // test(&disk_graph); + }); } #[test] diff --git a/raphtory/src/db/graph/graph.rs b/raphtory/src/db/graph/graph.rs index e1ef581d33..4153685334 100644 --- a/raphtory/src/db/graph/graph.rs +++ b/raphtory/src/db/graph/graph.rs @@ -205,14 +205,20 @@ mod db_tests { ArcStr, OptionAsStr, Prop, }, db::{ - api::view::{ - time::internal::InternalTimeOps, EdgeViewOps, Layer, LayerOps, NodeViewOps, - StaticGraphViewOps, TimeOps, + api::{ + properties::internal::ConstPropertiesOps, + view::{ + internal::{CoreGraphOps, EdgeFilterOps, TimeSemantics}, + time::internal::InternalTimeOps, + EdgeViewOps, Layer, LayerOps, NodeViewOps, TimeOps, + }, }, graph::{edge::EdgeView, edges::Edges, node::NodeView, path::PathFromNode}, }, graphgen::random_attachment::random_attachment, prelude::{AdditionOps, PropertyAdditionOps}, + test_storage, + test_utils::test_graph, }; use chrono::NaiveDateTime; use itertools::Itertools; @@ -225,12 +231,7 @@ mod db_tests { #[test] fn test_empty_graph() { let graph = Graph::new(); - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { assert!(!graph.has_edge(1, 2)); let test_time = 42; @@ -287,10 +288,7 @@ mod db_tests { assert!(graph.latest_date_time().is_none()); assert!(graph.latest_time_global().is_none()); assert!(graph.earliest_time_global().is_none()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[quickcheck] @@ -578,11 +576,7 @@ mod db_tests { graph.add_edge(t, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let e = graph .window(i64::MIN, i64::MAX) .layers(Layer::Default) @@ -591,10 +585,7 @@ mod db_tests { .unwrap(); assert_eq!(e.src().id(), 1u64); assert_eq!(e.dst().id(), 3u64); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -613,11 +604,7 @@ mod db_tests { for (t, src, dst) in &vs { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let expected = vec![(2, 3, 1), (1, 0, 0), (1, 0, 0)]; let actual = (1..=3) .map(|i| { @@ -631,10 +618,7 @@ mod db_tests { .collect::>(); assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -653,12 +637,7 @@ mod db_tests { for (t, src, dst) in &vs { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let expected = vec![(2, 3, 1), (1, 0, 0), (1, 0, 0)]; let actual = (1..=3) .map(|i| { @@ -672,10 +651,7 @@ mod db_tests { .collect::>(); assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -886,11 +862,8 @@ mod db_tests { .add_node(3, 1, [("cool".to_string(), Prop::Bool(false))], None) .unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: boolean properties not yet supported (Issue #48) + test_graph(&graph, |graph| { let wg = graph.window(3, 15); let v = wg.node(1).unwrap(); @@ -916,10 +889,7 @@ mod db_tests { .iter() .collect(); assert_eq!(hist, vec![(0, Prop::Bool(true)), (3, Prop::Bool(false))]); - } - test(&graph); - // FIXME: boolean properties not yet supported (Issue #48) - // test(&disk_graph); + }); } #[test] @@ -930,19 +900,12 @@ mod db_tests { .add_edge(1, 0, 1, vec![("distance".to_string(), Prop::U32(5))], None) .expect("add edge"); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let e = graph.edge(0, 1).unwrap(); let prop = e.properties().get("distance").unwrap(); assert_eq!(prop, Prop::U32(5)); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -961,12 +924,7 @@ mod db_tests { for (t, src, dst) in &vs { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let expected = vec![ (vec![1, 2], vec![1, 2, 3], vec![1]), (vec![1], vec![], vec![]), @@ -984,30 +942,20 @@ mod db_tests { .collect::>(); assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] fn test_time_range_on_empty_graph() { let graph = Graph::new(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let rolling = graph.rolling(1, None).unwrap().collect_vec(); assert!(rolling.is_empty()); let expanding = graph.expanding(1).unwrap().collect_vec(); assert!(expanding.is_empty()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1017,21 +965,13 @@ mod db_tests { graph.add_node(0, "haaroon", NO_PROPS, None).unwrap(); graph.add_node(1, "hamza", NO_PROPS, None).unwrap(); graph.add_node(1, 831, NO_PROPS, None).unwrap(); - - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { assert!(graph.has_node(831)); assert!(graph.has_node("haaroon")); assert!(graph.has_node("hamza")); assert_eq!(graph.count_nodes(), 3); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1044,11 +984,8 @@ mod db_tests { graph.add_edge(0, 11, 33, NO_PROPS, Some("layer2"))?; graph.add_edge(0, 11, 44, NO_PROPS, Some("layer2"))?; - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: needs multilayer support (Issue #47) + test_graph(&graph, |graph| { assert!(graph.has_edge(11, 22)); assert!(graph.default_layer().has_edge(11, 22)); assert!(!graph.default_layer().has_edge(11, 44)); @@ -1157,10 +1094,7 @@ mod db_tests { assert_eq!(to_ids(node_dft.in_neighbours()), vec![33]); assert!(to_ids(node1.in_neighbours()).is_empty()); assert!(to_ids(node2.in_neighbours()).is_empty()); - } - test(&graph); - // FIXME: needs multilayer support (Issue #47) - // test(&disk_graph); + }); Ok(()) } @@ -1193,12 +1127,7 @@ mod db_tests { graph .add_edge(2, 1, 2, [("weight", Prop::I64(3))], None) .unwrap(); - - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let exploded = graph.edge(1, 2).unwrap().explode(); let res = exploded.properties().map(|p| p.as_vec()).collect_vec(); @@ -1219,10 +1148,7 @@ mod db_tests { .map(|p| p.as_vec()) .collect_vec(); assert_eq!(e, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1235,11 +1161,7 @@ mod db_tests { graph.add_edge(1, 1, 3, NO_PROPS, None).unwrap(); graph.add_edge(2, 1, 3, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let mut res = graph.edge(1, 2).unwrap().earliest_time().unwrap(); assert_eq!(res, 0); @@ -1341,10 +1263,7 @@ mod db_tests { .flatten() .collect(); assert_eq!(res_list, vec![2, 2]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1362,11 +1281,8 @@ mod db_tests { graph.add_node(7, "Lord Farquaad", NO_PROPS, None).unwrap(); graph.add_node(8, "Lord Farquaad", NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Node updates without properties or edges are currently not supported in disk_graph (see issue #46) + test_graph(&graph, |graph| { let times_of_one = graph.node(1).unwrap().history(); let times_of_farquaad = graph.node("Lord Farquaad").unwrap().history(); @@ -1379,10 +1295,7 @@ mod db_tests { let windowed_times_of_farquaad = view.node("Lord Farquaad").unwrap().history(); assert_eq!(windowed_times_of_one, [1, 2, 3, 4]); assert_eq!(windowed_times_of_farquaad, [4, 6, 7]); - } - test(&graph); - // FIXME: Node updates without properties or edges are currently not supported in disk_graph (see issue #46) - // test(&disk_graph); + }); } #[test] @@ -1393,12 +1306,7 @@ mod db_tests { graph.add_edge(2, 1, 3, NO_PROPS, None).unwrap(); graph.add_edge(3, 1, 2, NO_PROPS, None).unwrap(); graph.add_edge(4, 1, 4, NO_PROPS, None).unwrap(); - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let times_of_onetwo = graph.edge(1, 2).unwrap().history(); let times_of_four = graph.edge(1, 4).unwrap().window(1, 5).history(); let view = graph.window(2, 5); @@ -1407,10 +1315,7 @@ mod db_tests { assert_eq!(times_of_onetwo, [1, 3]); assert_eq!(times_of_four, [4]); assert!(windowed_times_of_four.is_empty()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1428,11 +1333,7 @@ mod db_tests { graph.add_edge(9, 1, 4, NO_PROPS, None).unwrap(); graph.add_edge(10, 1, 4, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let times_of_onetwo = graph.edge(1, 2).unwrap().history(); let times_of_four = graph.edge(1, 4).unwrap().window(1, 5).history(); let times_of_outside_window = graph.edge(1, 4).unwrap().window(1, 4).history(); @@ -1448,10 +1349,7 @@ mod db_tests { assert!(times_of_outside_window.is_empty()); assert_eq!(windowed_times_of_four, [4]); assert_eq!(windowed_times_of_four_higher, [8, 9, 10]); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1474,11 +1372,8 @@ mod db_tests { graph.add_node(7, "Lord Farquaad", NO_PROPS, None).unwrap(); graph.add_node(8, "Lord Farquaad", NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Issue #46 + test_graph(&graph, |graph| { let times_of_one = graph.node(1).unwrap().history(); let times_of_farquaad = graph.node("Lord Farquaad").unwrap().history(); let times_of_upper = graph.node(2).unwrap().history(); @@ -1495,10 +1390,7 @@ mod db_tests { assert_eq!(windowed_times_of_one, [1, 2, 3, 4]); assert_eq!(windowed_times_of_farquaad, [4, 6, 7]); assert_eq!(windowed_times_of_two, [5, 6, 7]); - } - test(&graph); - // FIXME: Issue #46 - // test(&disk_graph); + }); } #[derive(Debug)] @@ -1740,12 +1632,7 @@ mod db_tests { graph .add_edge(3, 1, 2, vec![("weight".to_string(), Prop::I64(3))], None) .unwrap(); - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let e = graph.node(1).unwrap().out_edges().iter().next().unwrap(); let res: HashMap> = e .window(1, 3) @@ -1761,10 +1648,7 @@ mod db_tests { vec![(1, Prop::I64(1)), (2, Prop::I64(2))], ); assert_eq!(res, exp); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1774,11 +1658,8 @@ mod db_tests { graph.add_node(2, 1, NO_PROPS, None).unwrap(); graph.add_node(3, 1, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Node add without properties not showing up (Issue #46) + test_graph(&graph, |graph| { assert_eq!(graph.node(1).unwrap().earliest_time(), Some(1)); assert_eq!(graph.node(1).unwrap().latest_time(), Some(3)); @@ -1790,10 +1671,7 @@ mod db_tests { assert_eq!(graph.after(2).node(1).unwrap().earliest_time(), Some(3)); assert_eq!(graph.after(2).node(1).unwrap().latest_time(), Some(3)); - } - test(&graph); - // FIXME: Node add without properties not showing up (Issue #46) - // test(&disk_graph); + }) } #[test] @@ -1803,19 +1681,13 @@ mod db_tests { graph.add_node(1, 2, NO_PROPS, None).unwrap(); graph.add_node(2, 3, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Node add without properties not showing up (Issue #46) + test_graph(&graph, |graph| { assert_eq!(graph.nodes().id().collect::>(), vec![1, 2, 3]); let g_at = graph.at(1); assert_eq!(g_at.nodes().id().collect::>(), vec![1, 2]); - } - test(&graph); - // FIXME: Node add without properties not showing up (Issue #46) - // test(&disk_graph); + }); } #[test] @@ -1824,20 +1696,14 @@ mod db_tests { graph.add_edge(0, 0, 1, NO_PROPS, None)?; graph.add_edge(0, 0, 1, NO_PROPS, Some("awesome name"))?; - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let what = graph.edges().id().collect_vec(); assert_eq!(what, vec![(0, 1)]); let layer_names = graph.edges().layer_names().flatten().sorted().collect_vec(); assert_eq!(layer_names, vec!["_default", "awesome name"]); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); Ok(()) } @@ -1846,17 +1712,11 @@ mod db_tests { let graph = Graph::new(); graph.add_edge(0, 1, 2, NO_PROPS, Some("layer")).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { assert!(graph.edge(1, 2).is_some()); assert!(graph.layers("layer").unwrap().edge(1, 2).is_some()) - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -1871,11 +1731,8 @@ mod db_tests { .expect("add edge"); graph.add_edge(1, 1, 4, NO_PROPS, None).expect("add edge"); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let g_layers = graph.layers(vec!["layer1", "layer3"]).expect("layer"); assert!(g_layers.layers("layer1").unwrap().edge(1, 2).is_some()); @@ -1901,10 +1758,7 @@ mod db_tests { let one = g_layers2.node(1).expect("node"); let ns = one.neighbours().iter().map(|v| v.id()).collect::>(); assert_eq!(ns, vec![2]); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -1917,11 +1771,7 @@ mod db_tests { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let windowed_graph = graph.window(0, 5); let one = windowed_graph.node(1).expect("node"); let ns_win = one.neighbours().id().collect::>(); @@ -1930,10 +1780,7 @@ mod db_tests { let ns = one.neighbours().id().collect::>(); assert_eq!(ns, vec![2, 3]); assert_eq!(ns_win, ns); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1944,11 +1791,8 @@ mod db_tests { graph.add_edge(2, 1, 2, NO_PROPS, Some("layer1")).unwrap(); graph.add_edge(3, 1, 2, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let e = graph.edge(1, 2).expect("edge"); let layer_exploded = e @@ -1963,10 +1807,7 @@ mod db_tests { .collect::>(); assert_eq!(layer_exploded, vec![(1, 2, 0), (1, 2, 1), (1, 2, 2)]); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -1977,11 +1818,8 @@ mod db_tests { graph.add_edge(2, 1, 2, NO_PROPS, Some("layer1")).unwrap(); graph.add_edge(3, 1, 2, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let g = graph.window(0, 3); let e = g.edge(1, 2).expect("edge"); @@ -1997,10 +1835,7 @@ mod db_tests { .collect::>(); assert_eq!(layer_exploded, vec![(1, 2, 1), (1, 2, 2)]); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -2011,11 +1846,8 @@ mod db_tests { graph.add_edge(2, 1, 2, NO_PROPS, Some("layer1")).unwrap(); graph.add_edge(3, 1, 2, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let e = graph.edge(1, 2).expect("edge"); let layer_exploded = e @@ -2035,10 +1867,7 @@ mod db_tests { layer_exploded, vec![(3, 1, 2, 0), (0, 1, 2, 1), (2, 1, 2, 1), (1, 1, 2, 2)] ); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -2049,11 +1878,8 @@ mod db_tests { graph.add_edge(2, 1, 2, NO_PROPS, Some("layer1")).unwrap(); graph.add_edge(3, 1, 2, NO_PROPS, None).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let g = graph.window(0, 3); let e = g.edge(1, 2).expect("edge"); @@ -2074,10 +1900,7 @@ mod db_tests { layer_exploded, vec![(0, 1, 2, 1), (2, 1, 2, 1), (1, 1, 2, 2)] ); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -2094,11 +1917,8 @@ mod db_tests { .add_edge(1, 1, 2, [("tx_sent", 70u64)], "tether".into()) .expect("failed"); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let e = graph.edge(1, 2).expect("failed to get edge"); let sum: u64 = e .properties() @@ -2170,10 +1990,7 @@ mod db_tests { // layer does not have a way to reset yet! assert_eq!(eth_sum, 20); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -2181,11 +1998,8 @@ mod db_tests { let graph = Graph::new(); graph.add_edge(0, 1, 2, NO_PROPS, Some("layer1")).unwrap(); graph.add_edge(0, 1, 2, NO_PROPS, Some("layer2")).unwrap(); - let test_dir = tempfile::TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { assert_eq!( graph .layers("layer2") @@ -2194,23 +2008,34 @@ mod db_tests { .collect_vec(), vec!["layer2"] ) + }); + } + + #[quickcheck] + fn node_from_id_is_consistent(nodes: Vec) -> bool { + let g = Graph::new(); + for v in nodes.iter() { + g.add_node(0, *v, NO_PROPS, None).unwrap(); } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); - } - //TODO this needs to be fixed as part of the algorithm result switch to returning noderefs - // #[quickcheck] - // fn node_from_id_is_consistent(nodes: Vec) -> bool { - // let g = Graph::new(); - // for v in nodes.iter() { - // g.add_node(0, *v, NO_PROPS, None).unwrap(); - // } - // g.nodes() - // .name() - // .map(|name| g.node(name)) - // .all(|v| v.is_some()) - // } + g.nodes() + .name() + .into_iter() + .map(|name| g.node(name)) + .all(|v| v.is_some()) + } + + #[test] + fn large_id_is_consistent() { + let g = Graph::new(); + g.add_node(0, 10000000000000000006, NO_PROPS, None).unwrap(); + println!("names: {:?}", g.nodes().name().collect_vec()); + assert!(g + .nodes() + .name() + .into_iter() + .map(|name| g.node(name)) + .all(|v| v.is_some())) + } #[quickcheck] fn exploded_edge_times_is_consistent(edges: Vec<(u64, u64, Vec)>, offset: i64) -> bool { @@ -2313,11 +2138,7 @@ mod db_tests { graph.add_edge(2, 3, 4, [("layer", 2)], Some("2")).unwrap(); graph.add_edge(0, 1, 3, [("layer", 2)], Some("2")).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let v = graph.node(1).unwrap(); // filtering resets on neighbours @@ -2371,12 +2192,10 @@ mod db_tests { .id() .collect(); assert!(out_out_2.is_empty()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); - fn test2(graph: &G) { + // FIXME: requires multilayer edge view (Issue #47) + test_graph(&graph, |graph| { let v = graph.node(1).unwrap(); let out_out: Vec<_> = v .at(0) @@ -2407,11 +2226,7 @@ mod db_tests { .out_degree() .collect(); assert_eq!(degrees, [1]); - } - - test2(&graph); - // FIXME: requires multilayer edge view (Issue #47) - // test2(&disk_graph); + }); } #[test] @@ -2423,20 +2238,14 @@ mod db_tests { graph.add_edge(2, 3, 4, [("layer", 2)], Some("2")).unwrap(); graph.add_edge(0, 1, 3, [("layer", 2)], Some("2")).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Requires mutlilayer edge views + test_graph(&graph, |graph| { let wl = graph.window(0, 3).layers(vec!["1", "2"]).unwrap(); assert_eq!( weakly_connected_components(&wl, 10, None).get_all_values(), [1, 1, 1, 1] ); - } - test(&graph); - // FIXME: Requires mutlilayer edge views - // test(&disk_graph); + }); } #[test] @@ -2468,11 +2277,8 @@ mod db_tests { .add_edge(0, 0, 2, NO_PROPS, Some("awesome layer")) .unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { assert_eq!( graph.edge(0, 1).unwrap().layer_names().collect_vec(), ["_default"] @@ -2481,10 +2287,7 @@ mod db_tests { graph.edge(0, 2).unwrap().layer_names().collect_vec(), ["awesome layer"] ); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] diff --git a/raphtory/src/db/graph/node.rs b/raphtory/src/db/graph/node.rs index 75dbde35ed..497b8e2672 100644 --- a/raphtory/src/db/graph/node.rs +++ b/raphtory/src/db/graph/node.rs @@ -374,9 +374,8 @@ impl #[cfg(test)] mod node_test { - use crate::{core::ArcStr, db::api::view::StaticGraphViewOps, prelude::*}; + use crate::{core::ArcStr, prelude::*, test_utils::test_graph}; use std::collections::HashMap; - use tempfile::TempDir; #[test] fn test_earliest_time() { @@ -385,11 +384,8 @@ mod node_test { graph.add_node(1, 1, NO_PROPS, None).unwrap(); graph.add_node(2, 1, NO_PROPS, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Node add without properties not showing up (Issue #46) + test_graph(&graph, |graph| { let view = graph.before(2); assert_eq!(view.node(1).expect("v").earliest_time().unwrap(), 0); assert_eq!(view.node(1).expect("v").latest_time().unwrap(), 1); @@ -409,10 +405,7 @@ mod node_test { let view = graph.at(1); assert_eq!(view.node(1).expect("v").earliest_time().unwrap(), 1); assert_eq!(view.node(1).expect("v").latest_time().unwrap(), 1); - } - test(&graph); - // FIXME: Node add without properties not showing up (Issue #46) - // test(&disk_graph); + }); } #[test] @@ -422,11 +415,8 @@ mod node_test { graph.add_node(0, 1, NO_PROPS, None).unwrap(); graph.add_node(2, 1, props, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Node add without properties not showing up (Issue #46) + test_graph(&graph, |graph| { let v1 = graph.node(1).unwrap(); let v1_w = graph.window(0, 1).node(1).unwrap(); assert_eq!( @@ -434,10 +424,7 @@ mod node_test { [(ArcStr::from("test"), Prop::str("test"))].into() ); assert_eq!(v1_w.properties().as_map(), HashMap::default()) - } - test(&graph); - // FIXME: Node add without properties not showing up (Issue #46) - // test(&disk_graph); + }); } #[test] diff --git a/raphtory/src/db/graph/views/layer_graph.rs b/raphtory/src/db/graph/views/layer_graph.rs index e9671f2b23..852a13338b 100644 --- a/raphtory/src/db/graph/views/layer_graph.rs +++ b/raphtory/src/db/graph/views/layer_graph.rs @@ -129,9 +129,8 @@ impl<'graph, G: GraphViewOps<'graph>> InternalLayerOps for LayeredGraph { #[cfg(test)] mod test_layers { - use crate::{db::api::view::StaticGraphViewOps, prelude::*}; + use crate::{prelude::*, test_utils::test_graph}; use itertools::Itertools; - use tempfile::TempDir; #[test] fn test_layer_node() { @@ -141,11 +140,8 @@ mod test_layers { graph.add_edge(0, 2, 3, NO_PROPS, Some("layer2")).unwrap(); graph.add_edge(3, 2, 4, NO_PROPS, Some("layer1")).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let neighbours = graph .layers(vec!["layer1", "layer2"]) .unwrap() @@ -195,10 +191,7 @@ mod test_layers { .collect_vec(); edges.sort(); assert_eq!(edges, vec![(1, 2), (2, 3), (2, 4)]); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -211,11 +204,8 @@ mod test_layers { assert!(e1.has_layer("2")); assert!(e1.layers("2").unwrap().history().is_empty()); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let e = graph.edge(1, 2).unwrap(); // layers with non-existing layers errors assert!(e.layers(["1", "3"]).is_err()); @@ -229,9 +219,6 @@ mod test_layers { assert!(!e.has_layer("3")); assert!(e.valid_layers("1").has_layer("1")); assert!(!e.valid_layers("1").has_layer("2")); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } } diff --git a/raphtory/src/db/graph/views/node_subgraph.rs b/raphtory/src/db/graph/views/node_subgraph.rs index 9d9d0d71eb..19c5c07788 100644 --- a/raphtory/src/db/graph/views/node_subgraph.rs +++ b/raphtory/src/db/graph/views/node_subgraph.rs @@ -102,12 +102,10 @@ impl<'graph, G: GraphViewOps<'graph>> NodeFilterOps for NodeSubgraph { #[cfg(test)] mod subgraph_tests { use crate::{ - algorithms::motifs::triangle_count::triangle_count, db::api::view::StaticGraphViewOps, - prelude::*, + algorithms::motifs::triangle_count::triangle_count, prelude::*, test_storage, + test_utils::test_graph, }; use itertools::Itertools; - use std::fmt::Debug; - use tempfile::TempDir; #[test] fn test_materialize_no_edges() { @@ -116,19 +114,13 @@ mod subgraph_tests { graph.add_node(1, 1, NO_PROPS, None).unwrap(); graph.add_node(2, 2, NO_PROPS, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let sg = graph.subgraph([1, 2]); let actual = sg.materialize().unwrap().into_events().unwrap(); assert_eq!(actual, sg); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } #[test] @@ -162,19 +154,12 @@ mod subgraph_tests { for (src, dst, ts) in edges { graph.add_edge(ts, src, dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let subgraph = graph.subgraph(graph.nodes().into_iter().filter(|v| v.degree() > 1)); let ts = triangle_count(&subgraph, None); let tg = triangle_count(graph, None); assert_eq!(ts, tg) - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -183,20 +168,14 @@ mod subgraph_tests { graph.add_edge(0, 1, 2, NO_PROPS, Some("1")).unwrap(); graph.add_edge(0, 3, 4, NO_PROPS, Some("2")).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Needs multilayer support (Issue #47) + test_graph(&graph, |graph| { let sg = graph.subgraph([1, 2]); let sgm = sg.materialize().unwrap(); assert_eq!( sg.unique_layers().collect_vec(), sgm.unique_layers().collect_vec() ); - } - test(&graph); - // FIXME: Needs multilayer support (Issue #47) - // test(&disk_graph); + }); } } diff --git a/raphtory/src/db/graph/views/window_graph.rs b/raphtory/src/db/graph/views/window_graph.rs index ae557460c4..7d1eb67bc5 100644 --- a/raphtory/src/db/graph/views/window_graph.rs +++ b/raphtory/src/db/graph/views/window_graph.rs @@ -531,21 +531,19 @@ impl<'graph, G: GraphViewOps<'graph>> WindowedGraph { #[cfg(test)] mod views_test { + use super::*; + use crate::{ + algorithms::centrality::degree_centrality::degree_centrality, + db::graph::graph::assert_graph_equal, prelude::*, test_storage, test_utils::test_graph, + }; use itertools::Itertools; use quickcheck::TestResult; use quickcheck_macros::quickcheck; use rand::prelude::*; use rayon::prelude::*; + #[cfg(feature = "storage")] use tempfile::TempDir; - use crate::{ - algorithms::centrality::degree_centrality::degree_centrality, - db::{api::view::StaticGraphViewOps, graph::graph::assert_graph_equal}, - prelude::*, - }; - - use super::*; - #[test] fn windowed_graph_nodes_degree() { let vs = vec![ @@ -562,12 +560,7 @@ mod views_test { for (t, src, dst) in &vs { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let wg = graph.window(-1, 1); let actual = wg @@ -579,10 +572,7 @@ mod views_test { let expected = vec![(1, 2), (2, 1)]; assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -601,19 +591,11 @@ mod views_test { for (t, src, dst) in vs { graph.add_edge(t, src, dst, NO_PROPS, None).unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let wg = graph.window(i64::MIN, i64::MAX); assert_eq!(wg.edge(1, 3).unwrap().src().id(), 1); assert_eq!(wg.edge(1, 3).unwrap().dst().id(), 3); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -632,19 +614,11 @@ mod views_test { for (t, src, dst) in &vs { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let wg = graph.window(-1, 1); assert_eq!(wg.node(1).unwrap().id(), 1); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -666,17 +640,11 @@ mod views_test { .ok(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Issue #46: arrow_test(&graph, test) + test_graph(&graph, |graph| { let wg = graph.window(1, 2); assert!(!wg.has_node(262)) - } - test(&graph); - // FIXME: Issue #46 - // test(&disk_graph); + }); } #[quickcheck] @@ -817,6 +785,7 @@ mod views_test { } } + #[cfg(feature = "storage")] #[quickcheck] fn windowed_disk_graph_has_edge(mut edges: Vec<(i64, (u64, u64))>) -> TestResult { if edges.is_empty() { @@ -836,7 +805,6 @@ mod views_test { g.add_edge(*t, e.0, e.1, NO_PROPS, None).unwrap(); } let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] let g = g.persist_as_disk_graph(test_dir.path()).unwrap(); let start = edges.get(rand_start_index).expect("start index in range").0; @@ -945,11 +913,7 @@ mod views_test { graph.add_edge(*t, *src, *dst, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test1(graph: &G, args: &[(i64, i64)], expected: &[Vec]) { + test_storage!(&graph, |graph| { let res: Vec<_> = (0..=3) .map(|i| { let wg = graph.window(args[i].0, args[i].1); @@ -960,20 +924,13 @@ mod views_test { .collect_vec(); assert_eq!(res, expected); - } - test1(&graph, &args, &expected); - #[cfg(feature = "storage")] - test1(&disk_graph, &args, &expected); + }); let graph = Graph::new(); for (src, dst, t) in &vs { graph.add_edge(*src, *dst, *t, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test2(graph: &G, args: &[(i64, i64)], expected: &[Vec]) { + test_storage!(&graph, |graph| { let res: Vec<_> = (0..=3) .map(|i| { let wg = graph.window(args[i].0, args[i].1); @@ -983,10 +940,7 @@ mod views_test { }) .collect_vec(); assert_eq!(res, expected); - } - test2(&graph, &args, &expected); - #[cfg(feature = "storage")] - test2(&disk_graph, &args, &expected); + }); } #[test] @@ -1034,12 +988,7 @@ mod views_test { .add_edge(*t, *src, *dst, [("eprop", "commons")], None) .unwrap(); } - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let wg = graph.window(-2, 0); let actual = wg.nodes().id().collect::>(); @@ -1047,49 +996,32 @@ mod views_test { let expected = vec![1, 2]; assert_eq!(actual, expected); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] fn test_reference() { let graph = Graph::new(); graph.add_edge(0, 1, 2, NO_PROPS, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { let mut w = WindowedGraph::new(&graph, Some(0), Some(1)); assert_eq!(w, graph); w = WindowedGraph::new(&graph, Some(1), Some(2)); assert_eq!(w, Graph::new()); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] fn test_algorithm_on_windowed_graph() { let graph = Graph::new(); graph.add_edge(0, 1, 2, NO_PROPS, None).unwrap(); - - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + test_storage!(&graph, |graph| { let w = graph.window(0, 1); let res = degree_centrality(&w, None); println!("{:?}", res) - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1103,11 +1035,8 @@ mod views_test { graph.add_edge(t2, 2, 3, NO_PROPS, None).unwrap(); graph.add_edge(t3, 3, 1, NO_PROPS, None).unwrap(); } - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - fn test(graph: &G) { + test_storage!(&graph, |graph| { assert_graph_equal(&graph.before(9).after(2), &graph.window(3, 9)); let res = graph .window(3, 9) @@ -1122,10 +1051,7 @@ mod views_test { res, [[Some(3), Some(5)], [Some(3), Some(4)], [Some(5), Some(4)]] ); - } - test(&graph); - #[cfg(feature = "storage")] - test(&disk_graph); + }); } #[test] @@ -1144,11 +1070,8 @@ mod views_test { graph.add_edge(6, 1, 3, NO_PROPS, None).unwrap(); graph.add_edge(7, 1, 3, NO_PROPS, None).unwrap(); - let test_dir = TempDir::new().unwrap(); - #[cfg(feature = "storage")] - let _disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); - - fn test(graph: &G) { + // FIXME: Issue #46 + test_graph(&graph, |graph| { let e = graph.edge(1, 2).unwrap(); let v = graph.node(0).unwrap(); let full_history_1 = vec![0i64, 1, 2, 3]; @@ -1206,9 +1129,6 @@ mod views_test { .collect_vec(), [vec![], vec![0, 4], vec![0], vec![0],] ); - } - test(&graph); - // FIXME: Issue #46 - // test(&disk_graph); + }); } } diff --git a/raphtory/src/lib.rs b/raphtory/src/lib.rs index cc29983e9a..455f3ad28c 100644 --- a/raphtory/src/lib.rs +++ b/raphtory/src/lib.rs @@ -123,3 +123,31 @@ pub mod prelude { pub const BINCODE_VERSION: u32 = 1u32; #[cfg(feature = "storage")] pub use polars_arrow as arrow2; + +#[cfg(test)] +mod test_utils { + #[cfg(feature = "storage")] + use crate::disk_graph::graph_impl::DiskGraph; + use crate::prelude::Graph; + #[cfg(feature = "storage")] + use tempfile::TempDir; + + pub(crate) fn test_graph(graph: &Graph, test: impl FnOnce(&Graph)) { + test(graph) + } + + #[macro_export] + macro_rules! test_storage { + ($graph:expr, $test:expr) => { + $crate::test_utils::test_graph($graph, $test); + #[cfg(feature = "storage")] + $crate::test_utils::test_disk_graph($graph, $test); + }; + } + #[cfg(feature = "storage")] + pub(crate) fn test_disk_graph(graph: &Graph, test: impl FnOnce(&DiskGraph)) { + let test_dir = TempDir::new().unwrap(); + let disk_graph = graph.persist_as_disk_graph(test_dir.path()).unwrap(); + test(&disk_graph) + } +}