Skip to content

Commit

Permalink
[Turbopack] run tests multiple times to test caching (#68722)
Browse files Browse the repository at this point in the history
### What?

Test memory and eventually persistent caching
  • Loading branch information
sokra authored Aug 13, 2024
1 parent ce48d7c commit 7302f35
Show file tree
Hide file tree
Showing 20 changed files with 252 additions and 155 deletions.
64 changes: 35 additions & 29 deletions turbopack/crates/turbo-tasks-fetch/tests/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static REGISTRATION: Registration = register!(turbo_tasks_fetch::register);

#[tokio::test]
async fn basic_get() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let server = httpmock::MockServer::start();
let resource_mock = server.mock(|when, then| {
when.path("/foo.woff");
Expand All @@ -29,18 +29,20 @@ async fn basic_get() {
match result {
Err(_) => panic!(),
Ok(response) => {
let response = response.await.unwrap();
let response = response.await?;
assert_eq!(response.status, 200);
assert_eq!(*response.body.to_string().await.unwrap(), "responsebody");
assert_eq!(*response.body.to_string().await?, "responsebody");
}
}
anyhow::Ok(())
})
.await
.unwrap()
}

#[tokio::test]
async fn sends_user_agent() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let server = httpmock::MockServer::start();
let resource_mock = server.mock(|when, then| {
when.path("/foo.woff").header("User-Agent", "foo");
Expand All @@ -58,18 +60,20 @@ async fn sends_user_agent() {

let Ok(response) = result else { panic!() };

let response = response.await.unwrap();
let response = response.await?;
assert_eq!(response.status, 200);
assert_eq!(*response.body.to_string().await.unwrap(), "responsebody");
assert_eq!(*response.body.to_string().await?, "responsebody");
anyhow::Ok(())
})
.await
.unwrap()
}

// This is temporary behavior.
// TODO: Implement invalidation that respects Cache-Control headers.
#[tokio::test]
async fn invalidation_does_not_invalidate() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let server = httpmock::MockServer::start();
let resource_mock = server.mock(|when, then| {
when.path("/foo.woff").header("User-Agent", "foo");
Expand All @@ -79,50 +83,53 @@ async fn invalidation_does_not_invalidate() {
let url = Vc::cell(server.url("/foo.woff").into());
let user_agent = Vc::cell(Some("foo".into()));
let proxy = Vc::cell(None);
let result = &*fetch(url, user_agent, proxy).await.unwrap();
let result = &*fetch(url, user_agent, proxy).await?;
resource_mock.assert();

let Ok(response_vc) = result else { panic!() };
let response = response_vc.await.unwrap();
let response = response_vc.await?;
assert_eq!(response.status, 200);
assert_eq!(*response.body.to_string().await.unwrap(), "responsebody");
assert_eq!(*response.body.to_string().await?, "responsebody");

let second_result = &*fetch(url, user_agent, proxy).await.unwrap();
let second_result = &*fetch(url, user_agent, proxy).await?;
let Ok(second_response_vc) = second_result else {
panic!()
};
let second_response = second_response_vc.await.unwrap();
let second_response = second_response_vc.await?;

// Assert that a second request is never sent -- the result is cached via turbo
// tasks
resource_mock.assert_hits(1);
assert_eq!(response, second_response);
anyhow::Ok(())
})
.await
.unwrap()
}

#[tokio::test]
async fn errors_on_failed_connection() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let url = "https://doesnotexist/foo.woff";
let result = &*fetch(Vc::cell(url.into()), Vc::cell(None), Vc::cell(None)).await.unwrap();
let result = &*fetch(Vc::cell(url.into()), Vc::cell(None), Vc::cell(None)).await?;
let Err(err_vc) = result else {
panic!()
};
let err = &*err_vc.await.unwrap();
assert_eq!(*err.kind.await.unwrap(), FetchErrorKind::Connect);
assert_eq!(*err.url.await.unwrap(), url);
let err = &*err_vc.await?;
assert_eq!(*err.kind.await?, FetchErrorKind::Connect);
assert_eq!(*err.url.await?, url);

let issue = err_vc.to_issue(IssueSeverity::Error.into(), get_issue_context());
assert_eq!(*issue.severity().await.unwrap(), IssueSeverity::Error);
assert_eq!(*issue.description().await.unwrap().unwrap().await.unwrap(), StyledString::Text("There was an issue establishing a connection while requesting https://doesnotexist/foo.woff.".into()));
assert_eq!(*issue.severity().await?, IssueSeverity::Error);
assert_eq!(*issue.description().await?.unwrap().await?, StyledString::Text("There was an issue establishing a connection while requesting https://doesnotexist/foo.woff.".into()));
anyhow::Ok(())
})
.await
.await.unwrap()
}

