diff --git a/tests/helpers/mod.rs b/tests/helpers/mod.rs index a58a82e42b..baf0df31b6 100644 --- a/tests/helpers/mod.rs +++ b/tests/helpers/mod.rs @@ -18,6 +18,46 @@ use roc::types::{Expected, Type}; use std::hash::Hash; use std::path::{Path, PathBuf}; +/// Used in the with_larger_debug_stack() function, for tests that otherwise +/// run out of stack space in debug builds (but don't in --release builds) +#[allow(dead_code)] +const EXPANDED_STACK_SIZE: usize = 4 * 1024 * 1024; + +/// Without this, some tests pass in `cargo test --release` but fail without +/// the --release flag because they run out of stack space. This increases +/// stack size for debug builds only, while leaving the stack space at the default +/// amount for release builds. +#[allow(dead_code)] +#[cfg(debug_assertions)] +pub fn with_larger_debug_stack(run_test: F) +where + F: FnOnce() -> (), + F: Send, + F: 'static, +{ + std::thread::Builder::new() + .stack_size(EXPANDED_STACK_SIZE) + .spawn(run_test) + .expect("Error while spawning expanded dev stack size thread") + .join() + .expect("Error while joining expanded dev stack size thread") +} + +/// In --release builds, don't increase the stack size. Run the test normally. +/// This way, we find out if any of our tests are blowing the stack even after +/// optimizations in release builds. +#[allow(dead_code)] +#[cfg(not(debug_assertions))] +#[inline(always)] +pub fn with_larger_debug_stack(run_test: F) +where + F: FnOnce() -> (), + F: Send, + F: 'static, +{ + run_test() +} + #[allow(dead_code)] pub fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result, Fail> { parse_loc_with(arena, input).map(|loc_expr| loc_expr.value) diff --git a/tests/test_canonicalize.rs b/tests/test_canonicalize.rs index 21a6c45f36..ea63ecd55d 100644 --- a/tests/test_canonicalize.rs +++ b/tests/test_canonicalize.rs @@ -228,8 +228,9 @@ mod test_canonicalize { #[test] fn recognize_tail_calls() { - let src = indoc!( - r#" + with_larger_debug_stack(|| { + let src = indoc!( + r#" g = \x -> case x when 0 -> 0 @@ -248,39 +249,42 @@ mod test_canonicalize { 0 "# - ); - let arena = Bump::new(); - let (actual, _output, _problems, _var_store, _vars) = - can_expr_with(&arena, "Blah", src, &ImMap::default()); + ); + let arena = Bump::new(); + let (actual, _output, _problems, _var_store, _vars, _constraint) = + can_expr_with(&arena, "Blah", src, &ImMap::default()); - let detected = get_closure(&actual, 0); - assert_eq!(detected, Recursive::TailRecursive); + let detected = get_closure(&actual.value, 0); + assert_eq!(detected, Recursive::TailRecursive); - let detected = get_closure(&actual, 1); - assert_eq!(detected, Recursive::NotRecursive); + let detected = get_closure(&actual.value, 1); + assert_eq!(detected, Recursive::NotRecursive); - let detected = get_closure(&actual, 2); - assert_eq!(detected, Recursive::TailRecursive); + let detected = get_closure(&actual.value, 2); + assert_eq!(detected, Recursive::TailRecursive); + }); } #[test] fn case_tail_call() { - let src = indoc!( - r#" - g = \x -> - case x when - 0 -> 0 - _ -> g (x - 1) + with_larger_debug_stack(|| { + let src = indoc!( + r#" + g = \x -> + case x when + 0 -> 0 + _ -> g (x + 1) - 0 - "# - ); - let arena = Bump::new(); - let (actual, _output, _problems, _var_store, _vars) = - can_expr_with(&arena, "Blah", src, &ImMap::default()); + 0 + "# + ); + let arena = Bump::new(); + let (actual, _output, _problems, _var_store, _vars, _constraint) = + can_expr_with(&arena, "Blah", src, &ImMap::default()); - let detected = get_closure(&actual, 0); - assert_eq!(detected, Recursive::TailRecursive); + let detected = get_closure(&actual.value, 0); + assert_eq!(detected, Recursive::TailRecursive); + }); } #[test] @@ -313,18 +317,19 @@ mod test_canonicalize { "# ); let arena = Bump::new(); - let (actual, _output, _problems, _var_store, _vars) = + let (actual, _output, _problems, _var_store, _vars, _constraint) = can_expr_with(&arena, "Blah", src, &ImMap::default()); - let detected = get_closure(&actual, 0); + let detected = get_closure(&actual.value, 0); assert_eq!(detected, Recursive::Recursive); } #[test] fn mutual_recursion() { - // TODO when a case witn no branches parses, remove the pattern wildcard here - let src = indoc!( - r#" + with_larger_debug_stack(|| { + // TODO when a case with no branches parses, remove the pattern wildcard here + let src = indoc!( + r#" q = \x -> case x when 0 -> 0 @@ -337,16 +342,17 @@ mod test_canonicalize { 0 "# - ); - let arena = Bump::new(); - let (actual, _output, _problems, _var_store, _vars) = - can_expr_with(&arena, "Blah", src, &ImMap::default()); + ); + let arena = Bump::new(); + let (actual, _output, _problems, _var_store, _vars, _constraint) = + can_expr_with(&arena, "Blah", src, &ImMap::default()); - let detected = get_closure(&actual, 0); - assert_eq!(detected, Recursive::Recursive); + let detected = get_closure(&actual.value, 0); + assert_eq!(detected, Recursive::Recursive); - let detected = get_closure(&actual, 1); - assert_eq!(detected, Recursive::Recursive); + let detected = get_closure(&actual.value, 1); + assert_eq!(detected, Recursive::Recursive); + }); } //#[test]