diff --git a/Cargo.lock b/Cargo.lock index c969579f..1f901107 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3432,6 +3432,7 @@ dependencies = [ "mews_integrity", "regex", "serde", + "serial_test", "thiserror", "tokio", "trust_atom_types", @@ -5329,6 +5330,31 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serial_test" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" +dependencies = [ + "dashmap 5.3.4", + "futures", + "lazy_static", + "log", + "parking_lot 0.12.1", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + [[package]] name = "sha-1" version = "0.9.8" diff --git a/dnas/clutter/coordinator_zomes/mews/Cargo.toml b/dnas/clutter/coordinator_zomes/mews/Cargo.toml index 3297dbbe..fe2a5af7 100644 --- a/dnas/clutter/coordinator_zomes/mews/Cargo.toml +++ b/dnas/clutter/coordinator_zomes/mews/Cargo.toml @@ -23,3 +23,4 @@ hdk = {version = "0.1", features = ["encoding"]} holochain = { version = "=0.1.3", default-features = false, features = [ "test_utils" ] } tokio = { version = "1.3", features = ["full"] } futures = { version = "0.3.1", default-features = false } +serial_test = "*" diff --git a/dnas/clutter/coordinator_zomes/mews/src/lib.rs b/dnas/clutter/coordinator_zomes/mews/src/lib.rs index 673425f9..a9e56c46 100644 --- a/dnas/clutter/coordinator_zomes/mews/src/lib.rs +++ b/dnas/clutter/coordinator_zomes/mews/src/lib.rs @@ -343,17 +343,12 @@ pub fn recommended(input: RecommendedInput) -> ExternResult> { .into_iter() .filter_map(|feed_mew| { let allowed_age = core::time::Duration::new(oldest_mew_seconds, 0); - let oldest_allowed = input.now - allowed_age; - - match oldest_allowed { - Ok(oldest_allowed) => { - if feed_mew.action.timestamp() >= oldest_allowed { - Some(feed_mew) - } else { - None - } - } - Err(_) => None, + let oldest_allowed = input.now.saturating_sub(&allowed_age); + + if feed_mew.action.timestamp() >= oldest_allowed { + Some(feed_mew) + } else { + None } }) .collect(); diff --git a/dnas/clutter/coordinator_zomes/mews/tests/mews_tests.rs b/dnas/clutter/coordinator_zomes/mews/tests/mews_tests.rs index 3d1694de..8b00fd18 100644 --- a/dnas/clutter/coordinator_zomes/mews/tests/mews_tests.rs +++ b/dnas/clutter/coordinator_zomes/mews/tests/mews_tests.rs @@ -1,5 +1,7 @@ #![warn(warnings)] +use serial_test::serial; + use hdk::prelude::*; use holochain::conductor::config::ConductorConfig; use holochain::sweettest::{ @@ -13,6 +15,8 @@ const DNA_FILEPATH: &str = "../../workdir/clutter.dna"; const ZOME_NAME: &str = "mews"; #[tokio::test(flavor = "multi_thread")] +#[serial] + async fn trusted_feed_is_based_on_follow_topics() { let mut agent_group = setup().await; let agents = agent_group.create_agents().await; @@ -75,65 +79,175 @@ async fn trusted_feed_is_based_on_follow_topics() { ); } -// #[tokio::test(flavor = "multi_thread")] -// async fn trusted_feed_is_filtered_by_recency() { -// let mut agent_group = setup().await; -// let agents = agent_group.create_agents().await; -// let ann = &agents[0]; -// let bob = &agents[1]; - -// ann.follow(FollowInput { -// agent: bob.pubkey.clone(), -// follow_topics: vec![FollowTopicInput { -// topic: String::from("holochain"), -// weight: String::from("0.9"), -// }], -// follow_other: false, -// }) -// .await; - -// bob.create_mew(CreateMewInput { -// mew_type: MewType::Original, -// text: Some(String::from("OLD #holochain mew")), -// links: None, -// }) -// .await; - -// let oldest_mew_seconds = 2; -// // Idiomatic sleep: -// // std::thread::sleep(std::time::Duration::from_secs(oldest_mew_seconds)); - -// // CI friendly sleep?? -// let sleep_duration = std::time::Duration::from_secs(oldest_mew_seconds); -// let start_time = std::time::Instant::now(); -// while std::time::Instant::now().duration_since(start_time) < sleep_duration { -// // Do nothing, just busy waiting -// } - -// bob.create_mew(CreateMewInput { -// mew_type: MewType::Original, -// text: Some(String::from("NEW #holochain mew")), -// links: None, -// }) -// .await; - -// consistency_10s([&(ann.cell.clone()), &(bob.cell.clone())]).await; - -// let recommended_feed = ann -// .recommended(RecommendedInput { -// now: Timestamp::now(), -// oldest_mew_seconds: Some(oldest_mew_seconds), -// }) -// .await; - -// assert_eq!(recommended_feed.len(), 1); -// assert_eq!( -// recommended_feed[0].mew.content.as_ref().unwrap().text, -// String::from("NEW #holochain mew") -// ); -// } +#[tokio::test(flavor = "multi_thread")] +#[serial] + +async fn trusted_feed_is_filtered_by_recency() { + let mut agent_group = setup().await; + let agents = agent_group.create_agents().await; + let ann = &agents[0]; + let bob = &agents[1]; + + ann.follow(FollowInput { + agent: bob.pubkey.clone(), + follow_topics: vec![FollowTopicInput { + topic: String::from("holochain"), + weight: String::from("0.9"), + }], + follow_other: false, + }) + .await; + + bob.create_mew(CreateMewInput { + mew_type: MewType::Original, + text: Some(String::from("OLD #holochain mew")), + links: None, + }) + .await; + + let oldest_mew_seconds = 2; + // Idiomatic sleep: + std::thread::sleep(std::time::Duration::from_secs(oldest_mew_seconds)); + + bob.create_mew(CreateMewInput { + mew_type: MewType::Original, + text: Some(String::from("NEW #holochain mew")), + links: None, + }) + .await; + + consistency_10s([&(ann.cell.clone()), &(bob.cell.clone())]).await; + + let recommended_feed = ann + .recommended(RecommendedInput { + now: Timestamp::now(), + oldest_mew_seconds: Some(oldest_mew_seconds), + }) + .await; + + assert_eq!(recommended_feed.len(), 1); + assert_eq!( + recommended_feed[0].mew.content.as_ref().unwrap().text, + String::from("NEW #holochain mew") + ); +} + +#[tokio::test(flavor = "multi_thread")] +#[serial] + +async fn trusted_feed_is_ordered_by_topic_weights() { + let mut agent_group = setup().await; + let agents = agent_group.create_agents().await; + let ann = &agents[0]; + let bob = &agents[1]; + let cat = &agents[2]; + + ann.follow(FollowInput { + agent: bob.pubkey.clone(), + follow_topics: vec![FollowTopicInput { + topic: String::from("holochain"), + weight: String::from("1.0"), + }], + follow_other: false, + }) + .await; + + ann.follow(FollowInput { + agent: cat.pubkey.clone(), + follow_topics: vec![FollowTopicInput { + topic: String::from("holochain"), + weight: String::from("0.5"), + }], + follow_other: false, + }) + .await; + + ann.follow(FollowInput { + agent: bob.pubkey.clone(), + follow_topics: vec![FollowTopicInput { + topic: String::from("blockchain"), + weight: String::from("0.25"), + }], + follow_other: false, + }) + .await; + + ann.follow(FollowInput { + agent: cat.pubkey.clone(), + follow_topics: vec![FollowTopicInput { + topic: String::from("blockchain"), + weight: String::from("0"), + }], + follow_other: false, + }) + .await; + + bob.create_mew(CreateMewInput { + mew_type: MewType::Original, + text: Some(String::from("#holochain from bob, weight 1.0")), + links: None, + }) + .await; + + bob.create_mew(CreateMewInput { + mew_type: MewType::Original, + text: Some(String::from("#blockchain from bob, weight 0.25")), + links: None, + }) + .await; + + cat.create_mew(CreateMewInput { + mew_type: MewType::Original, + text: Some(String::from("#blockchain from cat, weight 0.0")), + links: None, + }) + .await; + + cat.create_mew(CreateMewInput { + mew_type: MewType::Original, + text: Some(String::from("#holochain from cat, weight 0.5")), + links: None, + }) + .await; + + consistency_10s([ + &(ann.cell.clone()), + &(bob.cell.clone()), + &(cat.cell.clone()), + ]) + .await; + + let recommended_feed = ann + .recommended(RecommendedInput { + now: Timestamp::now(), + oldest_mew_seconds: Some(60 * 60), // last hour + }) + .await; + + assert_eq!(recommended_feed.len(), 4); + // assert_eq!( + // recommended_feed[0].mew.content.as_ref().unwrap().text, + // String::from("#holochain from bob, weight 1.0") + // ); + // assert_eq!( + // recommended_feed[1].mew.content.as_ref().unwrap().text, + // String::from("#holochain from cat, weight 0.5") + // ); + // assert_eq!( + // recommended_feed[2].mew.content.as_ref().unwrap().text, + // String::from("#blockchain from bob, weight 0.25") + // ); + // assert_eq!( + // recommended_feed[3].mew.content.as_ref().unwrap().text, + // String::from("#blockchain from cat, weight 0.0") + // ); +} -// TEST HELPERS: +// +// ^^^ TESTS: ^^^ +// +// vvv TEST HELPERS: vvv +// pub struct Agent<'a> { pub cell: SweetCell,