#[tokio::test]
async fn errors_on_404() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let server = httpmock::MockServer::start();
let resource_url = server.url("/");
let result = &*fetch(
Expand All @@ -133,17 +140,14 @@ async fn errors_on_404() {
.await
.unwrap();
let Err(err_vc) = result else { panic!() };
let err = &*err_vc.await.unwrap();
assert!(matches!(
*err.kind.await.unwrap(),
FetchErrorKind::Status(404)
));
assert_eq!(*err.url.await.unwrap(), resource_url);
let err = &*err_vc.await?;
assert!(matches!(*err.kind.await?, FetchErrorKind::Status(404)));
assert_eq!(*err.url.await?, resource_url);

let issue = err_vc.to_issue(IssueSeverity::Error.into(), get_issue_context());
assert_eq!(*issue.severity().await.unwrap(), IssueSeverity::Error);
assert_eq!(*issue.severity().await?, IssueSeverity::Error);
assert_eq!(
*issue.description().await.unwrap().unwrap().await.unwrap(),
*issue.description().await?.unwrap().await?,
StyledString::Text(
format!(
"Received response with status 404 when requesting {}",
Expand All @@ -152,8 +156,10 @@ async fn errors_on_404() {
.into()
)
);
anyhow::Ok(())
})
.await
.unwrap()
}

fn get_issue_context() -> Vc<FileSystemPath> {
Expand Down
4 changes: 3 additions & 1 deletion turbopack/crates/turbo-tasks-fetch/tests/test_config.trs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
turbo_tasks::TurboTasks::new(turbo_tasks_memory::MemoryBackend::new(usize::MAX))
|_name, _initial | {
turbo_tasks::TurboTasks::new(turbo_tasks_memory::MemoryBackend::new(usize::MAX))
}
10 changes: 6 additions & 4 deletions turbopack/crates/turbo-tasks-macros-tests/tests/task_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ async fn one_unnamed_field(input: OneUnnamedField) -> Vc<Completion> {

#[tokio::test]
async fn tests() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
assert!(ReadRef::ptr_eq(
&one_unnamed_field(OneUnnamedField(42)).await.unwrap(),
&Completion::immutable().await.unwrap(),
))
&one_unnamed_field(OneUnnamedField(42)).await?,
&Completion::immutable().await?,
));
anyhow::Ok(())
})
.await
.unwrap()
}
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
turbo_tasks::TurboTasks::new(turbo_tasks_memory::MemoryBackend::new(usize::MAX))
|_name, _initial | {
turbo_tasks::TurboTasks::new(turbo_tasks_memory::MemoryBackend::new(usize::MAX))
}
12 changes: 5 additions & 7 deletions turbopack/crates/turbo-tasks-macros-tests/tests/value_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ async fn ignored_indexes() {
i32,
);

run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let input = IgnoredIndexes(-1, 2, -3);
let debug = input
.value_debug_format(usize::MAX)
.try_to_string()
.await
.unwrap();
let debug = input.value_debug_format(usize::MAX).try_to_string().await?;
assert!(!debug.contains("-1"));
assert!(debug.contains('2'));
assert!(!debug.contains("-3"));
anyhow::Ok(())
})
.await;
.await
.unwrap();
}
4 changes: 3 additions & 1 deletion turbopack/crates/turbo-tasks-memory/tests/test_config.trs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
turbo_tasks::TurboTasks::new(turbo_tasks_memory::MemoryBackend::new(usize::MAX))
|_name, _initial | {
turbo_tasks::TurboTasks::new(turbo_tasks_memory::MemoryBackend::new(usize::MAX))
}
2 changes: 1 addition & 1 deletion turbopack/crates/turbo-tasks-testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use turbo_tasks::{
TurboTasksCallApi,
};

pub use crate::run::{run, Registration};
pub use crate::run::{run, run_without_cache_check, Registration};

