From 7c789a1c0659ec2e997143dc4561d372057a0bc2 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 1 Dec 2023 12:11:19 +0100 Subject: [PATCH] tests are running with temp db --- Cargo.lock | 85 ++++++++++++++ Cargo.toml | 1 + migrations/2023-11-28-150402_article/up.sql | 4 +- src/api.rs | 7 +- src/federation/mod.rs | 19 +-- src/lib.rs | 40 +++++-- src/main.rs | 3 +- tests/common.rs | 78 ++++++++----- tests/scripts/start_dev_db.sh | 26 +++++ tests/scripts/stop_dev_db.sh | 9 ++ tests/test.rs | 121 +++++++++++--------- 11 files changed, 280 insertions(+), 113 deletions(-) create mode 100755 tests/scripts/start_dev_db.sh create mode 100755 tests/scripts/stop_dev_db.sh diff --git a/Cargo.lock b/Cargo.lock index dee9f1c..44d501a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -529,6 +529,17 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "diesel_migrations" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6036b3f0120c5961381b570ee20a02432d7e2d27ea60de9578799cf9156914ac" +dependencies = [ + "diesel", + "migrations_internals", + "migrations_macros", +] + [[package]] name = "diesel_table_macro_syntax" version = "0.1.0" @@ -669,6 +680,7 @@ dependencies = [ "chrono", "diesel", "diesel-derive-newtype", + "diesel_migrations", "diffy", "enum_delegate", "env_logger", @@ -1194,6 +1206,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "migrations_internals" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f23f71580015254b020e856feac3df5878c2c7a8812297edd6c0a485ac9dada" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "migrations_macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce3325ac70e67bbab5bd837a31cae01f1a6db64e0e744a33cb03a543469ef08" +dependencies = [ + "migrations_internals", + "proc-macro2", + "quote", +] + [[package]] name = "mime" version = "0.3.17" @@ -1810,6 +1843,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2100,6 +2142,40 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -2467,6 +2543,15 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "winnow" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/Cargo.toml b/Cargo.toml index 53fff7c..548609b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ axum-macros = "0.3.8" chrono = { version = "0.4.31", features = ["serde"] } diesel = {version = "2.1.4", features = ["postgres"] } diesel-derive-newtype = "2.1.0" +diesel_migrations = "2.1.0" diffy = "0.3.0" enum_delegate = "0.2.0" env_logger = { version = "0.10.1", default-features = false } diff --git a/migrations/2023-11-28-150402_article/up.sql b/migrations/2023-11-28-150402_article/up.sql index 675fecf..b9be3e7 100644 --- a/migrations/2023-11-28-150402_article/up.sql +++ b/migrations/2023-11-28-150402_article/up.sql @@ -2,7 +2,7 @@ create table article ( id serial primary key, title text not null, text text not null, - ap_id varchar(255) not null, + ap_id varchar(255) not null unique, instance_id varchar(255) not null, latest_version text not null, local bool not null @@ -10,7 +10,7 @@ create table article ( create table edit ( id serial primary key, - ap_id varchar(255) not null, + ap_id varchar(255) not null unique, diff text not null, article_id int REFERENCES article ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, version text not null, diff --git a/src/api.rs b/src/api.rs index 5f45d81..46d22b6 100644 --- a/src/api.rs +++ b/src/api.rs @@ -45,10 +45,12 @@ async fn create_article( data: Data, Form(create_article): Form, ) -> MyResult> { + dbg!(1); let existing_article = DbArticle::read_local_title(&create_article.title, &data.db_connection); if existing_article.is_ok() { return Err(anyhow!("A local article with this title already exists").into()); } + dbg!(2); let instance_id = data.local_instance().ap_id; let ap_id = ObjectId::parse(&format!( @@ -66,9 +68,12 @@ async fn create_article( instance_id, local: true, }; - let article = DbArticle::create(&form, &data.db_connection)?; + dbg!(3); + let article = dbg!(DbArticle::create(&form, &data.db_connection))?; + dbg!(4); CreateArticle::send_to_followers(article.clone(), &data).await?; + dbg!(5); Ok(Json(article)) } diff --git a/src/federation/mod.rs b/src/federation/mod.rs index 6cec4ac..6b73d00 100644 --- a/src/federation/mod.rs +++ b/src/federation/mod.rs @@ -1,8 +1,6 @@ -use crate::database::{FakeDatabase, MyData, MyDataHandle}; +use crate::database::FakeDatabase; use crate::error::Error; -use crate::establish_db_connection; use crate::federation::objects::instance::DbInstance; -use activitypub_federation::config::FederationConfig; use activitypub_federation::fetch::collection_id::CollectionId; use activitypub_federation::http_signatures::generate_actor_keypair; use chrono::Local; @@ -14,7 +12,7 @@ pub mod activities; pub mod objects; pub mod routes; -pub async fn federation_config(hostname: &str) -> Result, Error> { +pub async fn create_fake_db(hostname: &str) -> Result, Error> { let ap_id = Url::parse(&format!("http://{}", hostname))?; let articles_id = CollectionId::parse(&format!("http://{}/all_articles", hostname))?; let inbox = Url::parse(&format!("http://{}/inbox", hostname))?; @@ -37,16 +35,5 @@ pub async fn federation_config(hostname: &str) -> Result MyResult<()> { - let config = federation_config(hostname).await?; +const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations"); + +pub async fn start(hostname: &str, database_url: &str) -> MyResult<()> { + let fake_db = create_fake_db(hostname).await?; + + dbg!(database_url); + let db_connection = Arc::new(Mutex::new(PgConnection::establish(database_url)?)); + db_connection + .lock() + .unwrap() + .run_pending_migrations(MIGRATIONS) + .unwrap(); + + let data = MyData { + db_connection, + fake_db, + }; + let config = FederationConfig::builder() + .domain(hostname) + .app_data(data) + .debug(true) + .build() + .await?; info!("Listening with axum on {hostname}"); let config = config.clone(); @@ -36,9 +62,3 @@ pub async fn start(hostname: &str) -> MyResult<()> { Ok(()) } - -pub fn establish_db_connection() -> MyResult { - // TODO: read from config file - let database_url = "postgres://fediwiki:password@localhost:5432/fediwiki"; - Ok(PgConnection::establish(&database_url)?) -} diff --git a/src/main.rs b/src/main.rs index 3f81a0c..531d586 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ pub async fn main() -> MyResult<()> { .filter_module("activitypub_federation", LevelFilter::Info) .filter_module("fediwiki", LevelFilter::Info) .init(); - start("localhost:8131").await?; + let database_url = "postgres://fediwiki:password@localhost:5432/fediwiki"; + start("localhost:8131", &database_url).await?; Ok(()) } diff --git a/tests/common.rs b/tests/common.rs index aebe0dc..194e77c 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -9,6 +9,8 @@ use once_cell::sync::Lazy; use reqwest::Client; use serde::de::Deserialize; use serde::ser::Serialize; +use std::env::current_dir; +use std::process::{Command, Stdio}; use std::sync::Once; use tokio::task::JoinHandle; use tracing::log::LevelFilter; @@ -17,12 +19,9 @@ use url::Url; pub static CLIENT: Lazy = Lazy::new(Client::new); pub struct TestData { - pub hostname_alpha: &'static str, - pub hostname_beta: &'static str, - pub hostname_gamma: &'static str, - handle_alpha: JoinHandle<()>, - handle_beta: JoinHandle<()>, - handle_gamma: JoinHandle<()>, + pub alpha: Instance, + pub beta: Instance, + pub gamma: Instance, } impl TestData { @@ -36,36 +35,61 @@ impl TestData { .init(); }); - let hostname_alpha = "localhost:8131"; - let hostname_beta = "localhost:8132"; - let hostname_gamma = "localhost:8133"; - let handle_alpha = tokio::task::spawn(async { - start(hostname_alpha).await.unwrap(); - }); - let handle_beta = tokio::task::spawn(async { - start(hostname_beta).await.unwrap(); - }); - let handle_gamma = tokio::task::spawn(async { - start(hostname_gamma).await.unwrap(); - }); Self { - hostname_alpha, - hostname_beta, - hostname_gamma, - handle_alpha, - handle_beta, - handle_gamma, + alpha: Instance::start("alpha", 8131), + beta: Instance::start("beta", 8132), + gamma: Instance::start("gamma", 8133), } } pub fn stop(self) -> MyResult<()> { - self.handle_alpha.abort(); - self.handle_beta.abort(); - self.handle_gamma.abort(); + self.alpha.stop(); + self.beta.stop(); + self.gamma.stop(); Ok(()) } } +pub struct Instance { + db_path: String, + pub hostname: String, + handle: JoinHandle<()>, +} + +impl Instance { + fn start(name: &'static str, port: i32) -> Self { + let db_path = format!("{}/target/test_db/{name}", current_dir().unwrap().display()); + // TODO: would be faster to use async Command from tokio and run in parallel + Command::new("./tests/scripts/start_dev_db.sh") + .arg(&db_path) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .output() + .unwrap(); + let db_url = format!("postgresql://lemmy:password@/lemmy?host={db_path}"); + let hostname = format!("localhost:{port}"); + let hostname_ = hostname.clone(); + let handle = tokio::task::spawn(async move { + start(&hostname_, &db_url).await.unwrap(); + }); + Self { + db_path, + hostname, + handle, + } + } + + fn stop(self) { + self.handle.abort(); + Command::new("./tests/scripts/stop_dev_db.sh") + .arg(&self.db_path) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .output() + .unwrap(); + } +} + pub const TEST_ARTICLE_DEFAULT_TEXT: &str = "some\nexample\ntext\n"; pub async fn create_article(hostname: &str, title: String) -> MyResult { diff --git a/tests/scripts/start_dev_db.sh b/tests/scripts/start_dev_db.sh new file mode 100755 index 0000000..86980a6 --- /dev/null +++ b/tests/scripts/start_dev_db.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +export PGHOST=$1 +export PGDATA="$1/dev_pgdata" + +# If cluster exists, stop the server and delete the cluster +if [ -d $PGDATA ] +then + # Prevent `stop` from failing if server already stopped + pg_ctl restart > /dev/null + pg_ctl stop + rm -rf $PGDATA +fi + +# Create cluster +initdb --username=postgres --auth=trust --no-instructions + +#touch "$PGHOST/.s.PGSQL.5432" + +# Start server that only listens to socket in current directory +pg_ctl start --options="-c listen_addresses= -c unix_socket_directories=$PGHOST" + +# Setup database +psql -c "CREATE USER lemmy WITH PASSWORD 'password' SUPERUSER;" -U postgres +psql -c "CREATE DATABASE lemmy WITH OWNER lemmy;" -U postgres diff --git a/tests/scripts/stop_dev_db.sh b/tests/scripts/stop_dev_db.sh new file mode 100755 index 0000000..a052f4f --- /dev/null +++ b/tests/scripts/stop_dev_db.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +export PGHOST=$1 +export PGDATA="$1/dev_pgdata" +echo $PGHOST + +pg_ctl stop +rm -rf $PGDATA \ No newline at end of file diff --git a/tests/test.rs b/tests/test.rs index a9c666d..4c28628 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -24,18 +24,18 @@ async fn test_create_read_and_edit_article() -> MyResult<()> { // create article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_alpha, title.clone()).await?; + let create_res = create_article(&data.alpha.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); // now article can be read - let get_res = get_article(data.hostname_alpha, create_res.article.id).await?; + let get_res = get_article(&data.alpha.hostname, create_res.article.id).await?; assert_eq!(title, get_res.article.title); assert_eq!(TEST_ARTICLE_DEFAULT_TEXT, get_res.article.text); assert!(get_res.article.local); // error on article which wasnt federated - let not_found = get_article(data.hostname_beta, create_res.article.id).await; + let not_found = get_article(&data.beta.hostname, create_res.article.id).await; assert!(not_found.is_err()); // edit article @@ -45,7 +45,7 @@ async fn test_create_read_and_edit_article() -> MyResult<()> { previous_version: get_res.article.latest_version, resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; assert_eq!(edit_form.new_text, edit_res.article.text); assert_eq!(2, edit_res.edits.len()); @@ -53,7 +53,7 @@ async fn test_create_read_and_edit_article() -> MyResult<()> { query: title.clone(), }; let search_res: Vec = - get_query(data.hostname_alpha, "search", Some(search_form)).await?; + get_query(&data.alpha.hostname, "search", Some(search_form)).await?; assert_eq!(1, search_res.len()); assert_eq!(edit_res.article, search_res[0]); @@ -67,11 +67,11 @@ async fn test_create_duplicate_article() -> MyResult<()> { // create article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_alpha, title.clone()).await?; + let create_res = create_article(&data.alpha.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); - let create_res = create_article(data.hostname_alpha, title.clone()).await; + let create_res = create_article(&data.alpha.hostname, title.clone()).await; assert!(create_res.is_err()); data.stop() @@ -83,22 +83,23 @@ async fn test_follow_instance() -> MyResult<()> { let data = TestData::start(); // check initial state - let alpha_instance: DbInstance = get(data.hostname_alpha, "instance").await?; + let alpha_instance: DbInstance = get(&data.alpha.hostname, "instance").await?; assert_eq!(0, alpha_instance.follows.len()); - let beta_instance: DbInstance = get(data.hostname_beta, "instance").await?; + let beta_instance: DbInstance = get(&data.beta.hostname, "instance").await?; assert_eq!(0, beta_instance.followers.len()); - follow_instance(data.hostname_alpha, data.hostname_beta).await?; + follow_instance(&data.alpha.hostname, &data.beta.hostname).await?; // check that follow was federated - let beta_instance: DbInstance = get(data.hostname_beta, "instance").await?; + let beta_instance: DbInstance = get(&data.beta.hostname, "instance").await?; assert_eq!(1, beta_instance.followers.len()); - let alpha_instance: DbInstance = get(data.hostname_alpha, "instance").await?; + let alpha_instance: DbInstance = get(&data.alpha.hostname, "instance").await?; assert_eq!(1, alpha_instance.follows.len()); data.stop() } + #[tokio::test] #[serial] async fn test_synchronize_articles() -> MyResult<()> { @@ -106,7 +107,7 @@ async fn test_synchronize_articles() -> MyResult<()> { // create article on alpha let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_alpha, title.clone()).await?; + let create_res = create_article(&data.alpha.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert_eq!(1, create_res.edits.len()); assert!(create_res.article.local); @@ -118,21 +119,25 @@ async fn test_synchronize_articles() -> MyResult<()> { previous_version: create_res.article.latest_version, resolve_conflict_id: None, }; - edit_article(data.hostname_alpha, &edit_form).await?; + edit_article(&data.alpha.hostname, &edit_form).await?; // article is not yet on beta - let get_res = get_article(data.hostname_beta, create_res.article.id).await; + let get_res = get_article(&data.beta.hostname, create_res.article.id).await; assert!(get_res.is_err()); // fetch alpha instance on beta, articles are also fetched automatically let resolve_object = ResolveObject { - id: Url::parse(&format!("http://{}", data.hostname_alpha))?, + id: Url::parse(&format!("http://{}", &data.alpha.hostname))?, }; - get_query::(data.hostname_beta, "resolve_instance", Some(resolve_object)) - .await?; + get_query::( + &data.beta.hostname, + "resolve_instance", + Some(resolve_object), + ) + .await?; // get the article and compare - let get_res = get_article(data.hostname_beta, create_res.article.id).await?; + let get_res = get_article(&data.beta.hostname, create_res.article.id).await?; assert_eq!(create_res.article.ap_id, get_res.article.ap_id); assert_eq!(title, get_res.article.title); assert_eq!(2, get_res.edits.len()); @@ -147,16 +152,16 @@ async fn test_synchronize_articles() -> MyResult<()> { async fn test_edit_local_article() -> MyResult<()> { let data = TestData::start(); - follow_instance(data.hostname_alpha, data.hostname_beta).await?; + follow_instance(&data.alpha.hostname, &data.beta.hostname).await?; // create new article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_beta, title.clone()).await?; + let create_res = create_article(&data.beta.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); // article should be federated to alpha - let get_res = get_article(data.hostname_alpha, create_res.article.id).await?; + let get_res = get_article(&data.alpha.hostname, create_res.article.id).await?; assert_eq!(create_res.article.title, get_res.article.title); assert_eq!(1, get_res.edits.len()); assert!(!get_res.article.local); @@ -169,7 +174,7 @@ async fn test_edit_local_article() -> MyResult<()> { previous_version: get_res.article.latest_version, resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_beta, &edit_form).await?; + let edit_res = edit_article(&data.beta.hostname, &edit_form).await?; assert_eq!(edit_res.article.text, edit_form.new_text); assert_eq!(edit_res.edits.len(), 2); assert!(edit_res.edits[0] @@ -178,7 +183,7 @@ async fn test_edit_local_article() -> MyResult<()> { .starts_with(&edit_res.article.ap_id.to_string())); // edit should be federated to alpha - let get_res = get_article(data.hostname_alpha, edit_res.article.id).await?; + let get_res = get_article(&data.alpha.hostname, edit_res.article.id).await?; assert_eq!(edit_res.article.title, get_res.article.title); assert_eq!(edit_res.edits.len(), 2); assert_eq!(edit_res.article.text, get_res.article.text); @@ -191,22 +196,22 @@ async fn test_edit_local_article() -> MyResult<()> { async fn test_edit_remote_article() -> MyResult<()> { let data = TestData::start(); - follow_instance(data.hostname_alpha, data.hostname_beta).await?; - follow_instance(data.hostname_gamma, data.hostname_beta).await?; + follow_instance(&data.alpha.hostname, &data.beta.hostname).await?; + follow_instance(&data.gamma.hostname, &data.beta.hostname).await?; // create new article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_beta, title.clone()).await?; + let create_res = create_article(&data.beta.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); // article should be federated to alpha and gamma - let get_res = get_article(data.hostname_alpha, create_res.article.id).await?; + let get_res = get_article(&data.alpha.hostname, create_res.article.id).await?; assert_eq!(create_res.article.title, get_res.article.title); assert_eq!(1, get_res.edits.len()); assert!(!get_res.article.local); - let get_res = get_article(data.hostname_gamma, create_res.article.id).await?; + let get_res = get_article(&data.gamma.hostname, create_res.article.id).await?; assert_eq!(create_res.article.title, get_res.article.title); assert_eq!(create_res.article.text, get_res.article.text); @@ -216,7 +221,7 @@ async fn test_edit_remote_article() -> MyResult<()> { previous_version: get_res.article.latest_version, resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; assert_eq!(edit_form.new_text, edit_res.article.text); assert_eq!(2, edit_res.edits.len()); assert!(!edit_res.article.local); @@ -226,12 +231,12 @@ async fn test_edit_remote_article() -> MyResult<()> { .starts_with(&edit_res.article.ap_id.to_string())); // edit should be federated to beta and gamma - let get_res = get_article(data.hostname_alpha, create_res.article.id).await?; + let get_res = get_article(&data.alpha.hostname, create_res.article.id).await?; assert_eq!(edit_res.article.title, get_res.article.title); assert_eq!(edit_res.edits.len(), 2); assert_eq!(edit_res.article.text, get_res.article.text); - let get_res = get_article(data.hostname_gamma, create_res.article.id).await?; + let get_res = get_article(&data.gamma.hostname, create_res.article.id).await?; assert_eq!(edit_res.article.title, get_res.article.title); assert_eq!(edit_res.edits.len(), 2); assert_eq!(edit_res.article.text, get_res.article.text); @@ -246,7 +251,7 @@ async fn test_local_edit_conflict() -> MyResult<()> { // create new article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_alpha, title.clone()).await?; + let create_res = create_article(&data.alpha.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); @@ -257,7 +262,7 @@ async fn test_local_edit_conflict() -> MyResult<()> { previous_version: create_res.article.latest_version.clone(), resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; assert_eq!(edit_res.article.text, edit_form.new_text); assert_eq!(2, edit_res.edits.len()); @@ -268,13 +273,13 @@ async fn test_local_edit_conflict() -> MyResult<()> { previous_version: create_res.article.latest_version, resolve_conflict_id: None, }; - let edit_res = edit_article_with_conflict(data.hostname_alpha, &edit_form) + let edit_res = edit_article_with_conflict(&data.alpha.hostname, &edit_form) .await? .unwrap(); assert_eq!("<<<<<<< ours\nIpsum Lorem\n||||||| original\nsome\nexample\ntext\n=======\nLorem Ipsum\n>>>>>>> theirs\n", edit_res.three_way_merge); let conflicts: Vec = - get_query(data.hostname_alpha, "edit_conflicts", None::<()>).await?; + get_query(&data.alpha.hostname, "edit_conflicts", None::<()>).await?; assert_eq!(1, conflicts.len()); assert_eq!(conflicts[0], edit_res); @@ -284,11 +289,11 @@ async fn test_local_edit_conflict() -> MyResult<()> { previous_version: edit_res.previous_version, resolve_conflict_id: Some(edit_res.id), }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; assert_eq!(edit_form.new_text, edit_res.article.text); let conflicts: Vec = - get_query(data.hostname_alpha, "edit_conflicts", None::<()>).await?; + get_query(&data.alpha.hostname, "edit_conflicts", None::<()>).await?; assert_eq!(0, conflicts.len()); data.stop() @@ -299,11 +304,11 @@ async fn test_local_edit_conflict() -> MyResult<()> { async fn test_federated_edit_conflict() -> MyResult<()> { let data = TestData::start(); - follow_instance(data.hostname_alpha, data.hostname_beta).await?; + follow_instance(&data.alpha.hostname, &data.beta.hostname).await?; // create new article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_beta, title.clone()).await?; + let create_res = create_article(&data.beta.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); @@ -311,8 +316,12 @@ async fn test_federated_edit_conflict() -> MyResult<()> { let resolve_object = ResolveObject { id: create_res.article.ap_id.inner().clone(), }; - let resolve_res: DbArticle = - get_query(data.hostname_gamma, "resolve_article", Some(resolve_object)).await?; + let resolve_res: DbArticle = get_query( + &data.gamma.hostname, + "resolve_article", + Some(resolve_object), + ) + .await?; assert_eq!(create_res.article.text, resolve_res.text); // alpha edits article @@ -322,7 +331,7 @@ async fn test_federated_edit_conflict() -> MyResult<()> { previous_version: create_res.article.latest_version.clone(), resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; assert_eq!(edit_res.article.text, edit_form.new_text); assert_eq!(2, edit_res.edits.len()); assert!(!edit_res.article.local); @@ -339,13 +348,13 @@ async fn test_federated_edit_conflict() -> MyResult<()> { previous_version: create_res.article.latest_version, resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_gamma, &edit_form).await?; + let edit_res = edit_article(&data.gamma.hostname, &edit_form).await?; assert_ne!(edit_form.new_text, edit_res.article.text); assert_eq!(2, edit_res.edits.len()); assert!(!edit_res.article.local); let conflicts: Vec = - get_query(data.hostname_gamma, "edit_conflicts", None::<()>).await?; + get_query(&data.gamma.hostname, "edit_conflicts", None::<()>).await?; assert_eq!(1, conflicts.len()); // resolve the conflict @@ -355,12 +364,12 @@ async fn test_federated_edit_conflict() -> MyResult<()> { previous_version: conflicts[0].previous_version.clone(), resolve_conflict_id: Some(conflicts[0].id), }; - let edit_res = edit_article(data.hostname_gamma, &edit_form).await?; + let edit_res = edit_article(&data.gamma.hostname, &edit_form).await?; assert_eq!(edit_form.new_text, edit_res.article.text); assert_eq!(3, edit_res.edits.len()); let conflicts: Vec = - get_query(data.hostname_gamma, "edit_conflicts", None::<()>).await?; + get_query(&data.gamma.hostname, "edit_conflicts", None::<()>).await?; assert_eq!(0, conflicts.len()); data.stop() @@ -373,7 +382,7 @@ async fn test_overlapping_edits_no_conflict() -> MyResult<()> { // create new article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_alpha, title.clone()).await?; + let create_res = create_article(&data.alpha.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); @@ -384,7 +393,7 @@ async fn test_overlapping_edits_no_conflict() -> MyResult<()> { previous_version: create_res.article.latest_version.clone(), resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; assert_eq!(edit_res.article.text, edit_form.new_text); assert_eq!(2, edit_res.edits.len()); @@ -395,9 +404,9 @@ async fn test_overlapping_edits_no_conflict() -> MyResult<()> { previous_version: create_res.article.latest_version, resolve_conflict_id: None, }; - let edit_res = edit_article(data.hostname_alpha, &edit_form).await?; + let edit_res = edit_article(&data.alpha.hostname, &edit_form).await?; let conflicts: Vec = - get_query(data.hostname_alpha, "edit_conflicts", None::<()>).await?; + get_query(&data.alpha.hostname, "edit_conflicts", None::<()>).await?; assert_eq!(0, conflicts.len()); assert_eq!(3, edit_res.edits.len()); assert_eq!("my\nexample\narticle\n", edit_res.article.text); @@ -412,7 +421,7 @@ async fn test_fork_article() -> MyResult<()> { // create article let title = "Manu_Chao".to_string(); - let create_res = create_article(data.hostname_alpha, title.clone()).await?; + let create_res = create_article(&data.alpha.hostname, title.clone()).await?; assert_eq!(title, create_res.article.title); assert!(create_res.article.local); @@ -421,7 +430,7 @@ async fn test_fork_article() -> MyResult<()> { id: create_res.article.ap_id.into_inner(), }; let resolve_res: ArticleView = - get_query(data.hostname_beta, "resolve_article", Some(resolve_object)).await?; + get_query(&data.beta.hostname, "resolve_article", Some(resolve_object)).await?; let resolved_article = resolve_res.article; assert_eq!(create_res.edits.len(), resolve_res.edits.len()); @@ -429,7 +438,7 @@ async fn test_fork_article() -> MyResult<()> { let fork_form = ForkArticleData { article_id: resolved_article.id, }; - let fork_res: ArticleView = post(data.hostname_beta, "article/fork", &fork_form).await?; + let fork_res: ArticleView = post(&data.beta.hostname, "article/fork", &fork_form).await?; let forked_article = fork_res.article; assert_eq!(resolved_article.title, forked_article.title); assert_eq!(resolved_article.text, forked_article.text); @@ -441,7 +450,7 @@ async fn test_fork_article() -> MyResult<()> { assert_ne!(resolved_article.ap_id, forked_article.ap_id); assert!(forked_article.local); - let beta_instance: DbInstance = get(data.hostname_beta, "instance").await?; + let beta_instance: DbInstance = get(&data.beta.hostname, "instance").await?; assert_eq!(forked_article.instance_id, beta_instance.ap_id); // now search returns two articles for this title (original and forked) @@ -449,7 +458,7 @@ async fn test_fork_article() -> MyResult<()> { query: title.clone(), }; let search_res: Vec = - get_query(data.hostname_beta, "search", Some(search_form)).await?; + get_query(&data.beta.hostname, "search", Some(search_form)).await?; assert_eq!(2, search_res.len()); data.stop()