Mercurial > hg > orthanc-stone
comparison Deprecated/Resources/CodeGeneration/stonegentool_test.py @ 1401:f6a2d46d2b76
moved CodeGeneration into Deprecated
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Wed, 29 Apr 2020 20:48:18 +0200 |
parents | Resources/CodeGeneration/stonegentool_test.py@342f3e04bfa9 |
children |
comparison
equal
deleted
inserted
replaced
1400:419d0320c344 | 1401:f6a2d46d2b76 |
---|---|
1 # | |
2 # 1 2 3 4 5 6 7 8 | |
3 # 345678901234567890123456789012345678901234567890123456789012345678901234567890 | |
4 # | |
5 | |
6 from stonegentool import \ | |
7 EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \ | |
8 CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \ | |
9 GetTemplatingDictFromSchemaFilename,MakeTemplate,MakeTemplateFromFile,LoadSchemaFromString,GetTemplatingDictFromSchema | |
10 import unittest | |
11 import os | |
12 import re | |
13 import pprint | |
14 from jinja2 import Template | |
15 | |
16 def RemoveDateTimeLine(s : str): | |
17 # regex are non-multiline by default, and $ does NOT match the end of the line | |
18 s2 = re.sub(r"^// autogenerated by stonegentool on .*\n","",s) | |
19 return s2 | |
20 | |
21 class TestStonegentool(unittest.TestCase): | |
22 def test_EatToken_empty(self): | |
23 c = r"" | |
24 a,b = EatToken(c) | |
25 self.assertEqual(a,r"") | |
26 self.assertEqual(b,r"") | |
27 | |
28 def test_EatToken_simpleNonTemplate(self): | |
29 c = r"int32" | |
30 a,b = EatToken(c) | |
31 self.assertEqual(a,r"int32") | |
32 self.assertEqual(b,r"") | |
33 | |
34 def test_EatToken_simpleTemplate(self): | |
35 c = r"vector<string>" | |
36 a,b = EatToken(c) | |
37 self.assertEqual(a,r"vector<string>") | |
38 self.assertEqual(b,r"") | |
39 | |
40 def test_EatToken_complexTemplate(self): | |
41 c = r"vector<map<int64,string>>,vector<map<int32,string>>" | |
42 a,b = EatToken(c) | |
43 self.assertEqual(a,r"vector<map<int64,string>>") | |
44 self.assertEqual(b,r"vector<map<int32,string>>") | |
45 | |
46 def test_EatToken_complexTemplates(self): | |
47 c = r"vector<map<vector<string>,map<int32,string>>>,map<int32,string>,map<map<int32,string>,string>" | |
48 a,b = EatToken(c) | |
49 self.assertEqual(a,r"vector<map<vector<string>,map<int32,string>>>") | |
50 self.assertEqual(b,r"map<int32,string>,map<map<int32,string>,string>") | |
51 a,b = EatToken(b) | |
52 self.assertEqual(a,r"map<int32,string>") | |
53 self.assertEqual(b,r"map<map<int32,string>,string>") | |
54 | |
55 def test_SplitListOfTypes(self): | |
56 c = r"vector<map<vector<string>,map<int32,string>>>,map<int32,string>,map<map<int32,string>,string>" | |
57 lot = SplitListOfTypes(c) | |
58 self.assertEqual(3,len(lot)) | |
59 self.assertEqual("vector<map<vector<string>,map<int32,string>>>",lot[0]) | |
60 self.assertEqual("map<int32,string>",lot[1]) | |
61 self.assertEqual("map<map<int32,string>,string>",lot[2]) | |
62 | |
63 def test_SplitListOfTypes_bogus(self): | |
64 c = r"vector<map<vector<string>,map<int32,string>>,map<int32,string>,map<map<int32,string>,string" | |
65 self.assertRaises(Exception,SplitListOfTypes,c) # the argument c must be passed to assertRaises, not as a normal call of SplitListOfTypes | |
66 | |
67 def test_ParseTemplateType_true(self): | |
68 c = "map<vector<map<int,vector<string>>>,map<vector<int>,vector<string>>>" | |
69 (ok,a,b) = ParseTemplateType(c) | |
70 self.assertEqual(ok,True) | |
71 self.assertEqual(a,"map") | |
72 self.assertEqual(b,["vector<map<int,vector<string>>>","map<vector<int>,vector<string>>"]) | |
73 | |
74 (ok2,a2,b2) = ParseTemplateType(b[0]) | |
75 self.assertEqual(ok2,True) | |
76 self.assertEqual(a2,"vector") | |
77 self.assertEqual(b2,["map<int,vector<string>>"]) | |
78 | |
79 (ok3,a3,b3) = ParseTemplateType(b[1]) | |
80 self.assertEqual(ok3,True) | |
81 self.assertEqual(a3,"map") | |
82 self.assertEqual(b3,["vector<int>","vector<string>"]) | |
83 | |
84 (ok4,a4,b4) = ParseTemplateType(b2[0]) | |
85 self.assertEqual(ok4,True) | |
86 self.assertEqual(a4,"map") | |
87 self.assertEqual(b4,["int","vector<string>"]) | |
88 | |
89 def test_ParseSchema(self): | |
90 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
91 obj = LoadSchema(fn) | |
92 # we're happy if it does not crash :) | |
93 CheckSchemaSchema(obj) | |
94 | |
95 def test_ComputeRequiredDeclarationOrder(self): | |
96 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
97 obj = LoadSchema(fn) | |
98 genOrder: str = ComputeRequiredDeclarationOrder(obj) | |
99 self.assertEqual(5,len(genOrder)) | |
100 self.assertEqual("A",genOrder[0]) | |
101 self.assertEqual("B",genOrder[1]) | |
102 self.assertEqual("C",genOrder[2]) | |
103 self.assertEqual("Message1",genOrder[3]) | |
104 self.assertEqual("Message2",genOrder[4]) | |
105 | |
106 # def test_GeneratePreambleEnumerationAndStructs(self): | |
107 # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1.jsonc') | |
108 # obj = LoadSchema(fn) | |
109 # (_,genc,_) = ProcessSchema(obj) | |
110 | |
111 def test_genEnums(self): | |
112 self.maxDiff = None | |
113 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
114 obj = LoadSchema(fn) | |
115 genOrder: str = ComputeRequiredDeclarationOrder(obj) | |
116 processedSchema = ProcessSchema(obj, genOrder) | |
117 self.assertTrue('rootName' in processedSchema) | |
118 | |
119 structs = {} | |
120 for v in processedSchema['structs']: | |
121 structs[v['name']] = v | |
122 enums = {} | |
123 for v in processedSchema['enums']: | |
124 enums[v['name']] = v | |
125 | |
126 self.assertTrue('C' in structs) | |
127 self.assertTrue('someBs' in structs['C']['fields']) | |
128 self.assertTrue('CrispType' in enums) | |
129 self.assertTrue('Message1' in structs) | |
130 self.assertEqual('int32', structs['Message1']['fields']['memberInt32'].type) | |
131 self.assertEqual('string', structs['Message1']['fields']['memberString'].type) | |
132 self.assertEqual('EnumMonth0', structs['Message1']['fields']['memberEnumMonth'].type) | |
133 self.assertEqual('bool', structs['Message1']['fields']['memberBool'].type) | |
134 self.assertEqual('float32', structs['Message1']['fields']['memberFloat32'].type) | |
135 self.assertEqual('float64', structs['Message1']['fields']['memberFloat64'].type) | |
136 | |
137 def test_GenerateTypeScriptEnums(self): | |
138 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
139 tdico = GetTemplatingDictFromSchemaFilename(fn) | |
140 template = Template(""" // end of generic methods | |
141 {% for enum in enums%} export enum {{enum['name']}} { | |
142 {% for key in enum['fields']%} {{key}}, | |
143 {%endfor%} }; | |
144 | |
145 {%endfor%}""") | |
146 renderedCode = template.render(**tdico) | |
147 renderedCodeRef = """ // end of generic methods | |
148 export enum MovieType { | |
149 RomCom, | |
150 Horror, | |
151 ScienceFiction, | |
152 Vegetables, | |
153 }; | |
154 | |
155 export enum CrispType { | |
156 SaltAndPepper, | |
157 CreamAndChives, | |
158 Paprika, | |
159 Barbecue, | |
160 }; | |
161 | |
162 export enum EnumMonth0 { | |
163 January, | |
164 February, | |
165 March, | |
166 }; | |
167 | |
168 """ | |
169 self.assertEqual(renderedCodeRef,renderedCode) | |
170 | |
171 def test_GenerateCplusplusEnums(self): | |
172 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
173 tdico = GetTemplatingDictFromSchemaFilename(fn) | |
174 template = Template(""" // end of generic methods | |
175 {% for enum in enums%} enum {{enum['name']}} { | |
176 {% for key in enum['fields']%} {{key}}, | |
177 {%endfor%} }; | |
178 | |
179 {%endfor%}""") | |
180 renderedCode = template.render(**tdico) | |
181 renderedCodeRef = """ // end of generic methods | |
182 enum MovieType { | |
183 RomCom, | |
184 Horror, | |
185 ScienceFiction, | |
186 Vegetables, | |
187 }; | |
188 | |
189 enum CrispType { | |
190 SaltAndPepper, | |
191 CreamAndChives, | |
192 Paprika, | |
193 Barbecue, | |
194 }; | |
195 | |
196 enum EnumMonth0 { | |
197 January, | |
198 February, | |
199 March, | |
200 }; | |
201 | |
202 """ | |
203 self.assertEqual(renderedCodeRef,renderedCode) | |
204 | |
205 def test_generateTsStructType(self): | |
206 fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
207 tdico = GetTemplatingDictFromSchemaFilename(fn) | |
208 | |
209 # template = MakeTemplate(""" // end of generic methods | |
210 # {% for struct in struct%} export class {{struct['name']}} { | |
211 # {% for key in struct['fields']%} {{key}}:{{struct['fields'][key]}}, | |
212 # {% endfor %} | |
213 # constructor() { | |
214 # {% for key in struct['fields']%} | |
215 # {% if NeedsConstruction(struct['fields']['key'])} | |
216 # {{key}} = new {{CanonToTs(struct['fields']['key'])}}; | |
217 # {% end if %} | |
218 # {% endfor %} | |
219 # } | |
220 # {% endfor %} | |
221 # public StoneSerialize(): string { | |
222 # let container: object = {}; | |
223 # container['type'] = '{{rootName}}.{{struct['name']}}'; | |
224 # container['value'] = this; | |
225 # return JSON.stringify(container); | |
226 # } };""") | |
227 template = MakeTemplate(""" // end of generic methods | |
228 {% for struct in structs%} export class {{struct['name']}} { | |
229 {% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key]['type'])}}; | |
230 {% endfor %} | |
231 constructor() { | |
232 {% for key in struct['fields']%} this.{{key}} = new {{CanonToTs(struct['fields'][key]['type'])}}(); | |
233 {% endfor %} } | |
234 | |
235 public StoneSerialize(): string { | |
236 let container: object = {}; | |
237 container['type'] = '{{rootName}}.{{struct['name']}}'; | |
238 container['value'] = this; | |
239 return JSON.stringify(container); | |
240 } | |
241 }; | |
242 | |
243 {% endfor %}""") | |
244 renderedCode = template.render(**tdico) | |
245 renderedCodeRef = """ // end of generic methods | |
246 export class A { | |
247 someStrings:Array<string>; | |
248 someInts2:Array<number>; | |
249 movies:Array<MovieType>; | |
250 | |
251 constructor() { | |
252 this.someStrings = new Array<string>(); | |
253 this.someInts2 = new Array<number>(); | |
254 this.movies = new Array<MovieType>(); | |
255 } | |
256 | |
257 public StoneSerialize(): string { | |
258 let container: object = {}; | |
259 container['type'] = 'TestStoneCodeGen.A'; | |
260 container['value'] = this; | |
261 return JSON.stringify(container); | |
262 } | |
263 }; | |
264 | |
265 export class B { | |
266 someAs:Array<A>; | |
267 someInts:Array<number>; | |
268 | |
269 constructor() { | |
270 this.someAs = new Array<A>(); | |
271 this.someInts = new Array<number>(); | |
272 } | |
273 | |
274 public StoneSerialize(): string { | |
275 let container: object = {}; | |
276 container['type'] = 'TestStoneCodeGen.B'; | |
277 container['value'] = this; | |
278 return JSON.stringify(container); | |
279 } | |
280 }; | |
281 | |
282 export class C { | |
283 someBs:Array<B>; | |
284 ddd:Array<string>; | |
285 | |
286 constructor() { | |
287 this.someBs = new Array<B>(); | |
288 this.ddd = new Array<string>(); | |
289 } | |
290 | |
291 public StoneSerialize(): string { | |
292 let container: object = {}; | |
293 container['type'] = 'TestStoneCodeGen.C'; | |
294 container['value'] = this; | |
295 return JSON.stringify(container); | |
296 } | |
297 }; | |
298 | |
299 export class Message1 { | |
300 memberInt32:number; | |
301 memberString:string; | |
302 memberEnumMonth:EnumMonth0; | |
303 memberBool:boolean; | |
304 memberFloat32:number; | |
305 memberFloat64:number; | |
306 | |
307 constructor() { | |
308 this.memberInt32 = new number(); | |
309 this.memberString = new string(); | |
310 this.memberEnumMonth = new EnumMonth0(); | |
311 this.memberBool = new boolean(); | |
312 this.memberFloat32 = new number(); | |
313 this.memberFloat64 = new number(); | |
314 } | |
315 | |
316 public StoneSerialize(): string { | |
317 let container: object = {}; | |
318 container['type'] = 'TestStoneCodeGen.Message1'; | |
319 container['value'] = this; | |
320 return JSON.stringify(container); | |
321 } | |
322 }; | |
323 | |
324 export class Message2 { | |
325 memberString:string; | |
326 memberStringWithDefault:string; | |
327 memberVectorOfMessage1:Array<Message1>; | |
328 memberVectorOfString:Array<string>; | |
329 memberMapStringString:Map<string, string>; | |
330 memberMapStringStruct:Map<string, Message1>; | |
331 memberMapEnumFloat:Map<CrispType, number>; | |
332 memberEnumMovieType:MovieType; | |
333 memberJson:Object; | |
334 | |
335 constructor() { | |
336 this.memberString = new string(); | |
337 this.memberStringWithDefault = new string(); | |
338 this.memberVectorOfMessage1 = new Array<Message1>(); | |
339 this.memberVectorOfString = new Array<string>(); | |
340 this.memberMapStringString = new Map<string, string>(); | |
341 this.memberMapStringStruct = new Map<string, Message1>(); | |
342 this.memberMapEnumFloat = new Map<CrispType, number>(); | |
343 this.memberEnumMovieType = new MovieType(); | |
344 this.memberJson = new Object(); | |
345 } | |
346 | |
347 public StoneSerialize(): string { | |
348 let container: object = {}; | |
349 container['type'] = 'TestStoneCodeGen.Message2'; | |
350 container['value'] = this; | |
351 return JSON.stringify(container); | |
352 } | |
353 }; | |
354 | |
355 """ | |
356 # print(renderedCode) | |
357 self.maxDiff = None | |
358 self.assertEqual(renderedCodeRef, renderedCode) | |
359 | |
360 def test_generateWholeTsFile(self): | |
361 schemaFile = \ | |
362 os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') | |
363 tdico = GetTemplatingDictFromSchemaFilename(schemaFile) | |
364 tsTemplateFile = \ | |
365 os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') | |
366 template = MakeTemplateFromFile(tsTemplateFile) | |
367 renderedCode = template.render(**tdico) | |
368 print(renderedCode) | |
369 | |
370 def test_GenerateTypeScriptHandlerInterface(self): | |
371 pass | |
372 | |
373 def test_GenerateCppHandlerInterface(self): | |
374 pass | |
375 | |
376 def test_GenerateTypeScriptDispatcher(self): | |
377 pass | |
378 | |
379 def test_GenerateCppDispatcher(self): | |
380 pass | |
381 | |
382 def test_StringDefaultValueInTs(self): | |
383 schema = LoadSchemaFromString(""" | |
384 rootName: MyTest | |
385 struct Toto: | |
386 withoutDefault: string | |
387 withDefault: string = \"tutu\" | |
388 """) | |
389 tdico = GetTemplatingDictFromSchema(schema) | |
390 | |
391 tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') | |
392 template = MakeTemplateFromFile(tsTemplateFile) | |
393 renderedCode = template.render(**tdico) | |
394 self.assertIn("withDefault = \"tutu\"", renderedCode) | |
395 # print(renderedCode) | |
396 | |
397 cppTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.h.j2') | |
398 template = MakeTemplateFromFile(cppTemplateFile) | |
399 renderedCode = template.render(**tdico) | |
400 print(renderedCode) | |
401 self.assertIn("withDefault = \"tutu\"", renderedCode) | |
402 | |
403 | |
404 def test_EnumDefaultValue(self): | |
405 schema = LoadSchemaFromString(""" | |
406 rootName: MyTest | |
407 enum MyEnum: | |
408 - Toto | |
409 - Tutu | |
410 struct Toto: | |
411 withoutDefault: MyEnum | |
412 withDefault: MyEnum = Toto | |
413 """) | |
414 tdico = GetTemplatingDictFromSchema(schema) | |
415 | |
416 tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') | |
417 template = MakeTemplateFromFile(tsTemplateFile) | |
418 renderedCode = template.render(**tdico) | |
419 # print(renderedCode) | |
420 self.assertIn("withDefault = MyEnum.Toto", renderedCode) | |
421 | |
422 tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.h.j2') | |
423 template = MakeTemplateFromFile(tsTemplateFile) | |
424 renderedCode = template.render(**tdico) | |
425 self.assertIn("withDefault = MyTest::MyEnum_Toto", renderedCode) | |
426 # print(renderedCode) | |
427 | |
428 | |
429 # def test(self): | |
430 # s = 'hello world' | |
431 # self.assertEqual(s.split(), ['hello', 'world']) | |
432 # # check that s.split fails when the separator is not a string | |
433 # with self.assertRaises(TypeError): | |
434 # s.split(2) | |
435 | |
436 if __name__ == '__main__': | |
437 unittest.main() | |
438 |