summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/build.rs483
-rw-r--r--dhall/src/phase/resolve.rs13
-rw-r--r--dhall/src/tests.rs323
3 files changed, 457 insertions, 362 deletions
diff --git a/dhall/build.rs b/dhall/build.rs
index 166b036..4c654c9 100644
--- a/dhall/build.rs
+++ b/dhall/build.rs
@@ -2,77 +2,99 @@ use std::env;
use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use walkdir::WalkDir;
+#[derive(Debug, Clone, Copy)]
+enum FileType {
+ Text,
+ Binary,
+}
+
+impl FileType {
+ fn to_ext(self) -> &'static str {
+ match self {
+ FileType::Text => "dhall",
+ FileType::Binary => "dhallb",
+ }
+ }
+}
+
fn dhall_files_in_dir<'a>(
dir: &'a Path,
take_a_suffix: bool,
+ filetype: FileType,
) -> impl Iterator<Item = (String, String)> + 'a {
WalkDir::new(dir)
.into_iter()
.filter_map(|e| e.ok())
.filter_map(move |path| {
- let path = path.path();
- let path = path.strip_prefix(dir).unwrap();
- let ext = path.extension();
- if ext != Some(&OsString::from("dhall"))
- && ext != Some(&OsString::from("dhallb"))
- {
+ let path = path.path().strip_prefix(dir).unwrap();
+ let ext = path.extension()?;
+ if ext != &OsString::from(filetype.to_ext()) {
return None;
}
- let ext = ext.unwrap();
let path = path.to_string_lossy();
let path = &path[..path.len() - 1 - ext.len()];
- let path = if take_a_suffix {
- if &path[path.len() - 1..] != "A" {
- return None;
- } else {
- path[..path.len() - 1].to_owned()
- }
+ let path = if take_a_suffix && &path[path.len() - 1..] != "A" {
+ return None;
+ } else if take_a_suffix {
+ path[..path.len() - 1].to_owned()
} else {
path.to_owned()
};
+ // Transform path into a valie Rust identifier
let name = path.replace("/", "_").replace("-", "_");
Some((name, path))
})
}
+#[derive(Debug, Clone)]
+struct TestFeature<F> {
+ /// Name of the module, used in the output of `cargo test`
+ module_name: &'static str,
+ /// Directory containing the tests files
+ directory: PathBuf,
+ /// Relevant variant of `dhall::tests::Test`
+ variant: &'static str,
+ /// Given a file name, whether to exclude it
+ path_filter: F,
+ /// Type of the input file
+ input_type: FileType,
+ /// Type of the output file, if any
+ output_type: Option<FileType>,
+}
+
fn make_test_module(
w: &mut impl Write, // Where to output the generated code
- mod_name: &str, // Name of the module, used in the output of `cargo test`
- subdir: &str, // Directory containing the tests files
- feature: &str, // Relevant variant of `dhall::tests::Feature`
- mut exclude: impl FnMut(&str) -> bool, // Given a file name, whether to exclude it
+ mut feature: TestFeature<impl FnMut(&str) -> bool>,
) -> std::io::Result<()> {
- let all_tests_dir = Path::new("../dhall-lang/tests/");
- let tests_dir = all_tests_dir.join(subdir);
- writeln!(w, "mod {} {{", mod_name)?;
- for (name, path) in dhall_files_in_dir(&tests_dir.join("success/"), true) {
- if exclude(&("success/".to_owned() + &path)) {
+ let tests_dir = feature.directory;
+ writeln!(w, "mod {} {{", feature.module_name)?;
+ let take_a_suffix = feature.output_type.is_some();
+ for (name, path) in
+ dhall_files_in_dir(&tests_dir, take_a_suffix, feature.input_type)
+ {
+ if (feature.path_filter)(&path) {
continue;
}
- writeln!(
- w,
- r#"make_spec_test!({}, Success, success_{}, "{}/success/{}");"#,
- feature,
- name,
- tests_dir.to_string_lossy(),
- path
- )?;
- }
- for (name, path) in dhall_files_in_dir(&tests_dir.join("failure/"), false) {
- if exclude(&("failure/".to_owned() + &path)) {
- continue;
- }
- writeln!(
- w,
- r#"make_spec_test!({}, Failure, failure_{}, "{}/failure/{}");"#,
- feature,
- name,
- tests_dir.to_string_lossy(),
- path
- )?;
+ let path = tests_dir.join(path);
+ let path = path.to_string_lossy();
+ let test = match feature.output_type {
+ None => {
+ let input_file =
+ format!("\"{}.{}\"", path, feature.input_type.to_ext());
+ format!("{}({})", feature.variant, input_file)
+ }
+ Some(output_type) => {
+ let input_file =
+ format!("\"{}A.{}\"", path, feature.input_type.to_ext());
+ let output_file =
+ format!("\"{}B.{}\"", path, output_type.to_ext());
+ format!("{}({}, {})", feature.variant, input_file, output_file)
+ }
+ };
+ writeln!(w, "make_spec_test!({}, {});", test, name)?;
}
writeln!(w, "}}")?;
Ok(())
@@ -88,177 +110,270 @@ fn main() -> std::io::Result<()> {
let out_dir = env::var("OUT_DIR").unwrap();
let parser_tests_path = Path::new(&out_dir).join("spec_tests.rs");
+ let spec_tests_dir = Path::new("../dhall-lang/tests/");
let mut file = File::create(parser_tests_path)?;
- make_test_module(&mut file, "parse", "parser/", "Parser", |path| {
- false
- // Too slow in debug mode
- || path == "success/largeExpression"
- // TODO: projection by expression
- || path == "success/recordProjectionByExpression"
- || path == "success/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByTypeEmpty"
- || path == "success/unit/RecordProjectFields"
- // TODO: RFC3986 URLs
- || path == "success/unit/import/urls/emptyPath0"
- || path == "success/unit/import/urls/emptyPath1"
- || path == "success/unit/import/urls/emptyPathSegment"
- // TODO: toMap
- || path == "success/toMap"
- })?;
+ make_test_module(
+ &mut file,
+ TestFeature {
+ module_name: "parser_success",
+ directory: spec_tests_dir.join("parser/success/"),
+ variant: "ParserSuccess",
+ path_filter: |path: &str| {
+ false
+ // Too slow in debug mode
+ || path == "largeExpression"
+ // TODO: projection by expression
+ || path == "recordProjectionByExpression"
+ || path == "RecordProjectionByType"
+ || path == "unit/RecordProjectionByType"
+ || path == "unit/RecordProjectionByTypeEmpty"
+ || path == "unit/RecordProjectFields"
+ // TODO: RFC3986 URLs
+ || path == "unit/import/urls/emptyPath0"
+ || path == "unit/import/urls/emptyPath1"
+ || path == "unit/import/urls/emptyPathSegment"
+ // TODO: toMap
+ || path == "toMap"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Binary),
+ },
+ )?;
+
+ make_test_module(
+ &mut file,
+ TestFeature {
+ module_name: "parser_failure",
+ directory: spec_tests_dir.join("parser/failure/"),
+ variant: "ParserFailure",
+ path_filter: |_path: &str| false,
+ input_type: FileType::Text,
+ output_type: None,
+ },
+ )?;
+
+ make_test_module(
+ &mut file,
+ TestFeature {
+ module_name: "printer",
+ directory: spec_tests_dir.join("parser/success/"),
+ variant: "Printer",
+ path_filter: |path: &str| {
+ false
+ // Too slow in debug mode
+ || path == "largeExpression"
+ // TODO: projection by expression
+ || path == "recordProjectionByExpression"
+ || path == "RecordProjectionByType"
+ || path == "unit/RecordProjectionByType"
+ || path == "unit/RecordProjectionByTypeEmpty"
+ // TODO: RFC3986 URLs
+ || path == "unit/import/urls/emptyPath0"
+ || path == "unit/import/urls/emptyPath1"
+ || path == "unit/import/urls/emptyPathSegment"
+ // TODO: toMap
+ || path == "toMap"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Binary),
+ },
+ )?;
- make_test_module(&mut file, "printer", "parser/", "Printer", |path| {
- // Failure tests are only for the parser
- path.starts_with("failure/")
- // Too slow in debug mode
- || path == "success/largeExpression"
- // TODO: projection by expression
- || path == "success/recordProjectionByExpression"
- || path == "success/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByTypeEmpty"
- // TODO: RFC3986 URLs
- || path == "success/unit/import/urls/emptyPath0"
- || path == "success/unit/import/urls/emptyPath1"
- || path == "success/unit/import/urls/emptyPathSegment"
- // TODO: toMap
- || path == "success/toMap"
- })?;
+ make_test_module(
+ &mut file,
+ TestFeature {
+ module_name: "binary_encoding",
+ directory: spec_tests_dir.join("parser/success/"),
+ variant: "BinaryEncoding",
+ path_filter: |path: &str| {
+ false
+ // Too slow in debug mode
+ || path == "largeExpression"
+ // See https://github.com/pyfisch/cbor/issues/109
+ || path == "double"
+ || path == "unit/DoubleLitExponentNoDot"
+ || path == "unit/DoubleLitSecretelyInt"
+ // TODO: projection by expression
+ || path == "recordProjectionByExpression"
+ || path == "RecordProjectionByType"
+ || path == "unit/RecordProjectionByType"
+ || path == "unit/RecordProjectionByTypeEmpty"
+ // TODO: RFC3986 URLs
+ || path == "unit/import/urls/emptyPath0"
+ || path == "unit/import/urls/emptyPath1"
+ || path == "unit/import/urls/emptyPathSegment"
+ // TODO: toMap
+ || path == "toMap"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Binary),
+ },
+ )?;
+
+ make_test_module(
+ &mut file,
+ TestFeature {
+ module_name: "binary_decoding_success",
+ directory: spec_tests_dir.join("binary-decode/success/"),
+ variant: "BinaryDecodingSuccess",
+ path_filter: |path: &str| {
+ false
+ // TODO: projection by expression
+ || path == "unit/RecordProjectFields"
+ || path == "unit/recordProjectionByExpression"
+ // TODO: toMap
+ || path == "unit/ToMap"
+ || path == "unit/ToMapAnnotated"
+ },
+ input_type: FileType::Binary,
+ output_type: Some(FileType::Text),
+ },
+ )?;
+
+ make_test_module(
+ &mut file,
+ TestFeature {
+ module_name: "binary_decoding_failure",
+ directory: spec_tests_dir.join("binary-decode/failure/"),
+ variant: "BinaryDecodingFailure",
+ path_filter: |_path: &str| false,
+ input_type: FileType::Binary,
+ output_type: None,
+ },
+ )?;
make_test_module(
&mut file,
- "binary_encoding",
- "parser/",
- "BinaryEncoding",
- |path| {
- // Failure tests are only for the parser
- path.starts_with("failure/")
- // Too slow in debug mode
- || path == "success/largeExpression"
- // See https://github.com/pyfisch/cbor/issues/109
- || path == "success/double"
- || path == "success/unit/DoubleLitExponentNoDot"
- || path == "success/unit/DoubleLitSecretelyInt"
- // TODO: projection by expression
- || path == "success/recordProjectionByExpression"
- || path == "success/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByTypeEmpty"
- // TODO: RFC3986 URLs
- || path == "success/unit/import/urls/emptyPath0"
- || path == "success/unit/import/urls/emptyPath1"
- || path == "success/unit/import/urls/emptyPathSegment"
- // TODO: toMap
- || path == "success/toMap"
+ TestFeature {
+ module_name: "beta_normalize",
+ directory: spec_tests_dir.join("normalization/success/"),
+ variant: "Normalization",
+ path_filter: |path: &str| {
+ // We don't support bignums
+ path == "simple/integerToDouble"
+ // Too slow
+ || path == "remoteSystems"
+ // TODO: projection by expression
+ || path == "unit/RecordProjectionByTypeEmpty"
+ || path == "unit/RecordProjectionByTypeNonEmpty"
+ || path == "unit/RecordProjectionByTypeNormalizeProjection"
+ // TODO: fix Double/show
+ || path == "prelude/JSON/number/1"
+ // TODO: toMap
+ || path == "unit/EmptyToMap"
+ || path == "unit/ToMap"
+ || path == "unit/ToMapWithType"
+ // TODO: Normalize field selection further by inspecting the argument
+ || path == "simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection0"
+ || path == "simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection1"
+ || path == "simplifications/rightBiasedMergeWithinRecursiveRecordMergeWithinFieldselection"
+ || path == "unit/RecordProjectionByTypeWithinFieldSelection"
+ || path == "unit/RecordProjectionWithinFieldSelection"
+ || path == "unit/RecursiveRecordMergeWithinFieldSelection0"
+ || path == "unit/RecursiveRecordMergeWithinFieldSelection1"
+ || path == "unit/RecursiveRecordMergeWithinFieldSelection2"
+ || path == "unit/RecursiveRecordMergeWithinFieldSelection3"
+ || path == "unit/RightBiasedMergeWithinFieldSelection0"
+ || path == "unit/RightBiasedMergeWithinFieldSelection1"
+ || path == "unit/RightBiasedMergeWithinFieldSelection2"
+ || path == "unit/RightBiasedMergeWithinFieldSelection3"
+ || path == "unit/RightBiasedMergeEquivalentArguments"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Text),
},
)?;
make_test_module(
&mut file,
- "binary_decoding",
- "binary-decode/",
- "BinaryDecoding",
- |path| {
- false
- // TODO: projection by expression
- || path == "success/unit/RecordProjectFields"
- || path == "success/unit/recordProjectionByExpression"
- // TODO: toMap
- || path == "success/unit/ToMap"
- || path == "success/unit/ToMapAnnotated"
+ TestFeature {
+ module_name: "alpha_normalize",
+ directory: spec_tests_dir.join("alpha-normalization/success/"),
+ variant: "AlphaNormalization",
+ path_filter: |path: &str| {
+ // This test doesn't typecheck
+ path == "unit/FunctionNestedBindingXXFree"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Text),
},
)?;
make_test_module(
&mut file,
- "beta_normalize",
- "normalization/",
- "Normalization",
- |path| {
- // We don't support bignums
- path == "success/simple/integerToDouble"
- // Too slow
- || path == "success/remoteSystems"
- // TODO: projection by expression
- || path == "success/unit/RecordProjectionByTypeEmpty"
- || path == "success/unit/RecordProjectionByTypeNonEmpty"
- || path == "success/unit/RecordProjectionByTypeNormalizeProjection"
- // TODO: fix Double/show
- || path == "success/prelude/JSON/number/1"
- // TODO: toMap
- || path == "success/unit/EmptyToMap"
- || path == "success/unit/ToMap"
- || path == "success/unit/ToMapWithType"
- // TODO: Normalize field selection further by inspecting the argument
- || path == "success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection0"
- || path == "success/simplifications/rightBiasedMergeWithinRecordProjectionWithinFieldSelection1"
- || path == "success/simplifications/rightBiasedMergeWithinRecursiveRecordMergeWithinFieldselection"
- || path == "success/unit/RecordProjectionByTypeWithinFieldSelection"
- || path == "success/unit/RecordProjectionWithinFieldSelection"
- || path == "success/unit/RecursiveRecordMergeWithinFieldSelection0"
- || path == "success/unit/RecursiveRecordMergeWithinFieldSelection1"
- || path == "success/unit/RecursiveRecordMergeWithinFieldSelection2"
- || path == "success/unit/RecursiveRecordMergeWithinFieldSelection3"
- || path == "success/unit/RightBiasedMergeWithinFieldSelection0"
- || path == "success/unit/RightBiasedMergeWithinFieldSelection1"
- || path == "success/unit/RightBiasedMergeWithinFieldSelection2"
- || path == "success/unit/RightBiasedMergeWithinFieldSelection3"
- || path == "success/unit/RightBiasedMergeEquivalentArguments"
+ TestFeature {
+ module_name: "typecheck_success",
+ directory: spec_tests_dir.join("typecheck/success/"),
+ variant: "TypecheckSuccess",
+ path_filter: |path: &str| {
+ false
+ // Too slow
+ || path == "prelude"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Text),
},
)?;
make_test_module(
&mut file,
- "alpha_normalize",
- "alpha-normalization/",
- "AlphaNormalization",
- |path| {
- // This test doesn't typecheck
- path == "success/unit/FunctionNestedBindingXXFree"
+ TestFeature {
+ module_name: "typecheck_failure",
+ directory: spec_tests_dir.join("typecheck/failure/"),
+ variant: "TypecheckFailure",
+ path_filter: |path: &str| {
+ false
+ // TODO: Enable imports in typecheck tests
+ || path == "importBoundary"
+ || path == "customHeadersUsingBoundVariable"
+ // TODO: projection by expression
+ || path == "unit/RecordProjectionByTypeFieldTypeMismatch"
+ || path == "unit/RecordProjectionByTypeNotPresent"
+ // TODO: toMap
+ || path == "unit/EmptyToMap"
+ || path == "unit/HeterogenousToMap"
+ || path == "unit/MistypedToMap1"
+ || path == "unit/MistypedToMap2"
+ || path == "unit/MistypedToMap3"
+ || path == "unit/MistypedToMap4"
+ || path == "unit/NonRecordToMap"
+ },
+ input_type: FileType::Text,
+ output_type: None,
},
)?;
make_test_module(
&mut file,
- "typecheck",
- "typecheck/",
- "Typecheck",
- |path| {
- false
- // TODO: Enable imports in typecheck tests
- || path == "failure/importBoundary"
- || path == "failure/customHeadersUsingBoundVariable"
- // Too slow
- || path == "success/prelude"
- // TODO: projection by expression
- || path == "failure/unit/RecordProjectionByTypeFieldTypeMismatch"
- || path == "failure/unit/RecordProjectionByTypeNotPresent"
- // TODO: toMap
- || path == "failure/unit/EmptyToMap"
- || path == "failure/unit/HeterogenousToMap"
- || path == "failure/unit/MistypedToMap1"
- || path == "failure/unit/MistypedToMap2"
- || path == "failure/unit/MistypedToMap3"
- || path == "failure/unit/MistypedToMap4"
- || path == "failure/unit/NonRecordToMap"
+ TestFeature {
+ module_name: "type_inference_success",
+ directory: spec_tests_dir.join("type-inference/success/"),
+ variant: "TypeInferenceSuccess",
+ path_filter: |path: &str| {
+ false
+ // TODO: projection by expression
+ || path == "unit/RecordProjectionByType"
+ || path == "unit/RecordProjectionByTypeEmpty"
+ || path == "unit/RecordProjectionByTypeJudgmentalEquality"
+ // TODO: toMap
+ || path == "unit/ToMap"
+ || path == "unit/ToMapAnnotated"
+ },
+ input_type: FileType::Text,
+ output_type: Some(FileType::Text),
},
)?;
make_test_module(
&mut file,
- "type_inference",
- "type-inference/",
- "TypeInference",
- |path| {
- false
- // TODO: projection by expression
- || path == "success/unit/RecordProjectionByType"
- || path == "success/unit/RecordProjectionByTypeEmpty"
- || path == "success/unit/RecordProjectionByTypeJudgmentalEquality"
- // TODO: toMap
- || path == "success/unit/ToMap"
- || path == "success/unit/ToMapAnnotated"
+ TestFeature {
+ module_name: "type_inference_failure",
+ directory: spec_tests_dir.join("type-inference/failure/"),
+ variant: "TypeInferenceFailure",
+ path_filter: |_path: &str| false,
+ input_type: FileType::Text,
+ output_type: None,
},
)?;
diff --git a/dhall/src/phase/resolve.rs b/dhall/src/phase/resolve.rs
index b715e72..a58f5e4 100644
--- a/dhall/src/phase/resolve.rs
+++ b/dhall/src/phase/resolve.rs
@@ -109,13 +109,22 @@ pub(crate) fn skip_resolve_expr(
mod spec_tests {
macro_rules! import_success {
($name:ident, $path:expr) => {
- make_spec_test!(Import, Success, $name, &("../dhall-lang/tests/import/success/".to_owned() + $path));
+ make_spec_test!(
+ ImportSuccess(
+ &("../dhall-lang/tests/import/success/".to_owned() + $path + "A.dhall"),
+ &("../dhall-lang/tests/import/success/".to_owned() + $path + "B.dhall")
+ ),
+ $name
+ );
};
}
// macro_rules! import_failure {
// ($name:ident, $path:expr) => {
- // make_spec_test!(Import, Failure, $name, &("../dhall-lang/tests/import/failure/".to_owned() + $path));
+ // make_spec_test!(
+ // ImportFailure(&("../dhall-lang/tests/import/failure/".to_owned() + $path + ".dhall")),
+ // $name
+ // );
// };
// }
diff --git a/dhall/src/tests.rs b/dhall/src/tests.rs
index 3055717..ae41038 100644
--- a/dhall/src/tests.rs
+++ b/dhall/src/tests.rs
@@ -22,13 +22,13 @@ right: `{}`"#,
#[macro_export]
macro_rules! make_spec_test {
- ($type:ident, $status:ident, $name:ident, $path:expr) => {
+ ($type:expr, $name:ident) => {
#[test]
#[allow(non_snake_case)]
fn $name() {
+ use crate::tests::Test::*;
use crate::tests::*;
- match run_test_stringy_error($path, Feature::$type, Status::$status)
- {
+ match run_test_stringy_error($type) {
Ok(_) => {}
Err(s) => panic!(s),
}
@@ -44,24 +44,22 @@ use crate::error::{Error, Result};
use crate::phase::Parsed;
#[allow(dead_code)]
-#[derive(Copy, Clone)]
-pub enum Feature {
- Parser,
- Printer,
- BinaryEncoding,
- BinaryDecoding,
- Import,
- Normalization,
- AlphaNormalization,
- Typecheck,
- TypeInference,
-}
-
-#[allow(dead_code)]
-#[derive(Copy, Clone)]
-pub enum Status {
- Success,
- Failure,
+#[derive(Clone)]
+pub enum Test<'a> {
+ ParserSuccess(&'a str, &'a str),
+ ParserFailure(&'a str),
+ Printer(&'a str, &'a str),
+ BinaryEncoding(&'a str, &'a str),
+ BinaryDecodingSuccess(&'a str, &'a str),
+ BinaryDecodingFailure(&'a str),
+ ImportSuccess(&'a str, &'a str),
+ ImportFailure(&'a str),
+ TypecheckSuccess(&'a str, &'a str),
+ TypecheckFailure(&'a str),
+ TypeInferenceSuccess(&'a str, &'a str),
+ TypeInferenceFailure(&'a str),
+ Normalization(&'a str, &'a str),
+ AlphaNormalization(&'a str, &'a str),
}
fn parse_file_str(file_path: &str) -> Result<Parsed> {
@@ -70,180 +68,153 @@ fn parse_file_str(file_path: &str) -> Result<Parsed> {
#[allow(dead_code)]
pub fn run_test_stringy_error(
- base_path: &str,
- feature: Feature,
- status: Status,
+ test: Test<'_>,
) -> std::result::Result<(), String> {
- let base_path: String = base_path.to_string();
- run_test(&base_path, feature, status)
- .map_err(|e| e.to_string())
- .map(|_| ())
+ run_test(test).map_err(|e| e.to_string()).map(|_| ())
}
-#[allow(clippy::single_match)]
-pub fn run_test(
- base_path: &str,
- feature: Feature,
- status: Status,
-) -> Result<()> {
- use self::Feature::*;
- use self::Status::*;
- let base_path = base_path.to_owned();
- match status {
- Success => {
- match feature {
- BinaryDecoding => {
- let expr_file_path = base_path.clone() + "A.dhallb";
- let expr_file_path = PathBuf::from(&expr_file_path);
- let mut expr_data = Vec::new();
- {
- File::open(&expr_file_path)?
- .read_to_end(&mut expr_data)?;
- }
- let expr = Parsed::parse_binary(&expr_data)?;
- let expected_file_path = base_path + "B.dhall";
- let expected = parse_file_str(&expected_file_path)?;
- assert_eq_pretty!(expr, expected);
-
- return Ok(());
+pub fn run_test(test: Test<'_>) -> Result<()> {
+ use self::Test::*;
+ match test {
+ ParserSuccess(expr_file_path, expected_file_path) => {
+ let expr = parse_file_str(&expr_file_path)?;
+ // This exercices both parsing and binary decoding
+ // Compare parse/decoded
+ let expected =
+ Parsed::parse_binary_file(&PathBuf::from(expected_file_path))?;
+ assert_eq_pretty!(expr, expected);
+ }
+ ParserFailure(file_path) => {
+ let err = parse_file_str(&file_path).unwrap_err();
+ match &err {
+ Error::Parse(_) => {}
+ Error::IO(e) if e.kind() == std::io::ErrorKind::InvalidData => {
}
- _ => {}
+ e => panic!("Expected parse error, got: {:?}", e),
}
- let expr_file_path = base_path.clone() + "A.dhall";
+ }
+ BinaryEncoding(expr_file_path, expected_file_path) => {
let expr = parse_file_str(&expr_file_path)?;
-
- match feature {
- Parser => {
- // This exercices both parsing and binary decoding
- // Compare parse/decoded
- let expected_file_path = base_path + "B.dhallb";
- let expected_file_path = PathBuf::from(&expected_file_path);
- let mut expected_data = Vec::new();
- {
- File::open(&expected_file_path)?
- .read_to_end(&mut expected_data)?;
- }
- let expected = Parsed::parse_binary(&expected_data)?;
- assert_eq_pretty!(expr, expected);
-
- return Ok(());
- }
- Printer => {
- // Round-trip pretty-printer
- let expr_string = expr.to_string();
- let expected = expr;
- let expr: Parsed = Parsed::parse_str(&expr_string)?;
- assert_eq!(expr, expected);
-
- return Ok(());
- }
- BinaryEncoding => {
- let expected_file_path = base_path + "B.dhallb";
- let expected_file_path = PathBuf::from(&expected_file_path);
- let mut expected_data = Vec::new();
- {
- File::open(&expected_file_path)?
- .read_to_end(&mut expected_data)?;
- }
- let expr_data = expr.encode()?;
-
- // Compare bit-by-bit
- if expr_data != expected_data {
- // use std::io::Write;
- // File::create(&expected_file_path)?.write_all(&expr_data)?;
- // Pretty-print difference
- assert_eq_pretty!(
- serde_cbor::de::from_slice::<
- serde_cbor::value::Value,
- >(&expr_data)
- .unwrap(),
- serde_cbor::de::from_slice::<
- serde_cbor::value::Value,
- >(&expected_data)
- .unwrap()
- );
- // If difference was not visible in the cbor::Value
- assert_eq!(expr_data, expected_data);
- }
-
- return Ok(());
- }
- _ => {}
+ let mut expected_data = Vec::new();
+ {
+ File::open(&PathBuf::from(&expected_file_path))?
+ .read_to_end(&mut expected_data)?;
}
+ let expr_data = expr.encode()?;
+
+ // Compare bit-by-bit
+ if expr_data != expected_data {
+ // use std::io::Write;
+ // File::create(&expected_file_path)?.write_all(&expr_data)?;
+ // Pretty-print difference
+ assert_eq_pretty!(
+ serde_cbor::de::from_slice::<serde_cbor::value::Value>(
+ &expr_data
+ )
+ .unwrap(),
+ serde_cbor::de::from_slice::<serde_cbor::value::Value>(
+ &expected_data
+ )
+ .unwrap()
+ );
+ // If difference was not visible in the cbor::Value
+ assert_eq!(expr_data, expected_data);
+ }
+ }
+ BinaryDecodingSuccess(expr_file_path, expected_file_path) => {
+ let expr =
+ Parsed::parse_binary_file(&PathBuf::from(expr_file_path))?;
+ let expected = parse_file_str(&expected_file_path)?;
+ assert_eq_pretty!(expr, expected);
+ }
+ BinaryDecodingFailure(file_path) => {
+ Parsed::parse_binary_file(&PathBuf::from(file_path)).unwrap_err();
+ }
+ Printer(expr_file_path, _) => {
+ let expected = parse_file_str(&expr_file_path)?;
+ // Round-trip pretty-printer
+ let expr: Parsed = Parsed::parse_str(&expected.to_string())?;
+ assert_eq!(expr, expected);
+ }
+ ImportSuccess(expr_file_path, expected_file_path) => {
+ let expr = parse_file_str(&expr_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize();
+ let expected = parse_file_str(&expected_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize();
- let expr = expr.resolve()?;
-
- let expected_file_path = base_path + "B.dhall";
+ assert_eq_display!(expr, expected);
+ }
+ ImportFailure(file_path) => {
+ parse_file_str(&file_path)?.resolve().unwrap_err();
+ }
+ TypecheckSuccess(expr_file_path, expected_file_path) => {
+ let expr = parse_file_str(&expr_file_path)?.resolve()?;
let expected = parse_file_str(&expected_file_path)?
.resolve()?
.typecheck()?
.normalize();
- match feature {
- Parser | Printer | BinaryEncoding | BinaryDecoding => {
- unreachable!()
- }
- Import => {
- let expr = expr.typecheck()?.normalize();
- assert_eq_display!(expr, expected);
- }
- Typecheck => {
- expr.typecheck_with(&expected.into_typed())?.get_type()?;
- }
- TypeInference => {
- let expr = expr.typecheck()?;
- let ty = expr.get_type()?.normalize();
- assert_eq_display!(ty, expected);
- }
- Normalization => {
- let expr = expr.typecheck()?.normalize();
- assert_eq_display!(expr, expected);
- }
- AlphaNormalization => {
- let expr = expr.typecheck()?.normalize().to_expr_alpha();
- assert_eq_display!(expr, expected.to_expr());
+ expr.typecheck_with(&expected.into_typed())?.get_type()?;
+ }
+ TypecheckFailure(file_path) => {
+ let res = parse_file_str(&file_path)?.skip_resolve()?.typecheck();
+ match res {
+ Err(_) => {}
+ // If e did typecheck, check that it doesn't have a type
+ Ok(e) => {
+ e.get_type().unwrap_err();
}
}
}
- Failure => {
- let file_path = base_path + ".dhall";
- match feature {
- Parser => {
- let err = parse_file_str(&file_path).unwrap_err();
- match &err {
- Error::Parse(_) => {}
- Error::IO(e)
- if e.kind() == std::io::ErrorKind::InvalidData => {}
- e => panic!("Expected parse error, got: {:?}", e),
- }
- }
- Printer | BinaryEncoding => unreachable!(),
- BinaryDecoding => {
- let expr_file_path = file_path + "b";
- let mut expr_data = Vec::new();
- {
- File::open(&PathBuf::from(&expr_file_path))?
- .read_to_end(&mut expr_data)?;
- }
- Parsed::parse_binary(&expr_data).unwrap_err();
- }
- Import => {
- parse_file_str(&file_path)?.resolve().unwrap_err();
- }
- Normalization | AlphaNormalization => unreachable!(),
- Typecheck | TypeInference => {
- let res =
- parse_file_str(&file_path)?.skip_resolve()?.typecheck();
- match res {
- Err(_) => {}
- // If e did typecheck, check that it doesn't have a type
- Ok(e) => {
- e.get_type().unwrap_err();
- }
- }
+ TypeInferenceSuccess(expr_file_path, expected_file_path) => {
+ let expr =
+ parse_file_str(&expr_file_path)?.resolve()?.typecheck()?;
+ let ty = expr.get_type()?.normalize();
+ let expected = parse_file_str(&expected_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize();
+ assert_eq_display!(ty, expected);
+ }
+ TypeInferenceFailure(file_path) => {
+ let res = parse_file_str(&file_path)?.skip_resolve()?.typecheck();
+ match res {
+ Err(_) => {}
+ // If e did typecheck, check that it doesn't have a type
+ Ok(e) => {
+ e.get_type().unwrap_err();
}
}
}
+ Normalization(expr_file_path, expected_file_path) => {
+ let expr = parse_file_str(&expr_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize();
+ let expected = parse_file_str(&expected_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize();
+
+ assert_eq_display!(expr, expected);
+ }
+ AlphaNormalization(expr_file_path, expected_file_path) => {
+ let expr = parse_file_str(&expr_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize()
+ .to_expr_alpha();
+ let expected = parse_file_str(&expected_file_path)?
+ .resolve()?
+ .typecheck()?
+ .normalize();
+
+ assert_eq_display!(expr, expected.to_expr());
+ }
}
Ok(())
}