diff Resources/CodeGeneration/stonegentool_test.py @ 520:7a16fb9a4ba5 am-touch-events

merge bgo-commands-codegen
author Alain Mazy <alain@mazy.be>
date Tue, 12 Mar 2019 14:50:14 +0100
parents 1dbf2d9ed1e4
children b7fd0471281c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/CodeGeneration/stonegentool_test.py	Tue Mar 12 14:50:14 2019 +0100
@@ -0,0 +1,408 @@
+#
+#        1         2         3         4         5         6         7         8
+# 345678901234567890123456789012345678901234567890123456789012345678901234567890
+#
+
+from stonegentool import \
+EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \
+CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \
+GetTemplatingDictFromSchemaFilename,MakeTemplate,MakeTemplateFromFile
+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', 'test1.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', 'test1.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', 'test1.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)
+    message1Struct = structs['Message1']
+    self.assertDictEqual(message1Struct,
+    {
+      'name':'Message1',
+      'fields': {
+        'a': 'int32',
+        'b': 'string',
+        'c': 'EnumMonth0',
+        'd': 'bool'
+      }
+    })
+
+  def test_GenerateTypeScriptEnums(self):
+    fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.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,
+  };
+
+"""
+    self.assertEqual(renderedCodeRef,renderedCode)
+
+  def test_GenerateCplusplusEnums(self):
+    fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.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,
+  };
+
+"""
+    self.assertEqual(renderedCodeRef,renderedCode)
+
+  def test_generateTsStructType(self):
+    fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml')
+    tdico = GetTemplatingDictFromSchemaFilename(fn)
+    ref = """  export class Message1 {
+    a: number;
+    b: string;
+    c: EnumMonth0;
+    d: boolean;
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolStuff.Message1';
+      container['value'] = this;
+      return JSON.stringify(container);
+    }
+  };
+
+  export class Message2 {
+    toto: string;
+    tata: Message1[];
+    tutu: string[];
+    titi: Map<string, string>;
+    lulu: Map<string, Message1>;
+
+    constructor()
+    {
+      this.tata = new Array<Message1>();
+      this.tutu = new Array<string>();
+      this.titi = new Map<string, string>();
+      this.lulu = new Map<string, Message1>();  
+    }
+
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolStuff.Message2';
+      container['value'] = this;
+      return JSON.stringify(container);
+    }
+  };
+
+"""
+#     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])}};
+{% endfor %}
+    constructor() {
+{% for key in struct['fields']%}      this.{{key}} = new {{CanonToTs(struct['fields'][key])}}();
+{% 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() {
+      someStrings = new Array<string>();
+      someInts2 = new Array<number>();
+      movies = new Array<MovieType>();
+    }
+
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolMessages.A';
+      container['value'] = this;
+      return JSON.stringify(container);
+    }
+  };
+
+  export class B {
+    someAs:Array<A>;
+    someInts:Array<number>;
+
+    constructor() {
+      someAs = new Array<A>();
+      someInts = new Array<number>();
+    }
+
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolMessages.B';
+      container['value'] = this;
+      return JSON.stringify(container);
+    }
+  };
+
+  export class C {
+    someBs:Array<B>;
+    ddd:Array<string>;
+
+    constructor() {
+      someBs = new Array<B>();
+      ddd = new Array<string>();
+    }
+
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolMessages.C';
+      container['value'] = this;
+      return JSON.stringify(container);
+    }
+  };
+
+  export class Message1 {
+    a:number;
+    b:string;
+    c:EnumMonth0;
+    d:boolean;
+
+    constructor() {
+      a = new number();
+      b = new string();
+      c = new EnumMonth0();
+      d = new boolean();
+    }
+
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolMessages.Message1';
+      container['value'] = this;
+      return JSON.stringify(container);
+    }
+  };
+
+  export class Message2 {
+    toto:string;
+    tata:Array<Message1>;
+    tutu:Array<string>;
+    titi:Map<string, string>;
+    lulu:Map<string, Message1>;
+
+    constructor() {
+      toto = new string();
+      tata = new Array<Message1>();
+      tutu = new Array<string>();
+      titi = new Map<string, string>();
+      lulu = new Map<string, Message1>();
+    }
+
+    public StoneSerialize(): string {
+      let container: object = {};
+      container['type'] = 'VsolMessages.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', 'test1.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(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()
+