1# !/usr/bin/env python3 2# coding=utf-8 3""" 4* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 5* 6* HDF is dual licensed: you can use it either under the terms of 7* the GPL, or the BSD license, at your option. 8* See the LICENSE file in the root of this repository for complete details. 9""" 10import json 11import sys 12import unittest 13 14import CppHeaderParser 15 16sys.path.insert(0, '..') 17try: 18 from _header_parser import HeaderParser 19 from idl_generator import IDLGenerator 20finally: 21 pass 22 23 24class IDLGeneratorTestCase(unittest.TestCase): 25 def test_install_package(self): 26 generator = IDLGenerator() 27 generator._install_package("\\h\\audio\\test") 28 self.assertEqual(generator._idl, "package h.audio.test;\n\n") 29 30 generator._idl = "" 31 generator._install_package(".\\h\\audio\\test") 32 self.assertEqual(generator._idl, "package h.audio.test;\n\n") 33 34 generator._idl = "" 35 generator._install_package("C:\\h\\audio\\test") 36 self.assertEqual(generator._idl, "package h.audio.test;\n\n") 37 38 generator._idl = "" 39 generator._install_package("./h/audio/test") 40 self.assertEqual(generator._idl, "package h.audio.test;\n\n") 41 42 def test_install_import_interface(self): 43 generator = IDLGenerator() 44 generator._parse_results = { 45 'audio_render.h': { 46 'name': 'audio_render.h', 47 'path': '.\\include\\audio', 48 'import': [], 'enum': [], 'union': [], 'struct': [], 49 'interface': [{'name': 'AudioRender', 'members': []}], 50 'callback': [] 51 }, 52 'audio_test.h': { 53 'name': 'audio_test.h', 54 'path': '.\\include\\audio', 55 'import': ['audio_render.h'], 'enum': [], 'union': [], 'struct': [], 56 'interface': [{'name': 'AudioRender', 'members': []}], 57 'callback': [] 58 } 59 } 60 header = generator._parse_results['audio_test.h'] 61 generator._install_import(header) 62 self.assertEqual(generator._idl, "import include.audio.AudioRender;\n\n") 63 64 def test_install_import_interfaces(self): 65 generator = IDLGenerator() 66 generator._parse_results = { 67 'audio_render.h': { 68 'name': 'audio_render.h', 69 'path': '.\\include\\audio', 70 'import': [], 'enum': [], 'union': [], 'struct': [], 71 'interface': [{'name': 'AudioRender', 'members': []}], 72 'callback': [] 73 }, 74 'audio_adapter.h': { 75 'name': 'audio_adapter.h', 76 'path': '.\\include\\audio\\adapter', 77 'import': [], 'enum': [], 'union': [], 'struct': [], 78 'interface': [{'name': 'AudioAdapter', 'members': []}], 79 'callback': [] 80 }, 81 'audio_test.h': { 82 'name': 'audio_test.h', 83 'path': '.\\include\\audio', 84 'import': ['audio_render.h', 'audio_adapter.h'], 'enum': [], 'union': [], 'struct': [], 85 'interface': [{'name': 'AudioRender', 'members': []}], 86 'callback': [] 87 } 88 } 89 header = generator._parse_results['audio_test.h'] 90 generator._install_import(header) 91 self.assertEqual(generator._idl, "import include.audio.AudioRender;\n" 92 "import include.audio.adapter.AudioAdapter;\n\n") 93 94 def test_install_import_multiple_interfaces(self): 95 generator = IDLGenerator() 96 generator._parse_results = { 97 'audio_multiple_interfaces.h': { 98 'name': 'audio_multiple_interfaces.h', 99 'path': '.\\include', 100 'import': [], 'enum': [], 'union': [], 'struct': [], 101 'interface': [ 102 {'name': 'AudioInterfaceOne', 'members': []}, 103 {'name': 'AudioInterfaceTwo', 'members': []} 104 ], 105 'callback': [] 106 }, 107 'audio_test.h': { 108 'name': 'audio_test.h', 109 'path': '.\\include\\audio', 110 'import': ['audio_multiple_interfaces.h'], 'enum': [], 'union': [], 'struct': [], 111 'interface': [{'name': 'AudioRender', 'members': []}], 112 'callback': [] 113 } 114 } 115 header = generator._parse_results['audio_test.h'] 116 generator._install_import(header) 117 self.assertEqual(generator._idl, "import include.AudioInterfaceOne;\nimport include.AudioInterfaceTwo;\n\n") 118 119 def test_install_import_types(self): 120 generator = IDLGenerator() 121 generator._parse_results = { 122 'audio_types.h': { 123 'name': 'audio_types.h', 124 'path': '.\\include', 125 'import': [], 126 'enum': [{'name': 'AudioPortDirection', 'members': [{'name': 'PORT_OUT', 'value': 1}]}], 127 'union': [], 'struct': [], 'interface': [], 'callback': [] 128 }, 129 'audio_test.h': { 130 'name': 'audio_test.h', 131 'path': '.\\include\\audio', 132 'import': ['audio_types.h'], 'enum': [], 'union': [], 'struct': [], 133 'interface': [{'name': 'AudioRender', 'members': []}], 134 'callback': [] 135 } 136 } 137 header = generator._parse_results["audio_test.h"] 138 generator._install_import(header) 139 self.assertEqual(generator._idl, "import include.Types;\n\n") 140 141 def test_install_import_merge_types(self): 142 generator = IDLGenerator() 143 generator._parse_results = { 144 'audio_types.h': { 145 'name': 'audio_types.h', 146 'path': '.\\include', 147 'import': ['adapter_types.h'], 148 'enum': [{'name': 'AudioPortDirection', 'members': [{'name': 'PORT_OUT', 'value': 1}]}], 149 'union': [], 'struct': [], 'interface': [], 'callback': [] 150 }, 151 'adapter_types.h': { 152 'name': 'adapter_types.h', 153 'path': '.\\include', 154 'import': [], 155 'enum': [{'name': 'AudioAdapter', 'members': [{'name': 'PORT_OUT', 'value': 1}]}], 156 'union': [], 'struct': [], 'interface': [], 'callback': [] 157 }, 158 'audio_test.h': { 159 'name': 'audio_test.h', 160 'path': '.\\include\\audio', 161 'import': ['audio_types.h', 'adapter_types.h'], 'enum': [], 'union': [], 'struct': [], 162 'interface': [{'name': 'AudioRender', 'members': []}], 163 'callback': [] 164 } 165 } 166 header = generator._parse_results['audio_test.h'] 167 generator._install_import(header) 168 self.assertEqual(generator._idl, "import include.Types;\n\n") 169 170 def test_install_import_types_and_interfaces(self): 171 generator = IDLGenerator() 172 generator._parse_results = { 173 'audio_types.h': { 174 'name': 'audio_types.h', 175 'path': '.\\include', 176 'import': ['adapter_types.h'], 177 'enum': [{'name': 'AudioPortDirection', 'members': [{'name': 'PORT_OUT', 'value': 1}]}], 178 'union': [], 'struct': [], 'interface': [], 'callback': [] 179 }, 180 'audio_adapter.h': { 181 'name': 'audio_adapter.h', 182 'path': '.\\include\\audio\\adapter', 183 'import': [], 'enum': [], 'union': [], 'struct': [], 184 'interface': [{'name': 'AudioAdapter', 'members': []}], 185 'callback': [] 186 }, 187 'audio_test.h': { 188 'name': 'audio_test.h', 189 'path': '.\\include\\audio', 190 'import': ['audio_types.h', 'audio_adapter.h'], 'enum': [], 'union': [], 'struct': [], 191 'interface': [{'name': 'AudioRender', 'members': []}], 192 'callback': [] 193 } 194 } 195 header = generator._parse_results['audio_test.h'] 196 generator._install_import(header) 197 self.assertEqual(generator._idl, "import include.Types;\nimport include.audio.adapter.AudioAdapter;\n\n") 198 199 def test_install_import_callback(self): 200 generator = IDLGenerator() 201 generator._parse_results = { 202 'audio_test.h': { 203 'name': 'audio_test.h', 204 'path': '.\\include\\audio', 205 'import': [], 'enum': [], 'union': [], 'struct': [], 206 'interface': [{'name': 'AudioRender', 'members': []}], 207 'callback': [ 208 {'name': 'HotPlugCallback', 'members': []}, 209 {'name': 'VBlankCallback', 'members': []} 210 ] 211 } 212 } 213 header = generator._parse_results['audio_test.h'] 214 generator._install_import(header) 215 self.assertEqual(generator._idl, "import include.audio.HotPlugCallback;\n" 216 "import include.audio.VBlankCallback;\n\n") 217 218 def test_install_enum(self): 219 generator = IDLGenerator() 220 enum = [{ 221 'name': 'AudioPortDirection', 222 'members': [ 223 {'name': 'PORT_OUT', 'value': 1}, 224 {'name': 'PORT_IN', 'value': '- 2 // unexpected \'-\''}, 225 ]} 226 ] 227 generator._install_enum(enum) 228 self.assertEqual(generator._idl, "enum AudioPortDirection {\n" 229 " PORT_OUT = 1,\n" 230 " PORT_IN = - 2 // unexpected '-',\n" 231 "};\n") 232 233 def test_install_stack_union(self): 234 generator = IDLGenerator() 235 union = [{'name': 'SceneDesc', 236 'type': 'union', 237 'members': [ 238 {'name': 'id', 'type': 'uint32_t'}, 239 {'name': 'desc', 'type': 'const char *'} 240 ]}] 241 generator._install_stack(union) 242 self.assertEqual(generator._idl, "union SceneDesc {\n" 243 " unsigned int id;\n" 244 " byte[] desc;\n" 245 "};\n") 246 247 def test_install_stack_struct(self): 248 generator = IDLGenerator() 249 struct = [{'name': 'SceneDesc', 250 'type': 'struct', 251 'members': [ 252 {'name': 'id', 'type': 'uint32_t'}, 253 {'name': 'desc', 'type': 'const char *'} 254 ]}] 255 generator._install_stack(struct) 256 self.assertEqual(generator._idl, "struct SceneDesc {\n" 257 " unsigned int id;\n" 258 " byte[] desc;\n" 259 "};\n") 260 261 def test_install_interface(self): 262 header_file = """ 263 typedef struct { 264 int32_t (*RunExtraCommand)(struct InputController *self, uint32_t devIndex, uint32_t **cmd); 265 int32_t (*RunExtra)(struct InputController *self, struct InputControllerDesc desc); 266 } InputController; 267 """ 268 parser = HeaderParser() 269 hjson = json.loads(CppHeaderParser.CppHeader(header_file, "string").toJSON()) 270 parser._extract_interface(hjson["classes"]["InputController"]) 271 generator = IDLGenerator() 272 generator._key_list["InputController"] = "struct" 273 generator._key_list["InputControllerDesc"] = "struct" 274 generator._install_interface(parser._header_dict.get("interface")[0]) 275 self.assertEqual(generator._idl, "interface InputController {\n" 276 " RunExtraCommand([in] unsigned int devIndex,[out] unsigned int cmd);\n" 277 " RunExtra([in] struct InputControllerDesc desc);\n" 278 "}\n") 279 280 def test_install_interface_with_unknown_type(self): 281 header_file = """ 282 typedef struct { 283 int32_t (*RunExtra)(struct InputControllerDesc desc); 284 } InputController; 285 """ 286 parser = HeaderParser() 287 hjson = json.loads(CppHeaderParser.CppHeader(header_file, "string").toJSON()) 288 parser._extract_interface(hjson["classes"]["InputController"]) 289 generator = IDLGenerator() 290 generator._install_interface(parser._header_dict.get("interface")[0]) 291 self.assertEqual(generator._idl, "interface InputController {\n" 292 " RunExtra([in] /* unknown type: [InputControllerDesc] */ desc);\n" 293 "}\n") 294 295 def test_install_interface_callback(self): 296 header_file = """ 297 struct IFooCallback { 298 int32_t (*PushData)(struct IFooCallback *self, const char* message); 299 }; 300 """ 301 parser = HeaderParser() 302 hjson = json.loads(CppHeaderParser.CppHeader(header_file, "string").toJSON()) 303 parser._extract_interface(hjson["classes"]["IFooCallback"]) 304 generator = IDLGenerator() 305 generator._install_interface(parser._header_dict.get("interface")[0]) 306 self.assertEqual(generator._idl, "[callback] interface IFooCallback {\n" 307 " PushData([in] byte[] message);\n" 308 "}\n") 309 310 def test_convert_from_container_type(self): 311 generator = IDLGenerator() 312 self.assertEqual(generator._convert_container_type("const map<int, int> test"), 313 "Map<int, int>") 314 self.assertEqual(generator._convert_container_type("const std::map< int , int > test"), 315 "Map<int, int>") 316 self.assertEqual(generator._convert_container_type("const std::map<int, std::string> test"), 317 "Map<int, String>") 318 self.assertEqual(generator._convert_container_type("const std::map<struct KeyType, struct ValueType> test"), 319 "Map<KeyType, ValueType>") 320 self.assertEqual(generator._convert_container_type("const std::map<unsigned int, unsigned long> test"), 321 "Map<unsigned int, unsigned long>") 322 self.assertEqual(generator._convert_container_type("const std::vector<int> test"), 323 "List<int>") 324 self.assertEqual(generator._convert_container_type("const std::vector<struct ValueType> test"), 325 "List<ValueType>") 326 self.assertEqual(generator._convert_container_type("const std::vector<unsigned long> test"), 327 "List<unsigned long>") 328 329 330if __name__ == "__main__": 331 unittest.main() 332