Mercurial > hg > orthanc-stone
comparison Resources/CodeGeneration/stonegentool_test.py @ 493:6fbf2eae7c88 bgo-commands-codegen
All unit tests pass for generation, including handler and dispatcher
author | bgo-osimis |
---|---|
date | Fri, 22 Feb 2019 10:48:43 +0100 |
parents | 8e7e151ef472 |
children | fc17251477d6 |
comparison
equal
deleted
inserted
replaced
491:8e7e151ef472 | 493:6fbf2eae7c88 |
---|---|
4 # | 4 # |
5 | 5 |
6 from stonegentool import \ | 6 from stonegentool import \ |
7 EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \ | 7 EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \ |
8 CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \ | 8 CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \ |
9 GetTemplatingDictFromSchemaFilename | 9 GetTemplatingDictFromSchemaFilename,MakeTemplate |
10 import unittest | 10 import unittest |
11 import os | 11 import os |
12 import re | 12 import re |
13 import pprint | 13 import pprint |
14 from jinja2 import Template | 14 from jinja2 import Template |
15 | |
16 ymlSchema = trim("""rootName: VsolMessages | |
17 | |
18 struct B: | |
19 someAs: vector<A> | |
20 someInts: vector<int32> | |
21 | |
22 struct C: | |
23 someBs: vector<B> | |
24 ddd: vector<string> | |
25 | |
26 struct A: | |
27 someStrings: vector<string> | |
28 someInts2: vector<int32> | |
29 movies: vector<MovieType> | |
30 | |
31 enum MovieType: | |
32 - RomCom | |
33 - Horror | |
34 - ScienceFiction | |
35 - Vegetables | |
36 | |
37 enum CrispType: | |
38 - SaltAndPepper | |
39 - CreamAndChives | |
40 - Paprika | |
41 - Barbecue | |
42 ) | |
43 """) | |
44 | 15 |
45 def RemoveDateTimeLine(s : str): | 16 def RemoveDateTimeLine(s : str): |
46 # regex are non-multiline by default, and $ does NOT match the end of the line | 17 # regex are non-multiline by default, and $ does NOT match the end of the line |
47 s2 = re.sub(r"^// autogenerated by stonegentool on .*\n","",s) | 18 s2 = re.sub(r"^// autogenerated by stonegentool on .*\n","",s) |
48 return s2 | 19 return s2 |
119 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | 90 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') |
120 obj = LoadSchema(fn) | 91 obj = LoadSchema(fn) |
121 # we're happy if it does not crash :) | 92 # we're happy if it does not crash :) |
122 CheckSchemaSchema(obj) | 93 CheckSchemaSchema(obj) |
123 | 94 |
124 # def test_ParseSchema_bogus_json(self): | |
125 # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1_bogus_json.jsonc') | |
126 # self.assertRaises(Exception,LoadSchema,fn) | |
127 | |
128 # def test_ParseSchema_bogus_schema(self): | |
129 # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1_bogus_schema.jsonc') | |
130 # obj = LoadSchema(fn) | |
131 # self.assertRaises(Exception,CheckSchemaSchema,obj) | |
132 | |
133 def test_ComputeRequiredDeclarationOrder(self): | 95 def test_ComputeRequiredDeclarationOrder(self): |
134 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | 96 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') |
135 obj = LoadSchema(fn) | 97 obj = LoadSchema(fn) |
136 genOrder: str = ComputeRequiredDeclarationOrder(obj) | 98 genOrder: str = ComputeRequiredDeclarationOrder(obj) |
137 self.assertEqual(3,len(genOrder)) | 99 self.assertEqual(5,len(genOrder)) |
138 self.assertEqual("A",genOrder[0]) | 100 self.assertEqual("A",genOrder[0]) |
139 self.assertEqual("B",genOrder[1]) | 101 self.assertEqual("B",genOrder[1]) |
140 self.assertEqual("C",genOrder[2]) | 102 self.assertEqual("C",genOrder[2]) |
103 self.assertEqual("Message1",genOrder[3]) | |
104 self.assertEqual("Message2",genOrder[4]) | |
141 | 105 |
142 # def test_GeneratePreambleEnumerationAndStructs(self): | 106 # def test_GeneratePreambleEnumerationAndStructs(self): |
143 # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1.jsonc') | 107 # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1.jsonc') |
144 # obj = LoadSchema(fn) | 108 # obj = LoadSchema(fn) |
145 # (_,genc,_) = ProcessSchema(obj) | 109 # (_,genc,_) = ProcessSchema(obj) |
146 | 110 |
147 def test_genEnums(self): | 111 def test_genEnums(self): |
112 self.maxDiff = None | |
148 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | 113 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') |
149 obj = LoadSchema(fn) | 114 obj = LoadSchema(fn) |
150 genOrder: str = ComputeRequiredDeclarationOrder(obj) | 115 genOrder: str = ComputeRequiredDeclarationOrder(obj) |
151 processedSchema = ProcessSchema(obj, genOrder) | 116 processedSchema = ProcessSchema(obj, genOrder) |
152 processedSchemaStr = pprint.pformat(processedSchema,indent=2) | 117 self.assertTrue('rootName' in processedSchema) |
153 processedSchemaStrRef = """{ 'enums': [ { 'fields': ['RomCom', 'Horror', 'ScienceFiction', 'Vegetables'], | 118 |
154 'name': 'MovieType'}, | 119 structs = {} |
155 { 'fields': [ 'SaltAndPepper', | 120 for v in processedSchema['structs']: |
156 'CreamAndChives', | 121 structs[v['name']] = v |
157 'Paprika', | 122 enums = {} |
158 'Barbecue'], | 123 for v in processedSchema['enums']: |
159 'name': 'CrispType'}], | 124 enums[v['name']] = v |
160 'rootName': 'VsolMessages', | 125 |
161 'structs': [ { 'fields': { 'movies': 'vector<MovieType>', | 126 self.assertTrue('C' in structs) |
162 'someInts2': 'vector<int32>', | 127 self.assertTrue('someBs' in structs['C']['fields']) |
163 'someStrings': 'vector<string>'}, | 128 self.assertTrue('CrispType' in enums) |
164 'name': 'A'}, | 129 self.assertTrue('Message1' in structs) |
165 { 'fields': {'someAs': 'vector<A>', 'someInts': 'vector<int32>'}, | 130 message1Struct = structs['Message1'] |
166 'name': 'B'}, | 131 self.assertDictEqual(message1Struct, |
167 { 'fields': {'ddd': 'vector<string>', 'someBs': 'vector<B>'}, | 132 { |
168 'name': 'C'}]}""" | 133 'name':'Message1', |
169 | 134 'fields': { |
170 self.assertEqual(processedSchemaStrRef,processedSchemaStr) | 135 'a': 'int32', |
136 'b': 'string', | |
137 'c': 'EnumMonth0', | |
138 'd': 'bool' | |
139 } | |
140 }) | |
171 | 141 |
172 def test_GenerateTypeScriptEnums(self): | 142 def test_GenerateTypeScriptEnums(self): |
173 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | 143 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') |
174 tdico = GetTemplatingDictFromSchemaFilename(fn) | 144 tdico = GetTemplatingDictFromSchemaFilename(fn) |
175 template = Template(""" // end of generic methods | 145 template = Template(""" // end of generic methods |
195 }; | 165 }; |
196 | 166 |
197 """ | 167 """ |
198 self.assertEqual(renderedCodeRef,renderedCode) | 168 self.assertEqual(renderedCodeRef,renderedCode) |
199 | 169 |
170 def test_GenerateCplusplusEnums(self): | |
171 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | |
172 tdico = GetTemplatingDictFromSchemaFilename(fn) | |
173 template = Template(""" // end of generic methods | |
174 {% for enum in enums%} enum {{enum['name']}} { | |
175 {% for key in enum['fields']%} {{key}}, | |
176 {%endfor%} }; | |
177 | |
178 {%endfor%}""") | |
179 renderedCode = template.render(**tdico) | |
180 renderedCodeRef = """ // end of generic methods | |
181 enum MovieType { | |
182 RomCom, | |
183 Horror, | |
184 ScienceFiction, | |
185 Vegetables, | |
186 }; | |
187 | |
188 enum CrispType { | |
189 SaltAndPepper, | |
190 CreamAndChives, | |
191 Paprika, | |
192 Barbecue, | |
193 }; | |
194 | |
195 """ | |
196 self.assertEqual(renderedCodeRef,renderedCode) | |
197 | |
198 def test_generateTsStructType(self): | |
199 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | |
200 tdico = GetTemplatingDictFromSchemaFilename(fn) | |
201 ref = """ export class Message1 { | |
202 a: number; | |
203 b: string; | |
204 c: EnumMonth0; | |
205 d: boolean; | |
206 public StoneSerialize(): string { | |
207 let container: object = {}; | |
208 container['type'] = 'VsolStuff.Message1'; | |
209 container['value'] = this; | |
210 return JSON.stringify(container); | |
211 } | |
212 }; | |
213 | |
214 export class Message2 { | |
215 toto: string; | |
216 tata: Message1[]; | |
217 tutu: string[]; | |
218 titi: Map<string, string>; | |
219 lulu: Map<string, Message1>; | |
220 | |
221 constructor() | |
222 { | |
223 this.tata = new Array<Message1>(); | |
224 this.tutu = new Array<string>(); | |
225 this.titi = new Map<string, string>(); | |
226 this.lulu = new Map<string, Message1>(); | |
227 } | |
228 | |
229 public StoneSerialize(): string { | |
230 let container: object = {}; | |
231 container['type'] = 'VsolStuff.Message2'; | |
232 container['value'] = this; | |
233 return JSON.stringify(container); | |
234 } | |
235 }; | |
236 | |
237 """ | |
238 # template = MakeTemplate(""" // end of generic methods | |
239 # {% for struct in struct%} export class {{struct['name']}} { | |
240 # {% for key in struct['fields']%} {{key}}:{{struct['fields'][key]}}, | |
241 # {% endfor %} | |
242 # constructor() { | |
243 # {% for key in struct['fields']%} | |
244 # {% if NeedsConstruction(struct['fields']['key'])} | |
245 # {{key}} = new {{CanonToTs(struct['fields']['key'])}}; | |
246 # {% end if %} | |
247 # {% endfor %} | |
248 # } | |
249 # {% endfor %} | |
250 # public StoneSerialize(): string { | |
251 # let container: object = {}; | |
252 # container['type'] = '{{rootName}}.{{struct['name']}}'; | |
253 # container['value'] = this; | |
254 # return JSON.stringify(container); | |
255 # } };""") | |
256 template = MakeTemplate(""" // end of generic methods | |
257 {% for struct in structs%} export class {{struct['name']}} { | |
258 {% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key])}}; | |
259 {% endfor %} | |
260 constructor() { | |
261 {% for key in struct['fields']%} {{key}} = new {{CanonToTs(struct['fields'][key])}}(); | |
262 {% endfor %} } | |
263 | |
264 public StoneSerialize(): string { | |
265 let container: object = {}; | |
266 container['type'] = '{{rootName}}.{{struct['name']}}'; | |
267 container['value'] = this; | |
268 return JSON.stringify(container); | |
269 } | |
270 }; | |
271 | |
272 {% endfor %}""") | |
273 renderedCode = template.render(**tdico) | |
274 renderedCodeRef = """ // end of generic methods | |
275 export class A { | |
276 someStrings:Array<string>; | |
277 someInts2:Array<number>; | |
278 movies:Array<MovieType>; | |
279 | |
280 constructor() { | |
281 someStrings = new Array<string>(); | |
282 someInts2 = new Array<number>(); | |
283 movies = new Array<MovieType>(); | |
284 } | |
285 | |
286 public StoneSerialize(): string { | |
287 let container: object = {}; | |
288 container['type'] = 'VsolMessages.A'; | |
289 container['value'] = this; | |
290 return JSON.stringify(container); | |
291 } | |
292 }; | |
293 | |
294 export class B { | |
295 someAs:Array<A>; | |
296 someInts:Array<number>; | |
297 | |
298 constructor() { | |
299 someAs = new Array<A>(); | |
300 someInts = new Array<number>(); | |
301 } | |
302 | |
303 public StoneSerialize(): string { | |
304 let container: object = {}; | |
305 container['type'] = 'VsolMessages.B'; | |
306 container['value'] = this; | |
307 return JSON.stringify(container); | |
308 } | |
309 }; | |
310 | |
311 export class C { | |
312 someBs:Array<B>; | |
313 ddd:Array<string>; | |
314 | |
315 constructor() { | |
316 someBs = new Array<B>(); | |
317 ddd = new Array<string>(); | |
318 } | |
319 | |
320 public StoneSerialize(): string { | |
321 let container: object = {}; | |
322 container['type'] = 'VsolMessages.C'; | |
323 container['value'] = this; | |
324 return JSON.stringify(container); | |
325 } | |
326 }; | |
327 | |
328 export class Message1 { | |
329 a:number; | |
330 b:string; | |
331 c:EnumMonth0; | |
332 d:boolean; | |
333 | |
334 constructor() { | |
335 a = new number(); | |
336 b = new string(); | |
337 c = new EnumMonth0(); | |
338 d = new boolean(); | |
339 } | |
340 | |
341 public StoneSerialize(): string { | |
342 let container: object = {}; | |
343 container['type'] = 'VsolMessages.Message1'; | |
344 container['value'] = this; | |
345 return JSON.stringify(container); | |
346 } | |
347 }; | |
348 | |
349 export class Message2 { | |
350 toto:string; | |
351 tata:Array<Message1>; | |
352 tutu:Array<string>; | |
353 titi:Map<string, string>; | |
354 lulu:Map<string, Message1>; | |
355 | |
356 constructor() { | |
357 toto = new string(); | |
358 tata = new Array<Message1>(); | |
359 tutu = new Array<string>(); | |
360 titi = new Map<string, string>(); | |
361 lulu = new Map<string, Message1>(); | |
362 } | |
363 | |
364 public StoneSerialize(): string { | |
365 let container: object = {}; | |
366 container['type'] = 'VsolMessages.Message2'; | |
367 container['value'] = this; | |
368 return JSON.stringify(container); | |
369 } | |
370 }; | |
371 | |
372 """ | |
373 # print(renderedCode) | |
374 self.maxDiff = None | |
375 self.assertEqual(renderedCodeRef, renderedCode) | |
376 | |
377 def test_generateWholeTsFile(self): | |
378 schemaFile = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | |
379 tdico = GetTemplatingDictFromSchemaFilename(schemaFile) | |
380 tsTemplateFile = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') | |
381 template = MakeTemplateFromFile(tsTemplateFile) | |
382 renderedCode = template.render(**tdico) | |
383 | |
384 print(renderedCode) | |
200 | 385 |
201 def test_GenerateTypeScriptHandlerInterface(self): | 386 def test_GenerateTypeScriptHandlerInterface(self): |
202 pass | 387 pass |
203 | 388 |
204 def test_GenerateCppHandlerInterface(self): | 389 def test_GenerateCppHandlerInterface(self): |