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