#![cfg(feature = "experimental-ion-1-1")]
#![cfg(feature = "experimental-reader-writer")]
#![cfg(feature = "experimental-tooling-apis")]
mod conformance_dsl;
use conformance_dsl::prelude::*;
use test_generator::test_resources;
use std::sync::LazyLock;
mod ion_tests {
use super::*;
#[derive(Default)]
struct SkipItem {
source: &'static str,
canonicalized_source: Option<String>,
tests: &'static [&'static str],
}
impl SkipItem {
fn canonicalize(&self) -> Option<Self> {
match std::fs::canonicalize(self.source) {
Ok(path_buf) => Some(Self {
canonicalized_source: Some(path_buf.to_string_lossy().to_string()),
..*self
}),
Err(_) => None,
}
}
}
macro_rules! skip {
( $l:literal ) => {
SkipItem { source: $l, canonicalized_source: None, tests: &[] }
};
( $l:literal, $($t:literal),+
) => {
SkipItem {source: $l, canonicalized_source: None, tests: &[ $($t),+ ] }
}
}
type SkipList = &'static [SkipItem];
static GLOBAL_CONFORMANCE_SKIPLIST: SkipList = &[
skip!(
"ion-tests/conformance/data_model/float.ion",
"Ion 1.1 binary" ),
skip!(
"ion-tests/conformance/data_model/decimal.ion",
"the decimal positive zero"
),
skip!("ion-tests/conformance/core/toplevel_produces.ion"),
skip!("ion-tests/conformance/demos/metaprogramming.ion"),
skip!("ion-tests/conformance/demos/telemetry_log.ion"),
skip!("ion-tests/conformance/eexp/arg_inlining.ion"),
skip!("ion-tests/conformance/eexp/binary/tagless_types.ion"),
skip!("ion-tests/conformance/eexp/binary/argument_encoding.ion"),
skip!("ion-tests/conformance/system_macros/add_macros.ion"),
skip!("ion-tests/conformance/system_symbols.ion"),
skip!("ion-tests/conformance/system_macros/add_symbols.ion"),
skip!("ion-tests/conformance/system_macros/set_macros.ion"),
skip!("ion-tests/conformance/system_macros/set_symbols.ion"),
skip!(
"ion-tests/conformance/system_macros/default.ion",
"when the first argument is non-empty, the second argument is not expanded"
),
skip!(
"ion-tests/conformance/system_macros/delta.ion",
"delta and repeat can be combined to generate",
"it is possible to create a delta of deltas encoding"
),
skip!("ion-tests/conformance/system_macros/make_decimal.ion"),
skip!("ion-tests/conformance/system_macros/parse_ion.ion"),
skip!("ion-tests/conformance/system_macros/make_timestamp.ion"),
skip!("ion-tests/conformance/system_macros/annotate.ion"),
skip!("ion-tests/conformance/system_macros/make_field.ion"),
skip!("ion-tests/conformance/system_macros/use.ion"),
skip!("ion-tests/conformance/tdl/expression_groups.ion"),
skip!("ion-tests/conformance/tdl/for.ion"),
skip!("ion-tests/conformance/ivm.ion"),
skip!("ion-tests/conformance/local_symtab.ion"),
skip!("ion-tests/conformance/local_symtab_imports.ion"),
skip!("ion-tests/conformance/tdl/variable_expansion.ion"),
];
static CANONICAL_SKIP_LIST: LazyLock<Vec<SkipItem>> = LazyLock::new(|| {
GLOBAL_CONFORMANCE_SKIPLIST
.iter()
.filter_map(|skip| skip.canonicalize())
.collect()
});
#[test]
#[ignore = "Only used to maintain skiplist, no need to break builds because of it. (use --include-ignored to run)"]
fn check_skiplist() {
let mut skip_file_removed = true;
for skip_item in GLOBAL_CONFORMANCE_SKIPLIST.iter() {
if skip_item.canonicalize().is_none() {
skip_file_removed = false;
println!("MISSING: {}", skip_item.source);
}
}
assert!(skip_file_removed);
}
#[test_resources("ion-tests/conformance/**/*.ion")]
fn conformance(file_name: &str) {
let file_name: String = std::fs::canonicalize(file_name)
.unwrap()
.to_string_lossy()
.into();
let mut total_tests: usize = 0;
let mut total_skipped: usize = 0;
let skip_item = CANONICAL_SKIP_LIST.iter().find(|item| {
item.canonicalized_source
.as_ref()
.is_some_and(|source| *source == file_name)
});
if skip_item.is_some_and(|item| item.tests.is_empty()) {
println!("SKIPPING: {file_name}");
return;
}
let skip_tests: &[&'static str] = skip_item.map(|item| item.tests).unwrap_or(&[]);
let collection = TestCollection::load(&file_name).expect("unable to load test file");
for test in collection.iter() {
total_tests += 1;
let name = if let Some(name) = &test.name {
if skip_tests.contains(&name.as_str()) {
println!("Skipping: {file_name} => \"{name}\"");
total_skipped += 1;
continue;
}
name
} else {
""
};
println!("TESTING: {file_name} => {name}");
test.run().expect("test failed");
}
println!("SUMMARY: {file_name} : Total Tests {total_tests} : Skipped {total_skipped}",);
}
}