Skip to content

Commit a3778d0

Browse files
authored
Update Conformance Test Generator to latest partiql-tests (#208)
Update Conformance Test Generator to latest partiql-tests
1 parent 76f23d2 commit a3778d0

File tree

7 files changed

+511
-239
lines changed

7 files changed

+511
-239
lines changed

partiql-conformance-test-generator/src/generator.rs

Lines changed: 102 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use crate::schema::spec::{Assertion, Namespace, TestCase, TestDocument};
2-
use crate::schema::structure::{TestDir, TestEntry, TestFile, TestRoot};
1+
use crate::schema::spec::*;
2+
use crate::schema::structure::*;
33

44
use crate::util::Escaper;
55
use codegen::{Function, Module, Scope};
6-
use std::collections::HashMap;
6+
use std::collections::{HashMap, HashSet};
77

88
#[derive(Debug)]
99
pub enum TestComponent {
@@ -47,13 +47,15 @@ impl TestModule {
4747
pub struct Generator {
4848
result: TestModule,
4949
curr_path: Vec<String>,
50+
seen_fns: Vec<HashSet<String>>,
5051
}
5152

5253
impl Generator {
5354
pub fn new() -> Generator {
5455
Self {
5556
result: Default::default(),
5657
curr_path: Default::default(),
58+
seen_fns: Default::default(),
5759
}
5860
}
5961

@@ -79,63 +81,123 @@ impl Generator {
7981
contents,
8082
}) => {
8183
let mod_name = file_name.replace(".ion", "").escape_path();
84+
let mut module = Module::new(&mod_name);
85+
self.gen_tests(module.scope(), &contents);
86+
8287
let out_file = format!("{}.rs", &mod_name);
8388
let path: Vec<_> = self
8489
.curr_path
8590
.iter()
8691
.chain(std::iter::once(&out_file))
8792
.collect();
88-
let mut module = Module::new(&mod_name);
89-
gen_tests(module.scope(), &contents);
9093
self.result.insert(&path, TestScope { module });
9194
}
9295
}
9396
}
94-
}
9597

