• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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