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.7 kB 124 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::{CacheConfig, 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( 42 layout.clone(), 43 repo_resolver(), 44 None, 45 handle_resolver, 46 knot_resource::PackSlots::new(4), 47 CacheConfig::default(), 48 Arc::new(knot_messages::Catalog::defaults()), 49 knot_pack::default_hostname().clone(), 50 Arc::new(knot_runtime::SystemClock), 51 ); 52 advertisement.into_router() 53} 54 55async fn get(router: axum::Router, uri: &str) -> (StatusCode, Vec<u8>) { 56 let response = router 57 .oneshot(Request::get(uri).body(Body::empty()).unwrap()) 58 .await 59 .unwrap(); 60 let status = response.status(); 61 let body = response 62 .into_body() 63 .collect() 64 .await 65 .unwrap() 66 .to_bytes() 67 .to_vec(); 68 (status, body) 69} 70 71fn hosted_layout() -> (tempfile::TempDir, Layout) { 72 let scan = tempfile::tempdir().unwrap(); 73 let layout = Layout::new(scan.path()); 74 layout 75 .create(&RepoDid::new("did:plc:whelk").unwrap()) 76 .unwrap(); 77 (scan, layout) 78} 79 80#[tokio::test] 81async fn a_handle_owner_serves_the_same_repo_as_its_did() { 82 let (_scan, layout) = hosted_layout(); 83 let (handle_status, handle_body) = get( 84 build(&layout, Some(Arc::new(FakeHandles))), 85 "/nel.pet/squid/info/refs?service=git-upload-pack", 86 ) 87 .await; 88 let (did_status, did_body) = get( 89 build(&layout, Some(Arc::new(FakeHandles))), 90 "/did:plc:nel/squid/info/refs?service=git-upload-pack", 91 ) 92 .await; 93 assert_eq!(handle_status, StatusCode::OK); 94 assert_eq!(did_status, StatusCode::OK); 95 assert_eq!( 96 handle_body, did_body, 97 "handle owner and DID owner must serve the same repository" 98 ); 99} 100 101#[tokio::test] 102async fn a_handle_owner_is_not_found_when_unknown_or_unresolvable() { 103 let (_scan, layout) = hosted_layout(); 104 let (unknown, _) = get( 105 build(&layout, Some(Arc::new(FakeHandles))), 106 "/olaren.dev/squid/info/refs?service=git-upload-pack", 107 ) 108 .await; 109 assert_eq!( 110 unknown, 111 StatusCode::NOT_FOUND, 112 "a handle the resolver rejects isn't found" 113 ); 114 let (no_resolver, _) = get( 115 build(&layout, None), 116 "/nel.pet/squid/info/refs?service=git-upload-pack", 117 ) 118 .await; 119 assert_eq!( 120 no_resolver, 121 StatusCode::NOT_FOUND, 122 "a handle owner with no resolver configured isn't found" 123 ); 124}