• 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 
20 #include "libabckit/include/c/abckit.h"
21 #include "helpers/helpers.h"
22 #include "libabckit/include/c/metadata_core.h"
23 #include "logger.h"
24 
25 namespace libabckit::test {
26 
27 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
28 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
29 
30 static constexpr auto MODIFIED_DYNAMIC =
31     ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic_modified.abc";
32 static constexpr auto MODIFIED_STATIC =
33     ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static_modified.abc";
34 static constexpr auto MODIFIED_EMPTY_DYNAMIC =
35     ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_empty_dynamic_modified.abc";
36 
37 class LibAbcKitInspectApiClassesTest : public ::testing::Test {};
38 
ClassCountrer(AbckitCoreClass * klass,void * data)39 static bool ClassCountrer(AbckitCoreClass *klass, void *data)
40 {
41     helpers::AssertClassVisitor(klass, data);
42     (*(reinterpret_cast<std::size_t *>(data)))++;
43     return true;
44 }
45 
46 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateClasses, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,StaticModuleEnumerateClasses)47 TEST_F(LibAbcKitInspectApiClassesTest, StaticModuleEnumerateClasses)
48 {
49     AbckitFile *file = nullptr;
50     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
51 
52     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
53         std::size_t gotNumClasses = 0;
54         g_implI->moduleEnumerateClasses(m, &gotNumClasses, ClassCountrer);
55         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
56 
57         constexpr std::size_t EXPECTED_NUM_CLASSES = 1;
58         EXPECT_EQ(gotNumClasses, EXPECTED_NUM_CLASSES);
59 
60         return true;
61     });
62 
63     g_impl->closeFile(file);
64     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
65 }
66 
67 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateClasses, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicModuleEnumerateClasses)68 TEST_F(LibAbcKitInspectApiClassesTest, DynamicModuleEnumerateClasses)
69 {
70     AbckitFile *file = nullptr;
71     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
72 
73     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
74         std::size_t gotNumClasses = 0;
75         g_implI->moduleEnumerateClasses(m, &gotNumClasses, ClassCountrer);
76         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
77 
78         constexpr std::size_t EXPECTED_NUM_CLASSES = 1;
79         EXPECT_EQ(gotNumClasses, EXPECTED_NUM_CLASSES);
80 
81         return true;
82     });
83 
84     g_impl->closeFile(file);
85     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
86 }
87 
88 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateClasses, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,StaticModuleEnumerateClassesEmpty)89 TEST_F(LibAbcKitInspectApiClassesTest, StaticModuleEnumerateClassesEmpty)
90 {
91     AbckitFile *file = nullptr;
92     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_empty_static.abc", &file);
93 
94     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
95         std::size_t gotNumClasses = 0;
96         g_implI->moduleEnumerateClasses(m, &gotNumClasses, ClassCountrer);
97         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
98 
99         constexpr std::size_t EXPECTED_NUM_CLASSES = 1;
100         EXPECT_EQ(gotNumClasses, EXPECTED_NUM_CLASSES);
101 
102         return true;
103     });
104 
105     g_impl->closeFile(file);
106     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
107 }
108 
109 // Test: test-kind=api, api=InspectApiImpl::moduleEnumerateClasses, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicModuleEnumerateClassesEmpty)110 TEST_F(LibAbcKitInspectApiClassesTest, DynamicModuleEnumerateClassesEmpty)
111 {
112     AbckitFile *file = nullptr;
113     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_empty_dynamic.abc", &file);
114 
115     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
116         std::size_t gotNumClasses = 0;
117         g_implI->moduleEnumerateClasses(m, &gotNumClasses, ClassCountrer);
118         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
119 
120         constexpr std::size_t EXPECTED_NUM_CLASSES = 1;
121         EXPECT_EQ(gotNumClasses, EXPECTED_NUM_CLASSES);
122 
123         return true;
124     });
125 
126     g_impl->closeFile(file);
127     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
128 }
129 
130 // Test: test-kind=api, api=InspectApiImpl::classGetName, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,ClassGetNameSmoke)131 TEST_F(LibAbcKitInspectApiClassesTest, ClassGetNameSmoke)
132 {
133     AbckitFile *file = nullptr;
134     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
135 
136     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
137         AbckitString *name = nullptr;
138         name = g_implI->classGetName(nullptr);
139         EXPECT_EQ(name, nullptr);
140         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
141 
142         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
143         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
144         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
145         EXPECT_NE(ctxFinder.klass, nullptr);
146 
147         name = g_implI->classGetName(ctxFinder.klass);
148         EXPECT_NE(name, nullptr);
149         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
150         auto *file = g_implI->moduleGetFile(m);
151         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
152         EXPECT_NE(file, nullptr);
153         auto nameStr = helpers::AbckitStringToString(name);
154         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
155         EXPECT_EQ(nameStr, "C1");
156 
157         return true;
158     });
159 
160     g_impl->writeAbc(file, MODIFIED_STATIC, strlen(MODIFIED_STATIC));
161     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
162     g_impl->closeFile(file);
163     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
164 }
165 
166 // Test: test-kind=api, api=InspectApiImpl::classGetName, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassGetNameSmoke)167 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassGetNameSmoke)
168 {
169     AbckitFile *file = nullptr;
170     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
171 
172     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
173         AbckitString *name = nullptr;
174         name = g_implI->classGetName(nullptr);
175         EXPECT_EQ(name, nullptr);
176         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
177 
178         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
179         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
180         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
181         EXPECT_NE(ctxFinder.klass, nullptr);
182 
183         name = g_implI->classGetName(ctxFinder.klass);
184         EXPECT_NE(name, nullptr);
185         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
186         auto *file = g_implI->moduleGetFile(m);
187         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
188         EXPECT_NE(file, nullptr);
189         auto nameStr = helpers::AbckitStringToString(name);
190         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
191         EXPECT_EQ(nameStr, "C1");
192 
193         return true;
194     });
195 
196     g_impl->writeAbc(file, MODIFIED_DYNAMIC, strlen(MODIFIED_DYNAMIC));
197     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
198     g_impl->closeFile(file);
199     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
200 }
201 
ClassNameCollector(AbckitCoreClass * klass,void * data)202 static bool ClassNameCollector(AbckitCoreClass *klass, void *data)
203 {
204     helpers::AssertClassVisitor(klass, data);
205 
206     AbckitFile *file = g_implI->classGetFile(klass);
207     EXPECT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR);
208     EXPECT_TRUE(file != nullptr);
209     auto names = reinterpret_cast<std::set<std::string> *>(data);
210     auto className = g_implI->classGetName(klass);
211     EXPECT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR);
212 
213     auto name = helpers::AbckitStringToString(className);
214     LIBABCKIT_LOG(DEBUG) << "class name: " << name << std::endl;
215     EXPECT_TRUE(names->find(name.data()) == names->end());
216     names->insert(name.data());
217 
218     return true;
219 }
220 
221 // Test: test-kind=api, api=InspectApiImpl::classGetName, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,ClassGetName)222 TEST_F(LibAbcKitInspectApiClassesTest, ClassGetName)
223 {
224     AbckitFile *file = nullptr;
225     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
226 
227     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
228         std::set<std::string> gotNames;
229 
230         g_implI->moduleEnumerateClasses(m, &gotNames, ClassNameCollector);
231         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
232 
233         std::set<std::string> expectedNames = {"C1"};
234         EXPECT_EQ(expectedNames.size(), gotNames.size());
235         for (auto &expectedName : expectedNames) {
236             EXPECT_NE(gotNames.find(expectedName), gotNames.end());
237         }
238 
239         return true;
240     });
241 
242     g_impl->closeFile(file);
243     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
244 }
245 
246 // Test: test-kind=api, api=InspectApiImpl::classGetName, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassGetName)247 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassGetName)
248 {
249     AbckitFile *file = nullptr;
250     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
251 
252     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
253         std::set<std::string> gotNames;
254         g_implI->moduleEnumerateClasses(m, &gotNames, ClassNameCollector);
255         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
256 
257         std::set<std::string> expectedNames = {"C1"};
258         EXPECT_EQ(expectedNames.size(), gotNames.size());
259         for (auto &expectedName : expectedNames) {
260             EXPECT_NE(gotNames.find(expectedName), gotNames.end());
261         }
262 
263         return true;
264     });
265 
266     g_impl->writeAbc(file, MODIFIED_DYNAMIC, strlen(MODIFIED_DYNAMIC));
267     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
268     g_impl->closeFile(file);
269     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
270 }
271 
DummyMethodVisitor(AbckitCoreFunction * method,void *)272 static bool DummyMethodVisitor(AbckitCoreFunction *method, void * /*data*/)
273 {
274     EXPECT_TRUE(method != nullptr);
275     [[maybe_unused]] AbckitFile *file = g_implI->functionGetFile(method);
276     EXPECT_TRUE(file != nullptr);
277     return true;
278 }
279 
280 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,ClassEnumerateMethodsSmoke)281 TEST_F(LibAbcKitInspectApiClassesTest, ClassEnumerateMethodsSmoke)
282 {
283     AbckitFile *file = nullptr;
284     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
285 
286     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) -> bool {
287         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
288         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
289         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
290         EXPECT_NE(ctxFinder.klass, nullptr);
291         auto *klass = ctxFinder.klass;
292 
293         g_implI->classEnumerateMethods(nullptr, nullptr, nullptr);
294         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
295 
296         g_implI->classEnumerateMethods(klass, nullptr, nullptr);
297         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
298 
299         const auto implSomeData = 0xcafef00d;
300         void *someData = reinterpret_cast<void *>(implSomeData);
301         g_implI->classEnumerateMethods(klass, someData, nullptr);
302         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
303 
304         g_implI->classEnumerateMethods(ctxFinder.klass, nullptr, DummyMethodVisitor);
305         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
306 
307         g_implI->classEnumerateMethods(ctxFinder.klass, someData, DummyMethodVisitor);
308         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
309 
310         return true;
311     });
312 
313     g_impl->closeFile(file);
314     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
315 }
316 
317 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassEnumerateMethodsSmoke)318 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassEnumerateMethodsSmoke)
319 {
320     AbckitFile *file = nullptr;
321     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
322 
323     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) -> bool {
324         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
325         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
326         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
327         EXPECT_NE(ctxFinder.klass, nullptr);
328 
329         auto *klass = ctxFinder.klass;
330 
331         g_implI->classEnumerateMethods(nullptr, nullptr, nullptr);
332         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
333 
334         g_implI->classEnumerateMethods(klass, nullptr, nullptr);
335         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
336 
337         const auto implSomeData = 0xcafef00d;
338         void *someData = reinterpret_cast<void *>(implSomeData);
339         g_implI->classEnumerateMethods(klass, someData, nullptr);
340         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
341 
342         g_implI->classEnumerateMethods(ctxFinder.klass, nullptr, DummyMethodVisitor);
343         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
344 
345         g_implI->classEnumerateMethods(ctxFinder.klass, someData, DummyMethodVisitor);
346         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
347 
348         return true;
349     });
350 
351     g_impl->writeAbc(file, MODIFIED_DYNAMIC, strlen(MODIFIED_DYNAMIC));
352     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
353     g_impl->closeFile(file);
354     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
355 }
356 
MethodCountrer(AbckitCoreFunction * method,void * data)357 static bool MethodCountrer(AbckitCoreFunction *method, void *data)
358 {
359     helpers::AssertMethodVisitor(method, data);
360     (*(reinterpret_cast<std::size_t *>(data)))++;
361     return true;
362 }
363 
364 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,ClassEnumerateMethodsEmpty)365 TEST_F(LibAbcKitInspectApiClassesTest, ClassEnumerateMethodsEmpty)
366 {
367     AbckitFile *file = nullptr;
368     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_empty_static.abc", &file);
369 
370     // class C1 {
371     //     // Empty body, no explicit methods
372     //     <ctor>
373     // }
374 
375     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
376         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
377         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
378         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
379         EXPECT_NE(ctxFinder.klass, nullptr);
380         auto *klass = ctxFinder.klass;
381 
382         std::size_t gotNumMethods = 0;
383         g_implI->classEnumerateMethods(klass, &gotNumMethods, MethodCountrer);
384         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
385 
386         constexpr std::size_t EXPECTED_NUM_METHODS = 1;
387         EXPECT_EQ(gotNumMethods, EXPECTED_NUM_METHODS);
388 
389         return true;
390     });
391 
392     g_impl->closeFile(file);
393     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
394 }
395 
396 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassEnumerateMethodsEmpty)397 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassEnumerateMethodsEmpty)
398 {
399     AbckitFile *file = nullptr;
400     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_empty_dynamic.abc", &file);
401 
402     // class C1 {
403     //     // Empty body, no explicit methods
404     //     <ctor>
405     // }
406 
407     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
408         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
409         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
410         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
411         EXPECT_NE(ctxFinder.klass, nullptr);
412         auto *klass = ctxFinder.klass;
413 
414         std::size_t gotNumMethods = 0;
415         g_implI->classEnumerateMethods(klass, &gotNumMethods, MethodCountrer);
416         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
417 
418         constexpr std::size_t EXPECTED_NUM_METHODS = 1;
419         EXPECT_EQ(gotNumMethods, EXPECTED_NUM_METHODS);
420 
421         return true;
422     });
423 
424     g_impl->writeAbc(file, MODIFIED_EMPTY_DYNAMIC, strlen(MODIFIED_EMPTY_DYNAMIC));
425     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
426     g_impl->closeFile(file);
427     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
428 }
429 
430 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,ClassEnumerateMethodsSeveralMethods)431 TEST_F(LibAbcKitInspectApiClassesTest, ClassEnumerateMethodsSeveralMethods)
432 {
433     AbckitFile *file = nullptr;
434     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
435 
436     // class C1 {
437     //     public C1M1()
438     //     static C1M2()
439     //     <ctor>
440     // }
441 
442     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
443         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
444         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
445         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
446         EXPECT_NE(ctxFinder.klass, nullptr);
447         auto *klass = ctxFinder.klass;
448 
449         std::size_t gotNumMethods = 0;
450         g_implI->classEnumerateMethods(klass, &gotNumMethods, MethodCountrer);
451         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
452 
453         constexpr std::size_t EXPECTED_NUM_METHODS = 3;
454         EXPECT_EQ(gotNumMethods, EXPECTED_NUM_METHODS);
455 
456         return true;
457     });
458 
459     g_impl->closeFile(file);
460     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
461 }
462 
463 // Test: test-kind=api, api=InspectApiImpl::classEnumerateMethods, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassEnumerateMethodsSeveralMethods)464 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassEnumerateMethodsSeveralMethods)
465 {
466     AbckitFile *file = nullptr;
467     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
468 
469     // class C1 {
470     //     public C1M1()
471     //     static C1M2()
472     //     <ctor>
473     // }
474 
475     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) -> bool {
476         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
477         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
478         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
479         EXPECT_NE(ctxFinder.klass, nullptr);
480         auto *klass = ctxFinder.klass;
481 
482         std::size_t gotNumMethods = 0;
483         g_implI->classEnumerateMethods(klass, &gotNumMethods, MethodCountrer);
484         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
485 
486         constexpr std::size_t EXPECTED_NUM_METHODS = 3;
487         EXPECT_EQ(gotNumMethods, EXPECTED_NUM_METHODS);
488 
489         return true;
490     });
491 
492     g_impl->writeAbc(file, MODIFIED_EMPTY_DYNAMIC, strlen(MODIFIED_EMPTY_DYNAMIC));
493     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
494     g_impl->closeFile(file);
495     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
496 }
497 
498 // Test: test-kind=api, api=InspectApiImpl::classGetFile, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,ClassGetFile)499 TEST_F(LibAbcKitInspectApiClassesTest, ClassGetFile)
500 {
501     AbckitFile *file = nullptr;
502     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
503 
504     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) -> bool {
505         auto *ctxI1 = g_implI->moduleGetFile(m);
506 
507         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
508         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
509         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
510         EXPECT_NE(ctxFinder.klass, nullptr);
511 
512         auto *ctxI2 = g_implI->classGetFile(nullptr);
513         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
514         EXPECT_EQ(ctxI2, nullptr);
515 
516         ctxI2 = g_implI->classGetFile(ctxFinder.klass);
517         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
518         EXPECT_EQ(ctxI1, ctxI2);
519 
520         return true;
521     });
522 
523     g_impl->closeFile(file);
524     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
525 }
526 
527 // Test: test-kind=api, api=InspectApiImpl::classGetFile, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassGetFile)528 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassGetFile)
529 {
530     AbckitFile *file = nullptr;
531     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
532 
533     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) -> bool {
534         auto *ctxI1 = g_implI->moduleGetFile(m);
535 
536         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
537         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
538         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
539         EXPECT_NE(ctxFinder.klass, nullptr);
540 
541         auto *ctxI2 = g_implI->classGetFile(nullptr);
542         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
543         EXPECT_EQ(ctxI2, nullptr);
544 
545         ctxI2 = g_implI->classGetFile(ctxFinder.klass);
546         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
547         EXPECT_EQ(ctxI1, ctxI2);
548 
549         return true;
550     });
551 
552     g_impl->writeAbc(file, MODIFIED_DYNAMIC, strlen(MODIFIED_DYNAMIC));
553     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
554     g_impl->closeFile(file);
555     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
556 }
557 
558 // Test: test-kind=api, api=InspectApiImpl::classGetModule, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassGetModule)559 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassGetModule)
560 {
561     AbckitFile *file = nullptr;
562     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
563 
564     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
565         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
566         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
567         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
568         EXPECT_NE(ctxFinder.klass, nullptr);
569 
570         auto moduleNameRaw = g_implI->moduleGetName(g_implI->classGetModule(ctxFinder.klass));
571         EXPECT_NE(moduleNameRaw, nullptr);
572         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
573 
574         auto moduleName = helpers::AbckitStringToString(moduleNameRaw);
575         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
576         EXPECT_EQ(moduleName, "classes_dynamic");
577 
578         return true;
579     });
580 
581     g_impl->writeAbc(file, MODIFIED_DYNAMIC, strlen(MODIFIED_DYNAMIC));
582     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
583     g_impl->closeFile(file);
584     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
585 }
586 
587 // Test: test-kind=api, api=InspectApiImpl::classGetModule, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,StaticClassGetModule)588 TEST_F(LibAbcKitInspectApiClassesTest, StaticClassGetModule)
589 {
590     AbckitFile *file = nullptr;
591     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_static.abc", &file);
592 
593     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
594         helpers::ClassByNameContext ctxFinder = {nullptr, "C1"};
595         g_implI->moduleEnumerateClasses(m, &ctxFinder, helpers::ClassByNameFinder);
596         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
597         EXPECT_NE(ctxFinder.klass, nullptr);
598 
599         auto moduleNameRaw = g_implI->moduleGetName(g_implI->classGetModule(ctxFinder.klass));
600         EXPECT_NE(moduleNameRaw, nullptr);
601         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
602 
603         auto moduleName = helpers::AbckitStringToString(moduleNameRaw);
604         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
605         EXPECT_EQ(moduleName, "classes_static");
606 
607         return true;
608     });
609 
610     g_impl->writeAbc(file, MODIFIED_STATIC, strlen(MODIFIED_STATIC));
611     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
612     g_impl->closeFile(file);
613     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
614 }
615 
616 // Test: test-kind=api, api=InspectApiImpl::classGetParentFunction, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitInspectApiClassesTest,DynamicClassGetParentFunction)617 TEST_F(LibAbcKitInspectApiClassesTest, DynamicClassGetParentFunction)
618 {
619     AbckitFile *file = nullptr;
620     helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/metadata_core/inspect_api/classes/classes_dynamic.abc", &file);
621 
622     g_implI->fileEnumerateModules(file, nullptr, [](AbckitCoreModule *m, [[maybe_unused]] void *data) {
623         helpers::ClassByNameContext c0Finder = {nullptr, "C1"};
624         g_implI->moduleEnumerateClasses(m, &c0Finder, helpers::ClassByNameFinder);
625         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
626         EXPECT_NE(c0Finder.klass, nullptr);
627 
628         auto parentFunction1 = g_implI->classGetParentFunction(c0Finder.klass);
629         EXPECT_EQ(parentFunction1, nullptr);
630 
631         helpers::MethodByNameContext methodFinder = {nullptr, "f"};
632         g_implI->moduleEnumerateTopLevelFunctions(m, &methodFinder, helpers::MethodByNameFinder);
633         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
634         EXPECT_NE(methodFinder.method, nullptr);
635 
636         helpers::ClassByNameContext c1Finder = {nullptr, "C2"};
637         g_implI->functionEnumerateNestedClasses(methodFinder.method, &c1Finder, helpers::ClassByNameFinder);
638         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
639         EXPECT_NE(c1Finder.klass, nullptr);
640 
641         auto parentFunc = g_implI->classGetParentFunction(c1Finder.klass);
642         EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
643         EXPECT_EQ(parentFunc, methodFinder.method);
644 
645         return true;
646     });
647 
648     g_impl->writeAbc(file, MODIFIED_STATIC, strlen(MODIFIED_STATIC));
649     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
650     g_impl->closeFile(file);
651     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
652 }
653 
654 }  // namespace libabckit::test
655