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