Mercurial > hg > orthanc-stone
view Resources/CodeGeneration/stonegentool_test.py @ 1310:9bea7e15b519 broker
- first pass at changes to cope with the refactoring of the loading system
- global loader-related data accessible through ILoadersContext::ILock
- many changes in legacy loaders (CT, RTSTRUCT, DOSE) + loader cache
- NOT FINISHED! there are shared_from_this calls in ctors! this will crash!
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Mon, 09 Mar 2020 14:53:22 +0100 |
parents | 342f3e04bfa9 |
children |
line wrap: on
line source
# # 1 2 3 4 5 6 7 8 # 345678901234567890123456789012345678901234567890123456789012345678901234567890 # from stonegentool import \ EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \ CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \ GetTemplatingDictFromSchemaFilename,MakeTemplate,MakeTemplateFromFile,LoadSchemaFromString,GetTemplatingDictFromSchema import unittest import os import re import pprint from jinja2 import Template def RemoveDateTimeLine(s : str): # regex are non-multiline by default, and $ does NOT match the end of the line s2 = re.sub(r"^// autogenerated by stonegentool on .*\n","",s) return s2 class TestStonegentool(unittest.TestCase): def test_EatToken_empty(self): c = r"" a,b = EatToken(c) self.assertEqual(a,r"") self.assertEqual(b,r"") def test_EatToken_simpleNonTemplate(self): c = r"int32" a,b = EatToken(c) self.assertEqual(a,r"int32") self.assertEqual(b,r"") def test_EatToken_simpleTemplate(self): c = r"vector<string>" a,b = EatToken(c) self.assertEqual(a,r"vector<string>") self.assertEqual(b,r"") def test_EatToken_complexTemplate(self): c = r"vector<map<int64,string>>,vector<map<int32,string>>" a,b = EatToken(c) self.assertEqual(a,r"vector<map<int64,string>>") self.assertEqual(b,r"vector<map<int32,string>>") def test_EatToken_complexTemplates(self): c = r"vector<map<vector<string>,map<int32,string>>>,map<int32,string>,map<map<int32,string>,string>" a,b = EatToken(c) self.assertEqual(a,r"vector<map<vector<string>,map<int32,string>>>") self.assertEqual(b,r"map<int32,string>,map<map<int32,string>,string>") a,b = EatToken(b) self.assertEqual(a,r"map<int32,string>") self.assertEqual(b,r"map<map<int32,string>,string>") def test_SplitListOfTypes(self): c = r"vector<map<vector<string>,map<int32,string>>>,map<int32,string>,map<map<int32,string>,string>" lot = SplitListOfTypes(c) self.assertEqual(3,len(lot)) self.assertEqual("vector<map<vector<string>,map<int32,string>>>",lot[0]) self.assertEqual("map<int32,string>",lot[1]) self.assertEqual("map<map<int32,string>,string>",lot[2]) def test_SplitListOfTypes_bogus(self): c = r"vector<map<vector<string>,map<int32,string>>,map<int32,string>,map<map<int32,string>,string" self.assertRaises(Exception,SplitListOfTypes,c) # the argument c must be passed to assertRaises, not as a normal call of SplitListOfTypes def test_ParseTemplateType_true(self): c = "map<vector<map<int,vector<string>>>,map<vector<int>,vector<string>>>" (ok,a,b) = ParseTemplateType(c) self.assertEqual(ok,True) self.assertEqual(a,"map") self.assertEqual(b,["vector<map<int,vector<string>>>","map<vector<int>,vector<string>>"]) (ok2,a2,b2) = ParseTemplateType(b[0]) self.assertEqual(ok2,True) self.assertEqual(a2,"vector") self.assertEqual(b2,["map<int,vector<string>>"]) (ok3,a3,b3) = ParseTemplateType(b[1]) self.assertEqual(ok3,True) self.assertEqual(a3,"map") self.assertEqual(b3,["vector<int>","vector<string>"]) (ok4,a4,b4) = ParseTemplateType(b2[0]) self.assertEqual(ok4,True) self.assertEqual(a4,"map") self.assertEqual(b4,["int","vector<string>"]) def test_ParseSchema(self): fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') obj = LoadSchema(fn) # we're happy if it does not crash :) CheckSchemaSchema(obj) def test_ComputeRequiredDeclarationOrder(self): fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') obj = LoadSchema(fn) genOrder: str = ComputeRequiredDeclarationOrder(obj) self.assertEqual(5,len(genOrder)) self.assertEqual("A",genOrder[0]) self.assertEqual("B",genOrder[1]) self.assertEqual("C",genOrder[2]) self.assertEqual("Message1",genOrder[3]) self.assertEqual("Message2",genOrder[4]) # def test_GeneratePreambleEnumerationAndStructs(self): # fn = os.path.join(os.path.dirname(__file__), 'test', 'test1.jsonc') # obj = LoadSchema(fn) # (_,genc,_) = ProcessSchema(obj) def test_genEnums(self): self.maxDiff = None fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') obj = LoadSchema(fn) genOrder: str = ComputeRequiredDeclarationOrder(obj) processedSchema = ProcessSchema(obj, genOrder) self.assertTrue('rootName' in processedSchema) structs = {} for v in processedSchema['structs']: structs[v['name']] = v enums = {} for v in processedSchema['enums']: enums[v['name']] = v self.assertTrue('C' in structs) self.assertTrue('someBs' in structs['C']['fields']) self.assertTrue('CrispType' in enums) self.assertTrue('Message1' in structs) self.assertEqual('int32', structs['Message1']['fields']['memberInt32'].type) self.assertEqual('string', structs['Message1']['fields']['memberString'].type) self.assertEqual('EnumMonth0', structs['Message1']['fields']['memberEnumMonth'].type) self.assertEqual('bool', structs['Message1']['fields']['memberBool'].type) self.assertEqual('float32', structs['Message1']['fields']['memberFloat32'].type) self.assertEqual('float64', structs['Message1']['fields']['memberFloat64'].type) def test_GenerateTypeScriptEnums(self): fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(fn) template = Template(""" // end of generic methods {% for enum in enums%} export enum {{enum['name']}} { {% for key in enum['fields']%} {{key}}, {%endfor%} }; {%endfor%}""") renderedCode = template.render(**tdico) renderedCodeRef = """ // end of generic methods export enum MovieType { RomCom, Horror, ScienceFiction, Vegetables, }; export enum CrispType { SaltAndPepper, CreamAndChives, Paprika, Barbecue, }; export enum EnumMonth0 { January, February, March, }; """ self.assertEqual(renderedCodeRef,renderedCode) def test_GenerateCplusplusEnums(self): fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(fn) template = Template(""" // end of generic methods {% for enum in enums%} enum {{enum['name']}} { {% for key in enum['fields']%} {{key}}, {%endfor%} }; {%endfor%}""") renderedCode = template.render(**tdico) renderedCodeRef = """ // end of generic methods enum MovieType { RomCom, Horror, ScienceFiction, Vegetables, }; enum CrispType { SaltAndPepper, CreamAndChives, Paprika, Barbecue, }; enum EnumMonth0 { January, February, March, }; """ self.assertEqual(renderedCodeRef,renderedCode) def test_generateTsStructType(self): fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(fn) # template = MakeTemplate(""" // end of generic methods # {% for struct in struct%} export class {{struct['name']}} { # {% for key in struct['fields']%} {{key}}:{{struct['fields'][key]}}, # {% endfor %} # constructor() { # {% for key in struct['fields']%} # {% if NeedsConstruction(struct['fields']['key'])} # {{key}} = new {{CanonToTs(struct['fields']['key'])}}; # {% end if %} # {% endfor %} # } # {% endfor %} # public StoneSerialize(): string { # let container: object = {}; # container['type'] = '{{rootName}}.{{struct['name']}}'; # container['value'] = this; # return JSON.stringify(container); # } };""") template = MakeTemplate(""" // end of generic methods {% for struct in structs%} export class {{struct['name']}} { {% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key]['type'])}}; {% endfor %} constructor() { {% for key in struct['fields']%} this.{{key}} = new {{CanonToTs(struct['fields'][key]['type'])}}(); {% endfor %} } public StoneSerialize(): string { let container: object = {}; container['type'] = '{{rootName}}.{{struct['name']}}'; container['value'] = this; return JSON.stringify(container); } }; {% endfor %}""") renderedCode = template.render(**tdico) renderedCodeRef = """ // end of generic methods export class A { someStrings:Array<string>; someInts2:Array<number>; movies:Array<MovieType>; constructor() { this.someStrings = new Array<string>(); this.someInts2 = new Array<number>(); this.movies = new Array<MovieType>(); } public StoneSerialize(): string { let container: object = {}; container['type'] = 'TestStoneCodeGen.A'; container['value'] = this; return JSON.stringify(container); } }; export class B { someAs:Array<A>; someInts:Array<number>; constructor() { this.someAs = new Array<A>(); this.someInts = new Array<number>(); } public StoneSerialize(): string { let container: object = {}; container['type'] = 'TestStoneCodeGen.B'; container['value'] = this; return JSON.stringify(container); } }; export class C { someBs:Array<B>; ddd:Array<string>; constructor() { this.someBs = new Array<B>(); this.ddd = new Array<string>(); } public StoneSerialize(): string { let container: object = {}; container['type'] = 'TestStoneCodeGen.C'; container['value'] = this; return JSON.stringify(container); } }; export class Message1 { memberInt32:number; memberString:string; memberEnumMonth:EnumMonth0; memberBool:boolean; memberFloat32:number; memberFloat64:number; constructor() { this.memberInt32 = new number(); this.memberString = new string(); this.memberEnumMonth = new EnumMonth0(); this.memberBool = new boolean(); this.memberFloat32 = new number(); this.memberFloat64 = new number(); } public StoneSerialize(): string { let container: object = {}; container['type'] = 'TestStoneCodeGen.Message1'; container['value'] = this; return JSON.stringify(container); } }; export class Message2 { memberString:string; memberStringWithDefault:string; memberVectorOfMessage1:Array<Message1>; memberVectorOfString:Array<string>; memberMapStringString:Map<string, string>; memberMapStringStruct:Map<string, Message1>; memberMapEnumFloat:Map<CrispType, number>; memberEnumMovieType:MovieType; memberJson:Object; constructor() { this.memberString = new string(); this.memberStringWithDefault = new string(); this.memberVectorOfMessage1 = new Array<Message1>(); this.memberVectorOfString = new Array<string>(); this.memberMapStringString = new Map<string, string>(); this.memberMapStringStruct = new Map<string, Message1>(); this.memberMapEnumFloat = new Map<CrispType, number>(); this.memberEnumMovieType = new MovieType(); this.memberJson = new Object(); } public StoneSerialize(): string { let container: object = {}; container['type'] = 'TestStoneCodeGen.Message2'; container['value'] = this; return JSON.stringify(container); } }; """ # print(renderedCode) self.maxDiff = None self.assertEqual(renderedCodeRef, renderedCode) def test_generateWholeTsFile(self): schemaFile = \ os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(schemaFile) tsTemplateFile = \ os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') template = MakeTemplateFromFile(tsTemplateFile) renderedCode = template.render(**tdico) print(renderedCode) def test_GenerateTypeScriptHandlerInterface(self): pass def test_GenerateCppHandlerInterface(self): pass def test_GenerateTypeScriptDispatcher(self): pass def test_GenerateCppDispatcher(self): pass def test_StringDefaultValueInTs(self): schema = LoadSchemaFromString(""" rootName: MyTest struct Toto: withoutDefault: string withDefault: string = \"tutu\" """) tdico = GetTemplatingDictFromSchema(schema) tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') template = MakeTemplateFromFile(tsTemplateFile) renderedCode = template.render(**tdico) self.assertIn("withDefault = \"tutu\"", renderedCode) # print(renderedCode) cppTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.h.j2') template = MakeTemplateFromFile(cppTemplateFile) renderedCode = template.render(**tdico) print(renderedCode) self.assertIn("withDefault = \"tutu\"", renderedCode) def test_EnumDefaultValue(self): schema = LoadSchemaFromString(""" rootName: MyTest enum MyEnum: - Toto - Tutu struct Toto: withoutDefault: MyEnum withDefault: MyEnum = Toto """) tdico = GetTemplatingDictFromSchema(schema) tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.ts.j2') template = MakeTemplateFromFile(tsTemplateFile) renderedCode = template.render(**tdico) # print(renderedCode) self.assertIn("withDefault = MyEnum.Toto", renderedCode) tsTemplateFile = os.path.join(os.path.dirname(__file__), 'template.in.h.j2') template = MakeTemplateFromFile(tsTemplateFile) renderedCode = template.render(**tdico) self.assertIn("withDefault = MyTest::MyEnum_Toto", renderedCode) # print(renderedCode) # def test(self): # s = 'hello world' # self.assertEqual(s.split(), ['hello', 'world']) # # check that s.split fails when the separator is not a string # with self.assertRaises(TypeError): # s.split(2) if __name__ == '__main__': unittest.main()