• 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 <gtest/gtest.h>
17 #include <cstring>
18 
19 #include "libabckit/include/c/abckit.h"
20 #include "helpers/helpers.h"
21 #include "helpers/helpers_runtime.h"
22 #include "libabckit/include/c/metadata_core.h"
23 #include "libabckit/include/c/extensions/js/metadata_js.h"
24 #include "ir_impl.h"
25 #include "libabckit/include/c/isa/isa_dynamic.h"
26 #include "libabckit/include/c/statuses.h"
27 
28 namespace libabckit::test {
29 
30 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 static auto g_implJsI = AbckitGetJsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33 static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
34 static auto g_implJsM = AbckitGetJsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
35 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
36 static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0);
37 static constexpr auto EXPECTED0 =
38     "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
39     "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
40     "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew exported func "
41     "from module3\n";
42 static constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/extensions/js/modify_api/modules/JSmodules_dynamic_modify.abc";
43 static constexpr auto MODIFIED_PATH =
44     ABCKIT_ABC_DIR "ut/extensions/js/modify_api/modules/JSmodules_dynamic_modify_modified.abc";
45 ;
46 
47 class LibAbcKitJSModifyApiModulesTest : public ::testing::Test {};
48 
49 // ========================================
50 // Helpers
51 // ========================================
52 
53 template <class T>
TestNoError(T * ptr)54 static void TestNoError(T *ptr)
55 {
56     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
57     ASSERT_NE(ptr, nullptr);
58 }
59 
ModifyMetaDynModuleRemoveImport(AbckitFile * file,const std::string & name,bool shouldBeRemoved)60 static void ModifyMetaDynModuleRemoveImport(AbckitFile *file, const std::string &name, bool shouldBeRemoved)
61 {
62     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
63     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
64     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
65     ASSERT_NE(ctxFinder.module, nullptr);
66     auto *module = ctxFinder.module;
67 
68     std::set<AbckitCoreImportDescriptor *> gotImports;
69     g_implI->moduleEnumerateImports(module, &gotImports, helpers::ModuleImportsCollector);
70     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
71     ASSERT_EQ(gotImports.empty(), false);
72 
73     bool removed = false;
74     for (auto &gotImport : gotImports) {
75         auto impName = g_implI->importDescriptorGetAlias(gotImport);
76         auto strName = helpers::AbckitStringToString(impName);
77         if (strName == name) {
78             g_implJsM->moduleRemoveImport(g_implJsI->coreModuleToJsModule(module),
79                                           g_implJsI->coreImportDescriptorToJsImportDescriptor(gotImport));
80             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
81             removed = true;
82             break;
83         }
84     }
85 
86     ASSERT_EQ(removed, shouldBeRemoved);
87 
88     std::set<AbckitCoreImportDescriptor *> gotImportsAfter;
89     g_implI->moduleEnumerateImports(module, &gotImportsAfter, helpers::ModuleImportsCollector);
90     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
91     ASSERT_EQ(gotImportsAfter.empty(), false);
92 
93     for (auto &gotImportAfter : gotImportsAfter) {
94         auto impName = g_implI->importDescriptorGetAlias(gotImportAfter);
95         auto strName = helpers::AbckitStringToString(impName);
96         ASSERT_NE(strName, name);
97     }
98 }
99 
ModifyMetaDynModuleRemoveExport(AbckitFile * file,const std::string & exportName,bool shouldBeRemoved)100 static void ModifyMetaDynModuleRemoveExport(AbckitFile *file, const std::string &exportName, bool shouldBeRemoved)
101 {
102     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
103     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
104     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
105     ASSERT_NE(ctxFinder.module, nullptr);
106     auto *module = ctxFinder.module;
107 
108     std::set<AbckitCoreExportDescriptor *> gotExports;
109     g_implI->moduleEnumerateExports(module, &gotExports, helpers::ModuleExportsCollector);
110     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
111 
112     bool removed = false;
113     for (auto &gotExport : gotExports) {
114         auto expName = g_implI->exportDescriptorGetAlias(gotExport);
115         auto strName = helpers::AbckitStringToString(expName);
116         if (strName == exportName) {
117             g_implJsM->moduleRemoveExport(g_implJsI->coreModuleToJsModule(module),
118                                           g_implJsI->coreExportDescriptorToJsExportDescriptor(gotExport));
119             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
120             removed = true;
121             break;
122         }
123     }
124 
125     ASSERT_EQ(removed, shouldBeRemoved);
126 
127     std::set<AbckitCoreExportDescriptor *> gotExportsAfter;
128     g_implI->moduleEnumerateExports(module, &gotExportsAfter, helpers::ModuleExportsCollector);
129     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
130 
131     for (auto &gotExportAfter : gotExportsAfter) {
132         auto expName = g_implI->exportDescriptorGetAlias(gotExportAfter);
133         auto strName = helpers::AbckitStringToString(expName);
134         ASSERT_NE(strName, exportName);
135     }
136 }
137 
TransformIrDynModuleRemoveImport(AbckitGraph * graph,const std::string & name)138 void TransformIrDynModuleRemoveImport(AbckitGraph *graph, const std::string &name)
139 {
140     AbckitInst *instWithName = helpers::FindFirstInst(
141         graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_THROW_UNDEFINEDIFHOLEWITHNAME, [&](AbckitInst *inst) {
142             auto nameOffset = g_implG->iGetImmediate(inst, 0);
143             auto nameStr = graph->irInterface->GetStringIdByOffset(nameOffset);
144             return nameStr == name;
145         });
146 
147     ASSERT_NE(instWithName, nullptr);
148     auto ldExternalModuleVarInst = g_implG->iGetPrev(instWithName);
149     ASSERT_NE(ldExternalModuleVarInst, nullptr);
150     auto callArg0Inst = g_implG->iGetNext(instWithName);
151     ASSERT_NE(callArg0Inst, nullptr);
152 
153     g_implG->iRemove(instWithName);
154     g_implG->iRemove(ldExternalModuleVarInst);
155     g_implG->iRemove(callArg0Inst);
156 }
157 
TransformIrDynModuleRemoveNSImport(AbckitGraph * graph,const std::string & name)158 void TransformIrDynModuleRemoveNSImport(AbckitGraph *graph, const std::string &name)
159 {
160     AbckitInst *ldObjByNameInst =
161         helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, [&](AbckitInst *inst) {
162             auto nameOffset = g_implG->iGetImmediate(inst, 1);
163             auto nameStr = graph->irInterface->GetStringIdByOffset(nameOffset);
164             return nameStr == name;
165         });
166 
167     ASSERT_NE(ldObjByNameInst, nullptr);
168     auto callThis0Inst = g_implG->iGetNext(ldObjByNameInst);
169     ASSERT_NE(callThis0Inst, nullptr);
170 
171     g_implG->iRemove(ldObjByNameInst);
172     g_implG->iRemove(callThis0Inst);
173 }
174 
TransformIrDynModuleRemoveExport(AbckitGraph * graph,const std::string & exportName)175 void TransformIrDynModuleRemoveExport(AbckitGraph *graph, const std::string &exportName)
176 {
177     AbckitInst *instWithName = helpers::FindFirstInst(
178         graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_THROW_UNDEFINEDIFHOLEWITHNAME, [&](AbckitInst *inst) {
179             auto nameOffset = g_implG->iGetImmediate(inst, 0);
180             auto nameStr = graph->irInterface->GetStringIdByOffset(nameOffset);
181             return nameStr == exportName;
182         });
183 
184     ASSERT_NE(instWithName, nullptr);
185     auto ldLocalModuleVarInst = g_implG->iGetPrev(instWithName);
186     ASSERT_NE(ldLocalModuleVarInst, nullptr);
187     auto callArg1Inst = g_implG->iGetNext(instWithName);
188     ASSERT_NE(callArg1Inst, nullptr);
189 
190     g_implG->iRemove(instWithName);
191     g_implG->iRemove(ldLocalModuleVarInst);
192     g_implG->iRemove(callArg1Inst);
193 
194     AbckitInst *stModuleVarInst =
195         helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR, [&](AbckitInst *inst) {
196             return g_implG->iGetImmediate(inst, 0) == g_implG->iGetImmediate(ldLocalModuleVarInst, 0);
197         });
198 
199     ASSERT_NE(stModuleVarInst, nullptr);
200     g_implG->iRemove(stModuleVarInst);
201 }
202 
IsetModuleTest(AbckitGraph * graph,AbckitCoreModule * module,AbckitIsaApiDynamicOpcode opcode,bool negative=false,bool wrongCtx=false)203 void IsetModuleTest(AbckitGraph *graph, AbckitCoreModule *module, AbckitIsaApiDynamicOpcode opcode,
204                     bool negative = false, bool wrongCtx = false)
205 {
206     auto moduleRequestIdx = 0x2;
207     AbckitInst *instWithModule = helpers::FindFirstInst(graph, opcode, [moduleRequestIdx](AbckitInst *inst) {
208         auto imm = g_implG->iGetImmediate(inst, 0);
209         return imm == moduleRequestIdx;
210     });
211 
212     g_dynG->iSetModule(instWithModule, module);
213     if (negative) {
214         if (wrongCtx) {
215             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_WRONG_CTX);
216             return;
217         }
218         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
219         return;
220     }
221     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
222 }
223 
IsetImportDescriptorTest(AbckitGraph * graph,AbckitCoreModule * m,AbckitIsaApiDynamicOpcode opcode,bool negative=false,AbckitCoreImportDescriptor * importToRemove=nullptr)224 void IsetImportDescriptorTest(AbckitGraph *graph, AbckitCoreModule *m, AbckitIsaApiDynamicOpcode opcode,
225                               bool negative = false, AbckitCoreImportDescriptor *importToRemove = nullptr)
226 {
227     auto moduleRequestIdx = 0x2;
228     AbckitInst *instWithID = helpers::FindFirstInst(graph, opcode, [moduleRequestIdx](AbckitInst *inst) {
229         auto imm = g_implG->iGetImmediate(inst, 0);
230         return imm == moduleRequestIdx;
231     });
232     ASSERT_NE(instWithID, nullptr);
233 
234     if (importToRemove == nullptr) {
235         helpers::ImportByAliasContext importFinder = {nullptr, "MF1M2"};
236         g_implI->moduleEnumerateImports(m, &importFinder, helpers::ImportByAliasFinder);
237         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
238         ASSERT_NE(importFinder.id, nullptr);
239         importToRemove = importFinder.id;
240     }
241 
242     g_dynG->iSetImportDescriptor(instWithID, importToRemove);
243     if (negative) {
244         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
245         return;
246     }
247     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
248 }
249 
IsetExportDescriptorTest(AbckitGraph * graph,AbckitCoreModule * m,AbckitIsaApiDynamicOpcode opcode,bool negative=false,AbckitCoreExportDescriptor * exportToRemove=nullptr)250 void IsetExportDescriptorTest(AbckitGraph *graph, AbckitCoreModule *m, AbckitIsaApiDynamicOpcode opcode,
251                               bool negative = false, AbckitCoreExportDescriptor *exportToRemove = nullptr)
252 {
253     auto moduleRequestIdx = 0x3;
254     AbckitInst *instWithID = helpers::FindFirstInst(graph, opcode, [moduleRequestIdx](AbckitInst *inst) {
255         auto imm = g_implG->iGetImmediate(inst, 0);
256         return imm == moduleRequestIdx;
257     });
258     ASSERT_NE(instWithID, nullptr);
259 
260     if (exportToRemove == nullptr) {
261         helpers::ExportByAliasContext exportFinder = {nullptr, "LocalExportLet"};
262         g_implI->moduleEnumerateExports(m, &exportFinder, helpers::ExportByAliasFinder);
263         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
264         ASSERT_NE(exportFinder.ed, nullptr);
265         exportToRemove = exportFinder.ed;
266     }
267 
268     g_dynG->iSetExportDescriptor(instWithID, exportToRemove);
269     if (negative) {
270         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
271         return;
272     }
273     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
274 }
275 
276 struct UserTransformerData {
277     std::string name;
278     std::string alias;
279     std::string moduleName;
280     bool isRegular = false;
281     AbckitDynamicExportKind kind = ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT;
282 };
283 
AddImportFromDynamicModuleImpl(AbckitCoreModule * module,void * data)284 static void AddImportFromDynamicModuleImpl(AbckitCoreModule *module, void *data)
285 {
286     auto userTransformerData = reinterpret_cast<UserTransformerData *>(data);
287     AbckitFile *file = g_implI->moduleGetFile(module);
288 
289     helpers::ModuleByNameContext ctxFinder = {nullptr, (userTransformerData->moduleName).c_str()};
290     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
291     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
292     ASSERT_NE(ctxFinder.module, nullptr);
293 
294     AbckitJsImportFromDynamicModuleCreateParams params {};
295     params.name = (userTransformerData->name).c_str();
296     params.alias = (userTransformerData->alias).c_str();
297 
298     auto newImport = g_implJsM->moduleAddImportFromJsToJs(g_implJsI->coreModuleToJsModule(module),
299                                                           g_implJsI->coreModuleToJsModule(ctxFinder.module), &params);
300     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
301 
302     std::set<AbckitCoreImportDescriptor *> gotImports;
303     g_implI->moduleEnumerateImports(module, &gotImports, helpers::ModuleImportsCollector);
304 
305     bool existed = false;
306     for (auto &gotImport : gotImports) {
307         if (g_implJsI->coreImportDescriptorToJsImportDescriptor(gotImport) != newImport) {
308             continue;
309         }
310         existed = true;
311 
312         auto impName = g_implI->importDescriptorGetName(gotImport);
313         auto strName = helpers::AbckitStringToString(impName);
314         auto impAlias = g_implI->importDescriptorGetAlias(gotImport);
315         auto strAlias = helpers::AbckitStringToString(impAlias);
316         ASSERT_EQ(userTransformerData->name, strName);
317         ASSERT_EQ(userTransformerData->alias, strAlias);
318         ASSERT_EQ(g_implI->importDescriptorGetImportedModule(gotImport), ctxFinder.module);
319         ASSERT_EQ(g_implI->importDescriptorGetImportingModule(gotImport), module);
320         ASSERT_EQ(gotImport->GetJsImpl()->payload.GetDynId().isRegularImport, userTransformerData->isRegular);
321     }
322 
323     ASSERT_EQ(existed, true);
324 }
325 
DynamicModuleAddExportImpl(AbckitCoreModule * module,void * data)326 static void DynamicModuleAddExportImpl(AbckitCoreModule *module, void *data)
327 {
328     auto userTransformerData = reinterpret_cast<UserTransformerData *>(data);
329     AbckitFile *file = g_implI->moduleGetFile(module);
330 
331     AbckitJsDynamicModuleExportCreateParams params {};
332 
333     AbckitCoreModule *exported = nullptr;
334     if (!userTransformerData->moduleName.empty()) {
335         helpers::ModuleByNameContext ctxFinder = {nullptr, (userTransformerData->moduleName).c_str()};
336         g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
337         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
338         ASSERT_NE(ctxFinder.module, nullptr);
339         exported = ctxFinder.module;
340     }
341     params.name = (userTransformerData->name).c_str();
342 
343     if (userTransformerData->alias.empty()) {
344         params.alias = nullptr;
345     } else {
346         params.alias = (userTransformerData->alias).c_str();
347     }
348 
349     auto newExport = g_implJsM->moduleAddExportFromJsToJs(g_implJsI->coreModuleToJsModule(module),
350                                                           g_implJsI->coreModuleToJsModule(exported), &params);
351     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
352 
353     std::set<AbckitCoreExportDescriptor *> gotExports;
354     g_implI->moduleEnumerateExports(module, &gotExports, helpers::ModuleExportsCollector);
355 
356     bool existed = false;
357     for (auto &gotExport : gotExports) {
358         if (g_implJsI->coreExportDescriptorToJsExportDescriptor(gotExport) != newExport) {
359             continue;
360         }
361         existed = true;
362 
363         auto expName = g_implI->exportDescriptorGetName(gotExport);
364         auto strName = helpers::AbckitStringToString(expName);
365         auto expAlias = g_implI->exportDescriptorGetAlias(gotExport);
366         auto strAlias = helpers::AbckitStringToString(expAlias);
367         ASSERT_EQ(userTransformerData->name, strName);
368         ASSERT_EQ(userTransformerData->alias, strAlias);
369         ASSERT_EQ(userTransformerData->kind, gotExport->GetJsImpl()->payload.GetDynamicPayload().kind);
370         if (userTransformerData->kind == AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT) {
371             ASSERT_EQ(g_implI->exportDescriptorGetExportedModule(gotExport), module);
372         } else {
373             ASSERT_EQ(g_implI->exportDescriptorGetExportedModule(gotExport), exported);
374         }
375         ASSERT_EQ(g_implI->exportDescriptorGetExportingModule(gotExport), module);
376     }
377 
378     ASSERT_EQ(existed, true);
379 }
380 
TransformIrAddImportedFunctionCall(AbckitGraph * graph,AbckitFile * file,const std::string & funcName)381 void TransformIrAddImportedFunctionCall(AbckitGraph *graph, AbckitFile *file, const std::string &funcName)
382 {
383     auto abckitStrName = g_implM->createString(file, funcName.c_str(), funcName.size());
384     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
385     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
386     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
387     ASSERT_NE(ctxFinder.module, nullptr);
388     helpers::ImportByAliasContext importFinder = {nullptr, funcName.c_str()};
389     g_implI->moduleEnumerateImports(ctxFinder.module, &importFinder, helpers::ImportByAliasFinder);
390     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
391     ASSERT_NE(importFinder.id, nullptr);
392 
393     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
394     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
395     auto ldExternalModuleVarInst = g_dynG->iCreateLdexternalmodulevar(graph, importFinder.id);
396     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
397     auto throwUndef = g_dynG->iCreateThrowUndefinedifholewithname(graph, ldExternalModuleVarInst, abckitStrName);
398     auto callInst = g_dynG->iCreateCallarg0(graph, ldExternalModuleVarInst);
399     g_implG->iInsertBefore(ldExternalModuleVarInst, lastInst);
400     g_implG->iInsertBefore(throwUndef, lastInst);
401     g_implG->iInsertBefore(callInst, lastInst);
402 }
403 
TransformIrAddImportedFunctionCallNS(AbckitGraph * graph,AbckitFile * file,const std::string & funcName,const std::string & moduleName)404 void TransformIrAddImportedFunctionCallNS(AbckitGraph *graph, AbckitFile *file, const std::string &funcName,
405                                           const std::string &moduleName)
406 {
407     auto abckitStrName = g_implM->createString(file, funcName.c_str(), funcName.size());
408     helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()};
409     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
410     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
411     ASSERT_NE(ctxFinder.module, nullptr);
412 
413     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
414     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
415     auto getModuleNamespaceInst = g_dynG->iCreateGetmodulenamespace(graph, ctxFinder.module);
416     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
417     auto ldObjByNameInst = g_dynG->iCreateLdobjbyname(graph, getModuleNamespaceInst, abckitStrName);
418     auto callInst = g_dynG->iCreateCallthis0(graph, ldObjByNameInst, getModuleNamespaceInst);
419     g_implG->iInsertBefore(getModuleNamespaceInst, lastInst);
420     g_implG->iInsertBefore(ldObjByNameInst, lastInst);
421     g_implG->iInsertBefore(callInst, lastInst);
422 }
423 
TransformIrAddLocalExport(AbckitGraph * graph,AbckitFile * file,const std::string & varName,const std::string & moduleName)424 void TransformIrAddLocalExport(AbckitGraph *graph, AbckitFile *file, const std::string &varName,
425                                const std::string &moduleName)
426 {
427     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
428     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
429 
430     AbckitString *abckitStr = g_implM->createString(file, "print", strlen("print"));
431     auto tryLdGlobalByNameInst = g_dynG->iCreateTryldglobalbyname(graph, abckitStr);
432 
433     helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()};
434     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
435     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
436     ASSERT_NE(ctxFinder.module, nullptr);
437 
438     helpers::ExportByAliasContext exportFinder = {nullptr, varName.c_str()};
439     g_implI->moduleEnumerateExports(ctxFinder.module, &exportFinder, helpers::ExportByAliasFinder);
440     ASSERT_NE(exportFinder.ed, nullptr);
441 
442     auto constant = g_implG->gFindOrCreateConstantI32(graph, 5);
443     auto stModuleVarInst = g_dynG->iCreateStmodulevar(graph, constant, exportFinder.ed);
444     auto ldLocalModuleVarInst = g_dynG->iCreateLdlocalmodulevar(graph, exportFinder.ed);
445     AbckitString *varNameStr = g_implM->createString(file, varName.c_str(), varName.size());
446     auto throwUndef = g_dynG->iCreateThrowUndefinedifholewithname(graph, ldLocalModuleVarInst, varNameStr);
447     auto callInst = g_dynG->iCreateCallarg1(graph, tryLdGlobalByNameInst, ldLocalModuleVarInst);
448 
449     g_implG->iInsertBefore(stModuleVarInst, lastInst);
450     g_implG->iInsertBefore(tryLdGlobalByNameInst, lastInst);
451     g_implG->iInsertBefore(ldLocalModuleVarInst, lastInst);
452     g_implG->iInsertBefore(throwUndef, lastInst);
453     g_implG->iInsertBefore(callInst, lastInst);
454 }
455 
TransformIrAddIndirectExport(AbckitGraph * graph,AbckitFile * file,const std::string & varName,const std::string & moduleName)456 void TransformIrAddIndirectExport(AbckitGraph *graph, AbckitFile *file, const std::string &varName,
457                                   const std::string &moduleName)
458 {
459     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
460     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
461 
462     AbckitString *abckitStr = g_implM->createString(file, "print", strlen("print"));
463     auto tryLdGlobalByNameInst = g_dynG->iCreateTryldglobalbyname(graph, abckitStr);
464 
465     helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()};
466     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
467     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
468     ASSERT_NE(ctxFinder.module, nullptr);
469 
470     helpers::ImportByAliasContext importFinder = {nullptr, varName.c_str()};
471     g_implI->moduleEnumerateImports(ctxFinder.module, &importFinder, helpers::ImportByAliasFinder);
472     ASSERT_NE(importFinder.id, nullptr);
473 
474     auto ldExternalModuleVarInst = g_dynG->iCreateLdexternalmodulevar(graph, importFinder.id);
475     AbckitString *varNameStr = g_implM->createString(file, varName.c_str(), varName.size());
476     auto throwUndef = g_dynG->iCreateThrowUndefinedifholewithname(graph, ldExternalModuleVarInst, varNameStr);
477     auto callInst = g_dynG->iCreateCallarg1(graph, tryLdGlobalByNameInst, ldExternalModuleVarInst);
478     g_implG->iInsertBefore(tryLdGlobalByNameInst, lastInst);
479     g_implG->iInsertBefore(ldExternalModuleVarInst, lastInst);
480     g_implG->iInsertBefore(throwUndef, lastInst);
481     g_implG->iInsertBefore(callInst, lastInst);
482 }
483 
TransformIrAddStarExport(AbckitGraph * graph,AbckitFile * file,const std::string & funcName,const std::string & moduleName)484 void TransformIrAddStarExport(AbckitGraph *graph, AbckitFile *file, const std::string &funcName,
485                               const std::string &moduleName)
486 {
487     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
488     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
489 
490     helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()};
491     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
492     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
493     ASSERT_NE(ctxFinder.module, nullptr);
494 
495     auto getModuleNamespaceInst = g_dynG->iCreateGetmodulenamespace(graph, ctxFinder.module);
496     AbckitString *funcNameStr = g_implM->createString(file, funcName.c_str(), funcName.size());
497     auto ldObjByNameInst = g_dynG->iCreateLdobjbyname(graph, getModuleNamespaceInst, funcNameStr);
498     auto callInst = g_dynG->iCreateCallthis0(graph, ldObjByNameInst, getModuleNamespaceInst);
499     g_implG->iInsertBefore(getModuleNamespaceInst, lastInst);
500     g_implG->iInsertBefore(ldObjByNameInst, lastInst);
501     g_implG->iInsertBefore(callInst, lastInst);
502 }
503 
TransformIrAddStarExportFunc(AbckitGraph * graph,AbckitFile * file,const std::string & exportName,const std::string & moduleName)504 void TransformIrAddStarExportFunc(AbckitGraph *graph, AbckitFile *file, const std::string &exportName,
505                                   const std::string &moduleName)
506 {
507     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
508     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
509 
510     helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()};
511     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
512     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
513     ASSERT_NE(ctxFinder.module, nullptr);
514 
515     helpers::ModuleByNameContext ctxFinder2 = {nullptr, "modules/JSmodule4"};
516     g_implI->fileEnumerateModules(file, &ctxFinder2, helpers::ModuleByNameFinder);
517     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
518     ASSERT_NE(ctxFinder2.module, nullptr);
519 
520     helpers::ExportByAliasContext exportFinder = {nullptr, exportName.c_str()};
521     g_implI->moduleEnumerateExports(ctxFinder2.module, &exportFinder, helpers::ExportByAliasFinder);
522     ASSERT_NE(exportFinder.ed, nullptr);
523 
524     auto getModuleNamespaceInst = g_dynG->iCreateGetmodulenamespace(graph, ctxFinder.module);           // JSmodule3
525     auto stModuleVarInst = g_dynG->iCreateStmodulevar(graph, getModuleNamespaceInst, exportFinder.ed);  // NewStarExport
526     g_implG->iInsertBefore(getModuleNamespaceInst, lastInst);
527     g_implG->iInsertBefore(stModuleVarInst, lastInst);
528 }
529 
TransformIrAddStarExportFunc2(AbckitGraph * graph,AbckitFile * file,const std::string & funcName,const std::string & moduleName)530 void TransformIrAddStarExportFunc2(AbckitGraph *graph, AbckitFile *file, const std::string &funcName,
531                                    const std::string &moduleName)
532 {
533     AbckitBasicBlock *mainBB = g_implG->bbGetSuccBlock(g_implG->gGetStartBasicBlock(graph), 0);
534     AbckitInst *lastInst = g_implG->bbGetLastInst(mainBB);
535 
536     helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()};
537     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
538     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
539     ASSERT_NE(ctxFinder.module, nullptr);
540 
541     helpers::ImportByAliasContext importFinder = {nullptr, "NewStarExport"};
542     g_implI->moduleEnumerateImports(ctxFinder.module, &importFinder, helpers::ImportByAliasFinder);
543     ASSERT_NE(importFinder.id, nullptr);
544 
545     auto ldExternalModuleVarInst = g_dynG->iCreateLdexternalmodulevar(graph, importFinder.id);
546     auto exportStarName = g_implM->createString(file, "NewStarExport", strlen("NewStarExport"));
547     auto throwUndef = g_dynG->iCreateThrowUndefinedifholewithname(graph, ldExternalModuleVarInst, exportStarName);
548     auto funcNameStr = g_implM->createString(file, funcName.c_str(), funcName.size());
549     auto ldObjByNameInst = g_dynG->iCreateLdobjbyname(graph, ldExternalModuleVarInst, funcNameStr);
550     auto callInst = g_dynG->iCreateCallthis0(graph, ldObjByNameInst, ldExternalModuleVarInst);
551     g_implG->iInsertBefore(ldExternalModuleVarInst, lastInst);
552     g_implG->iInsertBefore(throwUndef, lastInst);
553     g_implG->iInsertBefore(ldObjByNameInst, lastInst);
554     g_implG->iInsertBefore(callInst, lastInst);
555 }
556 
557 // ========================================
558 // Modules Tests
559 // ========================================
560 
561 constexpr char const *UNMODIFIED_EXPECTED_OUTPUT =
562     "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
563     "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
564     "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n";
565 
566 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveImport, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveImport)567 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveImport)
568 {
569     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
570     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
571     EXPECT_TRUE(helpers::Match(output, expected));
572 
573     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
574                              [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
575                                  TransformIrDynModuleRemoveImport(graph, "regularImportFunc1FromModule1");
576                                  ModifyMetaDynModuleRemoveImport(file, "regularImportFunc1FromModule1", true);
577                              });
578 
579     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
580     expected =
581         "regular import func1 from module2\nregular default import func1 from module3\nregular default import func2 "
582         "from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace "
583         "import func3 from module2\nthe same func from module3\n";
584     EXPECT_TRUE(helpers::Match(output, expected));
585 }
586 
587 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveImport, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveNSImport)588 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveNSImport)
589 {
590     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
591     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
592     EXPECT_TRUE(helpers::Match(output, expected));
593 
594     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
595                              [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
596                                  TransformIrDynModuleRemoveNSImport(graph, "namespaceImportFunc2FromModule1");
597                                  TransformIrDynModuleRemoveNSImport(graph, "namespaceImportFunc3FromModule1");
598                                  ModifyMetaDynModuleRemoveImport(file, "NS1", true);
599                              });
600 
601     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
602     expected =
603         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
604         "module3\nregular default import func2 from module2\n1\n2\nnamespace import func3 from module2\nthe same func "
605         "from module3\n";
606     EXPECT_TRUE(helpers::Match(output, expected));
607 }
608 
609 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveImport, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveImportAndModule)610 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveImportAndModule)
611 {
612     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
613     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
614     EXPECT_TRUE(helpers::Match(output, expected));
615 
616     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
617                              [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
618                                  TransformIrDynModuleRemoveImport(graph, "regularDefaultImportFunc1FromModule3");
619                                  ModifyMetaDynModuleRemoveImport(file, "regularDefaultImportFunc1FromModule3", true);
620                              });
621 
622     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
623     expected =
624         "regular import func1 from module1\nregular import func1 from module2\nregular default import func2 from "
625         "module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import "
626         "func3 from module2\nthe same func from module3\n";
627     EXPECT_TRUE(helpers::Match(output, expected));
628 }
629 
630 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveImport, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveImportWithWrongName)631 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveImportWithWrongName)
632 {
633     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
634     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
635     EXPECT_TRUE(helpers::Match(output, expected));
636 
637     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
638                              [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *) {
639                                  ModifyMetaDynModuleRemoveImport(file, "R", false);
640                              });
641 
642     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
643     expected = UNMODIFIED_EXPECTED_OUTPUT;
644     EXPECT_TRUE(helpers::Match(output, expected));
645 }
646 
647 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveImport, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveWrongImport)648 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveWrongImport)
649 {
650     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
651     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
652     EXPECT_TRUE(helpers::Match(output, expected));
653 
654     helpers::TransformMethod(
655         INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
656         [](AbckitFile *file, AbckitCoreFunction *method, AbckitGraph *) {
657             auto *newID = new AbckitCoreImportDescriptor();
658             auto newAID = std::make_unique<AbckitJsImportDescriptor>();
659             newAID->core = newID;
660             newID->impl = std::move(newAID);
661             newID->importingModule = method->owningModule;
662             helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
663             g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
664             EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
665             EXPECT_NE(ctxFinder.module, nullptr);
666             auto *module = ctxFinder.module;
667             g_implJsM->moduleRemoveImport(g_implJsI->coreModuleToJsModule(module),
668                                           g_implJsI->coreImportDescriptorToJsImportDescriptor(newID));
669             EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
670             g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);  // just to clear last error
671             delete newID;
672         });
673 
674     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
675     expected = UNMODIFIED_EXPECTED_OUTPUT;
676     EXPECT_TRUE(helpers::Match(output, expected));
677 }
678 
679 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveExport, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveExport)680 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveExport)
681 {
682     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
683     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
684     EXPECT_TRUE(helpers::Match(output, expected));
685 
686     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
687                              [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
688                                  TransformIrDynModuleRemoveExport(graph, "LocalExportConst");
689                                  ModifyMetaDynModuleRemoveExport(file, "LocalExportConst", true);
690                              });
691 
692     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
693     expected =
694         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
695         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
696         "func3 from module1\n2\nnamespace import func3 from module2\nthe same func from module3\n";
697     EXPECT_TRUE(helpers::Match(output, expected));
698 }
699 
700 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveExport, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveExportWithWrongName)701 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveExportWithWrongName)
702 {
703     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
704     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
705     EXPECT_TRUE(helpers::Match(output, expected));
706 
707     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
708                              [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *) {
709                                  ModifyMetaDynModuleRemoveExport(file, "R", false);
710                              });
711 
712     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
713     expected = UNMODIFIED_EXPECTED_OUTPUT;
714     EXPECT_TRUE(helpers::Match(output, expected));
715 }
716 
717 // Test: test-kind=api, api=JsModifyApiImpl::moduleRemoveExport, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleRemoveWrongExport)718 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleRemoveWrongExport)
719 {
720     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
721     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
722     EXPECT_TRUE(helpers::Match(output, expected));
723 
724     helpers::TransformMethod(
725         INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
726         [](AbckitFile *file, AbckitCoreFunction *method, AbckitGraph *) {
727             auto *newED = new AbckitCoreExportDescriptor();
728             auto newAED = std::make_unique<AbckitJsExportDescriptor>();
729             newAED->core = newED;
730             newED->impl = std::move(newAED);
731             newED->exportingModule = method->owningModule;
732             helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
733             g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
734             EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
735             EXPECT_NE(ctxFinder.module, nullptr);
736             auto *module = ctxFinder.module;
737             g_implJsM->moduleRemoveExport(g_implJsI->coreModuleToJsModule(module),
738                                           g_implJsI->coreExportDescriptorToJsExportDescriptor(newED));
739             EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
740             g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);  // just to clear last error
741             delete newED;
742         });
743 
744     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
745     expected = UNMODIFIED_EXPECTED_OUTPUT;
746     EXPECT_TRUE(helpers::Match(output, expected));
747 }
748 
749 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetModule, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetModule)750 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetModule)
751 {
752     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
753     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
754     EXPECT_TRUE(helpers::Match(output, expected));
755 
756     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
757         helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule1"};
758         g_implI->fileEnumerateModules(graph->file, &ctxFinder, helpers::ModuleByNameFinder);
759         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
760         ASSERT_NE(ctxFinder.module, nullptr);
761 
762         IsetModuleTest(graph, ctxFinder.module, ABCKIT_ISA_API_DYNAMIC_OPCODE_GETMODULENAMESPACE);
763     };
764 
765     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
766 
767     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
768     expected =
769         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
770         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
771         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module1\n";
772     EXPECT_TRUE(helpers::Match(output, expected));
773 }
774 
775 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetModule, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetModuleWrongInst)776 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetModuleWrongInst)
777 {
778     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
779     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
780     EXPECT_TRUE(helpers::Match(output, expected));
781 
782     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
783         helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule1"};
784         g_implI->fileEnumerateModules(graph->file, &ctxFinder, helpers::ModuleByNameFinder);
785         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
786         ASSERT_NE(ctxFinder.module, nullptr);
787 
788         IsetModuleTest(graph, ctxFinder.module, ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR, true);
789     };
790 
791     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
792 
793     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
794     expected = UNMODIFIED_EXPECTED_OUTPUT;
795     EXPECT_TRUE(helpers::Match(output, expected));
796 }
797 
798 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetModule, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetModuleWrongModule)799 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetModuleWrongModule)
800 {
801     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
802     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
803     EXPECT_TRUE(helpers::Match(output, expected));
804 
805     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
806                              [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
807                                  auto *newM = new AbckitCoreModule();
808                                  newM->impl = std::make_unique<AbckitJsModule>();
809                                  IsetModuleTest(graph, newM, ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR, true, true);
810                                  delete newM;
811                              });
812 
813     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
814     expected = UNMODIFIED_EXPECTED_OUTPUT;
815     EXPECT_TRUE(helpers::Match(output, expected));
816 }
817 
818 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetImportDescriptor, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetImportDescriptor)819 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetImportDescriptor)
820 {
821     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
822     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
823     EXPECT_TRUE(helpers::Match(output, expected));
824 
825     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
826         helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
827         g_implI->fileEnumerateModules(graph->file, &ctxFinder, helpers::ModuleByNameFinder);
828         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
829         ASSERT_NE(ctxFinder.module, nullptr);
830         IsetImportDescriptorTest(graph, ctxFinder.module, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR);
831     };
832 
833     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
834 
835     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
836     expected =
837         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
838         "module3\nregular import func1 from module2\nnamespace import func2 from module1\nnamespace import func3 from "
839         "module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n";
840     EXPECT_TRUE(helpers::Match(output, expected));
841 }
842 
843 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetImportDescriptor, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetImportDescriptorWrongInst)844 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetImportDescriptorWrongInst)
845 {
846     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
847     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
848     EXPECT_TRUE(helpers::Match(output, expected));
849 
850     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
851         helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
852         g_implI->fileEnumerateModules(graph->file, &ctxFinder, helpers::ModuleByNameFinder);
853         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
854         ASSERT_NE(ctxFinder.module, nullptr);
855         IsetImportDescriptorTest(graph, ctxFinder.module, ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR, true);
856     };
857 
858     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
859 
860     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
861     expected = UNMODIFIED_EXPECTED_OUTPUT;
862     EXPECT_TRUE(helpers::Match(output, expected));
863 }
864 
865 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetImportDescriptor, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetImportDescriptorWrongImport)866 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetImportDescriptorWrongImport)
867 {
868     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
869     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
870     EXPECT_TRUE(helpers::Match(output, expected));
871 
872     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
873         auto *newID = new AbckitCoreImportDescriptor();
874         newID->impl = std::make_unique<AbckitJsImportDescriptor>();
875         IsetImportDescriptorTest(graph, nullptr, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR, true, newID);
876         delete newID;
877     };
878 
879     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
880 
881     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
882     expected = UNMODIFIED_EXPECTED_OUTPUT;
883     EXPECT_TRUE(helpers::Match(output, expected));
884 }
885 
886 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetExportDescriptor, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetExportDescriptor)887 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetExportDescriptor)
888 {
889     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
890     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
891     EXPECT_TRUE(helpers::Match(output, expected));
892 
893     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
894         helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
895         g_implI->fileEnumerateModules(graph->file, &ctxFinder, helpers::ModuleByNameFinder);
896         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
897         ASSERT_NE(ctxFinder.module, nullptr);
898         IsetExportDescriptorTest(graph, ctxFinder.module, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLOCALMODULEVAR);
899     };
900 
901     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
902 
903     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
904     expected =
905         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
906         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
907         "func3 from module1\n2\n2\nnamespace import func3 from module2\nthe same func from module3\n";
908     EXPECT_TRUE(helpers::Match(output, expected));
909 }
910 
911 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetExportDescriptor, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetExportDescriptorWrongInst)912 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetExportDescriptorWrongInst)
913 {
914     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
915     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
916     EXPECT_TRUE(helpers::Match(output, expected));
917 
918     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
919         helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
920         g_implI->fileEnumerateModules(graph->file, &ctxFinder, helpers::ModuleByNameFinder);
921         ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
922         ASSERT_NE(ctxFinder.module, nullptr);
923         IsetExportDescriptorTest(graph, ctxFinder.module, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR, true);
924     };
925 
926     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
927 
928     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
929     expected = UNMODIFIED_EXPECTED_OUTPUT;
930     EXPECT_TRUE(helpers::Match(output, expected));
931 }
932 
933 // Test: test-kind=api, api=IsaApiDynamicImpl::iSetExportDescriptor, abc-kind=JS, category=negative
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicIsetExportDescriptorWrongExport)934 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicIsetExportDescriptorWrongExport)
935 {
936     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
937     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
938     EXPECT_TRUE(helpers::Match(output, expected));
939 
940     auto cb = [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) {
941         auto *newED = new AbckitCoreExportDescriptor();
942         newED->impl = std::make_unique<AbckitJsExportDescriptor>();
943         IsetExportDescriptorTest(graph, nullptr, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLOCALMODULEVAR, true, newED);
944         delete newED;
945     };
946 
947     helpers::TransformMethod(INPUT_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0", cb);
948 
949     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
950     expected = UNMODIFIED_EXPECTED_OUTPUT;
951     EXPECT_TRUE(helpers::Match(output, expected));
952 }
953 
954 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddImportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,ModuleAddImportFromDynamicModule_RegularImport)955 TEST_F(LibAbcKitJSModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport)
956 {
957     AbckitFile *file = nullptr;
958     helpers::AssertOpenAbc(INPUT_PATH, &file);
959 
960     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
961     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
962     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
963     ASSERT_NE(ctxFinder.module, nullptr);
964     auto module = ctxFinder.module;
965     UserTransformerData utd;
966     utd.name = "newImportedFunc";
967     utd.alias = "newImportedFunc";
968     utd.moduleName = "modules/JSmodule3";
969     utd.isRegular = true;
970     AddImportFromDynamicModuleImpl(module, &utd);
971     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
972 
973     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
974     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
975     g_impl->closeFile(file);
976     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
977 
978     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
979     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
980     EXPECT_TRUE(helpers::Match(output, expected));
981 
982     helpers::TransformMethod(
983         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
984         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
985             TransformIrAddImportedFunctionCall(graph, g_implI->functionGetFile(method), "newImportedFunc");
986         },
987         []([[maybe_unused]] AbckitGraph *graph) {});
988 
989     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
990     expected =
991         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
992         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
993         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func "
994         "from module3\n";
995     EXPECT_TRUE(helpers::Match(output, expected));
996 }
997 
998 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddImportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,ModuleAddImportFromDynamicModule_RegularImport2)999 TEST_F(LibAbcKitJSModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport2)
1000 {
1001     AbckitFile *file = nullptr;
1002     helpers::AssertOpenAbc(INPUT_PATH, &file);
1003 
1004     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1005     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1006     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1007     ASSERT_NE(ctxFinder.module, nullptr);
1008     auto module = ctxFinder.module;
1009     UserTransformerData utd;
1010     utd.name = "newImportedFunc";
1011     utd.alias = "NewImportedFuncAlias";
1012     utd.moduleName = "modules/JSmodule3";
1013     utd.isRegular = true;
1014     AddImportFromDynamicModuleImpl(module, &utd);
1015     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1016 
1017     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1018     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1019     g_impl->closeFile(file);
1020     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1021 
1022     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1023     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1024     EXPECT_TRUE(helpers::Match(output, expected));
1025 
1026     helpers::TransformMethod(
1027         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1028         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1029             TransformIrAddImportedFunctionCall(graph, g_implI->functionGetFile(method), "NewImportedFuncAlias");
1030         },
1031         []([[maybe_unused]] AbckitGraph *graph) {});
1032 
1033     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1034     expected =
1035         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1036         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1037         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func "
1038         "from module3\n";
1039     EXPECT_TRUE(helpers::Match(output, expected));
1040 }
1041 
1042 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddImportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,ModuleAddImportFromDynamicModule_RegularImport3)1043 TEST_F(LibAbcKitJSModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport3)
1044 {
1045     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
1046     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1047     EXPECT_TRUE(helpers::Match(output, expected));
1048     AbckitFile *file = nullptr;
1049 
1050     helpers::AssertOpenAbc(INPUT_PATH, &file);
1051 
1052     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1053     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1054     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1055     ASSERT_NE(ctxFinder.module, nullptr);
1056     auto module = ctxFinder.module;
1057     UserTransformerData utd;
1058     utd.name = "newImportedFuncFromModule4";
1059     utd.alias = "NewImportedFuncAlias";
1060     utd.moduleName = "modules/JSmodule4";
1061     utd.isRegular = true;
1062     AddImportFromDynamicModuleImpl(module, &utd);
1063     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1064 
1065     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1066     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1067     g_impl->closeFile(file);
1068     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1069 
1070     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1071     expected = UNMODIFIED_EXPECTED_OUTPUT;
1072     EXPECT_TRUE(helpers::Match(output, expected));
1073 
1074     helpers::TransformMethod(
1075         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1076         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1077             TransformIrAddImportedFunctionCall(graph, g_implI->functionGetFile(method), "NewImportedFuncAlias");
1078         },
1079         []([[maybe_unused]] AbckitGraph *graph) {});
1080 
1081     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1082     expected =
1083         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1084         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1085         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func "
1086         "from module4\n";
1087     EXPECT_TRUE(helpers::Match(output, expected));
1088 }
1089 
1090 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddImportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,ModuleAddImportFromDynamicModule_RegularImport4)1091 TEST_F(LibAbcKitJSModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport4)
1092 {
1093     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
1094     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1095     EXPECT_TRUE(helpers::Match(output, expected));
1096     AbckitFile *file = nullptr;
1097 
1098     helpers::AssertOpenAbc(INPUT_PATH, &file);
1099 
1100     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1101     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1102     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1103     ASSERT_NE(ctxFinder.module, nullptr);
1104     auto module = ctxFinder.module;
1105     UserTransformerData utd;
1106     utd.name = "default";
1107     utd.alias = "newImportedDefaultFuncFromModule4";
1108     utd.moduleName = "modules/JSmodule4";
1109     utd.isRegular = true;
1110     AddImportFromDynamicModuleImpl(module, &utd);
1111     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1112 
1113     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1114     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1115     g_impl->closeFile(file);
1116     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1117 
1118     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1119     expected = UNMODIFIED_EXPECTED_OUTPUT;
1120     EXPECT_TRUE(helpers::Match(output, expected));
1121 
1122     helpers::TransformMethod(
1123         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1124         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1125             TransformIrAddImportedFunctionCall(graph, g_implI->functionGetFile(method),
1126                                                "newImportedDefaultFuncFromModule4");
1127         },
1128         []([[maybe_unused]] AbckitGraph *graph) {});
1129 
1130     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1131     expected =
1132         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1133         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1134         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported "
1135         "default func from module4\n";
1136     EXPECT_TRUE(helpers::Match(output, expected));
1137 }
1138 
1139 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddImportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,ModuleAddImportFromDynamicModule_NamespaceImport)1140 TEST_F(LibAbcKitJSModifyApiModulesTest, ModuleAddImportFromDynamicModule_NamespaceImport)
1141 {
1142     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
1143     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1144     EXPECT_TRUE(helpers::Match(output, expected));
1145     AbckitFile *file = nullptr;
1146 
1147     helpers::AssertOpenAbc(INPUT_PATH, &file);
1148 
1149     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1150     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1151     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1152     ASSERT_NE(ctxFinder.module, nullptr);
1153     auto module = ctxFinder.module;
1154     UserTransformerData utd;
1155     utd.name = "*";
1156     utd.alias = "NewImport";
1157     utd.moduleName = "modules/JSmodule3";
1158     utd.isRegular = false;
1159     AddImportFromDynamicModuleImpl(module, &utd);
1160     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1161 
1162     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1163     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1164     g_impl->closeFile(file);
1165     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1166 
1167     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1168     expected = UNMODIFIED_EXPECTED_OUTPUT;
1169     EXPECT_TRUE(helpers::Match(output, expected));
1170 
1171     helpers::TransformMethod(
1172         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1173         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1174             TransformIrAddImportedFunctionCallNS(graph, g_implI->functionGetFile(method), "newImportedFunc",
1175                                                  "modules/JSmodule3");
1176         },
1177         []([[maybe_unused]] AbckitGraph *graph) {});
1178 
1179     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1180     expected =
1181         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1182         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1183         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func "
1184         "from module3\n";
1185     EXPECT_TRUE(helpers::Match(output, expected));
1186 }
1187 
1188 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddImportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,ModuleAddImportFromDynamicModule_NamespaceImport2)1189 TEST_F(LibAbcKitJSModifyApiModulesTest, ModuleAddImportFromDynamicModule_NamespaceImport2)
1190 {
1191     auto output = helpers::ExecuteDynamicAbc(INPUT_PATH, "JSmodules_dynamic_modify");
1192     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1193     EXPECT_TRUE(helpers::Match(output, expected));
1194     AbckitFile *file = nullptr;
1195 
1196     helpers::AssertOpenAbc(INPUT_PATH, &file);
1197 
1198     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1199     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1200     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1201     ASSERT_NE(ctxFinder.module, nullptr);
1202     auto module = ctxFinder.module;
1203     UserTransformerData utd;
1204     utd.name = "*";
1205     utd.alias = "NewImport";
1206     utd.moduleName = "modules/JSmodule4";
1207     utd.isRegular = false;
1208     AddImportFromDynamicModuleImpl(module, &utd);
1209     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1210 
1211     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1212     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1213     g_impl->closeFile(file);
1214     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1215 
1216     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1217     expected = UNMODIFIED_EXPECTED_OUTPUT;
1218     EXPECT_TRUE(helpers::Match(output, expected));
1219 
1220     helpers::TransformMethod(
1221         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1222         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1223             TransformIrAddImportedFunctionCallNS(graph, g_implI->functionGetFile(method), "newImportedFuncFromModule4",
1224                                                  "modules/JSmodule4");
1225         },
1226         []([[maybe_unused]] AbckitGraph *graph) {});
1227 
1228     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1229     expected =
1230         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1231         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1232         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func "
1233         "from module4\n";
1234     EXPECT_TRUE(helpers::Match(output, expected));
1235 }
1236 
1237 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_LocalExport)1238 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_LocalExport)
1239 {
1240     AbckitFile *file = nullptr;
1241     helpers::AssertOpenAbc(INPUT_PATH, &file);
1242 
1243     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1244     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1245     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1246     ASSERT_NE(ctxFinder.module, nullptr);
1247     auto module = ctxFinder.module;
1248     UserTransformerData utd;
1249     utd.name = "NewExportedVar";
1250     utd.alias = "NewExportedVar";
1251     utd.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT;
1252     utd.moduleName = "JSmodules_dynamic_modify";
1253     DynamicModuleAddExportImpl(module, &utd);
1254     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1255 
1256     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1257     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1258     g_impl->closeFile(file);
1259     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1260 
1261     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1262     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1263     EXPECT_TRUE(helpers::Match(output, expected));
1264 
1265     helpers::TransformMethod(
1266         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1267         [&utd](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1268             TransformIrAddLocalExport(graph, g_implI->functionGetFile(method), utd.alias, "JSmodules_dynamic_modify");
1269         },
1270         []([[maybe_unused]] AbckitGraph *graph) {});
1271 
1272     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1273     expected =
1274         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1275         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1276         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n5\n";
1277     EXPECT_TRUE(helpers::Match(output, expected));
1278 }
1279 
1280 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_LocalExport2)1281 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_LocalExport2)
1282 {
1283     AbckitFile *file = nullptr;
1284     helpers::AssertOpenAbc(INPUT_PATH, &file);
1285 
1286     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1287     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1288     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1289     ASSERT_NE(ctxFinder.module, nullptr);
1290     auto module = ctxFinder.module;
1291     UserTransformerData utd;
1292     utd.name = "NewExportedVar";
1293     utd.alias = "NewExportedVarAlias";
1294     utd.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT;
1295     utd.moduleName = "JSmodules_dynamic_modify";
1296     DynamicModuleAddExportImpl(module, &utd);
1297     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1298 
1299     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1300     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1301     g_impl->closeFile(file);
1302     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1303 
1304     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1305     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1306     EXPECT_TRUE(helpers::Match(output, expected));
1307 
1308     helpers::TransformMethod(
1309         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1310         [&utd](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1311             TransformIrAddLocalExport(graph, g_implI->functionGetFile(method), utd.alias, "JSmodules_dynamic_modify");
1312         },
1313         []([[maybe_unused]] AbckitGraph *graph) {});
1314 
1315     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1316     expected =
1317         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1318         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1319         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n5\n";
1320     EXPECT_TRUE(helpers::Match(output, expected));
1321 }
1322 
1323 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_LocalExport3)1324 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_LocalExport3)
1325 {
1326     AbckitFile *file = nullptr;
1327     helpers::AssertOpenAbc(INPUT_PATH, &file);
1328 
1329     helpers::ModuleByNameContext ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1330     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1331     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1332     ASSERT_NE(ctxFinder.module, nullptr);
1333     auto module = ctxFinder.module;
1334     UserTransformerData utd;
1335     utd.name = "default";
1336     utd.alias = "NewExportedVarDefault";
1337     utd.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT;
1338     utd.moduleName = "JSmodules_dynamic_modify";
1339     DynamicModuleAddExportImpl(module, &utd);
1340     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1341 
1342     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1343     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1344     g_impl->closeFile(file);
1345     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1346 
1347     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1348     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1349     EXPECT_TRUE(helpers::Match(output, expected));
1350 
1351     helpers::TransformMethod(
1352         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1353         [&utd](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1354             TransformIrAddLocalExport(graph, g_implI->functionGetFile(method), utd.alias, "JSmodules_dynamic_modify");
1355         },
1356         []([[maybe_unused]] AbckitGraph *graph) {});
1357 
1358     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1359     expected =
1360         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1361         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1362         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n5\n";
1363     EXPECT_TRUE(helpers::Match(output, expected));
1364 }
1365 
1366 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_IndirectExport)1367 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_IndirectExport)
1368 {
1369     AbckitFile *file = nullptr;
1370     helpers::AssertOpenAbc(INPUT_PATH, &file);
1371 
1372     helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule2"};
1373     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1374     TestNoError(ctxFinder.module);
1375     auto module = ctxFinder.module;
1376     UserTransformerData utd {"NewLocalExportLet", "NewLocalExportLet", "modules/JSmodule1", false,
1377                              AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT};
1378     DynamicModuleAddExportImpl(module, &utd);
1379     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1380 
1381     UserTransformerData utd2 {utd.name, utd.alias, "modules/JSmodule2", true};
1382     ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1383     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1384     TestNoError(ctxFinder.module);
1385     AddImportFromDynamicModuleImpl(ctxFinder.module, &utd2);
1386     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1387 
1388     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1389     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1390     g_impl->closeFile(file);
1391     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1392 
1393     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1394     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1395     EXPECT_TRUE(helpers::Match(output, expected));
1396 
1397     helpers::TransformMethod(
1398         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1399         [&utd2](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1400             TransformIrAddIndirectExport(graph, g_implI->functionGetFile(method), utd2.alias,
1401                                          "JSmodules_dynamic_modify");
1402         },
1403         []([[maybe_unused]] AbckitGraph *graph) {});
1404 
1405     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1406     expected =
1407         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1408         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1409         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n3\n";
1410     EXPECT_TRUE(helpers::Match(output, expected));
1411 }
1412 
1413 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_IndirectExport2)1414 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_IndirectExport2)
1415 {
1416     AbckitFile *file = nullptr;
1417     helpers::AssertOpenAbc(INPUT_PATH, &file);
1418 
1419     helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule2"};
1420     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1421     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1422     ASSERT_NE(ctxFinder.module, nullptr);
1423     auto module = ctxFinder.module;
1424     UserTransformerData utd = {"NewLocalExportVar", "NewLocalExportVarAlias", "modules/JSmodule4", false,
1425                                AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT};
1426     DynamicModuleAddExportImpl(module, &utd);
1427     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1428 
1429     UserTransformerData utd2 = {utd.alias, "NewLocalExportVarFromModule4", "modules/JSmodule2", true};
1430     ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1431     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1432     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1433     ASSERT_NE(ctxFinder.module, nullptr);
1434     AddImportFromDynamicModuleImpl(ctxFinder.module, &utd2);
1435     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1436 
1437     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1438     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1439     g_impl->closeFile(file);
1440     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1441 
1442     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1443     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1444     EXPECT_TRUE(helpers::Match(output, expected));
1445 
1446     helpers::TransformMethod(
1447         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1448         [&utd2](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1449             TransformIrAddIndirectExport(graph, g_implI->functionGetFile(method), utd2.alias,
1450                                          "JSmodules_dynamic_modify");
1451         },
1452         []([[maybe_unused]] AbckitGraph *graph) {});
1453 
1454     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1455     expected =
1456         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1457         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1458         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n6\n";
1459     EXPECT_TRUE(helpers::Match(output, expected));
1460 }
1461 
1462 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_StarExport)1463 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_StarExport)
1464 {
1465     AbckitFile *file = nullptr;
1466     helpers::AssertOpenAbc(INPUT_PATH, &file);
1467 
1468     helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule4"};
1469     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1470     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1471     ASSERT_NE(ctxFinder.module, nullptr);
1472     auto module = ctxFinder.module;
1473     UserTransformerData utd;
1474     utd.name = "*";
1475     utd.moduleName = "modules/JSmodule3";
1476     utd.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT;
1477     DynamicModuleAddExportImpl(module, &utd);
1478     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1479 
1480     ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1481     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1482     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1483     ASSERT_NE(ctxFinder.module, nullptr);
1484     module = ctxFinder.module;
1485     UserTransformerData utd2 = {"*", "NS4", "modules/JSmodule4", false};
1486     AddImportFromDynamicModuleImpl(module, &utd2);
1487     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1488 
1489     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1490     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1491     g_impl->closeFile(file);
1492     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1493 
1494     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1495     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1496     EXPECT_TRUE(helpers::Match(output, expected));
1497 
1498     helpers::TransformMethod(
1499         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1500         [&utd2](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1501             TransformIrAddStarExport(graph, g_implI->functionGetFile(method), "newExportedFunc", utd2.moduleName);
1502         },
1503         []([[maybe_unused]] AbckitGraph *graph) {});
1504 
1505     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1506     EXPECT_TRUE(helpers::Match(output, EXPECTED0));
1507 }
1508 
1509 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_StarExport2)1510 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_StarExport2)
1511 {
1512     AbckitFile *file = nullptr;
1513     helpers::AssertOpenAbc(INPUT_PATH, &file);
1514 
1515     helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule3"};
1516     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1517     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1518     ASSERT_NE(ctxFinder.module, nullptr);
1519     auto module = ctxFinder.module;
1520     UserTransformerData utd;
1521     utd.name = "*";
1522     utd.moduleName = "modules/JSmodule4";
1523     utd.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT;
1524     DynamicModuleAddExportImpl(module, &utd);
1525     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1526 
1527     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1528     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1529     g_impl->closeFile(file);
1530     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1531 
1532     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1533     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1534     EXPECT_TRUE(helpers::Match(output, expected));
1535 
1536     helpers::TransformMethod(
1537         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1538         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1539             TransformIrAddStarExport(graph, g_implI->functionGetFile(method), "newExportedFuncFromModule4",
1540                                      "modules/JSmodule3");
1541         },
1542         []([[maybe_unused]] AbckitGraph *graph) {});
1543 
1544     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1545     expected =
1546         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1547         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1548         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew exported func "
1549         "from module4\n";
1550     EXPECT_TRUE(helpers::Match(output, expected));
1551 }
1552 
1553 // Test: test-kind=api, api=JsModifyApiImpl::moduleAddExportFromJsToJs, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,DynamicModuleAddExport_StarExport3)1554 TEST_F(LibAbcKitJSModifyApiModulesTest, DynamicModuleAddExport_StarExport3)
1555 {
1556     AbckitFile *file = nullptr;
1557     helpers::AssertOpenAbc(INPUT_PATH, &file);
1558 
1559     helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/JSmodule4"};
1560     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1561     TestNoError(ctxFinder.module);
1562     auto module = ctxFinder.module;
1563     UserTransformerData utd {"*", "NewStarExport", "modules/JSmodule3", false,
1564                              AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT};
1565     DynamicModuleAddExportImpl(module, &utd);
1566     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1567 
1568     ctxFinder = {nullptr, "JSmodules_dynamic_modify"};
1569     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1570     TestNoError(ctxFinder.module);
1571     module = ctxFinder.module;
1572     UserTransformerData utd2 {"NewStarExport", "NewStarExport", "modules/JSmodule4", true};
1573     AddImportFromDynamicModuleImpl(module, &utd2);
1574     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1575 
1576     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1577     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1578     g_impl->closeFile(file);
1579     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1580 
1581     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1582     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1583     EXPECT_TRUE(helpers::Match(output, expected));
1584 
1585     helpers::TransformMethod(
1586         MODIFIED_PATH, MODIFIED_PATH, "modules/JSmodule4.func_main_0",
1587         [&utd2, &utd](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1588             TransformIrAddStarExportFunc(graph, g_implI->functionGetFile(method), utd2.alias, utd.moduleName);
1589         },
1590         []([[maybe_unused]] AbckitGraph *graph) {});
1591 
1592     helpers::TransformMethod(
1593         MODIFIED_PATH, MODIFIED_PATH, "JSmodules_dynamic_modify.func_main_0",
1594         [](AbckitFile *, AbckitCoreFunction *method, AbckitGraph *graph) {
1595             TransformIrAddStarExportFunc2(graph, g_implI->functionGetFile(method), "newExportedFunc",
1596                                           "JSmodules_dynamic_modify");
1597         },
1598         []([[maybe_unused]] AbckitGraph *graph) {});
1599 
1600     output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1601     expected =
1602         "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from "
1603         "module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import "
1604         "func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew exported func "
1605         "from module3\n";
1606     EXPECT_TRUE(helpers::Match(output, expected));
1607 }
1608 
1609 // Test: test-kind=api, api=JsModifyApiImpl::fileAddExternalModule, abc-kind=JS, category=positive
TEST_F(LibAbcKitJSModifyApiModulesTest,FileAddExternalModule)1610 TEST_F(LibAbcKitJSModifyApiModulesTest, FileAddExternalModule)
1611 {
1612     AbckitFile *file = nullptr;
1613     helpers::AssertOpenAbc(INPUT_PATH, &file);
1614 
1615     AbckitJsExternalModuleCreateParams params {};
1616     params.name = "ExternalModule";
1617     g_implJsM->fileAddExternalModule(file, &params);
1618     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1619 
1620     AbckitJsModule *jsModule = g_implJsM->fileAddExternalModule(file, &params);
1621     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1622     ASSERT_NE(jsModule, nullptr);
1623 
1624     AbckitCoreModule *coreModule = g_implJsI->jsModuleToCoreModule(jsModule);
1625     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1626     ASSERT_NE(coreModule, nullptr);
1627 
1628     helpers::ModuleByNameContext ctxFinder = {nullptr, params.name};
1629     g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder);
1630     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1631     ASSERT_NE(ctxFinder.module, nullptr);
1632     ASSERT_EQ(g_implI->moduleIsExternal(ctxFinder.module), true);
1633 
1634     g_impl->writeAbc(file, MODIFIED_PATH, strlen(MODIFIED_PATH));
1635     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1636     g_impl->closeFile(file);
1637     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1638 
1639     auto output = helpers::ExecuteDynamicAbc(MODIFIED_PATH, "JSmodules_dynamic_modify");
1640     auto expected = UNMODIFIED_EXPECTED_OUTPUT;
1641     EXPECT_TRUE(helpers::Match(output, expected));
1642 }
1643 
1644 }  // namespace libabckit::test
1645