From c7a955e9fef5efd664cb3d06fb34b71c1e74f455 Mon Sep 17 00:00:00 2001 From: xphoniex Date: Wed, 8 Mar 2023 13:12:31 +0000 Subject: [PATCH] httpd: Run tests off another remote for `test::seed` Keep `test::contributor(..)` to test interactions with a contributor node. Signed-off-by: xphoniex --- radicle-httpd/Cargo.toml | 2 +- radicle-httpd/src/api/v1/projects.rs | 102 ++++++++++++++++----------- radicle-httpd/src/test.rs | 33 ++++++--- 3 files changed, 88 insertions(+), 49 deletions(-) diff --git a/radicle-httpd/Cargo.toml b/radicle-httpd/Cargo.toml index 619d0304..6f05ec6a 100644 --- a/radicle-httpd/Cargo.toml +++ b/radicle-httpd/Cargo.toml @@ -47,6 +47,6 @@ path = "../radicle-term" hyper = { version = "0.14.17", default-features = false, features = ["client"] } pretty_assertions = { version = "1.3.0" } radicle-cli = { path = "../radicle-cli" } -radicle-crypto = { path = "../radicle-crypto" } +radicle-crypto = { path = "../radicle-crypto", features = ["test"] } tempfile = { version = "3.3.0" } tower = { version = "0.4", features = ["util"] } diff --git a/radicle-httpd/src/api/v1/projects.rs b/radicle-httpd/src/api/v1/projects.rs index 19a0a071..11520f6c 100644 --- a/radicle-httpd/src/api/v1/projects.rs +++ b/radicle-httpd/src/api/v1/projects.rs @@ -618,11 +618,10 @@ mod routes { use serde_json::json; use crate::test::{ - self, get, patch, post, HEAD, HEAD_1, ISSUE_ID, PATCH_ID, SESSION_ID, TIMESTAMP, + self, get, patch, post, CONTRIBUTOR_ISSUE_ID, CONTRIBUTOR_PUB_KEY, CONTRIBUTOR_RID, HEAD, + HEAD_1, ISSUE_COMMENT_ID, ISSUE_DISCUSSION_ID, ISSUE_ID, PATCH_ID, SESSION_ID, TIMESTAMP, }; - const CREATED_ISSUE_ID: &str = "7596e4b788c37d633a8bd665e4d3a5a632c90eab"; - #[tokio::test] async fn test_projects_root() { let tmp = tempfile::tempdir().unwrap(); @@ -992,7 +991,11 @@ mod routes { async fn test_projects_remotes() { let tmp = tempfile::tempdir().unwrap(); let app = super::router(test::seed(tmp.path())); - let response = get(&app, "/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/remotes/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi").await; + let response = get( + &app, + "/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/remotes/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + ) + .await; assert_eq!(response.status(), StatusCode::OK); assert_eq!( @@ -1101,7 +1104,7 @@ mod routes { "assignees": [], "discussion": [ { - "id": "f0afe34f5bf4248df432f6b6a8818bcae360bbc2", + "id": ISSUE_DISCUSSION_ID, "author": { "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" }, @@ -1119,10 +1122,14 @@ mod routes { #[tokio::test] async fn test_projects_issues_create() { + const CREATED_ISSUE_ID: &str = "1b706bb9af971d43ec38718c71402e36055c5c89"; + let tmp = tempfile::tempdir().unwrap(); - let ctx = test::seed(tmp.path()); + let ctx = test::contributor(tmp.path()); let app = super::router(ctx.to_owned()); + test::create_session(ctx).await; + let body = serde_json::to_vec(&json!({ "title": "Issue #2", "description": "Change 'hello world' to 'hello everyone'", @@ -1130,9 +1137,10 @@ mod routes { "assignees": [], })) .unwrap(); + let response = post( &app, - "/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/issues", + format!("/projects/{CONTRIBUTOR_RID}/issues"), Some(Body::from(body)), Some(SESSION_ID.to_string()), ) @@ -1146,7 +1154,7 @@ mod routes { let response = get( &app, - format!("/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/issues/{CREATED_ISSUE_ID}"), + format!("/projects/{CONTRIBUTOR_RID}/issues/{CREATED_ISSUE_ID}"), ) .await; @@ -1155,7 +1163,7 @@ mod routes { json!({ "id": CREATED_ISSUE_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "assignees": [], "title": "Issue #2", @@ -1163,9 +1171,9 @@ mod routes { "status": "open", }, "discussion": [{ - "id": "f0afe34f5bf4248df432f6b6a8818bcae360bbc2", + "id": ISSUE_DISCUSSION_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "body": "Change 'hello world' to 'hello everyone'", "reactions": [], @@ -1182,9 +1190,11 @@ mod routes { #[tokio::test] async fn test_projects_issues_comment() { let tmp = tempfile::tempdir().unwrap(); - let ctx = test::seed(tmp.path()); + let ctx = test::contributor(tmp.path()); let app = super::router(ctx.to_owned()); + test::create_session(ctx).await; + let body = serde_json::to_vec(&json!({ "type": "thread", "action": { @@ -1193,9 +1203,10 @@ mod routes { } })) .unwrap(); + let response = patch( &app, - format!("/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/issues/{ISSUE_ID}"), + format!("/projects/{CONTRIBUTOR_RID}/issues/{CONTRIBUTOR_ISSUE_ID}"), Some(Body::from(body)), Some(SESSION_ID.to_string()), ) @@ -1206,16 +1217,16 @@ mod routes { let response = get( &app, - format!("/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/issues/{ISSUE_ID}"), + format!("/projects/{CONTRIBUTOR_RID}/issues/{CONTRIBUTOR_ISSUE_ID}"), ) .await; assert_eq!( response.json().await, json!({ - "id": ISSUE_ID, + "id": CONTRIBUTOR_ISSUE_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "assignees": [], "title": "Issue #1", @@ -1224,9 +1235,9 @@ mod routes { }, "discussion": [ { - "id": "f0afe34f5bf4248df432f6b6a8818bcae360bbc2", + "id": ISSUE_DISCUSSION_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "body": "Change 'hello world' to 'hello everyone'", "reactions": [], @@ -1234,9 +1245,9 @@ mod routes { "replyTo": null, }, { - "id": "f7da49e705f60c39265dbdd748d786a620bc8030", + "id": "265af21e409eacc8eb150b73882ac3ada9d4aea3", "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "body": "This is first-level comment", "reactions": [], @@ -1252,20 +1263,26 @@ mod routes { #[tokio::test] async fn test_projects_issues_reply() { let tmp = tempfile::tempdir().unwrap(); - let ctx = test::seed(tmp.path()); + let ctx = test::contributor(tmp.path()); let app = super::router(ctx.to_owned()); + test::create_session(ctx).await; + let body = serde_json::to_vec(&json!({ "type":"thread", "action": { "type": "comment", "body": "This is a reply to the first comment", - "replyTo": "f0afe34f5bf4248df432f6b6a8818bcae360bbc2", + "replyTo": ISSUE_DISCUSSION_ID, }})) .unwrap(); + + let response = get(&app, format!("/projects/{CONTRIBUTOR_RID}/issues")).await; + println!("{:?}", response.json().await); + let response = patch( &app, - format!("/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/issues/{ISSUE_ID}"), + format!("/projects/{CONTRIBUTOR_RID}/issues/{CONTRIBUTOR_ISSUE_ID}"), Some(Body::from(body)), Some(SESSION_ID.to_string()), ) @@ -1276,16 +1293,16 @@ mod routes { let response = get( &app, - format!("/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/issues/{ISSUE_ID}"), + format!("/projects/{CONTRIBUTOR_RID}/issues/{CONTRIBUTOR_ISSUE_ID}"), ) .await; assert_eq!( response.json().await, json!({ - "id": ISSUE_ID, + "id": CONTRIBUTOR_ISSUE_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "assignees": [], "title": "Issue #1", @@ -1294,9 +1311,9 @@ mod routes { }, "discussion": [ { - "id": "f0afe34f5bf4248df432f6b6a8818bcae360bbc2", + "id": ISSUE_DISCUSSION_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "body": "Change 'hello world' to 'hello everyone'", "reactions": [], @@ -1304,14 +1321,14 @@ mod routes { "replyTo": null, }, { - "id": "ab98b5b794d02c23d29769a39fe8e0b74624f3d8", + "id": ISSUE_COMMENT_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "id": CONTRIBUTOR_PUB_KEY, }, "body": "This is a reply to the first comment", "reactions": [], "timestamp": TIMESTAMP, - "replyTo": "f0afe34f5bf4248df432f6b6a8818bcae360bbc2", + "replyTo": ISSUE_DISCUSSION_ID, }, ], "tags": [], @@ -1341,7 +1358,7 @@ mod routes { "tags": [], "revisions": [ { - "id": "d6ba305f78e2fa1ebcc55d8c3be8806bbce25fb4", + "id": "47878ed82515772f4c44e4796c330f4a74473559", "description": "", "reviews": [], } @@ -1372,7 +1389,7 @@ mod routes { "tags": [], "revisions": [ { - "id": "d6ba305f78e2fa1ebcc55d8c3be8806bbce25fb4", + "id": "47878ed82515772f4c44e4796c330f4a74473559", "description": "", "reviews": [], } @@ -1384,10 +1401,14 @@ mod routes { #[tokio::test] async fn test_projects_create_patches() { + const CREATED_PATCH_ID: &str = "22f8fbe09f7430579dd0730e4f2394362d844647"; + let tmp = tempfile::tempdir().unwrap(); - let ctx = test::seed(tmp.path()); + let ctx = test::contributor(tmp.path()); let app = super::router(ctx.to_owned()); + test::create_session(ctx).await; + let body = serde_json::to_vec(&json!({ "title": "Update README", "description": "Do some changes to README", @@ -1396,9 +1417,10 @@ mod routes { "tags": [], })) .unwrap(); + let response = post( &app, - "/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/patches", + format!("/projects/{CONTRIBUTOR_RID}/patches"), Some(Body::from(body)), Some(SESSION_ID.to_string()), ) @@ -1410,14 +1432,14 @@ mod routes { json!( { "success": true, - "id": "48d6d96e1f80b3ccd5bd9675d407e09e7bbaa7ab", + "id": CREATED_PATCH_ID, } ) ); let response = get( &app, - "/projects/rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp/patches/48d6d96e1f80b3ccd5bd9675d407e09e7bbaa7ab", + format!("/projects/{CONTRIBUTOR_RID}/patches/{CREATED_PATCH_ID}"), ) .await; @@ -1426,9 +1448,9 @@ mod routes { response.json().await, json!( { - "id": "48d6d96e1f80b3ccd5bd9675d407e09e7bbaa7ab", + "id": CREATED_PATCH_ID, "author": { - "id": "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" + "id": CONTRIBUTOR_PUB_KEY }, "title": "Update README", "description": "Do some changes to README", @@ -1437,7 +1459,7 @@ mod routes { "tags": [], "revisions": [ { - "id": "a65512fc3b8ee7ec50f053c40266538fa11b82dd", + "id": "73efc59cd9f787deff0ae1629f47f1d90f307282", "description": "", "reviews": [], } diff --git a/radicle-httpd/src/test.rs b/radicle-httpd/src/test.rs index 31de2929..2c5214dc 100644 --- a/radicle-httpd/src/test.rs +++ b/radicle-httpd/src/test.rs @@ -15,20 +15,33 @@ use radicle::cob::issue::Issues; use radicle::cob::patch::{MergeTarget, Patches}; use radicle::git::{raw as git2, RefString}; use radicle::storage::ReadStorage; -use radicle_crypto::ssh::keystore::MemorySigner; +use radicle_crypto::test::signer::MockSigner; use crate::api::{auth, Context}; pub const HEAD: &str = "1e978d19f251cd9821d9d9a76d1bd436bf0690d5"; pub const HEAD_1: &str = "f604ce9fd5b7cc77b7609beda45ea8760bee78f7"; -pub const PATCH_ID: &str = "3cccb7ac7325215731c62c9c5aef2ec51ba91317"; -pub const ISSUE_ID: &str = "dc368184c379a7802c78b729ed631d2712ce22ab"; +pub const PATCH_ID: &str = "73d5187bb38835a232ce6ff41102a94bb92e5130"; +pub const ISSUE_ID: &str = "959afe03c1dbea4f47462bb7824584a78741f59c"; +pub const ISSUE_DISCUSSION_ID: &str = "e2874702515026daf62d4385cafb88fef1fad0c8"; +pub const ISSUE_COMMENT_ID: &str = "905d72c1f13f282f86cb93ce9f7eb9464a08ba79"; pub const SESSION_ID: &str = "u9MGAkkfkMOv0uDDB2WeUHBT7HbsO2Dy"; pub const TIMESTAMP: u64 = 1671125284; +pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG"; +pub const CONTRIBUTOR_PUB_KEY: &str = "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8"; +pub const CONTRIBUTOR_ISSUE_ID: &str = "b991ccfa866e164b81a4aa0a7e082357b6c75306"; const PASSWORD: &str = "radicle"; pub fn seed(dir: &Path) -> Context { + seed_with_signer(dir, false) +} + +pub fn contributor(dir: &Path) -> Context { + seed_with_signer(dir, true) +} + +fn seed_with_signer(dir: &Path, self_signer: bool) -> Context { let workdir = dir.join("hello-world"); let rad_home = dir.join("radicle"); @@ -36,7 +49,7 @@ pub fn seed(dir: &Path) -> Context { env::set_var("RAD_PASSPHRASE", PASSWORD); env::set_var( "RAD_SEED", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee", ); fs::create_dir_all(&workdir).unwrap(); @@ -86,13 +99,19 @@ pub fn seed(dir: &Path) -> Context { let profile = radicle::Profile::init(rad_home.try_into().unwrap(), PASSWORD.to_owned()).unwrap(); + let mock_signer = MockSigner::from_seed([0xff; 32]); + // rad init let repo = git2::Repository::open(&workdir).unwrap(); let name = "hello-world".to_string(); let description = "Rad repository for tests".to_string(); - let signer = profile.signer().unwrap(); + let signer = if self_signer { + profile.signer().unwrap() + } else { + Box::new(mock_signer) + }; let branch = RefString::try_from("master").unwrap(); - radicle::rad::init( + let (id, _, _) = radicle::rad::init( &repo, &name, &description, @@ -102,9 +121,7 @@ pub fn seed(dir: &Path) -> Context { ) .unwrap(); - let signer = MemorySigner::load(&profile.keystore, PASSWORD.to_owned().into()).unwrap(); let storage = &profile.storage; - let (_, id) = radicle::rad::repo(&workdir).unwrap(); let repo = storage.repository(id).unwrap(); let mut issues = Issues::open(&repo).unwrap(); issues