96-
fn gen_tests(scope: &mut Scope, test_document: &TestDocument) {
97-
for namespace in &test_document.namespaces {
98-
gen_mod(scope, namespace);
98+
fn gen_tests(&mut self, scope: &mut Scope, doc: &PartiQLTestDocument) {
99+
self.seen_fns.push(HashSet::new());
100+
self.gen_variants(scope, &doc.0);
101+
self.seen_fns.pop();
99102
}
100-
for test in &test_document.test_cases {
101-
gen_test(scope, test);
103+
104+
fn gen_variants(&mut self, scope: &mut Scope, variants: &[TestVariant]) {
105+
for var in variants {
106+
match var {
107+
TestVariant::TestCase(test) => self.gen_test(scope, test),
108+
TestVariant::Namespace(namespace) => self.gen_mod(scope, namespace),
109+
TestVariant::Environments(envs) => self.gen_envs(scope, envs),
110+
TestVariant::EquivalenceClass(equivs) => self.gen_equivs(scope, equivs),
111+
}
112+
}
102113
}
103-
}
104114

105-
fn gen_mod(scope: &mut Scope, namespace: &Namespace) {
106-
let module = scope.new_module(&namespace.name.escape_module_name());
115+
fn gen_envs(&mut self, _scope: &mut Scope, _envs: &Environments) {
116+
// TODO
117+
}
107118

108-
for ns in &namespace.namespaces {
109-
gen_mod(module.scope(), ns);
119+
fn gen_equivs(&mut self, _scope: &mut Scope, _equivs: &EquivalenceClass) {
120+
// TODO
110121
}
111-
for test in &namespace.test_cases {
112-
gen_test(module.scope(), test);
122+
123+
fn gen_mod(&mut self, scope: &mut Scope, namespace: &Namespace) {
124+
let module = scope.new_module(&namespace.name.escape_module_name());
125+
self.seen_fns.push(HashSet::new());
126+
self.gen_variants(module.scope(), &namespace.contents);
127+
self.seen_fns.pop();
113128
}
114-
}
115129

116-
fn gen_test(scope: &mut Scope, test_case: &TestCase) {
117-
let test_fn: &mut Function = scope.new_fn(&test_case.test_name.escape_test_name());
118-
test_fn.attr("test");
119-
for assertion in &test_case.assertions {
120-
match assertion {
121-
Assertion::SyntaxSuccess => {
122-
test_fn.line(format!(
123-
r####"crate::pass_syntax(r#"{}"#);"####,
124-
&test_case.statement
125-
));
126-
}
127-
Assertion::SyntaxFail => {
128-
test_fn.line(format!(
129-
r####"crate::fail_syntax(r#"{}"#);"####,
130-
&test_case.statement
131-
));
132-
}
133-
Assertion::NotYetImplemented => {
134-
// for `NotYetImplemented` assertions, add the 'ignore' annotation to the test case
135-
test_fn.attr("ignore = \"not yet implemented\"");
136-
test_fn.attr("allow(unused_variables)");
130+
fn intern_test_name(&mut self, mut name: String) -> String {
131+
let seen_fns = self.seen_fns.last_mut().unwrap();
132+
133+
while seen_fns.contains(&name) {
134+
name.push('_');
135+
}
136+
137+
seen_fns.insert(name.clone());
138+
name
139+
}
140+
141+
fn gen_test(&mut self, scope: &mut Scope, test_case: &TestCase) {
142+
let escaped_name = test_case.name.escape_test_name();
143+
let name = self.intern_test_name(escaped_name);
144+
145+
let test_fn: &mut Function = scope.new_fn(&name);
146+
test_fn.attr("test");
147+
test_fn.attr("allow(text_direction_codepoint_in_literal)");
148+
149+
let doc = format!("Generated test for test named `{}`", &test_case.name);
150+
test_fn.doc(&doc);
151+
152+
let mut ignore_test = false;
153+
154+
for assertion in &test_case.assert {
155+
match assertion {
156+
Assertion::SyntaxSuccess(_) => {
157+
test_fn.line(format!(
158+
r####"crate::pass_syntax(r#"{}"#);"####,
159+
&test_case.statement
160+
));
161+
}
162+
Assertion::SyntaxFail(_) => {
163+
test_fn.line(format!(
164+
r####"crate::fail_syntax(r#"{}"#);"####,
165+
&test_case.statement
166+
));
167+
}
168+
Assertion::StaticAnalysisFail(_) => {
169+
// TODO semantics tests are not yet implemented
170+
ignore_test = true;
171+
172+
test_fn.line(format!(
173+
r####"crate::fail_semantics(r#"{}"#);"####,
174+
&test_case.statement
175+
));
176+
}
177+
Assertion::EvaluationSuccess(_) => {
178+
// TODO evaluation success tests are not yet implemented
179+
ignore_test = true;
180+
181+
test_fn.line(format!(
182+
r####"crate::pass_eval(r##"{}"##);"####,
183+
&test_case.statement
184+
));
185+
}
186+
Assertion::EvaluationFail(_) => {
187+
// TODO evaluation fail tests are not yet implemented
188+
ignore_test = true;
189+
190+
test_fn.line(format!(
191+
r####"crate::fail_eval(r##"{}"##);"####,
192+
&test_case.statement
193+
));
194+
}
137195
}
138196
}
197+
198+
if ignore_test {
199+
test_fn.attr("ignore = \"not yet implemented\"");
200+
}
139201
}
140202
}
141203

partiql-conformance-test-generator/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ impl Config {
4040
test_data: impl AsRef<Path>,
4141
out_path: impl AsRef<Path>,
4242
) -> miette::Result<()> {
43-
let schema = read_schema(test_data)?;
44-
let scopes = Generator::new().generate(schema)?;
43+
let schema = read_schema(&test_data)?;
44+
let tests = Generator::new().generate(schema)?;
4545

46-
// TODO implement OverwriteStrategy
46+
// TODO overwrite vs. backup old content?
4747
let config = WriterConfig::new(TreeDepth::N(4));
48-
Writer::new(config).write(out_path, scopes)?;
48+
Writer::new(config).write(out_path, tests)?;
4949
Ok(())
5050
}
5151
}

0 commit comments

Comments
 (0)