• 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/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