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