• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cassert>
17 #include <cstring>
18 #include <gtest/gtest.h>
19 #include <numeric>
20 
21 #include "libabckit/include/c/abckit.h"
22 #include "helpers/helpers.h"
23 #include "libabckit/include/c/metadata_core.h"
24 #include "libabckit/include/c/statuses.h"
25 
26 namespace libabckit::test {
27 
28 namespace {
29 
30 auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33 
34 class LibAbcKitInspectApiEnumeratorsTest : public ::testing::Test {};
35 
36 using NamesT = std::unordered_map<std::string, std::vector<std::string>>;
37 
38 // clang-format off
39 NamesT g_m1NamesDynamic = {
40     {"m0N0N0F0", {"enumerators0_dynamic", "M0N0", "M0N0N0"}},
41     {"M0N0C0", {"enumerators0_dynamic", "M0N0", "M0N0C0"}},
42     {"M0N0C0F0", {"enumerators0_dynamic", "M0N0", "M0N0C0"}},
43     {"M0N0C0F1", {"enumerators0_dynamic", "M0N0", "M0N0C0"}},
44     {"M0N0C0F2", {"enumerators0_dynamic", "M0N0", "M0N0C0"}},
45     {"C", {"enumerators0_dynamic", "M0N0", "A", "B", "C"}},
46     {"D", {"enumerators0_dynamic", "M0N0", "A", "B", "C"}},
47     {"I", {"enumerators0_dynamic", "M0N0", "A", "B"}},
48     {"m0N0F0", {"enumerators0_dynamic", "M0N0"}},
49     {"m0N0F1", {"enumerators0_dynamic", "M0N0"}},
50     {"m0N0F2", {"enumerators0_dynamic", "M0N0"}},
51     {"M0C0", {"enumerators0_dynamic", "M0C0"}},
52     {"M0C0F0", {"enumerators0_dynamic", "M0C0"}},
53     {"M0C0F1", {"enumerators0_dynamic", "M0C0"}},
54     {"M0C0F2", {"enumerators0_dynamic", "M0C0"}},
55     {"m0F0", {"enumerators0_dynamic"}},
56     {"M0F0C0", {"enumerators0_dynamic", "m0F0", "M0F0C0"}},
57     {"M0F0C0F0", {"enumerators0_dynamic", "m0F0", "M0F0C0"}},
58     {"m0F1", {"enumerators0_dynamic"}},
59     {"m0F2", {"enumerators0_dynamic"}},
60     {"enumerators0_dynamic.#~@2=@2*#", {"enumerators0_dynamic"}},
61     {"enumerators0_dynamic.#&@3&A&B~C>D*#E", {"enumerators0_dynamic"}},
62     {"enumerators0_dynamic.#&@3&A&B~C>D*#E^1", {"enumerators0_dynamic"}},
63     {"enumerators0_dynamic.#&@3&A&B~C>D*E^1*#G", {"enumerators0_dynamic"}},
64     {"enumerators0_dynamic.#&@3&A&B~C>D*E*#F", {"enumerators0_dynamic"}},
65     {"enumerators0_dynamic.#&@3&A&B~C>D*#", {"enumerators0_dynamic"}},
66     {"enumerators0_dynamic.#&@3&A&B~C>D**#", {"enumerators0_dynamic"}},
67     {"enumerators0_dynamic.#&@3&A&B~C>D***#H", {"enumerators0_dynamic"}},
68     {"enumerators0_dynamic.#*@0*#", {"enumerators0_dynamic"}},
69     {"enumerators0_dynamic.#*@0*#^1", {"enumerators0_dynamic"}},
70     {"func_main_0", {"enumerators0_dynamic"}},
71 };
72 
73 NamesT g_m2NamesDynamic = {
74     {"M1N0C0", {"modules/enumerators1_dynamic", "M1N0", "M1N0C0"}},
75     {"M1N0C0F0", {"modules/enumerators1_dynamic", "M1N0", "M1N0C0"}},
76     {"M1N0C0F1", {"modules/enumerators1_dynamic", "M1N0", "M1N0C0"}},
77     {"M1N0C0F2", {"modules/enumerators1_dynamic", "M1N0", "M1N0C0"}},
78     {"m1N0F0", {"modules/enumerators1_dynamic", "M1N0"}},
79     {"m1N0F1", {"modules/enumerators1_dynamic", "M1N0"}},
80     {"M1C0", {"modules/enumerators1_dynamic", "M1C0"}},
81     {"M1C0F0", {"modules/enumerators1_dynamic", "M1C0"}},
82     {"M1C0F1", {"modules/enumerators1_dynamic", "M1C0"}},
83     {"M1C0F2", {"modules/enumerators1_dynamic", "M1C0"}},
84     {"m1F0", {"modules/enumerators1_dynamic"}},
85     {"m1F1", {"modules/enumerators1_dynamic"}},
86     {"modules/enumerators1_dynamic.#*@0*#", {"modules/enumerators1_dynamic"}},
87     {"func_main_0", {"modules/enumerators1_dynamic"}},
88 };
89 // clang-format on
90 
91 std::unordered_map<std::string, NamesT> g_namesDynamic = {
92     {"enumerators0_dynamic", g_m1NamesDynamic},
93     {"modules/enumerators1_dynamic", g_m2NamesDynamic},
94 };
95 
96 std::unordered_map<std::string, NamesT> g_namesStatic = {
97     {"enumerators0_dynamic", g_m1NamesDynamic},
98     {"modules/enumerators1_dynamic", g_m2NamesDynamic},
99 };
100 
GetCbNamespace(std::vector<std::string> & curNames,std::function<void (AbckitCoreNamespace *)> & cbNamespace,std::function<void (AbckitCoreClass *)> & cbClass,std::function<void (AbckitCoreFunction *)> & cbFunc)101 std::function<void(AbckitCoreNamespace *)> GetCbNamespace(std::vector<std::string> &curNames,
102                                                           std::function<void(AbckitCoreNamespace *)> &cbNamespace,
103                                                           std::function<void(AbckitCoreClass *)> &cbClass,
104                                                           std::function<void(AbckitCoreFunction *)> &cbFunc)
105 {
106     return [&](AbckitCoreNamespace *n) {
107         auto namespaceName = helpers::AbckitStringToString(g_implI->namespaceGetName(n));
108         curNames.emplace_back(namespaceName);
109         g_implI->namespaceEnumerateNamespaces(n, &cbNamespace, [](AbckitCoreNamespace *n, void *cb) {
110             (*reinterpret_cast<std::function<void(AbckitCoreNamespace *)> *>(cb))(n);
111             return true;
112         });
113         g_implI->namespaceEnumerateClasses(n, &cbClass, [](AbckitCoreClass *c, void *cb) {
114             (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
115             return true;
116         });
117         g_implI->namespaceEnumerateTopLevelFunctions(n, &cbFunc, [](AbckitCoreFunction *f, void *cb) {
118             (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(f);
119             return true;
120         });
121         curNames.pop_back();
122     };
123 }
124 
EnumerateAllMethodsInModule(AbckitFile * file,std::function<void (AbckitCoreClass *)> & cbClass,std::function<void (AbckitCoreFunction *)> & cbFunc,std::vector<std::string> & curNames,std::string & curModuleName)125 void EnumerateAllMethodsInModule(AbckitFile *file, std::function<void(AbckitCoreClass *)> &cbClass,
126                                  std::function<void(AbckitCoreFunction *)> &cbFunc, std::vector<std::string> &curNames,
127                                  std::string &curModuleName)
128 {
129     std::function<void(AbckitCoreNamespace *)> cbNamespace = GetCbNamespace(curNames, cbNamespace, cbClass, cbFunc);
130 
131     std::function<void(AbckitCoreModule *)> cbModule = [&](AbckitCoreModule *m) {
132         curModuleName = helpers::AbckitStringToString(g_implI->moduleGetName(m));
133         curNames.emplace_back(curModuleName);
134         g_implI->moduleEnumerateNamespaces(m, &cbNamespace, [](AbckitCoreNamespace *n, void *cb) {
135             (*reinterpret_cast<std::function<void(AbckitCoreNamespace *)> *>(cb))(n);
136             return true;
137         });
138         g_implI->moduleEnumerateClasses(m, &cbClass, [](AbckitCoreClass *c, void *cb) {
139             (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
140             return true;
141         });
142         g_implI->moduleEnumerateTopLevelFunctions(m, &cbFunc, [](AbckitCoreFunction *m, void *cb) {
143             (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(m);
144             return true;
145         });
146         curNames.pop_back();
147     };
148 
149     g_implI->fileEnumerateModules(file, &cbModule, [](AbckitCoreModule *m, void *cb) {
150         (*reinterpret_cast<std::function<void(AbckitCoreModule *)> *>(cb))(m);
151         return true;
152     });
153 }
154 
155 struct TestStructType {
156     size_t anonFuncsCounter = 0;
157     std::string nameModuleToSearch;
158     std::vector<std::string> namesOfAnonFuncs;
159 };
160 
161 }  // namespace
162 
EnumerateAllMethods(const std::string & inputPath,std::unordered_map<std::string,NamesT> & expectedNames)163 static void EnumerateAllMethods(const std::string &inputPath, std::unordered_map<std::string, NamesT> &expectedNames)
164 {
165     AbckitFile *file = nullptr;
166     helpers::AssertOpenAbc(inputPath.c_str(), &file);
167 
168     size_t funcsCounter = 0;
169     std::vector<std::string> curNames {};
170     std::string curModuleName {};
171 
172     std::function<void(AbckitCoreClass *)> cbClass;
173 
174     std::function<void(AbckitCoreFunction *)> cbFunc = [&](AbckitCoreFunction *f) {
175         auto funcName = helpers::AbckitStringToString(g_implI->functionGetName(f));
176         ASSERT_EQ(expectedNames.count(curModuleName), 1);
177         auto &moduleNames = expectedNames[curModuleName];
178         ASSERT_EQ(moduleNames.count(funcName.data()), 1);
179         auto &funcNames = moduleNames[funcName.data()];
180         ASSERT_EQ(funcNames.size(), curNames.size());
181         ASSERT_TRUE(std::equal(funcNames.begin(), funcNames.end(), curNames.begin()));
182         funcsCounter++;
183         curNames.emplace_back(funcName);
184         g_implI->functionEnumerateNestedFunctions(f, &cbFunc, [](AbckitCoreFunction *f, void *cb) {
185             (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(f);
186             return true;
187         });
188         g_implI->functionEnumerateNestedClasses(f, &cbClass, [](AbckitCoreClass *c, void *cb) {
189             (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
190             return true;
191         });
192         curNames.pop_back();
193     };
194 
195     cbClass = [&](AbckitCoreClass *c) {
196         auto className = helpers::AbckitStringToString(g_implI->classGetName(c));
197         curNames.emplace_back(className);
198         g_implI->classEnumerateMethods(c, &cbFunc, [](AbckitCoreFunction *m, void *cb) {
199             (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(m);
200             return true;
201         });
202         curNames.pop_back();
203     };
204 
205     EnumerateAllMethodsInModule(file, cbClass, cbFunc, curNames, curModuleName);
206     ASSERT_EQ(funcsCounter, std::accumulate(expectedNames.begin(), expectedNames.end(), 0,
207                                             [](size_t x, auto y) { return x + y.second.size(); }));
208 
209     g_impl->closeFile(file);
210     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
211 }
212 
EnumerateAnonymousFunctions(const char * abcFilePath,TestStructType & testStruct)213 static void EnumerateAnonymousFunctions(const char *abcFilePath, TestStructType &testStruct)
214 {
215     std::cerr << __PRETTY_FUNCTION__ << '\n';
216     AbckitFile *file = nullptr;
217     std::cerr << __PRETTY_FUNCTION__ << '\n';
218     helpers::AssertOpenAbc(abcFilePath, &file);
219     std::cerr << __PRETTY_FUNCTION__ << '\n';
220 
221     g_implI->fileEnumerateModules(file, &testStruct, [](AbckitCoreModule *m, void *data) {
222         auto testStruct = reinterpret_cast<TestStructType *>(data);
223 
224         auto strModule = g_implI->moduleGetName(m);
225         EXPECT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR);
226         auto nameModule = helpers::AbckitStringToString(strModule);
227         if (nameModule != testStruct->nameModuleToSearch) {
228             return true;
229         }
230         g_implI->moduleEnumerateAnonymousFunctions(m, data, [](AbckitCoreFunction *func, void *data1) {
231             auto testStruct = reinterpret_cast<TestStructType *>(data1);
232 
233             auto strFunc = g_implI->functionGetName(func);
234             EXPECT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR);
235 
236             auto nameFunc = helpers::AbckitStringToString(strFunc);
237 
238             auto &funcs = testStruct->namesOfAnonFuncs;
239 
240             auto iter = std::find_if(funcs.begin(), funcs.end(),
241                                      [&nameFunc](const std::string &name) { return nameFunc == name; });
242 
243             EXPECT_TRUE(iter != funcs.end());
244             testStruct->anonFuncsCounter++;
245             return true;
246         });
247         return true;
248     });
249     std::cerr << __PRETTY_FUNCTION__ << '\n';
250 
251     ASSERT_EQ(testStruct.anonFuncsCounter, testStruct.namesOfAnonFuncs.size());
252     g_impl->closeFile(file);
253     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
254 }
255 
256 // Test: test-kind=api, api=InspectApiImpl::fileEnumerateModules, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicFileEnumerateModules)257 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicFileEnumerateModules)
258 {
259     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
260                         g_namesDynamic);
261 }
262 
263 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateNamespaces, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicModuleEnumerateNamespaces)264 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicModuleEnumerateNamespaces)
265 {
266     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
267                         g_namesDynamic);
268 }
269 
270 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateClasses, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicModuleEnumerateClasses)271 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicModuleEnumerateClasses)
272 {
273     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
274                         g_namesDynamic);
275 }
276 
277 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateTopLevelFunctions, abc-kind=ArkTS1, category=positive,
278 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicModuleEnumerateTopLevelFunctions)279 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicModuleEnumerateTopLevelFunctions)
280 {
281     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
282                         g_namesDynamic);
283 }
284 
285 // Test: test-kind=api, api=InspectApiImpl::namespaceGetName, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicNamespaceGetName)286 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicNamespaceGetName)
287 {
288     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
289                         g_namesDynamic);
290 }
291 
292 // Test: test-kind=api, api=InspectApiImpl::namespaceEnumerateNamespaces, abc-kind=ArkTS1, category=positive,
293 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicNamespaceEnumerateNamespaces)294 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicNamespaceEnumerateNamespaces)
295 {
296     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
297                         g_namesDynamic);
298 }
299 
300 // Test: test-kind=api, api=InspectApiImpl::namespaceEnumerateClasses, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicNamespaceEnumerateClasses)301 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicNamespaceEnumerateClasses)
302 {
303     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
304                         g_namesDynamic);
305 }
306 
307 // Test: test-kind=api, api=InspectApiImpl::namespaceEnumerateTopLevelFunctions, abc-kind=ArkTS1, category=positive,
308 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicNamespaceEnumerateTopLevelFunctions)309 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicNamespaceEnumerateTopLevelFunctions)
310 {
311     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
312                         g_namesDynamic);
313 }
314 
315 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicClassEnumerateMethods)316 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicClassEnumerateMethods)
317 {
318     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
319                         g_namesDynamic);
320 }
321 
322 // Test: test-kind=api, api=InspectApiImpl::functionEnumerateNestedFunctions, abc-kind=ArkTS1, category=positive,
323 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicFunctionEnumerateNestedFunctions)324 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicFunctionEnumerateNestedFunctions)
325 {
326     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
327                         g_namesDynamic);
328 }
329 
330 // Test: test-kind=api, api=InspectApiImpl::functionEnumerateNestedClasses, abc-kind=ArkTS1, category=positive,
331 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicFunctionEnumerateNestedClasses)332 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicFunctionEnumerateNestedClasses)
333 {
334     EnumerateAllMethods(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
335                         g_namesDynamic);
336 }
337 
338 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateAnonymousFunctions, abc-kind=ArkTS1, category=positive,
339 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,DynamicClassEnumerateAnonymousFunctions)340 TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicClassEnumerateAnonymousFunctions)
341 {
342     std::cerr << __PRETTY_FUNCTION__ << '\n';
343     TestStructType testStruct;
344     testStruct.nameModuleToSearch = "enumerators0_dynamic";
345     testStruct.namesOfAnonFuncs = {
346         "enumerators0_dynamic.#&@3&A&B~C>D*#",
347         "enumerators0_dynamic.#&@3&A&B~C>D**#",
348         "enumerators0_dynamic.#&@3&A&B~C>D*#E",
349         "enumerators0_dynamic.#&@3&A&B~C>D*#E^1",
350         "enumerators0_dynamic.#&@3&A&B~C>D***#H",
351         "enumerators0_dynamic.#&@3&A&B~C>D*E*#F",
352         "enumerators0_dynamic.#&@3&A&B~C>D*E^1*#G",
353         "enumerators0_dynamic.#*@0*#",
354         "enumerators0_dynamic.#*@0*#^1",
355         "enumerators0_dynamic.#~@2=@2*#",
356     };
357 
358     EnumerateAnonymousFunctions(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators0_dynamic.abc",
359                                 testStruct);
360 }
361 
362 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateAnonymousFunctions, abc-kind=ArkTS2, category=positive,
363 // extension=c
TEST_F(LibAbcKitInspectApiEnumeratorsTest,StaticClassEnumerateAnonymousFunctions)364 TEST_F(LibAbcKitInspectApiEnumeratorsTest, StaticClassEnumerateAnonymousFunctions)
365 {
366     TestStructType testStruct;
367     testStruct.nameModuleToSearch = "enumerators_static";
368     testStruct.namesOfAnonFuncs = std::vector<std::string> {"lambda$invoke$0:void;", "lambda$invoke$1:void;"};
369 
370     EnumerateAnonymousFunctions(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/enumerators/enumerators_static.abc",
371                                 testStruct);
372 }
373 
374 }  // namespace libabckit::test
375