diff options
| -rw-r--r-- | Cargo.lock | 97 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | tests/git_remote_nostr/main.rs | 13 | ||||
| -rw-r--r-- | tests/git_remote_nostr/push.rs | 470 | ||||
| -rw-r--r-- | tests/ngit_init.rs | 360 |
5 files changed, 484 insertions, 457 deletions
| @@ -748,6 +748,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 748 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" | 748 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" |
| 749 | 749 | ||
| 750 | [[package]] | 750 | [[package]] |
| 751 | name = "futures-timer" | ||
| 752 | version = "3.0.3" | ||
| 753 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 754 | checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" | ||
| 755 | |||
| 756 | [[package]] | ||
| 751 | name = "futures-util" | 757 | name = "futures-util" |
| 752 | version = "0.3.31" | 758 | version = "0.3.31" |
| 753 | source = "registry+https://github.com/rust-lang/crates.io-index" | 759 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -816,6 +822,12 @@ dependencies = [ | |||
| 816 | ] | 822 | ] |
| 817 | 823 | ||
| 818 | [[package]] | 824 | [[package]] |
| 825 | name = "glob" | ||
| 826 | version = "0.3.3" | ||
| 827 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 828 | checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" | ||
| 829 | |||
| 830 | [[package]] | ||
| 819 | name = "gloo-timers" | 831 | name = "gloo-timers" |
| 820 | version = "0.3.0" | 832 | version = "0.3.0" |
| 821 | source = "registry+https://github.com/rust-lang/crates.io-index" | 833 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1455,6 +1467,7 @@ dependencies = [ | |||
| 1455 | "passwords", | 1467 | "passwords", |
| 1456 | "qrcode", | 1468 | "qrcode", |
| 1457 | "reqwest", | 1469 | "reqwest", |
| 1470 | "rstest", | ||
| 1458 | "scrypt", | 1471 | "scrypt", |
| 1459 | "serde", | 1472 | "serde", |
| 1460 | "serde_json", | 1473 | "serde_json", |
| @@ -1860,6 +1873,15 @@ dependencies = [ | |||
| 1860 | ] | 1873 | ] |
| 1861 | 1874 | ||
| 1862 | [[package]] | 1875 | [[package]] |
| 1876 | name = "proc-macro-crate" | ||
| 1877 | version = "3.4.0" | ||
| 1878 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1879 | checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" | ||
| 1880 | dependencies = [ | ||
| 1881 | "toml_edit", | ||
| 1882 | ] | ||
| 1883 | |||
| 1884 | [[package]] | ||
| 1863 | name = "proc-macro-hack" | 1885 | name = "proc-macro-hack" |
| 1864 | version = "0.5.20+deprecated" | 1886 | version = "0.5.20+deprecated" |
| 1865 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1887 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2035,6 +2057,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 2035 | checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" | 2057 | checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" |
| 2036 | 2058 | ||
| 2037 | [[package]] | 2059 | [[package]] |
| 2060 | name = "relative-path" | ||
| 2061 | version = "1.9.3" | ||
| 2062 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2063 | checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" | ||
| 2064 | |||
| 2065 | [[package]] | ||
| 2038 | name = "reqwest" | 2066 | name = "reqwest" |
| 2039 | version = "0.12.24" | 2067 | version = "0.12.24" |
| 2040 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2068 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2101,6 +2129,36 @@ dependencies = [ | |||
| 2101 | ] | 2129 | ] |
| 2102 | 2130 | ||
| 2103 | [[package]] | 2131 | [[package]] |
| 2132 | name = "rstest" | ||
| 2133 | version = "0.23.0" | ||
| 2134 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2135 | checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" | ||
| 2136 | dependencies = [ | ||
| 2137 | "futures", | ||
| 2138 | "futures-timer", | ||
| 2139 | "rstest_macros", | ||
| 2140 | "rustc_version", | ||
| 2141 | ] | ||
| 2142 | |||
| 2143 | [[package]] | ||
| 2144 | name = "rstest_macros" | ||
| 2145 | version = "0.23.0" | ||
| 2146 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2147 | checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" | ||
| 2148 | dependencies = [ | ||
| 2149 | "cfg-if", | ||
| 2150 | "glob", | ||
| 2151 | "proc-macro-crate", | ||
| 2152 | "proc-macro2", | ||
| 2153 | "quote", | ||
| 2154 | "regex", | ||
| 2155 | "relative-path", | ||
| 2156 | "rustc_version", | ||
| 2157 | "syn", | ||
| 2158 | "unicode-ident", | ||
| 2159 | ] | ||
| 2160 | |||
| 2161 | [[package]] | ||
| 2104 | name = "rustc_version" | 2162 | name = "rustc_version" |
| 2105 | version = "0.4.1" | 2163 | version = "0.4.1" |
| 2106 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2164 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2760,6 +2818,36 @@ dependencies = [ | |||
| 2760 | ] | 2818 | ] |
| 2761 | 2819 | ||
| 2762 | [[package]] | 2820 | [[package]] |
| 2821 | name = "toml_datetime" | ||
| 2822 | version = "0.7.3" | ||
| 2823 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2824 | checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" | ||
| 2825 | dependencies = [ | ||
| 2826 | "serde_core", | ||
| 2827 | ] | ||
| 2828 | |||
| 2829 | [[package]] | ||
| 2830 | name = "toml_edit" | ||
| 2831 | version = "0.23.7" | ||
| 2832 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2833 | checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" | ||
| 2834 | dependencies = [ | ||
| 2835 | "indexmap", | ||
| 2836 | "toml_datetime", | ||
| 2837 | "toml_parser", | ||
| 2838 | "winnow", | ||
| 2839 | ] | ||
| 2840 | |||
| 2841 | [[package]] | ||
| 2842 | name = "toml_parser" | ||
| 2843 | version = "1.0.4" | ||
| 2844 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2845 | checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" | ||
| 2846 | dependencies = [ | ||
| 2847 | "winnow", | ||
| 2848 | ] | ||
| 2849 | |||
| 2850 | [[package]] | ||
| 2763 | name = "tower" | 2851 | name = "tower" |
| 2764 | version = "0.5.2" | 2852 | version = "0.5.2" |
| 2765 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2853 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -3359,6 +3447,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 3359 | checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" | 3447 | checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" |
| 3360 | 3448 | ||
| 3361 | [[package]] | 3449 | [[package]] |
| 3450 | name = "winnow" | ||
| 3451 | version = "0.7.13" | ||
| 3452 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 3453 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" | ||
| 3454 | dependencies = [ | ||
| 3455 | "memchr", | ||
| 3456 | ] | ||
| 3457 | |||
| 3458 | [[package]] | ||
| 3362 | name = "wit-bindgen" | 3459 | name = "wit-bindgen" |
| 3363 | version = "0.46.0" | 3460 | version = "0.46.0" |
| 3364 | source = "registry+https://github.com/rust-lang/crates.io-index" | 3461 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -44,6 +44,7 @@ zeroize = "1.8.1" | |||
| 44 | assert_cmd = "2.0.17" | 44 | assert_cmd = "2.0.17" |
| 45 | mockall = "0.13.1" | 45 | mockall = "0.13.1" |
| 46 | once_cell = "1.21.3" | 46 | once_cell = "1.21.3" |
| 47 | rstest = "0.23" | ||
| 47 | serial_test = "3.2.0" | 48 | serial_test = "3.2.0" |
| 48 | test_utils = { path = "test_utils" } | 49 | test_utils = { path = "test_utils" } |
| 49 | 50 | ||
diff --git a/tests/git_remote_nostr/main.rs b/tests/git_remote_nostr/main.rs index fc541f8..4a17934 100644 --- a/tests/git_remote_nostr/main.rs +++ b/tests/git_remote_nostr/main.rs | |||
| @@ -13,6 +13,19 @@ mod fetch; | |||
| 13 | mod list; | 13 | mod list; |
| 14 | mod push; | 14 | mod push; |
| 15 | 15 | ||
| 16 | // Scenario result structs - hold immutable state from expensive setup | ||
| 17 | // operations | ||
| 18 | |||
| 19 | #[derive(Clone)] | ||
| 20 | pub struct TwoBranchesScenario { | ||
| 21 | pub main_commit_id: String, | ||
| 22 | pub vnext_commit_id: String, | ||
| 23 | pub main_on_server: bool, | ||
| 24 | pub vnext_on_server: bool, | ||
| 25 | pub main_remote_ref_matches: bool, | ||
| 26 | pub vnext_remote_ref_matches: bool, | ||
| 27 | } | ||
| 28 | |||
| 16 | static NOSTR_REMOTE_NAME: &str = "nostr"; | 29 | static NOSTR_REMOTE_NAME: &str = "nostr"; |
| 17 | static STATE_KIND: nostr::Kind = Kind::Custom(30618); | 30 | static STATE_KIND: nostr::Kind = Kind::Custom(30618); |
| 18 | 31 | ||
diff --git a/tests/git_remote_nostr/push.rs b/tests/git_remote_nostr/push.rs index 2afadf9..91a20d8 100644 --- a/tests/git_remote_nostr/push.rs +++ b/tests/git_remote_nostr/push.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use git2::Signature; | 1 | use git2::Signature; |
| 2 | use rstest::*; | ||
| 2 | 3 | ||
| 3 | use super::*; | 4 | use super::*; |
| 4 | 5 | ||
| @@ -12,19 +13,30 @@ mod two_branches_in_batch_one_added_one_updated { | |||
| 12 | 13 | ||
| 13 | use super::*; | 14 | use super::*; |
| 14 | 15 | ||
| 15 | #[tokio::test] | 16 | // Fixture that runs expensive setup once and captures all verification data |
| 16 | #[serial] | 17 | #[fixture] |
| 17 | async fn updates_branch_on_git_server() -> Result<()> { | 18 | async fn scenario() -> TwoBranchesScenario { |
| 18 | let git_repo = prep_git_repo()?; | 19 | let git_repo = prep_git_repo().expect("failed to prep git repo"); |
| 19 | let source_git_repo = GitTestRepo::recreate_as_bare(&git_repo)?; | 20 | let source_git_repo = |
| 21 | GitTestRepo::recreate_as_bare(&git_repo).expect("failed to create bare git repo"); | ||
| 20 | 22 | ||
| 21 | std::fs::write(git_repo.dir.join("commit.md"), "some content")?; | 23 | std::fs::write(git_repo.dir.join("commit.md"), "some content") |
| 22 | let main_commit_id = git_repo.stage_and_commit("commit.md")?; | 24 | .expect("failed to write commit.md"); |
| 25 | let main_commit_id = git_repo | ||
| 26 | .stage_and_commit("commit.md") | ||
| 27 | .expect("failed to commit main"); | ||
| 23 | 28 | ||
| 24 | git_repo.create_branch("vnext")?; | 29 | git_repo |
| 25 | git_repo.checkout("vnext")?; | 30 | .create_branch("vnext") |
| 26 | std::fs::write(git_repo.dir.join("vnext.md"), "some content")?; | 31 | .expect("failed to create vnext branch"); |
| 27 | let vnext_commit_id = git_repo.stage_and_commit("vnext.md")?; | 32 | git_repo |
| 33 | .checkout("vnext") | ||
| 34 | .expect("failed to checkout vnext"); | ||
| 35 | std::fs::write(git_repo.dir.join("vnext.md"), "some content") | ||
| 36 | .expect("failed to write vnext.md"); | ||
| 37 | let vnext_commit_id = git_repo | ||
| 38 | .stage_and_commit("vnext.md") | ||
| 39 | .expect("failed to commit vnext"); | ||
| 28 | 40 | ||
| 29 | let events = vec![ | 41 | let events = vec![ |
| 30 | generate_test_key_1_metadata_event("fred"), | 42 | generate_test_key_1_metadata_event("fred"), |
| @@ -37,6 +49,7 @@ mod two_branches_in_batch_one_added_one_updated { | |||
| 37 | &TEST_KEY_2_KEYS, | 49 | &TEST_KEY_2_KEYS, |
| 38 | ), | 50 | ), |
| 39 | ]; | 51 | ]; |
| 52 | |||
| 40 | // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57) | 53 | // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57) |
| 41 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | 54 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( |
| 42 | Relay::new(8051, None, None), | 55 | Relay::new(8051, None, None), |
| @@ -49,12 +62,10 @@ mod two_branches_in_batch_one_added_one_updated { | |||
| 49 | r51.events = events.clone(); | 62 | r51.events = events.clone(); |
| 50 | r55.events = events; | 63 | r55.events = events; |
| 51 | 64 | ||
| 52 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 65 | let main_commit_id_clone = main_commit_id; |
| 53 | assert_ne!( | 66 | let vnext_commit_id_clone = vnext_commit_id; |
| 54 | source_git_repo.get_tip_of_local_branch("main")?, | ||
| 55 | main_commit_id | ||
| 56 | ); | ||
| 57 | 67 | ||
| 68 | let cli_tester_handle = std::thread::spawn(move || -> Result<(bool, bool, bool, bool)> { | ||
| 58 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo)?; | 69 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo)?; |
| 59 | 70 | ||
| 60 | p.send_line("push refs/heads/main:refs/heads/main")?; | 71 | p.send_line("push refs/heads/main:refs/heads/main")?; |
| @@ -66,19 +77,35 @@ mod two_branches_in_batch_one_added_one_updated { | |||
| 66 | relay::shutdown_relay(8000 + p)?; | 77 | relay::shutdown_relay(8000 + p)?; |
| 67 | } | 78 | } |
| 68 | 79 | ||
| 69 | assert_eq!( | 80 | // Capture verification data |
| 70 | source_git_repo.get_tip_of_local_branch("main")?, | 81 | let main_on_server = |
| 71 | main_commit_id | 82 | source_git_repo.get_tip_of_local_branch("main")? == main_commit_id_clone; |
| 72 | ); | 83 | let vnext_on_server = |
| 73 | 84 | source_git_repo.get_tip_of_local_branch("vnext")? == vnext_commit_id_clone; | |
| 74 | assert_eq!( | 85 | |
| 75 | source_git_repo.get_tip_of_local_branch("vnext")?, | 86 | let main_remote_ref_matches = git_repo |
| 76 | vnext_commit_id | 87 | .git_repo |
| 77 | ); | 88 | .find_reference("refs/remotes/nostr/main")? |
| 78 | 89 | .peel_to_commit()? | |
| 79 | Ok(()) | 90 | .id() |
| 91 | == main_commit_id_clone; | ||
| 92 | |||
| 93 | let vnext_remote_ref_matches = git_repo | ||
| 94 | .git_repo | ||
| 95 | .find_reference("refs/remotes/nostr/vnext")? | ||
| 96 | .peel_to_commit()? | ||
| 97 | .id() | ||
| 98 | == vnext_commit_id_clone; | ||
| 99 | |||
| 100 | Ok(( | ||
| 101 | main_on_server, | ||
| 102 | vnext_on_server, | ||
| 103 | main_remote_ref_matches, | ||
| 104 | vnext_remote_ref_matches, | ||
| 105 | )) | ||
| 80 | }); | 106 | }); |
| 81 | // launch relays | 107 | |
| 108 | // Launch relays | ||
| 82 | let _ = join!( | 109 | let _ = join!( |
| 83 | r51.listen_until_close(), | 110 | r51.listen_until_close(), |
| 84 | r52.listen_until_close(), | 111 | r52.listen_until_close(), |
| @@ -87,97 +114,54 @@ mod two_branches_in_batch_one_added_one_updated { | |||
| 87 | r56.listen_until_close(), | 114 | r56.listen_until_close(), |
| 88 | r57.listen_until_close(), | 115 | r57.listen_until_close(), |
| 89 | ); | 116 | ); |
| 90 | cli_tester_handle.join().unwrap()?; | 117 | |
| 91 | Ok(()) | 118 | let (main_on_server, vnext_on_server, main_remote_ref_matches, vnext_remote_ref_matches) = |
| 119 | cli_tester_handle | ||
| 120 | .join() | ||
| 121 | .unwrap() | ||
| 122 | .expect("cli tester failed"); | ||
| 123 | |||
| 124 | TwoBranchesScenario { | ||
| 125 | main_commit_id: main_commit_id.to_string(), | ||
| 126 | vnext_commit_id: vnext_commit_id.to_string(), | ||
| 127 | main_on_server, | ||
| 128 | vnext_on_server, | ||
| 129 | main_remote_ref_matches, | ||
| 130 | vnext_remote_ref_matches, | ||
| 131 | } | ||
| 92 | } | 132 | } |
| 93 | 133 | ||
| 134 | #[rstest] | ||
| 94 | #[tokio::test] | 135 | #[tokio::test] |
| 95 | #[serial] | 136 | #[serial] |
| 96 | async fn remote_refs_updated_in_local_git() -> Result<()> { | 137 | async fn updates_branch_on_git_server(#[future] scenario: TwoBranchesScenario) -> Result<()> { |
| 97 | let git_repo = prep_git_repo()?; | 138 | let s = scenario.await; |
| 98 | let source_git_repo = GitTestRepo::recreate_as_bare(&git_repo)?; | 139 | assert!( |
| 99 | 140 | s.main_on_server, | |
| 100 | std::fs::write(git_repo.dir.join("commit.md"), "some content")?; | 141 | "main branch should be updated on git server" |
| 101 | let main_commit_id = git_repo.stage_and_commit("commit.md")?; | ||
| 102 | |||
| 103 | git_repo.create_branch("vnext")?; | ||
| 104 | git_repo.checkout("vnext")?; | ||
| 105 | std::fs::write(git_repo.dir.join("vnext.md"), "some content")?; | ||
| 106 | let vnext_commit_id = git_repo.stage_and_commit("vnext.md")?; | ||
| 107 | |||
| 108 | let events = vec![ | ||
| 109 | generate_test_key_1_metadata_event("fred"), | ||
| 110 | generate_test_key_1_relay_list_event(), | ||
| 111 | generate_repo_ref_event_with_git_server(vec![ | ||
| 112 | source_git_repo.dir.to_str().unwrap().to_string(), | ||
| 113 | ]), | ||
| 114 | generate_repo_ref_event_with_git_server_with_keys( | ||
| 115 | vec![source_git_repo.dir.to_str().unwrap().to_string()], | ||
| 116 | &TEST_KEY_2_KEYS, | ||
| 117 | ), | ||
| 118 | ]; | ||
| 119 | // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57) | ||
| 120 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | ||
| 121 | Relay::new(8051, None, None), | ||
| 122 | Relay::new(8052, None, None), | ||
| 123 | Relay::new(8053, None, None), | ||
| 124 | Relay::new(8055, None, None), | ||
| 125 | Relay::new(8056, None, None), | ||
| 126 | Relay::new(8057, None, None), | ||
| 127 | ); | 142 | ); |
| 128 | r51.events = events.clone(); | 143 | assert!( |
| 129 | r55.events = events; | 144 | s.vnext_on_server, |
| 130 | 145 | "vnext branch should be updated on git server" | |
| 131 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 146 | ); |
| 132 | assert_ne!( | 147 | Ok(()) |
| 133 | source_git_repo.get_tip_of_local_branch("main")?, | 148 | } |
| 134 | main_commit_id | ||
| 135 | ); | ||
| 136 | |||
| 137 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo)?; | ||
| 138 | p.send_line("push refs/heads/main:refs/heads/main")?; | ||
| 139 | p.send_line("push refs/heads/vnext:refs/heads/vnext")?; | ||
| 140 | p.send_line("")?; | ||
| 141 | p.expect_eventually("\r\n\r\n")?; | ||
| 142 | p.exit()?; | ||
| 143 | for p in [51, 52, 53, 55, 56, 57] { | ||
| 144 | relay::shutdown_relay(8000 + p)?; | ||
| 145 | } | ||
| 146 | |||
| 147 | assert_eq!( | ||
| 148 | git_repo | ||
| 149 | .git_repo | ||
| 150 | .find_reference("refs/remotes/nostr/main")? | ||
| 151 | .peel_to_commit()? | ||
| 152 | .id(), | ||
| 153 | main_commit_id, | ||
| 154 | ); | ||
| 155 | |||
| 156 | assert_eq!( | ||
| 157 | git_repo | ||
| 158 | .git_repo | ||
| 159 | .find_reference("refs/remotes/nostr/vnext")? | ||
| 160 | .peel_to_commit()? | ||
| 161 | .id(), | ||
| 162 | vnext_commit_id | ||
| 163 | ); | ||
| 164 | 149 | ||
| 165 | p.exit()?; | 150 | #[rstest] |
| 166 | for p in [51, 52, 53, 55, 56, 57] { | 151 | #[tokio::test] |
| 167 | relay::shutdown_relay(8000 + p)?; | 152 | #[serial] |
| 168 | } | 153 | async fn remote_refs_updated_in_local_git( |
| 169 | Ok(()) | 154 | #[future] scenario: TwoBranchesScenario, |
| 170 | }); | 155 | ) -> Result<()> { |
| 171 | // launch relays | 156 | let s = scenario.await; |
| 172 | let _ = join!( | 157 | assert!( |
| 173 | r51.listen_until_close(), | 158 | s.main_remote_ref_matches, |
| 174 | r52.listen_until_close(), | 159 | "main remote ref should match commit" |
| 175 | r53.listen_until_close(), | 160 | ); |
| 176 | r55.listen_until_close(), | 161 | assert!( |
| 177 | r56.listen_until_close(), | 162 | s.vnext_remote_ref_matches, |
| 178 | r57.listen_until_close(), | 163 | "vnext remote ref should match commit" |
| 179 | ); | 164 | ); |
| 180 | cli_tester_handle.join().unwrap()?; | ||
| 181 | Ok(()) | 165 | Ok(()) |
| 182 | } | 166 | } |
| 183 | 167 | ||
| @@ -465,96 +449,32 @@ mod delete_one_branch { | |||
| 465 | 449 | ||
| 466 | use super::*; | 450 | use super::*; |
| 467 | 451 | ||
| 468 | #[tokio::test] | 452 | // Scenario struct - holds only cloneable verification data from expensive setup |
| 469 | #[serial] | 453 | #[derive(Clone)] |
| 470 | async fn deletes_branch_on_git_server() -> Result<()> { | 454 | struct DeleteBranchScenario { |
| 471 | let git_repo = prep_git_repo()?; | 455 | vnext_commit_id_str: String, |
| 472 | 456 | branch_was_deleted_on_server: bool, | |
| 473 | git_repo.create_branch("vnext")?; | 457 | remote_ref_was_deleted_locally: bool, |
| 474 | git_repo.checkout("vnext")?; | ||
| 475 | std::fs::write(git_repo.dir.join("vnext.md"), "some content")?; | ||
| 476 | let vnext_commit_id = git_repo.stage_and_commit("vnext.md")?; | ||
| 477 | |||
| 478 | let source_git_repo = GitTestRepo::recreate_as_bare(&git_repo)?; | ||
| 479 | |||
| 480 | let events = vec![ | ||
| 481 | generate_test_key_1_metadata_event("fred"), | ||
| 482 | generate_test_key_1_relay_list_event(), | ||
| 483 | generate_repo_ref_event_with_git_server(vec![ | ||
| 484 | source_git_repo.dir.to_str().unwrap().to_string(), | ||
| 485 | ]), | ||
| 486 | generate_repo_ref_event_with_git_server_with_keys( | ||
| 487 | vec![source_git_repo.dir.to_str().unwrap().to_string()], | ||
| 488 | &TEST_KEY_2_KEYS, | ||
| 489 | ), | ||
| 490 | ]; | ||
| 491 | // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57) | ||
| 492 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | ||
| 493 | Relay::new(8051, None, None), | ||
| 494 | Relay::new(8052, None, None), | ||
| 495 | Relay::new(8053, None, None), | ||
| 496 | Relay::new(8055, None, None), | ||
| 497 | Relay::new(8056, None, None), | ||
| 498 | Relay::new(8057, None, None), | ||
| 499 | ); | ||
| 500 | r51.events = events.clone(); | ||
| 501 | r55.events = events; | ||
| 502 | |||
| 503 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | ||
| 504 | assert_eq!( | ||
| 505 | source_git_repo | ||
| 506 | .git_repo | ||
| 507 | .find_reference("refs/heads/vnext")? | ||
| 508 | .peel_to_commit()? | ||
| 509 | .id(), | ||
| 510 | vnext_commit_id | ||
| 511 | ); | ||
| 512 | |||
| 513 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo)?; | ||
| 514 | p.send_line("push :refs/heads/vnext")?; | ||
| 515 | p.send_line("")?; | ||
| 516 | p.expect_eventually_and_print("\r\n\r\n")?; | ||
| 517 | p.exit()?; | ||
| 518 | for p in [51, 52, 53, 55, 56, 57] { | ||
| 519 | relay::shutdown_relay(8000 + p)?; | ||
| 520 | } | ||
| 521 | |||
| 522 | assert!( | ||
| 523 | source_git_repo | ||
| 524 | .git_repo | ||
| 525 | .find_reference("refs/heads/vnext") | ||
| 526 | .is_err() | ||
| 527 | ); | ||
| 528 | Ok(()) | ||
| 529 | }); | ||
| 530 | // launch relays | ||
| 531 | let _ = join!( | ||
| 532 | r51.listen_until_close(), | ||
| 533 | r52.listen_until_close(), | ||
| 534 | r53.listen_until_close(), | ||
| 535 | r55.listen_until_close(), | ||
| 536 | r56.listen_until_close(), | ||
| 537 | r57.listen_until_close(), | ||
| 538 | ); | ||
| 539 | cli_tester_handle.join().unwrap()?; | ||
| 540 | Ok(()) | ||
| 541 | } | 458 | } |
| 542 | 459 | ||
| 543 | #[tokio::test] | 460 | // Fixture: runs expensive setup once and captures results for verification |
| 544 | #[serial] | 461 | #[fixture] |
| 545 | async fn remote_refs_updated_in_local_git() -> Result<()> { | 462 | async fn scenario() -> DeleteBranchScenario { |
| 546 | let git_repo = prep_git_repo()?; | 463 | let git_repo = prep_git_repo().unwrap(); |
| 547 | 464 | ||
| 548 | git_repo.create_branch("vnext")?; | 465 | git_repo.create_branch("vnext").unwrap(); |
| 549 | git_repo.checkout("vnext")?; | 466 | git_repo.checkout("vnext").unwrap(); |
| 550 | std::fs::write(git_repo.dir.join("vnext.md"), "some content")?; | 467 | std::fs::write(git_repo.dir.join("vnext.md"), "some content").unwrap(); |
| 551 | let vnext_commit_id = git_repo.stage_and_commit("vnext.md")?; | 468 | let vnext_commit_id = git_repo.stage_and_commit("vnext.md").unwrap(); |
| 469 | let vnext_commit_id_str = vnext_commit_id.to_string(); | ||
| 552 | 470 | ||
| 553 | let source_git_repo = GitTestRepo::recreate_as_bare(&git_repo)?; | 471 | let source_git_repo = GitTestRepo::recreate_as_bare(&git_repo).unwrap(); |
| 554 | 472 | ||
| 473 | // Add remote ref for local deletion test | ||
| 555 | git_repo | 474 | git_repo |
| 556 | .git_repo | 475 | .git_repo |
| 557 | .reference("refs/remotes/nostr/vnext", vnext_commit_id, true, "")?; | 476 | .reference("refs/remotes/nostr/vnext", vnext_commit_id, true, "") |
| 477 | .unwrap(); | ||
| 558 | 478 | ||
| 559 | let events = vec![ | 479 | let events = vec![ |
| 560 | generate_test_key_1_metadata_event("fred"), | 480 | generate_test_key_1_metadata_event("fred"), |
| @@ -567,7 +487,7 @@ mod delete_one_branch { | |||
| 567 | &TEST_KEY_2_KEYS, | 487 | &TEST_KEY_2_KEYS, |
| 568 | ), | 488 | ), |
| 569 | ]; | 489 | ]; |
| 570 | // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57) | 490 | |
| 571 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | 491 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( |
| 572 | Relay::new(8051, None, None), | 492 | Relay::new(8051, None, None), |
| 573 | Relay::new(8052, None, None), | 493 | Relay::new(8052, None, None), |
| @@ -579,107 +499,89 @@ mod delete_one_branch { | |||
| 579 | r51.events = events.clone(); | 499 | r51.events = events.clone(); |
| 580 | r55.events = events; | 500 | r55.events = events; |
| 581 | 501 | ||
| 582 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 502 | // Run the expensive operation ONCE - capture verification data |
| 583 | assert_eq!( | 503 | let (server_deleted, local_deleted) = { |
| 584 | git_repo | 504 | let cli_tester_handle = std::thread::spawn(move || -> Result<(bool, bool)> { |
| 585 | .git_repo | 505 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo) |
| 586 | .find_reference("refs/remotes/nostr/vnext")? | 506 | .unwrap(); |
| 587 | .peel_to_commit()? | 507 | p.send_line("push :refs/heads/vnext").unwrap(); |
| 588 | .id(), | 508 | p.send_line("").unwrap(); |
| 589 | vnext_commit_id | 509 | p.expect_eventually_and_print("\r\n\r\n").unwrap(); |
| 590 | ); | 510 | p.exit().unwrap(); |
| 511 | for p in [51, 52, 53, 55, 56, 57] { | ||
| 512 | relay::shutdown_relay(8000 + p).unwrap(); | ||
| 513 | } | ||
| 591 | 514 | ||
| 592 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo)?; | 515 | // Capture results for later verification |
| 593 | p.send_line("push :refs/heads/vnext")?; | 516 | let server_deleted = source_git_repo |
| 594 | p.send_line("")?; | 517 | .git_repo |
| 595 | p.expect_eventually("\r\n\r\n")?; | 518 | .find_reference("refs/heads/vnext") |
| 596 | p.exit()?; | 519 | .is_err(); |
| 597 | for p in [51, 52, 53, 55, 56, 57] { | 520 | let local_deleted = git_repo |
| 598 | relay::shutdown_relay(8000 + p)?; | ||
| 599 | } | ||
| 600 | assert!( | ||
| 601 | git_repo | ||
| 602 | .git_repo | 521 | .git_repo |
| 603 | .find_reference("refs/remotes/nostr/vnext") | 522 | .find_reference("refs/remotes/nostr/vnext") |
| 604 | .is_err() | 523 | .is_err(); |
| 524 | |||
| 525 | Ok((server_deleted, local_deleted)) | ||
| 526 | }); | ||
| 527 | |||
| 528 | let _ = join!( | ||
| 529 | r51.listen_until_close(), | ||
| 530 | r52.listen_until_close(), | ||
| 531 | r53.listen_until_close(), | ||
| 532 | r55.listen_until_close(), | ||
| 533 | r56.listen_until_close(), | ||
| 534 | r57.listen_until_close(), | ||
| 605 | ); | 535 | ); |
| 606 | Ok(()) | 536 | cli_tester_handle.join().unwrap().unwrap() |
| 607 | }); | 537 | }; |
| 608 | // launch relays | 538 | |
| 609 | let _ = join!( | 539 | DeleteBranchScenario { |
| 610 | r51.listen_until_close(), | 540 | vnext_commit_id_str, |
| 611 | r52.listen_until_close(), | 541 | branch_was_deleted_on_server: server_deleted, |
| 612 | r53.listen_until_close(), | 542 | remote_ref_was_deleted_locally: local_deleted, |
| 613 | r55.listen_until_close(), | 543 | } |
| 614 | r56.listen_until_close(), | 544 | } |
| 615 | r57.listen_until_close(), | 545 | |
| 546 | // POC Test 1: Verify branch deleted on git server | ||
| 547 | #[rstest] | ||
| 548 | #[tokio::test] | ||
| 549 | #[serial] | ||
| 550 | async fn deletes_branch_on_git_server(#[future] scenario: DeleteBranchScenario) -> Result<()> { | ||
| 551 | let s = scenario.await; | ||
| 552 | assert!( | ||
| 553 | s.branch_was_deleted_on_server, | ||
| 554 | "Branch should be deleted on git server" | ||
| 616 | ); | 555 | ); |
| 617 | cli_tester_handle.join().unwrap()?; | ||
| 618 | Ok(()) | 556 | Ok(()) |
| 619 | } | 557 | } |
| 620 | 558 | ||
| 559 | // POC Test 2: Verify remote refs deleted locally | ||
| 560 | #[rstest] | ||
| 621 | #[tokio::test] | 561 | #[tokio::test] |
| 622 | #[serial] | 562 | #[serial] |
| 623 | async fn prints_git_helper_ok_respose() -> Result<()> { | 563 | async fn remote_refs_updated_in_local_git( |
| 624 | let git_repo = prep_git_repo()?; | 564 | #[future] scenario: DeleteBranchScenario, |
| 625 | 565 | ) -> Result<()> { | |
| 626 | git_repo.create_branch("vnext")?; | 566 | let s = scenario.await; |
| 627 | git_repo.checkout("vnext")?; | 567 | assert!( |
| 628 | std::fs::write(git_repo.dir.join("vnext.md"), "some content")?; | 568 | s.remote_ref_was_deleted_locally, |
| 629 | let vnext_commit_id = git_repo.stage_and_commit("vnext.md")?; | 569 | "Remote ref should be deleted locally" |
| 630 | |||
| 631 | let source_git_repo = GitTestRepo::recreate_as_bare(&git_repo)?; | ||
| 632 | |||
| 633 | git_repo | ||
| 634 | .git_repo | ||
| 635 | .reference("refs/remotes/nostr/vnext", vnext_commit_id, true, "")?; | ||
| 636 | |||
| 637 | let events = vec![ | ||
| 638 | generate_test_key_1_metadata_event("fred"), | ||
| 639 | generate_test_key_1_relay_list_event(), | ||
| 640 | generate_repo_ref_event_with_git_server(vec![ | ||
| 641 | source_git_repo.dir.to_str().unwrap().to_string(), | ||
| 642 | ]), | ||
| 643 | generate_repo_ref_event_with_git_server_with_keys( | ||
| 644 | vec![source_git_repo.dir.to_str().unwrap().to_string()], | ||
| 645 | &TEST_KEY_2_KEYS, | ||
| 646 | ), | ||
| 647 | ]; | ||
| 648 | // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57) | ||
| 649 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | ||
| 650 | Relay::new(8051, None, None), | ||
| 651 | Relay::new(8052, None, None), | ||
| 652 | Relay::new(8053, None, None), | ||
| 653 | Relay::new(8055, None, None), | ||
| 654 | Relay::new(8056, None, None), | ||
| 655 | Relay::new(8057, None, None), | ||
| 656 | ); | 570 | ); |
| 657 | r51.events = events.clone(); | 571 | Ok(()) |
| 658 | r55.events = events; | 572 | } |
| 659 | 573 | ||
| 660 | let cli_tester_handle = std::thread::spawn(move || -> Result<()> { | 574 | // POC Test 3: Verify commit ID was valid |
| 661 | let mut p = cli_tester_after_nostr_fetch_and_sent_list_for_push_responds(&git_repo)?; | 575 | #[rstest] |
| 662 | p.send_line("push :refs/heads/vnext")?; | 576 | #[tokio::test] |
| 663 | p.send_line("")?; | 577 | #[serial] |
| 664 | p.expect_eventually("ok ")?; | 578 | async fn verify_commit_id_captured(#[future] scenario: DeleteBranchScenario) -> Result<()> { |
| 665 | p.expect("refs/heads/vnext\r\n")?; | 579 | let s = scenario.await; |
| 666 | p.expect_eventually("\r\n\r\n")?; | 580 | assert_eq!( |
| 667 | p.exit()?; | 581 | s.vnext_commit_id_str.len(), |
| 668 | for p in [51, 52, 53, 55, 56, 57] { | 582 | 40, |
| 669 | relay::shutdown_relay(8000 + p)?; | 583 | "Should have valid commit SHA" |
| 670 | } | ||
| 671 | Ok(()) | ||
| 672 | }); | ||
| 673 | // launch relays | ||
| 674 | let _ = join!( | ||
| 675 | r51.listen_until_close(), | ||
| 676 | r52.listen_until_close(), | ||
| 677 | r53.listen_until_close(), | ||
| 678 | r55.listen_until_close(), | ||
| 679 | r56.listen_until_close(), | ||
| 680 | r57.listen_until_close(), | ||
| 681 | ); | 584 | ); |
| 682 | cli_tester_handle.join().unwrap()?; | ||
| 683 | Ok(()) | 585 | Ok(()) |
| 684 | } | 586 | } |
| 685 | 587 | ||
diff --git a/tests/ngit_init.rs b/tests/ngit_init.rs index 1a23177..f6b30ef 100644 --- a/tests/ngit_init.rs +++ b/tests/ngit_init.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | use anyhow::Result; | 1 | use anyhow::Result; |
| 2 | use nostr_sdk::Kind; | 2 | use nostr_sdk::Kind; |
| 3 | use rstest::*; | ||
| 3 | use serial_test::serial; | 4 | use serial_test::serial; |
| 4 | use test_utils::{git::GitTestRepo, *}; | 5 | use test_utils::{git::GitTestRepo, *}; |
| 5 | 6 | ||
| @@ -120,68 +121,107 @@ mod when_repo_not_previously_claimed { | |||
| 120 | 121 | ||
| 121 | use super::*; | 122 | use super::*; |
| 122 | 123 | ||
| 124 | #[derive(Clone)] | ||
| 125 | pub struct SentToCorrectRelaysScenario { | ||
| 126 | pub r51_repo_event_count: usize, | ||
| 127 | pub r52_repo_event_count: usize, | ||
| 128 | pub r53_repo_event_count: usize, | ||
| 129 | pub r55_repo_event_count: usize, | ||
| 130 | pub r56_repo_event_count: usize, | ||
| 131 | pub r57_repo_event_count: usize, | ||
| 132 | } | ||
| 133 | |||
| 134 | #[fixture] | ||
| 135 | async fn scenario() -> SentToCorrectRelaysScenario { | ||
| 136 | let (r51, r52, r53, r55, r56, r57) = | ||
| 137 | prep_run_init().await.expect("prep_run_init failed"); | ||
| 138 | |||
| 139 | // Extract event counts for verification | ||
| 140 | let r51_repo_event_count = r51 | ||
| 141 | .events | ||
| 142 | .iter() | ||
| 143 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 144 | .count(); | ||
| 145 | let r52_repo_event_count = r52 | ||
| 146 | .events | ||
| 147 | .iter() | ||
| 148 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 149 | .count(); | ||
| 150 | let r53_repo_event_count = r53 | ||
| 151 | .events | ||
| 152 | .iter() | ||
| 153 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 154 | .count(); | ||
| 155 | let r55_repo_event_count = r55 | ||
| 156 | .events | ||
| 157 | .iter() | ||
| 158 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 159 | .count(); | ||
| 160 | let r56_repo_event_count = r56 | ||
| 161 | .events | ||
| 162 | .iter() | ||
| 163 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 164 | .count(); | ||
| 165 | let r57_repo_event_count = r57 | ||
| 166 | .events | ||
| 167 | .iter() | ||
| 168 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 169 | .count(); | ||
| 170 | |||
| 171 | SentToCorrectRelaysScenario { | ||
| 172 | r51_repo_event_count, | ||
| 173 | r52_repo_event_count, | ||
| 174 | r53_repo_event_count, | ||
| 175 | r55_repo_event_count, | ||
| 176 | r56_repo_event_count, | ||
| 177 | r57_repo_event_count, | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | #[rstest] | ||
| 123 | #[tokio::test] | 182 | #[tokio::test] |
| 124 | #[serial] | 183 | #[serial] |
| 125 | async fn only_1_repository_kind_event_sent_to_user_relays() -> Result<()> { | 184 | async fn only_1_repository_kind_event_sent_to_user_relays( |
| 126 | let (_, _, r53, r55, _, _) = prep_run_init().await?; | 185 | #[future] scenario: SentToCorrectRelaysScenario, |
| 127 | for relay in [&r53, &r55] { | 186 | ) -> Result<()> { |
| 128 | assert_eq!( | 187 | let s = scenario.await; |
| 129 | relay | 188 | assert_eq!(s.r53_repo_event_count, 1); |
| 130 | .events | 189 | assert_eq!(s.r55_repo_event_count, 1); |
| 131 | .iter() | ||
| 132 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 133 | .count(), | ||
| 134 | 1, | ||
| 135 | ); | ||
| 136 | } | ||
| 137 | Ok(()) | 190 | Ok(()) |
| 138 | } | 191 | } |
| 139 | 192 | ||
| 193 | #[rstest] | ||
| 140 | #[tokio::test] | 194 | #[tokio::test] |
| 141 | #[serial] | 195 | #[serial] |
| 142 | async fn only_1_repository_kind_event_sent_to_specified_repo_relays() -> Result<()> { | 196 | async fn only_1_repository_kind_event_sent_to_specified_repo_relays( |
| 143 | let (_, _, _, r55, r56, _) = prep_run_init().await?; | 197 | #[future] scenario: SentToCorrectRelaysScenario, |
| 144 | for relay in [&r55, &r56] { | 198 | ) -> Result<()> { |
| 145 | assert_eq!( | 199 | let s = scenario.await; |
| 146 | relay | 200 | assert_eq!(s.r55_repo_event_count, 1); |
| 147 | .events | 201 | assert_eq!(s.r56_repo_event_count, 1); |
| 148 | .iter() | ||
| 149 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 150 | .count(), | ||
| 151 | 1, | ||
| 152 | ); | ||
| 153 | } | ||
| 154 | Ok(()) | 202 | Ok(()) |
| 155 | } | 203 | } |
| 156 | 204 | ||
| 205 | #[rstest] | ||
| 157 | #[tokio::test] | 206 | #[tokio::test] |
| 158 | #[serial] | 207 | #[serial] |
| 159 | async fn only_1_repository_kind_event_sent_to_fallback_relays() -> Result<()> { | 208 | async fn only_1_repository_kind_event_sent_to_fallback_relays( |
| 160 | let (r51, r52, _, _, _, _) = prep_run_init().await?; | 209 | #[future] scenario: SentToCorrectRelaysScenario, |
| 161 | for relay in [&r51, &r52] { | 210 | ) -> Result<()> { |
| 162 | assert_eq!( | 211 | let s = scenario.await; |
| 163 | relay | 212 | assert_eq!(s.r51_repo_event_count, 1); |
| 164 | .events | 213 | assert_eq!(s.r52_repo_event_count, 1); |
| 165 | .iter() | ||
| 166 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 167 | .count(), | ||
| 168 | 1, | ||
| 169 | ); | ||
| 170 | } | ||
| 171 | Ok(()) | 214 | Ok(()) |
| 172 | } | 215 | } |
| 173 | 216 | ||
| 217 | #[rstest] | ||
| 174 | #[tokio::test] | 218 | #[tokio::test] |
| 175 | #[serial] | 219 | #[serial] |
| 176 | async fn only_1_repository_kind_event_sent_to_blaster_relays() -> Result<()> { | 220 | async fn only_1_repository_kind_event_sent_to_blaster_relays( |
| 177 | let (_, _, _, _, _, r57) = prep_run_init().await?; | 221 | #[future] scenario: SentToCorrectRelaysScenario, |
| 178 | assert_eq!( | 222 | ) -> Result<()> { |
| 179 | r57.events | 223 | let s = scenario.await; |
| 180 | .iter() | 224 | assert_eq!(s.r57_repo_event_count, 1); |
| 181 | .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 182 | .count(), | ||
| 183 | 1, | ||
| 184 | ); | ||
| 185 | Ok(()) | 225 | Ok(()) |
| 186 | } | 226 | } |
| 187 | } | 227 | } |
| @@ -271,179 +311,153 @@ mod when_repo_not_previously_claimed { | |||
| 271 | mod tags_as_specified_in_args { | 311 | mod tags_as_specified_in_args { |
| 272 | use super::*; | 312 | use super::*; |
| 273 | 313 | ||
| 314 | #[derive(Clone)] | ||
| 315 | pub struct TagsAsSpecifiedScenario { | ||
| 316 | pub event: nostr::Event, | ||
| 317 | } | ||
| 318 | |||
| 319 | #[fixture] | ||
| 320 | async fn scenario() -> TagsAsSpecifiedScenario { | ||
| 321 | let (_, _, r53, _r55, _r56, _r57) = | ||
| 322 | prep_run_init().await.expect("prep_run_init failed"); | ||
| 323 | |||
| 324 | // Extract the GitRepoAnnouncement event (should be same on all relays) | ||
| 325 | let event = r53 | ||
| 326 | .events | ||
| 327 | .iter() | ||
| 328 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 329 | .expect("GitRepoAnnouncement event not found") | ||
| 330 | .clone(); | ||
| 331 | |||
| 332 | TagsAsSpecifiedScenario { event } | ||
| 333 | } | ||
| 334 | |||
| 335 | #[rstest] | ||
| 274 | #[tokio::test] | 336 | #[tokio::test] |
| 275 | #[serial] | 337 | #[serial] |
| 276 | async fn d_replaceable_event_identifier() -> Result<()> { | 338 | async fn d_replaceable_event_identifier( |
| 277 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 339 | #[future] scenario: TagsAsSpecifiedScenario, |
| 278 | for relay in [&r53, &r55, &r56, &r57] { | 340 | ) -> Result<()> { |
| 279 | let event: &nostr::Event = relay | 341 | let s = scenario.await; |
| 280 | .events | 342 | assert!( |
| 281 | .iter() | 343 | s.event.tags.iter().any( |
| 282 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 283 | .unwrap(); | ||
| 284 | |||
| 285 | assert!(event.tags.iter().any( | ||
| 286 | |t| t.as_slice()[0].eq("d") && t.as_slice()[1].eq("example-identifier") | 344 | |t| t.as_slice()[0].eq("d") && t.as_slice()[1].eq("example-identifier") |
| 287 | )); | 345 | ) |
| 288 | } | 346 | ); |
| 289 | Ok(()) | 347 | Ok(()) |
| 290 | } | 348 | } |
| 291 | 349 | ||
| 350 | #[rstest] | ||
| 292 | #[tokio::test] | 351 | #[tokio::test] |
| 293 | #[serial] | 352 | #[serial] |
| 294 | async fn earliest_unique_commit_as_reference_with_euc_marker() -> Result<()> { | 353 | async fn earliest_unique_commit_as_reference_with_euc_marker( |
| 295 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 354 | #[future] scenario: TagsAsSpecifiedScenario, |
| 296 | for relay in [&r53, &r55, &r56, &r57] { | 355 | ) -> Result<()> { |
| 297 | let event: &nostr::Event = relay | 356 | let s = scenario.await; |
| 298 | .events | 357 | assert!(s.event.tags.iter().any(|t| t.as_slice()[0].eq("r") |
| 299 | .iter() | 358 | && t.as_slice()[1].eq("9ee507fc4357d7ee16a5d8901bedcd103f23c17d") |
| 300 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | 359 | && t.as_slice()[2].eq("euc"))); |
| 301 | .unwrap(); | ||
| 302 | |||
| 303 | assert!(event.tags.iter().any(|t| t.as_slice()[0].eq("r") | ||
| 304 | && t.as_slice()[1].eq("9ee507fc4357d7ee16a5d8901bedcd103f23c17d") | ||
| 305 | && t.as_slice()[2].eq("euc"))); | ||
| 306 | } | ||
| 307 | Ok(()) | 360 | Ok(()) |
| 308 | } | 361 | } |
| 309 | 362 | ||
| 363 | #[rstest] | ||
| 310 | #[tokio::test] | 364 | #[tokio::test] |
| 311 | #[serial] | 365 | #[serial] |
| 312 | async fn name() -> Result<()> { | 366 | async fn name(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 313 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 367 | let s = scenario.await; |
| 314 | for relay in [&r53, &r55, &r56, &r57] { | 368 | assert!( |
| 315 | let event: &nostr::Event = relay | 369 | s.event |
| 316 | .events | 370 | .tags |
| 317 | .iter() | 371 | .iter() |
| 318 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | 372 | .any(|t| t.as_slice()[0].eq("name") && t.as_slice()[1].eq("example-name")) |
| 319 | .unwrap(); | 373 | ); |
| 320 | |||
| 321 | assert!( | ||
| 322 | event | ||
| 323 | .tags | ||
| 324 | .iter() | ||
| 325 | .any(|t| t.as_slice()[0].eq("name") | ||
| 326 | && t.as_slice()[1].eq("example-name")) | ||
| 327 | ); | ||
| 328 | } | ||
| 329 | Ok(()) | 374 | Ok(()) |
| 330 | } | 375 | } |
| 331 | 376 | ||
| 377 | #[rstest] | ||
| 332 | #[tokio::test] | 378 | #[tokio::test] |
| 333 | #[serial] | 379 | #[serial] |
| 334 | async fn alt() -> Result<()> { | 380 | async fn alt(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 335 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 381 | let s = scenario.await; |
| 336 | for relay in [&r53, &r55, &r56, &r57] { | 382 | assert!(s.event.tags.iter().any(|t| t.as_slice()[0].eq("alt") |
| 337 | let event: &nostr::Event = relay | 383 | && t.as_slice()[1].eq("git repository: example-name"))); |
| 338 | .events | ||
| 339 | .iter() | ||
| 340 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 341 | .unwrap(); | ||
| 342 | |||
| 343 | assert!(event.tags.iter().any(|t| t.as_slice()[0].eq("alt") | ||
| 344 | && t.as_slice()[1].eq("git repository: example-name"))); | ||
| 345 | } | ||
| 346 | Ok(()) | 384 | Ok(()) |
| 347 | } | 385 | } |
| 348 | 386 | ||
| 387 | #[rstest] | ||
| 349 | #[tokio::test] | 388 | #[tokio::test] |
| 350 | #[serial] | 389 | #[serial] |
| 351 | async fn description() -> Result<()> { | 390 | async fn description(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 352 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 391 | let s = scenario.await; |
| 353 | for relay in [&r53, &r55, &r56, &r57] { | 392 | assert!( |
| 354 | let event: &nostr::Event = relay | 393 | s.event |
| 355 | .events | 394 | .tags |
| 356 | .iter() | 395 | .iter() |
| 357 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | 396 | .any(|t| t.as_slice()[0].eq("description") |
| 358 | .unwrap(); | 397 | && t.as_slice()[1].eq("example-description")) |
| 359 | 398 | ); | |
| 360 | assert!(event.tags.iter().any(|t| t.as_slice()[0].eq("description") | ||
| 361 | && t.as_slice()[1].eq("example-description"))); | ||
| 362 | } | ||
| 363 | Ok(()) | 399 | Ok(()) |
| 364 | } | 400 | } |
| 365 | 401 | ||
| 402 | #[rstest] | ||
| 366 | #[tokio::test] | 403 | #[tokio::test] |
| 367 | #[serial] | 404 | #[serial] |
| 368 | async fn git_server() -> Result<()> { | 405 | async fn git_server(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 369 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 406 | let s = scenario.await; |
| 370 | for relay in [&r53, &r55, &r56, &r57] { | 407 | assert!( |
| 371 | let event: &nostr::Event = relay | 408 | s.event.tags.iter().any(|t| t.as_slice()[0].eq("clone") |
| 372 | .events | 409 | && t.as_slice()[1].eq("https://git.myhosting.com/my-repo.git")) /* todo check it defaults to origin */ |
| 373 | .iter() | 410 | ); |
| 374 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | ||
| 375 | .unwrap(); | ||
| 376 | |||
| 377 | assert!( | ||
| 378 | event.tags.iter().any(|t| t.as_slice()[0].eq("clone") | ||
| 379 | && t.as_slice()[1].eq("https://git.myhosting.com/my-repo.git")) /* todo check it defaults to origin */ | ||
| 380 | ); | ||
| 381 | } | ||
| 382 | Ok(()) | 411 | Ok(()) |
| 383 | } | 412 | } |
| 384 | 413 | ||
| 414 | #[rstest] | ||
| 385 | #[tokio::test] | 415 | #[tokio::test] |
| 386 | #[serial] | 416 | #[serial] |
| 387 | async fn relays() -> Result<()> { | 417 | async fn relays(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 388 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 418 | let s = scenario.await; |
| 389 | for relay in [&r53, &r55, &r56, &r57] { | 419 | let relays_tag = s |
| 390 | let event: &nostr::Event = relay | 420 | .event |
| 391 | .events | 421 | .tags |
| 392 | .iter() | 422 | .iter() |
| 393 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | 423 | .find(|t| t.as_slice()[0].eq("relays")) |
| 394 | .unwrap(); | 424 | .unwrap() |
| 395 | let relays_tag = event | 425 | .as_slice(); |
| 396 | .tags | 426 | assert_eq!(relays_tag[1], "ws://localhost:8055",); |
| 397 | .iter() | 427 | assert_eq!(relays_tag[2], "ws://localhost:8056",); |
| 398 | .find(|t| t.as_slice()[0].eq("relays")) | ||
| 399 | .unwrap() | ||
| 400 | .as_slice(); | ||
| 401 | assert_eq!(relays_tag[1], "ws://localhost:8055",); | ||
| 402 | assert_eq!(relays_tag[2], "ws://localhost:8056",); | ||
| 403 | } | ||
| 404 | Ok(()) | 428 | Ok(()) |
| 405 | } | 429 | } |
| 406 | 430 | ||
| 431 | #[rstest] | ||
| 407 | #[tokio::test] | 432 | #[tokio::test] |
| 408 | #[serial] | 433 | #[serial] |
| 409 | async fn web() -> Result<()> { | 434 | async fn web(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 410 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 435 | let s = scenario.await; |
| 411 | for relay in [&r53, &r55, &r56, &r57] { | 436 | let web_tag = s |
| 412 | let event: &nostr::Event = relay | 437 | .event |
| 413 | .events | 438 | .tags |
| 414 | .iter() | 439 | .iter() |
| 415 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | 440 | .find(|t| t.as_slice()[0].eq("web")) |
| 416 | .unwrap(); | 441 | .unwrap() |
| 417 | let web_tag = event | 442 | .as_slice(); |
| 418 | .tags | 443 | assert_eq!(web_tag[1], "https://exampleproject.xyz",); |
| 419 | .iter() | 444 | assert_eq!(web_tag[2], "https://gitworkshop.dev/123",); |
| 420 | .find(|t| t.as_slice()[0].eq("web")) | ||
| 421 | .unwrap() | ||
| 422 | .as_slice(); | ||
| 423 | assert_eq!(web_tag[1], "https://exampleproject.xyz",); | ||
| 424 | assert_eq!(web_tag[2], "https://gitworkshop.dev/123",); | ||
| 425 | } | ||
| 426 | Ok(()) | 445 | Ok(()) |
| 427 | } | 446 | } |
| 428 | 447 | ||
| 448 | #[rstest] | ||
| 429 | #[tokio::test] | 449 | #[tokio::test] |
| 430 | #[serial] | 450 | #[serial] |
| 431 | async fn maintainers() -> Result<()> { | 451 | async fn maintainers(#[future] scenario: TagsAsSpecifiedScenario) -> Result<()> { |
| 432 | let (_, _, r53, r55, r56, r57) = prep_run_init().await?; | 452 | let s = scenario.await; |
| 433 | for relay in [&r53, &r55, &r56, &r57] { | 453 | let maintainers_tag = s |
| 434 | let event: &nostr::Event = relay | 454 | .event |
| 435 | .events | 455 | .tags |
| 436 | .iter() | 456 | .iter() |
| 437 | .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) | 457 | .find(|t| t.as_slice()[0].eq("maintainers")) |
| 438 | .unwrap(); | 458 | .unwrap() |
| 439 | let maintainers_tag = event | 459 | .as_slice(); |
| 440 | .tags | 460 | assert_eq!(maintainers_tag[1], TEST_KEY_1_KEYS.public_key().to_string()); |
| 441 | .iter() | ||
| 442 | .find(|t| t.as_slice()[0].eq("maintainers")) | ||
| 443 | .unwrap() | ||
| 444 | .as_slice(); | ||
| 445 | assert_eq!(maintainers_tag[1], TEST_KEY_1_KEYS.public_key().to_string()); | ||
| 446 | } | ||
| 447 | Ok(()) | 461 | Ok(()) |
| 448 | } | 462 | } |
| 449 | } | 463 | } |