This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / knot2 / crates / knot-pack / tests / handle_owner.rs
3.6 kB 122 lines
1use std::future::Future; 2use std::pin::Pin; 3use std::sync::Arc; 4 5use axum::body::Body; 6use axum::http::{Request, StatusCode}; 7use http_body_util::BodyExt; 8use knot_git::Layout; 9use knot_pack::{HandleResolver, RepoLookup, RepoResolver, RepoTarget}; 10use knot_types::{AccountDid, Handle, OwnerDid, RepoDid}; 11use tower::ServiceExt; 12 13struct FakeHandles; 14 15impl HandleResolver for FakeHandles { 16 fn resolve( 17 &self, 18 handle: Handle, 19 ) -> Pin<Box<dyn Future<Output = Option<AccountDid>> + Send + '_>> { 20 Box::pin(async move { 21 (handle.as_str() == "nel.pet").then(|| AccountDid::new("did:plc:nel").unwrap()) 22 }) 23 } 24} 25 26fn repo_resolver() -> Arc<dyn RepoResolver> { 27 let owner = OwnerDid::new("did:plc:nel").unwrap(); 28 let repo = RepoDid::new("did:plc:whelk").unwrap(); 29 Arc::new(move |target: &RepoTarget| match target { 30 RepoTarget::OwnerPath(o, p) 31 if *o == owner && p.rkeys().any(|rkey| rkey.as_str() == "squid") => 32 { 33 RepoLookup::Hosted(repo.clone()) 34 } 35 RepoTarget::Did(d) if *d == repo => RepoLookup::Hosted(d.clone()), 36 _ => RepoLookup::Unhosted, 37 }) 38} 39 40fn build(layout: &Layout, handle_resolver: Option<Arc<dyn HandleResolver>>) -> axum::Router { 41 let (_write, advertisement) = knot_pack::edge_routes(knot_pack::EdgeConfig { 42 handle_resolver, 43 pack_slots: knot_resource::PackSlots::new(4), 44 ..knot_pack::EdgeConfig::serving( 45 layout.clone(), 46 repo_resolver(), 47 Arc::new(knot_runtime::SystemClock), 48 ) 49 }); 50 advertisement.into_router() 51} 52 53async fn get(router: axum::Router, uri: &str) -> (StatusCode, Vec<u8>) { 54 let response = router 55 .oneshot(Request::get(uri).body(Body::empty()).unwrap()) 56 .await 57 .unwrap(); 58 let status = response.status(); 59 let body = response 60 .into_body() 61 .collect() 62 .await 63 .unwrap() 64 .to_bytes() 65 .to_vec(); 66 (status, body) 67} 68 69fn hosted_layout() -> (tempfile::TempDir, Layout) { 70 let scan = tempfile::tempdir().unwrap(); 71 let layout = Layout::new(scan.path()); 72 layout 73 .create(&RepoDid::new("did:plc:whelk").unwrap()) 74 .unwrap(); 75 (scan, layout) 76} 77 78#[tokio::test] 79async fn a_handle_owner_serves_the_same_repo_as_its_did() { 80 let (_scan, layout) = hosted_layout(); 81 let (handle_status, handle_body) = get( 82 build(&layout, Some(Arc::new(FakeHandles))), 83 "/nel.pet/squid/info/refs?service=git-upload-pack", 84 ) 85 .await; 86 let (did_status, did_body) = get( 87 build(&layout, Some(Arc::new(FakeHandles))), 88 "/did:plc:nel/squid/info/refs?service=git-upload-pack", 89 ) 90 .await; 91 assert_eq!(handle_status, StatusCode::OK); 92 assert_eq!(did_status, StatusCode::OK); 93 assert_eq!( 94 handle_body, did_body, 95 "handle owner and DID owner must serve the same repository" 96 ); 97} 98 99#[tokio::test] 100async fn a_handle_owner_is_not_found_when_unknown_or_unresolvable() { 101 let (_scan, layout) = hosted_layout(); 102 let (unknown, _) = get( 103 build(&layout, Some(Arc::new(FakeHandles))), 104 "/olaren.dev/squid/info/refs?service=git-upload-pack", 105 ) 106 .await; 107 assert_eq!( 108 unknown, 109 StatusCode::NOT_FOUND, 110 "a handle the resolver rejects isn't found" 111 ); 112 let (no_resolver, _) = get( 113 build(&layout, None), 114 "/nel.pet/squid/info/refs?service=git-upload-pack", 115 ) 116 .await; 117 assert_eq!( 118 no_resolver, 119 StatusCode::NOT_FOUND, 120 "a handle owner with no resolver configured isn't found" 121 ); 122}