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), ¶ms);
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), ¶ms);
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, ¶ms);
1618 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
1619
1620 AbckitJsModule *jsModule = g_implJsM->fileAddExternalModule(file, ¶ms);
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