From ece6ce26d11a2a9d7062c6d96ac8d22446e87b68 Mon Sep 17 00:00:00 2001 From: vandomej Date: Mon, 8 Sep 2025 16:40:57 -0700 Subject: [PATCH] Getting additional test coverage --- gemla/src/core/genetic_node.rs | 45 +++++++++++++++++++++ gemla/src/core/mod.rs | 73 ++++++++++++++++++++++++++++++++++ gemla/src/error.rs | 69 ++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) diff --git a/gemla/src/core/genetic_node.rs b/gemla/src/core/genetic_node.rs index abcb15f..6bc550d 100644 --- a/gemla/src/core/genetic_node.rs +++ b/gemla/src/core/genetic_node.rs @@ -325,4 +325,49 @@ mod tests { Ok(()) } + + #[test] + fn test_take_some() -> Result<(), Error> { + let val = TestState { + score: 5.0, + max_generations: 10, + }; + let uuid = Uuid::new_v4(); + let mut genetic_node = GeneticNodeWrapper::from(val.clone(), uuid); + + let taken = genetic_node.take(); + assert_eq!(taken, Some(val)); + assert!(genetic_node.as_ref().is_none()); + + Ok(()) + } + + #[test] + fn test_take_none() -> Result<(), Error> { + let mut genetic_node = GeneticNodeWrapper::::new(); + assert!(genetic_node.take().is_none()); + assert!(genetic_node.as_ref().is_none()); + + Ok(()) + } + + #[test] + fn test_generation_default() -> Result<(), Error> { + let genetic_node = GeneticNodeWrapper::::new(); + assert_eq!(genetic_node.generation(), 1); + Ok(()) + } + + #[test] + fn test_generation_custom() -> Result<(), Error> { + let val = TestState { + score: 2.0, + max_generations: 10, + }; + let uuid = Uuid::new_v4(); + let mut genetic_node = GeneticNodeWrapper::from(val, uuid); + genetic_node.generation = 42; + assert_eq!(genetic_node.generation(), 42); + Ok(()) + } } diff --git a/gemla/src/core/mod.rs b/gemla/src/core/mod.rs index d3de3f3..e57e50b 100644 --- a/gemla/src/core/mod.rs +++ b/gemla/src/core/mod.rs @@ -561,4 +561,77 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_tree_ref_returns_arc_rwlock() -> Result<(), Error> { + use std::path::PathBuf; + let path = PathBuf::from("test_tree_ref"); + + // Use `spawn_blocking` to run the synchronous closure that internally awaits async code. + tokio::task::spawn_blocking(move || { + let rt = tokio::runtime::Runtime::new().unwrap(); + super::tests::CleanUp::new(&path).run(move |p| { + rt.block_on(async { + let config = GemlaConfig { overwrite: true }; + let gemla = Gemla::::new(&p, config, DataFormat::Json).await?; + let arc_rwlock = gemla.tree_ref(); + + // Check that the returned value is an Arc> + let data = arc_rwlock.read().await; + assert!(data.0.is_none()); + assert_eq!(data.1.overwrite, true); + + Ok(()) + }) + }) + }) + .await + .unwrap()?; // Wait for the blocking task to complete, then handle the Result. + + Ok(()) + } + + #[tokio::test] + async fn test_merge_completed_nodes_merges_children() -> Result<(), Error> { + // Create two finished child nodes with different scores + let left_state = TestState { score: 10.0, max_generations: 10 }; + let right_state = TestState { score: 20.0, max_generations: 10 }; + let left_id = Uuid::new_v4(); + let right_id = Uuid::new_v4(); + + // Use the public constructor + let mut left_node = GeneticNodeWrapper::from(left_state.clone(), left_id); + let mut right_node = GeneticNodeWrapper::from(right_state.clone(), right_id); + + // Set state to Finish using the process_node method (simulate processing) + while left_node.state() != GeneticState::Finish { + left_node.process_node(()).await?; + } + + while right_node.state() != GeneticState::Finish { + right_node.process_node(()).await?; + } + + // Create tree nodes + let left = Box::new(crate::tree::Tree::new(left_node, None, None)); + let right = Box::new(crate::tree::Tree::new(right_node, None, None)); + + // Use GeneticNodeWrapper::new() for the parent node (node: None, state: Initialize) + let parent_node = GeneticNodeWrapper::new(); + // Set the correct id for the parent node (if needed for your logic) + // If you need to set the id, you may need to add a setter or constructor for testing. + + let mut tree = Box::new(crate::tree::Tree::new(parent_node, Some(left), Some(right))); + + // Call merge_completed_nodes + Gemla::::merge_completed_nodes(&mut tree, ()).await?; + + // After merging, parent should contain the right_node's data (since right.score > left.score) + let merged = &tree.val; + let merged_score = merged.as_ref().unwrap().score; + // Score plus max generations because simulate adds 1.0 to score for each generation + assert_eq!(merged_score, 30.0); + + Ok(()) + } } diff --git a/gemla/src/error.rs b/gemla/src/error.rs index 3b8b6a7..638d5bb 100644 --- a/gemla/src/error.rs +++ b/gemla/src/error.rs @@ -32,3 +32,72 @@ pub fn log_error(result: Result) -> Result { e }) } + +#[cfg(test)] +mod tests { + use super::*; + use std::io; + use anyhow::anyhow; + + // Re-import the dummy error for test scope + use file_linked::error as fle; + + #[test] + fn test_error_from_file_linked_other() { + let anyhow_err = anyhow!("test anyhow"); + let fle_err = fle::Error::Other(anyhow_err); + let err = Error::from(fle_err); + match err { + Error::Other(e) => assert_eq!(e.to_string(), "test anyhow"), + _ => panic!("Expected Error::Other"), + } + } + + #[test] + fn test_error_from_file_linked_non_other() { + let io_err = io::Error::new(io::ErrorKind::Other, "io error"); + let fle_err = fle::Error::IO(io_err); + let err = Error::from(fle_err); + match err { + Error::FileLinked(_) => (), + _ => panic!("Expected Error::FileLinked"), + } + } + + #[test] + fn test_error_from_io() { + let io_err = io::Error::new(io::ErrorKind::NotFound, "not found"); + let err = Error::from(io_err); + match err { + Error::IO(e) => assert_eq!(e.kind(), io::ErrorKind::NotFound), + _ => panic!("Expected Error::IO"), + } + } + + #[test] + fn test_error_from_anyhow() { + let anyhow_err = anyhow!("anyhow error"); + let err = Error::Other(anyhow_err); + match err { + Error::Other(e) => assert_eq!(e.to_string(), "anyhow error"), + _ => panic!("Expected Error::Other"), + } + } + + #[test] + fn test_log_error_ok() { + let result: Result = Ok(42); + let logged = log_error(result); + assert_eq!(logged.unwrap(), 42); + } + + #[test] + fn test_log_error_err() { + // Use a simple error for this test + let io_err = io::Error::new(io::ErrorKind::Other, "fail"); + let err = Error::IO(io_err); + let result: Result = Err(err); + let logged = log_error(result); + assert!(logged.is_err()); + } +} \ No newline at end of file