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 "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 bar:void;", 1},
76 {"api_scanner_static bar2:void;", 0},
77 {"api_scanner_static _cctor_:void;", 0},
78 {"api_scanner_static MyClass.foo2:api_scanner_static.MyClass;void;", 0},
79 {"api_scanner_static MyClass.foo1:api_scanner_static.MyClass;void;", 2},
80 {"api_scanner_static bar3:void;", 0},
81 {"api_scanner_static MyClass._ctor_:api_scanner_static.MyClass;void;", 1}};
82
83 if (expected.size() != methodsMap.size()) {
84 return false;
85 }
86
87 for (auto &exp : expected) {
88 auto f = methodsMap.find(exp.first);
89 if (f == methodsMap.end()) {
90 return false;
91 }
92 if (f->second != exp.second) {
93 return false;
94 }
95 }
96 return true;
97 }
98
99 class AbckitScenarioTest : public ::testing::Test {};
100
101 // Test: test-kind=scenario, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(AbckitScenarioTest,LibAbcKitTestApiScannerStatic)102 TEST_F(AbckitScenarioTest, LibAbcKitTestApiScannerStatic)
103 {
104 constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "scenarios/api_scanner/static/api_scanner_static.abc";
105 AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
106
107 std::unordered_map<std::string, int> methodsMap;
108 helpers::EnumerateAllMethods(file,
109 [&](AbckitCoreFunction *method) { methodsMap.emplace(GetMethodName(method), 0); });
110
111 helpers::EnumerateAllMethods(file, [&](AbckitCoreFunction *method) {
112 auto *graph = g_implI->createGraphFromFunction(method);
113 VisitAllBBs(graph, methodsMap);
114 g_impl->destroyGraph(graph);
115 });
116 for (auto &foo : methodsMap) {
117 LIBABCKIT_LOG_TEST(DEBUG) << foo.first << " " << foo.second << std::endl;
118 }
119
120 ASSERT_TRUE(CheckRessult(methodsMap));
121
122 constexpr auto OUTPUT_PATH = ABCKIT_ABC_DIR "scenarios/api_scanner/static/api_scanner_static_modified.abc";
123 g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH));
124 g_impl->closeFile(file);
125 }
126
127 } // namespace libabckit::test
128