#![cfg(test)]
use crate::facts::{AllFacts, Loan, Point, Region};
use crate::intern;
use crate::program::parse_from_program;
use crate::tab_delim;
use crate::test_util::assert_equal;
use failure::Error;
use polonius_engine::{Algorithm, Output};
use rustc_hash::FxHashMap;
use std::path::Path;
fn test_facts(all_facts: &AllFacts, algorithms: &[Algorithm]) {
let naive = Output::compute(all_facts, Algorithm::Naive, true);
for &optimized_algorithm in algorithms {
println!("Algorithm {:?}", optimized_algorithm);
let opt = Output::compute(all_facts, optimized_algorithm, true);
assert_equal(&naive.borrow_live_at, &opt.borrow_live_at);
}
}
fn test_fn(dir_name: &str, fn_name: &str, algorithm: Algorithm) -> Result<(), Error> {
let facts_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("inputs")
.join(dir_name)
.join("nll-facts")
.join(fn_name);
println!("facts_dir = {:?}", facts_dir);
let tables = &mut intern::InternerTables::new();
let all_facts = tab_delim::load_tab_delimited_facts(tables, &facts_dir)?;
Ok(test_facts(&all_facts, &[algorithm]))
}
macro_rules! tests {
($($name:ident($dir:expr, $fn:expr),)*) => {
$(
mod $name {
use super::*;
#[test]
fn datafrog_opt() -> Result<(), Error> {
test_fn($dir, $fn, Algorithm::DatafrogOpt)
}
}
)*
}
}
tests! {
issue_47680("issue-47680", "main"),
}
#[test]
fn test_insensitive_errors() -> Result<(), Error> {
let facts_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("inputs")
.join("issue-47680")
.join("nll-facts")
.join("main");
println!("facts_dir = {:?}", facts_dir);
let tables = &mut intern::InternerTables::new();
let all_facts = tab_delim::load_tab_delimited_facts(tables, &facts_dir)?;
let insensitive = Output::compute(&all_facts, Algorithm::LocationInsensitive, false);
let mut expected = FxHashMap::default();
expected.insert(Point::from(1), vec![Loan::from(1)]);
expected.insert(Point::from(2), vec![Loan::from(2)]);
assert_equal(&insensitive.errors, &expected);
Ok(())
}
#[test]
fn test_sensitive_passes_issue_47680() -> Result<(), Error> {
let facts_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("inputs")
.join("issue-47680")
.join("nll-facts")
.join("main");
let tables = &mut intern::InternerTables::new();
let all_facts = tab_delim::load_tab_delimited_facts(tables, &facts_dir)?;
let sensitive = Output::compute(&all_facts, Algorithm::DatafrogOpt, false);
assert!(sensitive.errors.is_empty());
Ok(())
}
#[test]
fn no_subset_symmetries_exist() -> Result<(), Error> {
let facts_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("inputs")
.join("issue-47680")
.join("nll-facts")
.join("main");
let tables = &mut intern::InternerTables::new();
let all_facts = tab_delim::load_tab_delimited_facts(tables, &facts_dir)?;
let subset_symmetries_exist = |output: &Output<Region, Loan, Point>| {
for (_, subsets) in &output.subset {
for (r1, rs) in subsets {
if rs.contains(&r1) {
return true;
}
}
}
false
};
let naive = Output::compute(&all_facts, Algorithm::Naive, true);
assert!(!subset_symmetries_exist(&naive));
let opt = Output::compute(&all_facts, Algorithm::DatafrogOpt, true);
assert!(!subset_symmetries_exist(&opt));
Ok(())
}
#[test]
fn send_is_not_static_std_sync() {
let program = r"
universal_regions { }
block B0 {
borrow_region_at('a, L0), outlives('a: 'b), region_live_at('b);
}
";
let mut tables = intern::InternerTables::new();
let facts = parse_from_program(program, &mut tables).expect("Parsing failure");
test_facts(&facts, Algorithm::OPTIMIZED);
}
#[test]
fn escape_upvar_nested() {
let program = r"
universal_regions { }
block B0 {
borrow_region_at('a, L0), outlives('a: 'b), outlives('b: 'c), region_live_at('c);
}
";
let mut tables = intern::InternerTables::new();
let facts = parse_from_program(program, &mut tables).expect("Parsing failure");
test_facts(&facts, Algorithm::OPTIMIZED);
}
#[test]
fn issue_31567() {
let program = r"
universal_regions { }
block B0 {
borrow_region_at('a, L0),
outlives('a: 'b),
outlives('b: 'c),
outlives('c: 'd),
region_live_at('d);
}
";
let mut tables = intern::InternerTables::new();
let facts = parse_from_program(program, &mut tables).expect("Parsing failure");
test_facts(&facts, Algorithm::OPTIMIZED);
}
#[test]
fn borrowed_local_error() {
let program = r"
universal_regions { 'c }
block B0 {
borrow_region_at('a, L0), outlives('a: 'b), outlives('b: 'c);
}
";
let mut tables = intern::InternerTables::new();
let facts = parse_from_program(program, &mut tables).expect("Parsing failure");
test_facts(&facts, Algorithm::OPTIMIZED);
}