• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 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 g_implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <algorithm>
17 #include <cstddef>
18 #include <iostream>
19 #include <ir/expression.h>
20 #include <ostream>
21 #include <string>
22 #include "test/unit/plugin/util.h"
23 #include "public/es2panda_lib.h"
24 
25 // NOLINTBEGIN
26 
27 /*
28  * Covered C API List:
29  *   AstNodeDumpEtsSrcConst
30  *   AstNodeDumpJSONConst
31  *   AstNodeForEach
32  *   AstNodeIterateConst
33  *   AstNodeRebind
34  *   AstNodeRecheck
35  *   AstNodeSetParent
36  *   BinaryExpressionIsArithmeticConst
37  *   BinaryExpressionIsBitwiseConst
38  *   BinaryExpressionIsLogicalConst
39  *   BinaryExpressionIsLogicalExtendedConst
40  *   BinaryExpressionLeft
41  *   BinaryExpressionLeftConst
42  *   BinaryExpressionOperationType
43  *   BinaryExpressionOperationTypeConst
44  *   BinaryExpressionOperatorTypeConst
45  *   BinaryExpressionResult
46  *   BinaryExpressionResultConst
47  *   BinaryExpressionRight
48  *   BinaryExpressionRightConst
49  *   BinaryExpressionSetLeft
50  *   BinaryExpressionSetOperationType
51  *   BinaryExpressionSetOperator
52  *   BinaryExpressionSetResult
53  *   BinaryExpressionSetRight
54  *   BlockStatementSetStatements
55  *   ContextProgram
56  *   ContextState
57  *   CreateBinaryExpression
58  *   CreateConfig
59  *   CreateContextFromString
60  *   CreateDoubleType
61  *   CreateExpressionStatement
62  *   CreateNumberLiteral
63  *   DestroyConfig
64  *   DestroyContext
65  *   FunctionDeclarationFunction
66  *   IdentifierName
67  *   IsBinaryExpression
68  *   IsFunctionDeclaration
69  *   ProceedToState
70  *   ProgramAst
71  *   ScriptFunctionBody
72  *   ScriptFunctionId
73  *   UpdateBinaryExpression
74  */
75 
76 static std::string source = R"(
77 function main() {
78     1 + 2;
79 }
80 )";
81 
82 static es2panda_Impl *g_impl = nullptr;
83 static es2panda_AstNode *binExpr = nullptr;
84 static es2panda_AstNode *mainScriptFunc = nullptr;
85 static es2panda_Context *g_ctx = nullptr;
86 
87 es2panda_AstNode *parNode = nullptr;
88 es2panda_Context *newCtx = nullptr;
89 
FindBinaryExpression(es2panda_AstNode * ast)90 static void FindBinaryExpression(es2panda_AstNode *ast)
91 {
92     if (!g_impl->IsBinaryExpression(ast)) {
93         g_impl->AstNodeIterateConst(g_ctx, ast, FindBinaryExpression);
94         return;
95     }
96     binExpr = ast;
97 }
98 
FindMainDef(es2panda_AstNode * ast)99 static void FindMainDef(es2panda_AstNode *ast)
100 {
101     if (!g_impl->IsFunctionDeclaration(ast)) {
102         g_impl->AstNodeIterateConst(g_ctx, ast, FindMainDef);
103         return;
104     }
105     auto scriptFunc = g_impl->FunctionDeclarationFunction(g_ctx, ast);
106     if (scriptFunc == nullptr ||
107         std::string("main") != g_impl->IdentifierName(g_ctx, g_impl->ScriptFunctionId(g_ctx, scriptFunc))) {
108         return;
109     }
110     mainScriptFunc = scriptFunc;
111 }
112 
changeParent(es2panda_AstNode * child)113 static void changeParent(es2panda_AstNode *child)
114 {
115     g_impl->AstNodeSetParent(newCtx, child, parNode);
116 }
117 
SetRightParent(es2panda_AstNode * node,void * arg)118 static void SetRightParent(es2panda_AstNode *node, void *arg)
119 {
120     es2panda_Context *context = static_cast<es2panda_Context *>(arg);
121     newCtx = context;
122     parNode = node;
123     g_impl->AstNodeIterateConst(context, node, changeParent);
124 }
125 
SetAndGetBinaryExpressionValue(es2panda_Context * context)126 static bool SetAndGetBinaryExpressionValue(es2panda_Context *context)
127 {
128     es2panda_AstNode *leftValue = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 8));
129     g_impl->BinaryExpressionSetLeft(context, binExpr, leftValue);
130     es2panda_AstNode *rightValue = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 7));
131     g_impl->BinaryExpressionSetRight(context, binExpr, rightValue);
132     es2panda_AstNode *result = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 15));
133     g_impl->BinaryExpressionSetResult(context, binExpr, result);
134     Es2pandaTokenType operatorValue = Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_GREATER_THAN;
135     g_impl->BinaryExpressionSetOperator(context, binExpr, operatorValue);
136     es2panda_Type *doubleType = g_impl->CreateDoubleType(context);
137     g_impl->BinaryExpressionSetOperationType(context, binExpr, doubleType);
138     es2panda_AstNode *resultLeftValue = g_impl->BinaryExpressionLeft(context, binExpr);
139     if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, resultLeftValue), "8") == 0)) {
140         return false;
141     }
142     const es2panda_AstNode *leftConst = g_impl->BinaryExpressionLeftConst(context, binExpr);
143     if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, const_cast<es2panda_AstNode *>(leftConst)), "8") == 0)) {
144         return false;
145     }
146     es2panda_AstNode *resultRightValue = g_impl->BinaryExpressionRight(context, binExpr);
147     if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, resultRightValue), "7") == 0)) {
148         return false;
149     }
150     const es2panda_AstNode *rightConst = g_impl->BinaryExpressionRightConst(context, binExpr);
151     if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, const_cast<es2panda_AstNode *>(rightConst)), "7") == 0)) {
152         return false;
153     }
154     es2panda_AstNode *resultValue = g_impl->BinaryExpressionResult(context, binExpr);
155     if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, resultValue), "15") == 0)) {
156         return false;
157     }
158     const es2panda_AstNode *resultConst = g_impl->BinaryExpressionResultConst(context, binExpr);
159     if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, const_cast<es2panda_AstNode *>(resultConst)), "15") == 0)) {
160         return false;
161     }
162     Es2pandaTokenType operatorType = g_impl->BinaryExpressionOperatorTypeConst(context, binExpr);
163     if (operatorType != Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_GREATER_THAN) {
164         return false;
165     }
166     es2panda_Type *operationTypeVal = g_impl->BinaryExpressionOperationType(context, binExpr);
167     if (operationTypeVal != doubleType) {
168         return false;
169     }
170     const es2panda_Type *operationTypeValConst = g_impl->BinaryExpressionOperationTypeConst(context, binExpr);
171     if (operationTypeValConst != doubleType) {
172         return false;
173     }
174     return true;
175 }
176 
177 /*
178  *  1 + 2
179  *  is changed to
180  *  12 > 10
181  */
BinaryExpressionHandle(es2panda_Context * context,es2panda_AstNode * ast)182 static bool BinaryExpressionHandle(es2panda_Context *context, es2panda_AstNode *ast)
183 {
184     es2panda_AstNode *left = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 4));
185     es2panda_AstNode *right = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 5));
186     Es2pandaTokenType operatorType = Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_LESS_THAN;
187     es2panda_AstNode *binExpression = g_impl->CreateBinaryExpression(context, left, right, operatorType);
188     if (!g_impl->IsBinaryExpression(binExpression)) {
189         return false;
190     }
191     g_impl->AstNodeIterateConst(context, ast, FindBinaryExpression);
192     g_impl->AstNodeIterateConst(context, ast, FindMainDef);
193     if (mainScriptFunc == nullptr || binExpr == nullptr) {
194         return false;
195     }
196     auto mainFuncBody = g_impl->ScriptFunctionBody(context, mainScriptFunc);
197     es2panda_AstNode *exprStatement = g_impl->CreateExpressionStatement(context, binExpression);
198     es2panda_AstNode *newMainStatements[1] = {exprStatement};
199     g_impl->BlockStatementSetStatements(context, mainFuncBody, newMainStatements, 1U);
200     g_impl->AstNodeForEach(ast, SetRightParent, context);
201     g_impl->AstNodeIterateConst(context, ast, FindBinaryExpression);
202     if (!SetAndGetBinaryExpressionValue(context)) {
203         return false;
204     }
205     Es2pandaTokenType value = static_cast<Es2pandaTokenType>(ark::es2panda::lexer::TokenType::PUNCTUATOR_LOGICAL_AND);
206     g_impl->BinaryExpressionSetOperator(context, binExpr, value);
207     if (!g_impl->BinaryExpressionIsLogicalConst(context, binExpr) ||
208         !g_impl->BinaryExpressionIsLogicalExtendedConst(context, binExpr)) {
209         return false;
210     }
211     Es2pandaTokenType value1 = static_cast<Es2pandaTokenType>(ark::es2panda::lexer::TokenType::PUNCTUATOR_BITWISE_OR);
212     g_impl->BinaryExpressionSetOperator(context, binExpr, value1);
213     if (!g_impl->BinaryExpressionIsBitwiseConst(context, binExpr) ||
214         !g_impl->BinaryExpressionIsArithmeticConst(context, binExpr)) {
215         return false;
216     }
217     es2panda_AstNode *leftUpdate = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 12));
218     es2panda_AstNode *rightUpdate = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 10));
219     Es2pandaTokenType operatorUpdate = Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_GREATER_THAN;
220     es2panda_AstNode *binExpressionUpdate =
221         g_impl->UpdateBinaryExpression(context, binExpr, leftUpdate, rightUpdate, operatorUpdate);
222     exprStatement = g_impl->CreateExpressionStatement(context, binExpressionUpdate);
223     newMainStatements[0] = {exprStatement};
224     g_impl->BlockStatementSetStatements(context, mainFuncBody, newMainStatements, 1U);
225     g_impl->AstNodeForEach(ast, SetRightParent, context);
226     std::string str(g_impl->AstNodeDumpEtsSrcConst(context, ast));
227     if (str.find("((12) > (10));") == std::string::npos) {
228         std::cout << "Fail to find update expression value." << std::endl;
229         return false;
230     }
231     return true;
232 }
233 
main(int argc,char ** argv)234 int main(int argc, char **argv)
235 {
236     if (argc < MIN_ARGC) {
237         return INVALID_ARGC_ERROR_CODE;
238     }
239 
240     if (GetImpl() == nullptr) {
241         return NULLPTR_IMPL_ERROR_CODE;
242     }
243 
244     g_impl = GetImpl();
245 
246     const char **args = const_cast<const char **>(&(argv[1]));
247     auto config = g_impl->CreateConfig(argc - 1, args);
248 
249     g_ctx = g_impl->CreateContextFromString(config, source.data(), argv[argc - 1]);
250     if (g_ctx == nullptr) {
251         std::cerr << "Fail to create context." << std::endl;
252         return NULLPTR_CONTEXT_ERROR_CODE;
253     }
254 
255     int retCode = Test(g_ctx, g_impl, ES2PANDA_STATE_PARSED, BinaryExpressionHandle);
256     if (retCode != 0) {
257         g_impl->DestroyConfig(config);
258         return retCode;
259     }
260 
261     g_impl->DestroyConfig(config);
262 
263     return 0;
264 }
265 
266 // NOLINTEND
267