1 /**
2 * Copyright (c) 2025 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 "libabckit/include/c/abckit.h"
17 #include "libabckit/include/c/ir_core.h"
18
19 #include "helpers/helpers.h"
20
21 #include <gtest/gtest.h>
22 #include <ostream>
23 #include <string>
24 #include <unordered_map>
25
26 namespace libabckit::test {
27
28 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
29 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
30 static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 static auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33
GetMethodName(AbckitCoreFunction * method)34 std::string GetMethodName(AbckitCoreFunction *method)
35 {
36 auto mname = g_implI->functionGetName(method);
37 auto methodName = helpers::AbckitStringToString(mname);
38 auto modname = g_implI->moduleGetName(g_implI->functionGetModule(method));
39 auto moduleName = helpers::AbckitStringToString(modname);
40 auto *cls = g_implI->functionGetParentClass(method);
41 if (cls == nullptr) {
42 return std::string(moduleName) + ' ' + std::string(methodName);
43 }
44 auto cname = g_implI->classGetName(cls);
45 auto className = helpers::AbckitStringToString(cname);
46 return std::string(moduleName) + ' ' + std::string(className) + '.' + std::string(methodName);
47 }
48
EnumerateInsts(AbckitBasicBlock * bb,std::unordered_map<std::string,int> * methodsMap)49 void EnumerateInsts(AbckitBasicBlock *bb, std::unordered_map<std::string, int> *methodsMap)
50 {
51 auto *inst = g_implG->bbGetFirstInst(bb);
52 while (inst != nullptr) {
53 if (g_implG->iCheckIsCall(inst)) {
54 auto *method = g_implG->iGetFunction(inst);
55 if (method != nullptr) {
56 auto methodName = GetMethodName(method);
57 methodsMap->at(methodName) += 1;
58 }
59 }
60 inst = g_implG->iGetNext(inst);
61 }
62 }
63
VisitAllBBs(AbckitGraph * graph,std::unordered_map<std::string,int> & methodsMap)64 void VisitAllBBs(AbckitGraph *graph, std::unordered_map<std::string, int> &methodsMap)
65 {
66 g_implG->gVisitBlocksRpo(graph, &methodsMap, [](AbckitBasicBlock *bb, void *data) {
67 EnumerateInsts(bb, reinterpret_cast<std::unordered_map<std::string, int> *>(data));
68 return true;
69 });
70 }
71
CheckRessult(std::unordered_map<std::string,int> & methodsMap)72 bool CheckRessult(std::unordered_map<std::string, int> &methodsMap)
73 {
74 std::unordered_map<std::string, int> expected = {
75 {"api_scanner_static main:void;", 0},
76 {"api_scanner_static bar:void;", 1},
77 {"api_scanner_static bar2:void;", 0},
78 {"api_scanner_static _cctor_:void;", 0},
79 {"api_scanner_static MyClass.foo2:api_scanner_static.MyClass;void;", 0},
80 {"api_scanner_static MyClass.foo1:api_scanner_static.MyClass;void;", 2},
81 {"api_scanner_static bar3:void;", 0},
82 {"api_scanner_static MyClass._ctor_:api_scanner_static.MyClass;void;", 1}};
83
84 if (expected.size() != methodsMap.size()) {
85 return false;
86 }
87
88 for (auto &exp : expected) {
89 auto f = methodsMap.find(exp.first);
90 if (f == methodsMap.end()) {
91 return false;
92 }
93 if (f->second != exp.second) {
94 return false;
95 }
96 }
97 return true;
98 }
99
100 class AbckitScenarioTest : public ::testing::Test {};
101
102 // Test: test-kind=scenario, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(AbckitScenarioTest,LibAbcKitTestApiScannerStatic)103 TEST_F(AbckitScenarioTest, LibAbcKitTestApiScannerStatic)
104 {
105 constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "scenarios/api_scanner/static/api_scanner_static.abc";
106 AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
107
108 std::unordered_map<std::string, int> methodsMap;
109 helpers::EnumerateAllMethods(file,
110 [&](AbckitCoreFunction *method) { methodsMap.emplace(GetMethodName(method), 0); });
111
112 helpers::EnumerateAllMethods(file, [&](AbckitCoreFunction *method) {
113 auto *graph = g_implI->createGraphFromFunction(method);
114 VisitAllBBs(graph, methodsMap);
115 g_impl->destroyGraph(graph);
116 });
117 for (auto &foo : methodsMap) {
118 LIBABCKIT_LOG_TEST(DEBUG) << foo.first << " " << foo.second << std::endl;
119 }
120
121 ASSERT_TRUE(CheckRessult(methodsMap));
122
123 constexpr auto OUTPUT_PATH = ABCKIT_ABC_DIR "scenarios/api_scanner/static/api_scanner_static_modified.abc";
124 g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH));
125 g_impl->closeFile(file);
126 }
127
128 } // namespace libabckit::test
129