enum Task {
Spawned(Event),
Expand Down
57 changes: 48 additions & 9 deletions turbopack/crates/turbo-tasks-testing/src/run.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
use std::{
fmt::Debug,
future::Future,
sync::{Arc, OnceLock},
};

use anyhow::Result;
use turbo_tasks::{run_once, trace::TraceRawVcs, TurboTasksApi};

pub struct Registration {
execution_lock: OnceLock<()>,
func: fn(),
create_turbo_tasks: fn() -> Arc<dyn TurboTasksApi>,
create_turbo_tasks: fn(&str, bool) -> Arc<dyn TurboTasksApi>,
}

impl Registration {
#[doc(hidden)]
pub const fn new(create_turbo_tasks: fn() -> Arc<dyn TurboTasksApi>, func: fn()) -> Self {
pub const fn new(
create_turbo_tasks: fn(&str, bool) -> Arc<dyn TurboTasksApi>,
func: fn(),
) -> Self {
Registration {
execution_lock: OnceLock::new(),
func,
Expand All @@ -28,8 +33,8 @@ impl Registration {
self.execution_lock.get_or_init(self.func);
}

pub fn create_turbo_tasks(&self) -> Arc<dyn TurboTasksApi> {
(self.create_turbo_tasks)()
pub fn create_turbo_tasks(&self, name: &str, initial: bool) -> Arc<dyn TurboTasksApi> {
(self.create_turbo_tasks)(name, initial)
}
}

Expand All @@ -38,11 +43,12 @@ macro_rules! register {
($($other_register_fns:expr),* $(,)?) => {{
use turbo_tasks::TurboTasksApi;
use std::sync::Arc;
fn create_turbo_tasks() -> Arc<dyn TurboTasksApi> {
include!(concat!(
fn create_turbo_tasks(name: &str, initial: bool) -> Arc<dyn TurboTasksApi> {
let inner = include!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/test_config.trs"
))
));
(inner)(name, initial)
}
fn register_impl() {
$($other_register_fns();)*
Expand All @@ -58,11 +64,44 @@ macro_rules! register {
}};
}

pub async fn run<T>(registration: &Registration, fut: impl Future<Output = T> + Send + 'static) -> T
pub async fn run_without_cache_check<T>(
registration: &Registration,
fut: impl Future<Output = T> + Send + 'static,
) -> T
where
T: TraceRawVcs + Send + 'static,
{
registration.ensure_registered();
let tt = registration.create_turbo_tasks();
let name = closure_to_name(&fut);
let tt = registration.create_turbo_tasks(&name, true);
run_once(tt, async move { Ok(fut.await) }).await.unwrap()
}

fn closure_to_name<T>(value: &T) -> String {
let name = std::any::type_name_of_val(value);
name.replace("::{{closure}}", "").replace("::", "_")
}

pub async fn run<T, F>(
registration: &Registration,
fut: impl Fn() -> F + Send + 'static,
) -> Result<()>
where
F: Future<Output = Result<T>> + Send + 'static,
T: Debug + PartialEq + Eq + TraceRawVcs + Send + 'static,
{
registration.ensure_registered();

let name = closure_to_name(&fut);
let tt = registration.create_turbo_tasks(&name, true);
println!("Run #1 (without cache)");
let first = run_once(tt.clone(), fut()).await?;
println!("Run #2 (with memory cache, same TurboTasks instance)");
let second = run_once(tt, fut()).await?;
assert_eq!(first, second);
let tt = registration.create_turbo_tasks(&name, false);
println!("Run #3 (with persistent cache if available, new TurboTasks instance)");
let third = run_once(tt.clone(), fut()).await?;
assert_eq!(first, third);
Ok(())
}
2 changes: 1 addition & 1 deletion turbopack/crates/turbo-tasks-testing/tests/all_in_one.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ static REGISTRATION: Registration = register!();

#[tokio::test]
async fn all_in_one() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
let a: Vc<u32> = Vc::cell(4242);
assert_eq!(*a.await?, 4242);

Expand Down
6 changes: 3 additions & 3 deletions turbopack/crates/turbo-tasks-testing/tests/call_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ static REGISTRATION: Registration = register!();

#[tokio::test]
async fn functions() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
assert_eq!(*fn_plain().await?, 42);
assert_eq!(*fn_arg(43).await?, 43);
assert_eq!(*fn_vc_arg(Vc::cell(44)).await?, 44);
Expand Down Expand Up @@ -53,7 +53,7 @@ async fn async_fn_vc_arg(n: Vc<u32>) -> Result<Vc<u32>> {

#[tokio::test]
async fn methods() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
assert_eq!(*Value::static_method().await?, 42);
assert_eq!(*Value::async_static_method().await?, 42);

Expand Down Expand Up @@ -106,7 +106,7 @@ impl Value {

#[tokio::test]
async fn trait_methods() {
run(&REGISTRATION, async {
run(&REGISTRATION, || async {
assert_eq!(*Value::static_trait_method().await?, 42);
assert_eq!(*Value::async_static_trait_method().await?, 42);

Expand Down
Loading

0 comments on commit 7302f35

Please sign in to comment.