Add Phase 1 frxd implementation with conformance test suite
This commit is contained in:
+116
@@ -0,0 +1,116 @@
|
||||
mod common;
|
||||
|
||||
use std::fs;
|
||||
|
||||
use common::{ask, client, collection, config_for, publish, spawn_relay};
|
||||
use frxd::index::LocalIndex;
|
||||
use frxd::message::{EXPOSURE_FULL, Envelope, TYPE_RESPONSE};
|
||||
use frxd::node::Node;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
|
||||
async fn two_node_broadcast_query_flow() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let relay_url = spawn_relay().await;
|
||||
|
||||
let shared_dir = root.path().join("bob/shared");
|
||||
let private_dir = root.path().join("bob/private");
|
||||
fs::create_dir_all(&shared_dir).unwrap();
|
||||
fs::create_dir_all(&private_dir).unwrap();
|
||||
fs::write(
|
||||
shared_dir.join("alpha.txt"),
|
||||
"Tantivy provides BM25 relevance scoring for rust search",
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
shared_dir.join("beta.txt"),
|
||||
"Rust lifetimes and borrowing explained",
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(private_dir.join("gamma.txt"), "rust secret launch codes").unwrap();
|
||||
|
||||
let bob_config = config_for(&root.path().join("bob"), "bob", &relay_url);
|
||||
{
|
||||
let index = LocalIndex::open(&bob_config.index_dir()).unwrap();
|
||||
index
|
||||
.add_collection(&collection("shared", &shared_dir, true, EXPOSURE_FULL))
|
||||
.unwrap();
|
||||
index
|
||||
.add_collection(&collection("private", &private_dir, false, "metadata"))
|
||||
.unwrap();
|
||||
}
|
||||
let _bob = Node::start(bob_config).await.unwrap();
|
||||
|
||||
let alice_dir = root.path().join("alice");
|
||||
let alice_local = root.path().join("alice_mine");
|
||||
fs::create_dir_all(&alice_local).unwrap();
|
||||
fs::write(alice_local.join("notes.txt"), "my rust notes").unwrap();
|
||||
let alice_config = config_for(&alice_dir, "alice", &relay_url);
|
||||
{
|
||||
let index = LocalIndex::open(&alice_config.index_dir()).unwrap();
|
||||
index
|
||||
.add_collection(&collection("mine", &alice_local, false, "metadata"))
|
||||
.unwrap();
|
||||
}
|
||||
let alice = Node::start(alice_config).await.unwrap();
|
||||
|
||||
let http = client();
|
||||
let addr = alice.addr.to_string();
|
||||
|
||||
let (status, raw, value) = ask(&http, &addr, "rust", 1).await;
|
||||
assert!(status.is_success());
|
||||
assert_eq!(
|
||||
value.pointer("/local/total").and_then(|v| v.as_u64()),
|
||||
Some(1)
|
||||
);
|
||||
let responses = value.get("responses").and_then(|v| v.as_array()).unwrap();
|
||||
assert_eq!(responses.len(), 1, "expected one responder: {value}");
|
||||
let response = &responses[0];
|
||||
let results = response.get("results").and_then(|v| v.as_array()).unwrap();
|
||||
assert_eq!(results.len(), 1);
|
||||
assert_eq!(
|
||||
response.get("truncated").and_then(|v| v.as_bool()),
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
response.get("more_available").and_then(|v| v.as_u64()),
|
||||
Some(1)
|
||||
);
|
||||
assert!(!raw.contains("gamma"), "unshared collection leaked: {raw}");
|
||||
assert!(!raw.contains("\"score\""), "response carries scores: {raw}");
|
||||
|
||||
let (_status, _raw, value) = ask(&http, &addr, "rust", 5).await;
|
||||
let responses = value.get("responses").and_then(|v| v.as_array()).unwrap();
|
||||
assert_eq!(responses.len(), 1);
|
||||
assert_eq!(
|
||||
responses[0]
|
||||
.get("results")
|
||||
.and_then(|v| v.as_array())
|
||||
.unwrap()
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
responses[0].get("truncated").and_then(|v| v.as_bool()),
|
||||
Some(false)
|
||||
);
|
||||
|
||||
let (_status, _raw, value) = ask(&http, &addr, "secret launch codes", 5).await;
|
||||
let responses = value.get("responses").and_then(|v| v.as_array()).unwrap();
|
||||
assert!(
|
||||
responses.is_empty(),
|
||||
"private collection was served: {value}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
|
||||
async fn relay_rejects_non_query_broadcasts() {
|
||||
let relay_url = spawn_relay().await;
|
||||
let key = frxd::crypto::Keypair::generate();
|
||||
let envelope = Envelope::new(
|
||||
&key,
|
||||
TYPE_RESPONSE,
|
||||
serde_json::json!({"qid": "x", "results": []}),
|
||||
);
|
||||
let response = publish(&client(), &relay_url, &envelope).await;
|
||||
assert_eq!(response.status(), reqwest::StatusCode::BAD_REQUEST);
|
||||
}
|
||||
Reference in New Issue
Block a user