• 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 <sstream>
17 #include <iostream>
18 
19 #include <gtest/gtest.h>
20 
21 #include "libabckit/include/c/abckit.h"
22 #include "libabckit/include/c/isa/isa_dynamic.h"
23 #include "helpers/helpers_runtime.h"
24 
25 #include "branch_eliminator.h"
26 #include "helpers/helpers.h"
27 
28 namespace libabckit::test {
29 
30 static constexpr auto VERSION = ABCKIT_VERSION_RELEASE_1_0_0;
31 static const AbckitApi *g_impl = AbckitGetApiImpl(VERSION);
32 static const AbckitInspectApi *g_implI = AbckitGetInspectApiImpl(VERSION);
33 static const AbckitGraphApi *g_implG = AbckitGetGraphApiImpl(VERSION);
34 static const AbckitIsaApiDynamic *g_dynG = AbckitGetIsaApiDynamicImpl(VERSION);
35 
MethodHasBranch(const std::string & moduleName,const std::string & methodName,AbckitFile * file)36 static bool MethodHasBranch(const std::string &moduleName, const std::string &methodName, AbckitFile *file)
37 {
38     EXPECT_NE(file, nullptr);
39     EXPECT_NE(g_impl, nullptr);
40     EXPECT_NE(g_implI, nullptr);
41     EXPECT_NE(g_implG, nullptr);
42     EXPECT_NE(g_dynG, nullptr);
43     VisitHelper vh = VisitHelper(file, g_impl, g_implI, g_implG, g_dynG);
44     bool found = false;
45     bool ret = false;
46     vh.EnumerateModules([&](AbckitCoreModule *mod) {
47         if (vh.GetString(g_implI->moduleGetName(mod)) != moduleName) {
48             return;
49         }
50         vh.EnumerateModuleFunctions(mod, [&](AbckitCoreFunction *func) {
51             if (found || vh.GetString(g_implI->functionGetName(func)) != methodName) {
52                 return;
53             }
54             found = true;
55             auto *graph = g_implI->createGraphFromFunction(func);
56             auto *ifInst = vh.GraphInstsFindIf(
57                 graph, [&](AbckitInst *inst) { return g_dynG->iGetOpcode(inst) == ABCKIT_ISA_API_DYNAMIC_OPCODE_IF; });
58             ret = ifInst != nullptr;
59             g_impl->destroyGraph(graph);
60         });
61     });
62 
63     EXPECT_TRUE(found);
64     return ret;
65 }
66 
67 class AbckitScenarioTest : public ::testing::Test {};
68 
69 static const std::string DIR = std::string(ABCKIT_ABC_DIR "scenarios/branch_eliminator/dynamic/");
70 static const std::string INPUT = DIR + "branch_eliminator.abc";
71 static constexpr bool CONFIG_IS_DEBUG_ORIGIN_VALUE = false;
72 
73 /*
74  * @param value: the value of isDebug when we handle, it can be different from configIsDebugOriginValue
75  */
GetExpectOutput(bool value)76 static std::string GetExpectOutput(bool value)
77 {
78     std::stringstream expectOutput;
79     expectOutput << std::boolalpha;
80     expectOutput << "Config.isDebug = " << value << std::endl;
81     expectOutput << "myfoo: Config.isDebug is " << value << std::endl;
82     expectOutput << "Mybar.test1: Config.isDebug is " << value << std::endl;
83     expectOutput << "Mybar.test2: Config.isDebug is " << value << std::endl;
84     return expectOutput.str();
85 }
86 
GeneralBranchEliminatorTest(bool configIsDebugFinal)87 static void GeneralBranchEliminatorTest(bool configIsDebugFinal)
88 {
89     auto *impl = AbckitGetApiImpl(VERSION);
90     const auto originOutput = helpers::ExecuteDynamicAbc(INPUT, "branch_eliminator");
91 
92     auto expectOutput = GetExpectOutput(CONFIG_IS_DEBUG_ORIGIN_VALUE);
93     ASSERT_EQ(originOutput, expectOutput);
94 
95     AbckitFile *file = impl->openAbc(INPUT.c_str(), INPUT.size());
96     ASSERT_NE(file, nullptr);
97     ASSERT_TRUE(MethodHasBranch("modules/myfoo", "myfoo", file));
98     ASSERT_TRUE(MethodHasBranch("modules/mybar", "test1", file));
99     ASSERT_TRUE(MethodHasBranch("modules/mybar", "test2", file));
100     // Delete true branch
101     const std::vector<ConstantInfo> infos = {{"modules/config", "Config", "isDebug", configIsDebugFinal}};
102     BranchEliminator b(VERSION, file, infos);
103     b.Run();
104     ASSERT_FALSE(MethodHasBranch("modules/myfoo", "myfoo", file));
105     ASSERT_FALSE(MethodHasBranch("modules/mybar", "test1", file));
106     ASSERT_FALSE(MethodHasBranch("modules/mybar", "test2", file));
107 
108     const auto modifiedPath = DIR + "branch_eliminator_modified.abc";
109     impl->writeAbc(file, modifiedPath.c_str(), modifiedPath.size());
110     g_impl->closeFile(file);
111     auto output = helpers::ExecuteDynamicAbc(modifiedPath, "branch_eliminator");
112     auto expectOutput2 = GetExpectOutput(configIsDebugFinal);
113     ASSERT_EQ(output, expectOutput2);
114 }
115 
116 // Test: test-kind=scenario, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(AbckitScenarioTest,LibAbcKitTestBranchEliminatorDynamic1)117 TEST_F(AbckitScenarioTest, LibAbcKitTestBranchEliminatorDynamic1)
118 {
119     GeneralBranchEliminatorTest(false);
120 }
121 
122 // Test: test-kind=scenario, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(AbckitScenarioTest,LibAbcKitTestBranchEliminatorDynamic2)123 TEST_F(AbckitScenarioTest, LibAbcKitTestBranchEliminatorDynamic2)
124 {
125     GeneralBranchEliminatorTest(true);
126 }
127 
128 }  // namespace libabckit::test
129