Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697use std::sync::Arc;
use axum::body::Body;use bobbin_edge_index::{CoverageWatch, EdgeStore};use bobbin_record_lru::{CacheCapacity, LruRecordStore};use bobbin_resolver::RepoIdResolver;use bobbin_runtime::{RuntimeHasher, SystemClock};use bobbin_search::{DEFAULT_WRITER_HEAP_BYTES, SearchIndex, SearchReader};use bobbin_slingshot_client::SlingshotClient;use bobbin_xrpc::{AppState, CodeSearch, router};use http::{Request, StatusCode};use tower::ServiceExt;use url::Url;use wiremock::matchers::{header, method, path};use wiremock::{Mock, MockServer, ResponseTemplate};
const NSID: &str = "org.tangled.temp.search.searchCode";
fn app() -> axum::Router { let base = Url::parse("http://127.0.0.1:1").unwrap(); let state = AppState::new( Arc::new(LruRecordStore::new(CacheCapacity::from_bytes(64 * 1024))), SlingshotClient::with_default_http(base.clone()).unwrap(), Arc::new(EdgeStore::new(RuntimeHasher::default())), Arc::new(CoverageWatch::new()), Arc::new(SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap()) as Arc<dyn SearchReader>, Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), Arc::new(bobbin_xrpc::default_directory()), ) .with_codesearch(Some(Arc::new(CodeSearch::new(&base).unwrap()))); router(state)}
fn get(auth: Option<&str>) -> Request<Body> { let mut req = Request::builder().uri(format!("/xrpc/{NSID}?q=fn+main")); if let Some(token) = auth { req = req.header("authorization", token); } req.body(Body::empty()).unwrap()}
/// Code search is gated on login, matching the appview ui it backs, so an anonymous request/// must never reach zoekt.#[tokio::test]async fn an_anonymous_request_is_rejected() { let resp = app().oneshot(get(None)).await.unwrap(); assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);}
#[tokio::test]async fn a_malformed_authorization_header_is_rejected() { for header in ["", "Bearer", "Bearer not-a-jwt", "Basic abc"] { let resp = app().oneshot(get(Some(header))).await.unwrap(); assert_eq!( resp.status(), StatusCode::UNAUTHORIZED, "header {header:?} must not pass" ); }}
/// The lexicon declares a query, so the route must not accept a POST.#[tokio::test]async fn the_nsid_is_a_query_not_a_procedure() { let resp = app() .oneshot( Request::builder() .method("POST") .uri(format!("/xrpc/{NSID}?q=fn")) .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);}
/// The zoekt origin sits behind basic auth, so a configured credential must reach it.#[tokio::test]async fn zoekt_gets_the_configured_authorization() { let zoekt = MockServer::start().await; Mock::given(method("POST")) .and(path("/api/search")) .and(header("authorization", "Basic dXNlcjpwYXNz")) .respond_with(ResponseTemplate::new(200).set_body_string(r#"{"Result":null}"#)) .expect(1) .mount(&zoekt) .await;
let search = CodeSearch::new(&Url::parse(&zoekt.uri()).unwrap()) .unwrap() .with_authorization("Basic dXNlcjpwYXNz") .unwrap(); search.search("fn main", 0, 10).await.unwrap();}