Expand stack size for some tests.

This commit is contained in:
Richard Feldman 2019-12-05 19:35:20 -05:00
parent 35177f0e56
commit c862ee9fca
2 changed files with 85 additions and 39 deletions

View file

@ -18,6 +18,46 @@ use roc::types::{Expected, Type};
use std::hash::Hash; use std::hash::Hash;
use std::path::{Path, PathBuf}; 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<F>(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<F>(run_test: F)
where
F: FnOnce() -> (),
F: Send,
F: 'static,
{
run_test()
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<ast::Expr<'a>, Fail> { pub fn parse_with<'a>(arena: &'a Bump, input: &'a str) -> Result<ast::Expr<'a>, Fail> {
parse_loc_with(arena, input).map(|loc_expr| loc_expr.value) parse_loc_with(arena, input).map(|loc_expr| loc_expr.value)

View file

@ -228,6 +228,7 @@ mod test_canonicalize {
#[test] #[test]
fn recognize_tail_calls() { fn recognize_tail_calls() {
with_larger_debug_stack(|| {
let src = indoc!( let src = indoc!(
r#" r#"
g = \x -> g = \x ->
@ -250,37 +251,40 @@ mod test_canonicalize {
"# "#
); );
let arena = Bump::new(); 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()); 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::TailRecursive); assert_eq!(detected, Recursive::TailRecursive);
let detected = get_closure(&actual, 1); let detected = get_closure(&actual.value, 1);
assert_eq!(detected, Recursive::NotRecursive); assert_eq!(detected, Recursive::NotRecursive);
let detected = get_closure(&actual, 2); let detected = get_closure(&actual.value, 2);
assert_eq!(detected, Recursive::TailRecursive); assert_eq!(detected, Recursive::TailRecursive);
});
} }
#[test] #[test]
fn case_tail_call() { fn case_tail_call() {
with_larger_debug_stack(|| {
let src = indoc!( let src = indoc!(
r#" r#"
g = \x -> g = \x ->
case x when case x when
0 -> 0 0 -> 0
_ -> g (x - 1) _ -> g (x + 1)
0 0
"# "#
); );
let arena = Bump::new(); 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()); 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::TailRecursive); assert_eq!(detected, Recursive::TailRecursive);
});
} }
#[test] #[test]
@ -313,16 +317,17 @@ mod test_canonicalize {
"# "#
); );
let arena = Bump::new(); 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()); 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); assert_eq!(detected, Recursive::Recursive);
} }
#[test] #[test]
fn mutual_recursion() { fn mutual_recursion() {
// TODO when a case witn no branches parses, remove the pattern wildcard here with_larger_debug_stack(|| {
// TODO when a case with no branches parses, remove the pattern wildcard here
let src = indoc!( let src = indoc!(
r#" r#"
q = \x -> q = \x ->
@ -339,14 +344,15 @@ mod test_canonicalize {
"# "#
); );
let arena = Bump::new(); 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()); 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); assert_eq!(detected, Recursive::Recursive);
let detected = get_closure(&actual, 1); let detected = get_closure(&actual.value, 1);
assert_eq!(detected, Recursive::Recursive); assert_eq!(detected, Recursive::Recursive);
});
} }
//#[test] //#[test]