Skip to content

Commit 069804a

Browse files
committed
test: extract test helpers and add anchors anonymous coverage
1 parent 81a5772 commit 069804a

1 file changed

Lines changed: 119 additions & 131 deletions

File tree

‎crates/gitlawb-node/src/test_support.rs‎

Lines changed: 119 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,33 @@ mod tests {
18781878
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
18791879
}
18801880

1881+
struct PinTestFixture {
1882+
owner: gitlawb_core::identity::Keypair,
1883+
owner_did: String,
1884+
fx: CidFixture,
1885+
repo: crate::db::RepoRecord,
1886+
}
1887+
1888+
async fn setup_pin_test(state: &AppState, repo_name: &str) -> PinTestFixture {
1889+
use gitlawb_core::identity::Keypair;
1890+
1891+
let owner = Keypair::generate();
1892+
let owner_did = owner.did().to_string();
1893+
let fs_slug = owner_did.replace([':', '/'], "_");
1894+
let short = owner_did.split(':').next_back().unwrap().to_string();
1895+
1896+
let fx = seed_cid_repos(&fs_slug, &short, &[repo_name]);
1897+
let repo = seed_repo(&owner_did, repo_name);
1898+
state.db.create_repo(&repo).await.unwrap();
1899+
1900+
PinTestFixture {
1901+
owner,
1902+
owner_did,
1903+
fx,
1904+
repo,
1905+
}
1906+
}
1907+
18811908
/// #121: authenticated caller gets 200 from /api/v1/ipfs/pins.
18821909
///
18831910
/// list_pins only returns pins whose SHA-256 appears in a repo the caller
@@ -1889,41 +1916,20 @@ mod tests {
18891916
/// 3. Records a pin for the real object OID.
18901917
#[sqlx::test]
18911918
async fn pins_list_allows_authenticated(pool: PgPool) {
1892-
use gitlawb_core::identity::Keypair;
1893-
1894-
let owner = Keypair::generate();
1895-
let owner_did = owner.did().to_string();
1896-
// RepoStore maps owner_did to a filesystem slug by replacing ':' and '/' with '_'.
1897-
let fs_slug = owner_did.replace([':', '/'], "_");
1898-
// The short slug is the last ':'-separated segment of the DID (what push writes).
1899-
let short = owner_did.split(':').next_back().unwrap().to_string();
1900-
19011919
let state = test_state(pool).await;
1920+
let setup = setup_pin_test(&state, "pinrepo").await;
19021921

1903-
// Build a real SHA-256 bare git repo under /tmp/<fs_slug>/pinrepo.git so
1904-
// list_all_objects can enumerate actual object SHA-256 IDs.
1905-
let fx = seed_cid_repos(&fs_slug, &short, &["pinrepo"]);
1906-
// seed_cid_repos uses sha256 object format; fx.public_oid is a real git OID.
1907-
let pinned_sha = fx.public_oid.clone();
1922+
let pinned_sha = setup.fx.public_oid.clone();
19081923
let pinned_cid = cid_for_oid(&pinned_sha);
19091924

1910-
// Seed the repo DB record with the same owner_did so list_all_repos returns
1911-
// it and visibility_check passes (public repo, no rules).
1912-
state
1913-
.db
1914-
.create_repo(&seed_repo(&owner_did, "pinrepo"))
1915-
.await
1916-
.unwrap();
1917-
1918-
// Record the pin for the real git object SHA.
19191925
state
19201926
.db
19211927
.record_pinned_cid(&pinned_sha, &pinned_cid)
19221928
.await
19231929
.unwrap();
19241930

19251931
let resp = pins_router(&state)
1926-
.oneshot(signed_get(&owner, "/api/v1/ipfs/pins"))
1932+
.oneshot(signed_get(&setup.owner, "/api/v1/ipfs/pins"))
19271933
.await
19281934
.unwrap();
19291935
assert_eq!(resp.status(), StatusCode::OK);
@@ -1940,22 +1946,17 @@ mod tests {
19401946

19411947
#[sqlx::test]
19421948
async fn pins_list_excludes_quarantined_repos(pool: PgPool) {
1943-
use gitlawb_core::identity::Keypair;
1944-
1945-
let owner = Keypair::generate();
1946-
let owner_did = owner.did().to_string();
1947-
let fs_slug = owner_did.replace([':', '/'], "_");
1948-
let short = owner_did.split(':').next_back().unwrap().to_string();
1949-
19501949
let state = test_state(pool).await;
1950+
let setup = setup_pin_test(&state, "pinrepo").await;
19511951

1952-
let fx = seed_cid_repos(&fs_slug, &short, &["pinrepo"]);
1953-
let pinned_sha = fx.public_oid.clone();
1952+
let pinned_sha = setup.fx.public_oid.clone();
19541953
let pinned_cid = cid_for_oid(&pinned_sha);
19551954

1956-
let repo = seed_repo(&owner_did, "pinrepo");
1957-
state.db.create_repo(&repo).await.unwrap();
1958-
state.db.set_repo_quarantine(&repo.id, true).await.unwrap();
1955+
state
1956+
.db
1957+
.set_repo_quarantine(&setup.repo.id, true)
1958+
.await
1959+
.unwrap();
19591960

19601961
state
19611962
.db
@@ -1964,7 +1965,7 @@ mod tests {
19641965
.unwrap();
19651966

19661967
let resp = pins_router(&state)
1967-
.oneshot(signed_get(&owner, "/api/v1/ipfs/pins"))
1968+
.oneshot(signed_get(&setup.owner, "/api/v1/ipfs/pins"))
19681969
.await
19691970
.unwrap();
19701971
assert_eq!(resp.status(), StatusCode::OK);
@@ -1980,27 +1981,24 @@ mod tests {
19801981
use crate::db::VisibilityMode;
19811982
use gitlawb_core::identity::Keypair;
19821983

1983-
let owner = Keypair::generate();
1984-
let owner_did = owner.did().to_string();
1985-
let fs_slug = owner_did.replace([':', '/'], "_");
1986-
let short = owner_did.split(':').next_back().unwrap().to_string();
1987-
1988-
let stranger = Keypair::generate();
1989-
19901984
let state = test_state(pool).await;
1985+
let setup = setup_pin_test(&state, "pinrepo").await;
1986+
let stranger = Keypair::generate();
19911987

1992-
let fx = seed_cid_repos(&fs_slug, &short, &["pinrepo"]);
1993-
let public_sha = fx.public_oid.clone();
1988+
let public_sha = setup.fx.public_oid.clone();
19941989
let public_cid = cid_for_oid(&public_sha);
1995-
let secret_sha = fx.secret_oid.clone();
1990+
let secret_sha = setup.fx.secret_oid.clone();
19961991
let secret_cid = cid_for_oid(&secret_sha);
19971992

1998-
let repo = seed_repo(&owner_did, "pinrepo");
1999-
state.db.create_repo(&repo).await.unwrap();
2000-
20011993
state
20021994
.db
2003-
.set_visibility_rule(&repo.id, "/secret/**", VisibilityMode::B, &[], &owner_did)
1995+
.set_visibility_rule(
1996+
&setup.repo.id,
1997+
"/secret/**",
1998+
VisibilityMode::B,
1999+
&[],
2000+
&setup.owner_did,
2001+
)
20042002
.await
20052003
.unwrap();
20062004

@@ -2069,6 +2067,35 @@ mod tests {
20692067
assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
20702068
}
20712069

2070+
struct AnchorTestFixture {
2071+
owner: gitlawb_core::identity::Keypair,
2072+
owner_did: String,
2073+
}
2074+
2075+
async fn setup_anchor_test(
2076+
state: &AppState,
2077+
repo_name: &str,
2078+
is_public: bool,
2079+
) -> AnchorTestFixture {
2080+
use gitlawb_core::identity::Keypair;
2081+
2082+
let owner = Keypair::generate();
2083+
let owner_did = owner.did().to_string();
2084+
let owner_short = owner_did.split(':').next_back().unwrap().to_string();
2085+
let short_slug = format!("{owner_short}/{repo_name}");
2086+
2087+
let repo = if is_public {
2088+
seed_repo(&owner_did, repo_name)
2089+
} else {
2090+
seed_private_repo(&owner_did, repo_name)
2091+
};
2092+
2093+
state.db.create_repo(&repo).await.unwrap();
2094+
seed_anchor(&state.db, &short_slug, &owner_did).await;
2095+
2096+
AnchorTestFixture { owner, owner_did }
2097+
}
2098+
20722099
/// #121: /api/v1/arweave/anchors without ?repo= allows authenticated.
20732100
///
20742101
/// The global listing filters each anchor through authorize_repo_read, which
@@ -2078,29 +2105,11 @@ mod tests {
20782105
/// LIKE match finds the repo record.
20792106
#[sqlx::test]
20802107
async fn anchors_global_allows_authenticated(pool: PgPool) {
2081-
use gitlawb_core::identity::Keypair;
2082-
20832108
let state = test_state(pool).await;
2084-
let kp = Keypair::generate();
2085-
let owner_did = kp.did().to_string();
2086-
let repo_name = "globalrepo";
2087-
// Short slug: the last ':'-separated segment of the DID, matching what
2088-
// repos.rs writes to the arweave_anchors table on push.
2089-
let owner_short = owner_did.split(':').next_back().unwrap().to_string();
2090-
let short_slug = format!("{owner_short}/{repo_name}");
2091-
2092-
// Seed a public repo so authorize_repo_read succeeds for this anchor.
2093-
state
2094-
.db
2095-
.create_repo(&seed_repo(&owner_did, repo_name))
2096-
.await
2097-
.unwrap();
2098-
2099-
// Record the anchor with the short-form slug that production writes.
2100-
seed_anchor(&state.db, &short_slug, &owner_did).await;
2109+
let fx = setup_anchor_test(&state, "globalrepo", true).await;
21012110

21022111
let resp = anchors_router(&state)
2103-
.oneshot(signed_get(&kp, "/api/v1/arweave/anchors"))
2112+
.oneshot(signed_get(&fx.owner, "/api/v1/arweave/anchors"))
21042113
.await
21052114
.unwrap();
21062115
assert_eq!(resp.status(), StatusCode::OK);
@@ -2114,22 +2123,9 @@ mod tests {
21142123
#[sqlx::test]
21152124
async fn anchors_global_denies_non_reader(pool: PgPool) {
21162125
use gitlawb_core::identity::Keypair;
2117-
21182126
let state = test_state(pool).await;
2119-
let owner = Keypair::generate();
2120-
let owner_did = owner.did().to_string();
2127+
let _fx = setup_anchor_test(&state, "privaterepo", false).await;
21212128
let stranger = Keypair::generate();
2122-
let repo_name = "privaterepo";
2123-
let owner_short = owner_did.split(':').next_back().unwrap().to_string();
2124-
let short_slug = format!("{owner_short}/{repo_name}");
2125-
2126-
state
2127-
.db
2128-
.create_repo(&seed_private_repo(&owner_did, repo_name))
2129-
.await
2130-
.unwrap();
2131-
2132-
seed_anchor(&state.db, &short_slug, &owner_did).await;
21332129

21342130
let resp = anchors_router(&state)
21352131
.oneshot(signed_get(&stranger, "/api/v1/arweave/anchors"))
@@ -2149,31 +2145,42 @@ mod tests {
21492145
/// 404 for anon on private) — no anonymous-rejection guard is needed here.
21502146
#[sqlx::test]
21512147
async fn anchors_repo_denies_anonymous_on_private(pool: PgPool) {
2152-
use gitlawb_core::identity::Keypair;
2153-
21542148
let state = test_state(pool).await;
2155-
let owner = Keypair::generate();
2156-
let owner_did = owner.did().to_string();
21572149
let repo_name = "private-repo";
2158-
// Short slug written by the push path.
2159-
let owner_short = owner_did.split(':').next_back().unwrap().to_string();
2160-
let short_slug = format!("{owner_short}/{repo_name}");
2150+
let fx = setup_anchor_test(&state, repo_name, false).await;
21612151

2162-
state
2163-
.db
2164-
.create_repo(&seed_private_repo(&owner_did, repo_name))
2152+
let uri = format!(
2153+
"/api/v1/arweave/anchors?repo={}/{}",
2154+
fx.owner_did, repo_name
2155+
);
2156+
let resp = anchors_router(&state)
2157+
.oneshot(anon_get(&uri))
21652158
.await
21662159
.unwrap();
2167-
// Store anchor with the short slug that production writes.
2168-
seed_anchor(&state.db, &short_slug, &owner_did).await;
2160+
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
2161+
}
2162+
2163+
/// #121: /api/v1/arweave/anchors with ?repo= allows anonymous on public repo.
2164+
#[sqlx::test]
2165+
async fn anchors_repo_allows_anonymous_on_public(pool: PgPool) {
2166+
let state = test_state(pool).await;
2167+
let repo_name = "public-repo";
2168+
let fx = setup_anchor_test(&state, repo_name, true).await;
21692169

2170-
// ?repo= accepts the full DID form; list_anchors normalises it before querying.
2171-
let uri = format!("/api/v1/arweave/anchors?repo={owner_did}/{repo_name}");
2170+
let uri = format!(
2171+
"/api/v1/arweave/anchors?repo={}/{}",
2172+
fx.owner_did, repo_name
2173+
);
21722174
let resp = anchors_router(&state)
21732175
.oneshot(anon_get(&uri))
21742176
.await
21752177
.unwrap();
2176-
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
2178+
assert_eq!(resp.status(), StatusCode::OK);
2179+
let body = json_body(resp).await;
2180+
assert_eq!(
2181+
body["count"], 1,
2182+
"anonymous caller sees the seeded public anchor"
2183+
);
21772184
}
21782185

21792186
/// #121: /api/v1/arweave/anchors with ?repo= allows repo owner.
@@ -2183,27 +2190,16 @@ mod tests {
21832190
/// slug before issuing the DB query.
21842191
#[sqlx::test]
21852192
async fn anchors_repo_allows_owner(pool: PgPool) {
2186-
use gitlawb_core::identity::Keypair;
2187-
21882193
let state = test_state(pool).await;
2189-
let owner = Keypair::generate();
2190-
let owner_did = owner.did().to_string();
21912194
let repo_name = "owners-repo";
2192-
// Short slug matching what repos.rs writes on push.
2193-
let owner_short = owner_did.split(':').next_back().unwrap().to_string();
2194-
let short_slug = format!("{owner_short}/{repo_name}");
2195-
2196-
state
2197-
.db
2198-
.create_repo(&seed_private_repo(&owner_did, repo_name))
2199-
.await
2200-
.unwrap();
2201-
// Store anchor with the short slug that production writes.
2202-
seed_anchor(&state.db, &short_slug, &owner_did).await;
2195+
let fx = setup_anchor_test(&state, repo_name, false).await;
22032196

2204-
let uri = format!("/api/v1/arweave/anchors?repo={owner_did}/{repo_name}");
2197+
let uri = format!(
2198+
"/api/v1/arweave/anchors?repo={}/{}",
2199+
fx.owner_did, repo_name
2200+
);
22052201
let resp = anchors_router(&state)
2206-
.oneshot(signed_get(&owner, &uri))
2202+
.oneshot(signed_get(&fx.owner, &uri))
22072203
.await
22082204
.unwrap();
22092205
assert_eq!(resp.status(), StatusCode::OK);
@@ -2215,23 +2211,15 @@ mod tests {
22152211
#[sqlx::test]
22162212
async fn anchors_repo_denies_non_reader(pool: PgPool) {
22172213
use gitlawb_core::identity::Keypair;
2218-
22192214
let state = test_state(pool).await;
2220-
let owner = Keypair::generate();
2221-
let owner_did = owner.did().to_string();
2222-
let stranger = Keypair::generate();
22232215
let repo_name = "private-repo";
2224-
let owner_short = owner_did.split(':').next_back().unwrap().to_string();
2225-
let short_slug = format!("{owner_short}/{repo_name}");
2226-
2227-
state
2228-
.db
2229-
.create_repo(&seed_private_repo(&owner_did, repo_name))
2230-
.await
2231-
.unwrap();
2232-
seed_anchor(&state.db, &short_slug, &owner_did).await;
2216+
let fx = setup_anchor_test(&state, repo_name, false).await;
2217+
let stranger = Keypair::generate();
22332218

2234-
let uri = format!("/api/v1/arweave/anchors?repo={owner_did}/{repo_name}");
2219+
let uri = format!(
2220+
"/api/v1/arweave/anchors?repo={}/{}",
2221+
fx.owner_did, repo_name
2222+
);
22352223
let resp = anchors_router(&state)
22362224
.oneshot(signed_get(&stranger, &uri))
22372225
.await

0 commit comments

Comments
 (0)