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/metadata_core.h"
18 #include "libabckit/include/c/ir_core.h"
19
20 #include "helpers/helpers.h"
21 #include "helpers/helpers_runtime.h"
22
23 #include <gtest/gtest.h>
24 #include <cstddef>
25
26 // NOTE:
27 // * Printed filename is "NOTE", should be real name
28 // * Use actual stdlib calls (instead of user's DateGetTime, ConsoleLogNum, ConsoleLogStr)
29 // * There are several issues related to SaveState in this test:
30 // * Start calls are inserted after first SaveState (not at the beginning of function)
31 // * SaveStates are manipulated by user explicitly
32 // * SaveStates are "INVALID" operations in validation schema
33
34 namespace libabckit::test {
35
36 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
37 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
38 static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
39 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
40 static auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0);
41
42 struct UserData {
43 AbckitString *str1 = nullptr;
44 AbckitString *str2 = nullptr;
45 AbckitCoreFunction *consoleLogStr = nullptr;
46 AbckitCoreFunction *consoleLogNum = nullptr;
47 AbckitCoreFunction *dateGetTime = nullptr;
48 AbckitInst *startTime = nullptr;
49 };
50
TransformIr(AbckitGraph * graph,UserData * userData)51 static void TransformIr(AbckitGraph *graph, UserData *userData)
52 {
53 AbckitInst *callOp = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC);
54
55 // console.log("file: FileName; function: FunctionName")
56 AbckitInst *loadString = g_statG->iCreateLoadString(graph, userData->str1);
57 g_implG->iInsertBefore(loadString, callOp);
58 AbckitInst *log1 = g_statG->iCreateCallStatic(graph, userData->consoleLogStr, 1, loadString);
59 g_implG->iInsertAfter(log1, loadString);
60
61 // const start = Date().getTime()
62 userData->startTime = g_statG->iCreateCallStatic(graph, userData->dateGetTime, 0);
63 g_implG->iInsertAfter(userData->startTime, log1);
64
65 g_implG->gVisitBlocksRpo(graph, userData, [](AbckitBasicBlock *bb, void *data) {
66 auto *inst = g_implG->bbGetFirstInst(bb);
67 auto *userData = reinterpret_cast<UserData *>(data);
68 auto *graph = g_implG->bbGetGraph(bb);
69 while (inst != nullptr) {
70 if (g_statG->iGetOpcode(inst) == ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID) {
71 // const end = Date().getTime()
72 AbckitInst *endTime = g_statG->iCreateCallStatic(graph, userData->dateGetTime, 0);
73 g_implG->iInsertBefore(endTime, inst);
74
75 // console.log("Elapsed time:")
76 auto *loadString = g_statG->iCreateLoadString(graph, userData->str2);
77 g_implG->iInsertAfter(loadString, endTime);
78 AbckitInst *log = g_statG->iCreateCallStatic(graph, userData->consoleLogStr, 1, loadString);
79 g_implG->iInsertAfter(log, loadString);
80
81 // console.log(end - start)
82 AbckitInst *sub = g_statG->iCreateSub(graph, endTime, userData->startTime);
83 g_implG->iInsertAfter(sub, log);
84 AbckitInst *log2 = g_statG->iCreateCallStatic(graph, userData->consoleLogNum, 1, sub);
85 g_implG->iInsertAfter(log2, sub);
86 }
87 inst = g_implG->iGetNext(inst);
88 }
89 return true;
90 });
91 }
92
93 class AbckitScenarioTest : public ::testing::Test {};
94
95 // Test: test-kind=scenario, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(AbckitScenarioTest,LibAbcKitTestStaticAddLog)96 TEST_F(AbckitScenarioTest, LibAbcKitTestStaticAddLog)
97 {
98 auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_static.abc",
99 "add_log_static/ETSGLOBAL", "main");
100 EXPECT_TRUE(helpers::Match(output, "buisiness logic...\n"));
101
102 helpers::TransformMethod(
103 ABCKIT_ABC_DIR "scenarios/add_log/add_log_static.abc",
104 ABCKIT_ABC_DIR "scenarios/add_log/add_log_static_modified.abc", "handle",
105 []([[maybe_unused]] AbckitFile *file, [[maybe_unused]] AbckitCoreFunction *method,
106 [[maybe_unused]] AbckitGraph *graph) {
107 UserData userData;
108 userData.consoleLogStr = helpers::FindMethodByName(file, "ConsoleLogStr");
109 userData.consoleLogNum = helpers::FindMethodByName(file, "ConsoleLogNum");
110 userData.dateGetTime = helpers::FindMethodByName(file, "DateGetTime");
111 auto mname = g_implI->functionGetName(method);
112 auto methodName = helpers::GetCropFuncName(helpers::AbckitStringToString(mname).data());
113 std::string startMsg = "file: NOTE; function: " + methodName;
114 userData.str1 = g_implM->createString(file, startMsg.c_str(), startMsg.size());
115 userData.str2 = g_implM->createString(file, "Elapsed time:", strlen("Elapsed time:"));
116
117 TransformIr(graph, &userData);
118 },
119 [](AbckitGraph *graph) {
120 // NOLINTBEGIN(readability-magic-numbers)
121 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas(
122 {{{}, {1}, {{0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}}}},
123 {{0},
124 {2},
125 {
126 {3, ABCKIT_ISA_API_STATIC_OPCODE_LOADSTRING, {}},
127 {5, ABCKIT_ISA_API_STATIC_OPCODE_LOADSTRING, {}},
128 {8, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {5}},
129 {11, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {}},
130 {14, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {3}},
131 {17, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {}},
132 {19, ABCKIT_ISA_API_STATIC_OPCODE_LOADSTRING, {}},
133 {22, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {19}},
134 {23, ABCKIT_ISA_API_STATIC_OPCODE_SUB, {17, 11}},
135 {26, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {23}},
136 {27, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
137 }},
138 {{1}, {}, {}}});
139 // NOLINTEND(readability-magic-numbers)
140 helpers::VerifyGraph(graph, bbSchemas);
141 });
142
143 output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_static_modified.abc",
144 "add_log_static/ETSGLOBAL", "main");
145 EXPECT_TRUE(helpers::Match(output,
146 "file: NOTE; function: handle\n"
147 "buisiness logic...\n"
148 "Elapsed time:\n"
149 "\\d+\n"));
150 }
151
152 } // namespace libabckit::test
153