use anyhow::ensure;
use futures::stream::{FuturesUnordered, StreamExt};
use harness::{Post, Query, User, assert_is_sine, make_request, parse_response};
use std::time::Duration;
mod harness;
#[tokio::test(start_paused = true)]
async fn default_latency_and_port() -> anyhow::Result<()> {
let (port, state) = harness::initialize(None, None)?;
let rng_seed = 0;
let subgraph_name = None;
assert_eq!(port, 8080);
assert_is_sine(
5,
2,
Duration::from_secs(10),
rng_seed,
state,
subgraph_name,
)
.await
}
#[tokio::test]
async fn default_headers() -> anyhow::Result<()> {
let (_, state) = harness::initialize(None, None)?;
let response = make_request(42, state, None).await?;
let headers = response.headers();
assert_eq!(200, response.status());
assert_eq!(1, headers.len());
assert!(headers.contains_key("content-type"));
Ok(())
}
#[tokio::test]
async fn default_response_generation_caches() -> anyhow::Result<()> {
let (_, state) = harness::initialize(None, None)?;
let mut responses: Vec<Query> = Vec::with_capacity(10);
for _ in 0..10 {
let response = make_request(4449, state.clone(), None).await?;
assert_eq!(200, response.status());
responses.push(parse_response(response).await?);
}
for (index, response) in responses.iter().enumerate() {
if index > 0 {
assert_eq!(response, &responses[index - 1]);
}
}
Ok(())
}
#[tokio::test(flavor = "multi_thread")]
async fn default_response_generation() -> anyhow::Result<()> {
let (_, state) = harness::initialize(Some("default_no_cache.yaml"), None)?;
let mut responses: Vec<Query> = Vec::with_capacity(1000);
let mut requests: FuturesUnordered<_> = (0..1000)
.map(|_| {
async {
let response = make_request(7, state.clone(), None).await?;
ensure!(200 == response.status());
parse_response(response).await
}
})
.collect();
while let Some(response) = requests.next().await {
responses.push(response?);
}
let user_alias = "nwHYPt6HYPXJ1";
let user_name_alias = "mH3ACoBr2";
let user_is_active_alias = "wVHIP0WIkF3xJVkyxw3";
for response in &responses {
assert!(
response
.posts
.as_ref()
.is_some_and(|posts| (0..=10).contains(&posts.len()))
);
}
let (users, posts): (Vec<User>, Vec<Post>) = {
let (users, posts): (Vec<_>, Vec<_>) = responses
.into_iter()
.map(|mut response| {
(
response
.aliased
.remove(user_alias)
.and_then(|user| serde_json_bytes::from_value(user).ok()),
response.post,
)
})
.collect();
(
users.into_iter().flatten().collect(),
posts.into_iter().flatten().collect(),
)
};
let user_count = users.len();
assert_eq!("0.5", format!("{:.1}", user_count as f32 / 1000.0));
for user in &users {
assert!(
user.distance
.is_some_and(|distance| (-1.0..=1.0).contains(&distance))
);
assert!(
user.aliased
.get(user_name_alias)
.and_then(|name| name.as_str())
.is_some_and(|name| (1..=10).contains(&name.chars().count()))
);
assert!(user.id.is_some_and(|id| (0..=100).contains(&id)));
}
let true_count = users
.iter()
.filter(|user| {
user.aliased
.get(user_is_active_alias)
.and_then(|is_active| is_active.as_bool())
.expect("is_active should be a bool")
})
.count();
assert_eq!(
"0.5",
format!("{:.1}", true_count as f32 / user_count as f32)
);
for post in posts {
assert!(post.views.is_some_and(|views| (0..=100).contains(&views)));
}
Ok(())
}