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/statuses.h"
24
25 namespace libabckit::test {
26
27 namespace {
28
29 auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
30 auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32
33 class LibAbcKitJSInspectApiEnumeratorsTest : public ::testing::Test {};
34
35 // clang-format off
36 std::unordered_map<std::string, std::vector<std::string>> g_jsM1Names = {
37 {"m0N0N0F0", {"JSenumerators0_dynamic"}},
38 {"M0N0C0", {"JSenumerators0_dynamic", "M0N0C0"}},
39 {"M0N0C0F0", {"JSenumerators0_dynamic", "M0N0C0"}},
40 {"M0N0C0F1", {"JSenumerators0_dynamic", "M0N0C0"}},
41 {"M0N0C0F2", {"JSenumerators0_dynamic", "M0N0C0"}},
42 {"C", {"JSenumerators0_dynamic", "C"}},
43 {"D", {"JSenumerators0_dynamic", "C"}},
44 {"e", {"JSenumerators0_dynamic"}},
45 {"m0N0F0", {"JSenumerators0_dynamic"}},
46 {"m0N0F1", {"JSenumerators0_dynamic"}},
47 {"m0N0F2", {"JSenumerators0_dynamic"}},
48 {"M0C0", {"JSenumerators0_dynamic", "M0C0"}},
49 {"M0C0F0", {"JSenumerators0_dynamic", "M0C0"}},
50 {"M0C0F1", {"JSenumerators0_dynamic", "M0C0"}},
51 {"M0C0F2", {"JSenumerators0_dynamic", "M0C0"}},
52 {"m0F0", {"JSenumerators0_dynamic"}},
53 {"m0F0F0", {"JSenumerators0_dynamic", "m0F0"}},
54 {"m0F0F1", {"JSenumerators0_dynamic", "m0F0"}},
55 {"M0F0C0", {"JSenumerators0_dynamic", "m0F0", "M0F0C0"}},
56 {"M0F0C0F0", {"JSenumerators0_dynamic", "m0F0", "M0F0C0"}},
57 {"m0F1", {"JSenumerators0_dynamic"}},
58 {"m0F2", {"JSenumerators0_dynamic"}},
59 {"JSenumerators0_dynamic.#*@0*#", {"JSenumerators0_dynamic"}},
60 {"JSenumerators0_dynamic.#*@0*#^1", {"JSenumerators0_dynamic"}},
61 {"func_main_0", {"JSenumerators0_dynamic"}},
62 };
63
64 std::unordered_map<std::string, std::vector<std::string>> g_jsM2Names = {
65 {"M1N0C0", {"modules/JSenumerators1_dynamic", "M1N0C0"}},
66 {"M1N0C0F0", {"modules/JSenumerators1_dynamic", "M1N0C0"}},
67 {"M1N0C0F1", {"modules/JSenumerators1_dynamic", "M1N0C0"}},
68 {"M1N0C0F2", {"modules/JSenumerators1_dynamic", "M1N0C0"}},
69 {"m1N0F0", {"modules/JSenumerators1_dynamic"}},
70 {"m1N0F1", {"modules/JSenumerators1_dynamic"}},
71 {"M1C0", {"modules/JSenumerators1_dynamic", "M1C0"}},
72 {"M1C0F0", {"modules/JSenumerators1_dynamic", "M1C0"}},
73 {"M1C0F1", {"modules/JSenumerators1_dynamic", "M1C0"}},
74 {"M1C0F2", {"modules/JSenumerators1_dynamic", "M1C0"}},
75 {"m1F0", {"modules/JSenumerators1_dynamic"}},
76 {"m1F1", {"modules/JSenumerators1_dynamic"}},
77 {"modules/JSenumerators1_dynamic.#*@0*#", {"modules/JSenumerators1_dynamic"}},
78 {"func_main_0", {"modules/JSenumerators1_dynamic"}},
79 };
80 // clang-format on
81
82 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> g_jsnames = {
83 {"JSenumerators0_dynamic", g_jsM1Names},
84 {"modules/JSenumerators1_dynamic", g_jsM2Names},
85 };
86
GetCbNamespace(std::vector<std::string> & curNames,std::function<void (AbckitCoreNamespace *)> & cbNamespace,std::function<void (AbckitCoreClass *)> & cbClass,std::function<void (AbckitCoreFunction *)> & cbFunc)87 std::function<void(AbckitCoreNamespace *)> GetCbNamespace(std::vector<std::string> &curNames,
88 std::function<void(AbckitCoreNamespace *)> &cbNamespace,
89 std::function<void(AbckitCoreClass *)> &cbClass,
90 std::function<void(AbckitCoreFunction *)> &cbFunc)
91 {
92 return [&](AbckitCoreNamespace *n) {
93 auto namespaceName = helpers::AbckitStringToString(g_implI->namespaceGetName(n));
94 curNames.emplace_back(namespaceName);
95 g_implI->namespaceEnumerateNamespaces(n, &cbNamespace, [](AbckitCoreNamespace *n, void *cb) {
96 (*reinterpret_cast<std::function<void(AbckitCoreNamespace *)> *>(cb))(n);
97 return true;
98 });
99 g_implI->namespaceEnumerateClasses(n, &cbClass, [](AbckitCoreClass *c, void *cb) {
100 (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
101 return true;
102 });
103 g_implI->namespaceEnumerateTopLevelFunctions(n, &cbFunc, [](AbckitCoreFunction *f, void *cb) {
104 (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(f);
105 return true;
106 });
107 curNames.pop_back();
108 };
109 }
110
EnumerateAllMethodsInModule(AbckitFile * file,std::function<void (AbckitCoreClass *)> & cbClass,std::function<void (AbckitCoreFunction *)> & cbFunc,std::vector<std::string> & curNames,std::string & curModuleName)111 void EnumerateAllMethodsInModule(AbckitFile *file, std::function<void(AbckitCoreClass *)> &cbClass,
112 std::function<void(AbckitCoreFunction *)> &cbFunc, std::vector<std::string> &curNames,
113 std::string &curModuleName)
114 {
115 std::function<void(AbckitCoreNamespace *)> cbNamespace = GetCbNamespace(curNames, cbNamespace, cbClass, cbFunc);
116
117 std::function<void(AbckitCoreModule *)> cbModule = [&](AbckitCoreModule *m) {
118 curModuleName = helpers::AbckitStringToString(g_implI->moduleGetName(m));
119 curNames.emplace_back(curModuleName);
120 g_implI->moduleEnumerateNamespaces(m, &cbNamespace, [](AbckitCoreNamespace *n, void *cb) {
121 (*reinterpret_cast<std::function<void(AbckitCoreNamespace *)> *>(cb))(n);
122 return true;
123 });
124 g_implI->moduleEnumerateClasses(m, &cbClass, [](AbckitCoreClass *c, void *cb) {
125 (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
126 return true;
127 });
128 g_implI->moduleEnumerateTopLevelFunctions(m, &cbFunc, [](AbckitCoreFunction *m, void *cb) {
129 (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(m);
130 return true;
131 });
132 curNames.pop_back();
133 };
134
135 g_implI->fileEnumerateModules(file, &cbModule, [](AbckitCoreModule *m, void *cb) {
136 (*reinterpret_cast<std::function<void(AbckitCoreModule *)> *>(cb))(m);
137 return true;
138 });
139 }
140
141 struct TestStructType {
142 size_t anonFuncsCounter = 0;
143 std::string nameModuleToSearch;
144 std::vector<std::string> namesOfAnonFuncs;
145 };
146
147 } // namespace
148
EnumerateAllMethods(const char * abcFilePath,std::unordered_map<std::string,std::unordered_map<std::string,std::vector<std::string>>> expectedNames)149 static void EnumerateAllMethods(
150 const char *abcFilePath,
151 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> expectedNames)
152 {
153 AbckitFile *file = nullptr;
154 helpers::AssertOpenAbc(abcFilePath, &file);
155
156 size_t funcsCounter = 0;
157 std::vector<std::string> curNames {};
158 std::string curModuleName {};
159
160 std::function<void(AbckitCoreClass *)> cbClass;
161 std::function<void(AbckitCoreFunction *)> cbFunc;
162
163 cbFunc = [&](AbckitCoreFunction *f) {
164 auto funcName = helpers::AbckitStringToString(g_implI->functionGetName(f));
165 ASSERT_EQ(expectedNames.count(curModuleName), 1);
166 auto &moduleNames = expectedNames[curModuleName];
167 ASSERT_EQ(moduleNames.count(funcName.data()), 1);
168 auto &funcNames = moduleNames[funcName.data()];
169 ASSERT_EQ(funcNames.size(), curNames.size());
170 ASSERT_TRUE(std::equal(funcNames.begin(), funcNames.end(), curNames.begin()));
171 funcsCounter++;
172 curNames.emplace_back(funcName);
173 g_implI->functionEnumerateNestedFunctions(f, &cbFunc, [](AbckitCoreFunction *f, void *cb) {
174 (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(f);
175 return true;
176 });
177 g_implI->functionEnumerateNestedClasses(f, &cbClass, [](AbckitCoreClass *c, void *cb) {
178 (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
179 return true;
180 });
181 curNames.pop_back();
182 };
183
184 cbClass = [&](AbckitCoreClass *c) {
185 auto className = helpers::AbckitStringToString(g_implI->classGetName(c));
186 curNames.emplace_back(className);
187 g_implI->classEnumerateMethods(c, &cbFunc, [](AbckitCoreFunction *m, void *cb) {
188 (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(m);
189 return true;
190 });
191 curNames.pop_back();
192 };
193
194 EnumerateAllMethodsInModule(file, cbClass, cbFunc, curNames, curModuleName);
195 ASSERT_EQ(funcsCounter, std::accumulate(expectedNames.begin(), expectedNames.end(), 0,
196 [](size_t x, auto y) { return x + y.second.size(); }));
197
198 g_impl->closeFile(file);
199 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
200 }
201
EnumerateAnonymousFunctions(const char * abcFilePath,TestStructType & testStruct)202 static void EnumerateAnonymousFunctions(const char *abcFilePath, TestStructType &testStruct)
203 {
204 AbckitFile *file = nullptr;
205 helpers::AssertOpenAbc(abcFilePath, &file);
206
207 g_implI->fileEnumerateModules(file, &testStruct, [](AbckitCoreModule *m, void *data) {
208 auto testStruct = reinterpret_cast<TestStructType *>(data);
209
210 auto strModule = g_implI->moduleGetName(m);
211 EXPECT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR);
212 auto nameModule = helpers::AbckitStringToString(strModule);
213 if (nameModule != testStruct->nameModuleToSearch) {
214 return true;
215 }
216 g_implI->moduleEnumerateAnonymousFunctions(m, data, [](AbckitCoreFunction *func, void *data1) {
217 auto testStruct = reinterpret_cast<TestStructType *>(data1);
218
219 auto strFunc = g_implI->functionGetName(func);
220 EXPECT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR);
221
222 auto nameFunc = helpers::AbckitStringToString(strFunc);
223
224 auto &funcs = testStruct->namesOfAnonFuncs;
225
226 auto iter = std::find_if(funcs.begin(), funcs.end(),
227 [&nameFunc](const std::string &name) { return nameFunc == name; });
228
229 EXPECT_TRUE(iter != funcs.end());
230 testStruct->anonFuncsCounter++;
231 return true;
232 });
233 return true;
234 });
235
236 ASSERT_EQ(testStruct.anonFuncsCounter, testStruct.namesOfAnonFuncs.size());
237 g_impl->closeFile(file);
238 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
239 }
240
241 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateAnonymousFunctions, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSClassEnumerateAnonymousFunctions)242 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSClassEnumerateAnonymousFunctions)
243 {
244 TestStructType testStruct;
245 testStruct.nameModuleToSearch = "JSenumerators0_dynamic";
246 testStruct.namesOfAnonFuncs =
247 std::vector<std::string> {"JSenumerators0_dynamic.#*@0*#", "JSenumerators0_dynamic.#*@0*#^1"};
248
249 EnumerateAnonymousFunctions(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
250 testStruct);
251 }
252
253 // Test: test-kind=api, api=InspectApiImpl::fileEnumerateModules, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSFileEnumerateModules)254 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSFileEnumerateModules)
255 {
256 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
257 g_jsnames);
258 }
259
260 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateNamespaces, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSModuleEnumerateNamespaces)261 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSModuleEnumerateNamespaces)
262 {
263 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
264 g_jsnames);
265 }
266
267 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateClasses, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSModuleEnumerateClasses)268 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSModuleEnumerateClasses)
269 {
270 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
271 g_jsnames);
272 }
273
274 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateTopLevelFunctions, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSModuleEnumerateTopLevelFunctions)275 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSModuleEnumerateTopLevelFunctions)
276 {
277 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
278 g_jsnames);
279 }
280
281 // Test: test-kind=api, api=InspectApiImpl::namespaceGetName, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSNamespaceGetName)282 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSNamespaceGetName)
283 {
284 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
285 g_jsnames);
286 }
287
288 // Test: test-kind=api, api=InspectApiImpl::namespaceEnumerateNamespaces, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSNamespaceEnumerateNamespaces)289 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSNamespaceEnumerateNamespaces)
290 {
291 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
292 g_jsnames);
293 }
294
295 // Test: test-kind=api, api=InspectApiImpl::namespaceEnumerateClasses, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSNamespaceEnumerateClasses)296 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSNamespaceEnumerateClasses)
297 {
298 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
299 g_jsnames);
300 }
301
302 // Test: test-kind=api, api=InspectApiImpl::namespaceEnumerateTopLevelFunctions, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSNamespaceEnumerateTopLevelFunctions)303 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSNamespaceEnumerateTopLevelFunctions)
304 {
305 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
306 g_jsnames);
307 }
308
309 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSInspectApiEnumeratorsTest,JSClassEnumerateMethods)310 TEST_F(LibAbcKitJSInspectApiEnumeratorsTest, JSClassEnumerateMethods)
311 {
312 EnumerateAllMethods(ABCKIT_ABC_DIR "ut/extensions/js/inspect_api/enumerators/JSenumerators0_dynamic.abc",
313 g_jsnames);
314 }
315
316 } // namespace libabckit::test
317