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:: * ;
3
3
4
4
use crate :: util:: Escaper ;
5
5
use codegen:: { Function , Module , Scope } ;
6
- use std:: collections:: HashMap ;
6
+ use std:: collections:: { HashMap , HashSet } ;
7
7
8
8
#[ derive( Debug ) ]
9
9
pub enum TestComponent {
@@ -47,13 +47,15 @@ impl TestModule {
47
47
pub struct Generator {
48
48
result : TestModule ,
49
49
curr_path : Vec < String > ,
50
+ seen_fns : Vec < HashSet < String > > ,
50
51
}
51
52
52
53
impl Generator {
53
54
pub fn new ( ) -> Generator {
54
55
Self {
55
56
result : Default :: default ( ) ,
56
57
curr_path : Default :: default ( ) ,
58
+ seen_fns : Default :: default ( ) ,
57
59
}
58
60
}
59
61
@@ -79,63 +81,123 @@ impl Generator {
79
81
contents,
80
82
} ) => {
81
83
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
+
82
87
let out_file = format ! ( "{}.rs" , & mod_name) ;
83
88
let path: Vec < _ > = self
84
89
. curr_path
85
90
. iter ( )
86
91
. chain ( std:: iter:: once ( & out_file) )
87
92
. collect ( ) ;
88
- let mut module = Module :: new ( & mod_name) ;
89
- gen_tests ( module. scope ( ) , & contents) ;
90
93
self . result . insert ( & path, TestScope { module } ) ;
91
94
}
92
95
}
93
96
}
94
- }
95
97
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 ( ) ;
99
102
}
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
+ }
102
113
}
103
- }
104
114
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
+ }
107
118
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
110
121
}
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 ( ) ;
113
128
}
114
- }
115
129
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
+ }
137
195
}
138
196
}
197
+
198
+ if ignore_test {
199
+ test_fn. attr ( "ignore = \" not yet implemented\" " ) ;
200
+ }
139
201
}
140
202
}
141
203
0 commit comments