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/cpp/abckit_cpp.h"
17 #include "helpers/helpers.h"
18 #include "helpers/helpers_runtime.h"
19 #include "libabckit/src/logger.h"
20
21 #include <gtest/gtest.h>
22 #include <string>
23 #include <vector>
24
25 namespace {
26
27 class GTestAssertErrorHandler final : public abckit::IErrorHandler {
28 public:
HandleError(abckit::Exception && err)29 void HandleError(abckit::Exception &&err) override
30 {
31 EXPECT_TRUE(false) << "Abckit expection raised: " << err.what();
32 }
33 };
34
35 } // namespace
36
37 namespace libabckit::test {
38
39 class AbckitScenarioCppTestClean : public ::testing::Test {};
40
FindRunFunc(const abckit::File * file)41 static abckit::core::Function FindRunFunc(const abckit::File *file)
42 {
43 std::vector<abckit::core::Function> functions;
44 for (auto &module : file->GetModules()) {
45 for (auto &klass : module.GetClasses()) {
46 for (auto &function : klass.GetAllMethods()) {
47 functions.push_back(function);
48 }
49 }
50 for (auto &function : module.GetTopLevelFunctions()) {
51 functions.push_back(function);
52 }
53 }
54
55 abckit::core::Function runFunc;
56 for (auto &func : functions) {
57 if (func.GetName() == "run") {
58 runFunc = func;
59 break;
60 }
61 }
62
63 return runFunc;
64 }
65
66 // Test: test-kind=scenario, abc-kind=ArkTS1, category=positive, extension=cpp
TEST_F(AbckitScenarioCppTestClean,LibAbcKitTestDynamicAddTryCatchClean)67 TEST_F(AbckitScenarioCppTestClean, LibAbcKitTestDynamicAddTryCatchClean)
68 {
69 const std::string inputPath = ABCKIT_ABC_DIR "clean_scenarios/cpp_api/dynamic/add_try_catch/add_try_catch.abc";
70 auto output = helpers::ExecuteDynamicAbc(inputPath, "add_try_catch");
71 EXPECT_TRUE(helpers::Match(output, "THROW\n"));
72
73 abckit::File file(inputPath, std::make_unique<GTestAssertErrorHandler>());
74
75 auto runFunc = FindRunFunc(&file);
76 ASSERT_TRUE(runFunc);
77
78 abckit::Graph graph = runFunc.CreateGraph();
79 abckit::BasicBlock startBB = graph.GetStartBb();
80 abckit::BasicBlock endBB = graph.GetEndBb();
81 abckit::BasicBlock bb = startBB.GetSuccs()[0];
82 abckit::Instruction initInst = bb.GetFirstInst();
83 abckit::Instruction prevRetInst = bb.GetLastInst().GetPrev();
84 abckit::BasicBlock tryBegin = bb.SplitBlockAfterInstruction(initInst, true);
85 abckit::BasicBlock tryEnd = prevRetInst.GetBasicBlock().SplitBlockAfterInstruction(prevRetInst, true);
86
87 // Fill catch block
88 abckit::BasicBlock catchBlock = graph.CreateEmptyBb();
89 abckit::Instruction catchPhi = catchBlock.CreateCatchPhi();
90 abckit::Instruction print = graph.DynIsa().CreateTryldglobalbyname("print");
91 abckit::Instruction callArg = graph.DynIsa().CreateCallarg1(print, catchPhi);
92 catchBlock.AddInstBack(print).AddInstBack(callArg);
93
94 abckit::BasicBlock epilogueBB = endBB.GetPreds()[0];
95 abckit::Instruction retInst = epilogueBB.GetLastInst();
96 abckit::Instruction firstPhiInput = retInst.GetInput(0);
97 abckit::Instruction secondPhiInput = graph.DynIsa().CreateLdfalse();
98 bb.AddInstBack(secondPhiInput);
99 abckit::Instruction phiInst = epilogueBB.CreatePhi(firstPhiInput, secondPhiInput);
100 retInst.SetInput(0, phiInst);
101
102 graph.InsertTryCatch(tryBegin, tryEnd, catchBlock, catchBlock);
103
104 runFunc.SetGraph(graph);
105
106 const std::string modifiedPath =
107 ABCKIT_ABC_DIR "clean_scenarios/cpp_api/dynamic/add_try_catch/add_try_catch_modified.abc";
108 file.WriteAbc(modifiedPath);
109
110 output = helpers::ExecuteDynamicAbc(modifiedPath, "add_try_catch");
111 EXPECT_TRUE(helpers::Match(output,
112 "THROW\n"
113 "Error: DUMMY_ERROR\n"
114 "false\n"));
115 }
116
117 } // namespace libabckit::test
118