From 8534cc49a6aeea49ad91515a3530fcfaea2ea7d5 Mon Sep 17 00:00:00 2001 From: bergamot88 Date: Sat, 21 Jun 2025 02:53:00 +0300 Subject: [PATCH] Add tests for compilation multiple files Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICH2VD Description:Add tests for compilation multiple files Testing: All required pre-merge tests passed. Results are available in the internal CI Signed-off-by: Tokmakov Alexander --- ets2panda/test/tsconfig/CMakeLists.txt | 1 + .../CMakeLists.txt | 35 +++++ .../file_creator.py | 65 ++++++++ .../known_failures.kfl | 12 ++ .../test-compilation-multiple-files/main.py | 139 ++++++++++++++++++ .../parse_options.py | 72 +++++++++ .../templates/cycle-imports-1k-method.ets.j2 | 41 ++++++ ...-each-previous-file-and-first-large.ets.j2 | 59 ++++++++ ...t-each-previous-file-in-empty-files.ets.j2 | 20 +++ .../templates/import-type.ets.j2 | 38 +++++ .../templates/import-with-alias.ets.j2 | 24 +++ .../templates/simple-and-alias-import.ets.j2 | 24 +++ .../templates/simple-named-import.ets.j2 | 27 ++++ .../test_runner.py | 110 ++++++++++++++ 14 files changed, 667 insertions(+) create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/CMakeLists.txt create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/file_creator.py create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/known_failures.kfl create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/main.py create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/parse_options.py create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/cycle-imports-1k-method.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-and-first-large.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-in-empty-files.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-type.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-with-alias.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-and-alias-import.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-named-import.ets.j2 create mode 100644 ets2panda/test/tsconfig/test-compilation-multiple-files/test_runner.py diff --git a/ets2panda/test/tsconfig/CMakeLists.txt b/ets2panda/test/tsconfig/CMakeLists.txt index 182e3aaa09..c8760cfa53 100644 --- a/ets2panda/test/tsconfig/CMakeLists.txt +++ b/ets2panda/test/tsconfig/CMakeLists.txt @@ -16,6 +16,7 @@ if(NOT PANDA_REGRESSION_TESTS) endif() add_subdirectory(test-config) +add_subdirectory(test-compilation-multiple-files) # 25872 # add_subdirectory(test-build) # add_subdirectory(test-decl) diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/CMakeLists.txt b/ets2panda/test/tsconfig/test-compilation-multiple-files/CMakeLists.txt new file mode 100644 index 0000000000..1e6925cf88 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(TARGET_NAME "es2panda-tsconfig-compilation-multiple-files") +set(VENV_PYTHON "$ENV{HOME}/.venv-panda/bin/python3") + +if(NOT DEFINED FILES_COUNT) + set(FILES_COUNT 5) +endif() + +if(PANDA_QEMU_BUILD) + return() +endif() + +add_custom_target(${TARGET_NAME} + COMMENT "Testing arktsconfig for: ${TARGET_NAME}" + DEPENDS es2panda + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + COMMAND ${VENV_PYTHON} main.py + --files-number ${FILES_COUNT} + --stdlib-path ${PANDA_ROOT}/plugins/ets/stdlib + --build-dir-path ${PANDA_BINARY_ROOT} +) + +add_dependencies(es2panda_tests ${TARGET_NAME}) diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/file_creator.py b/ets2panda/test/tsconfig/test-compilation-multiple-files/file_creator.py new file mode 100644 index 0000000000..a7039b65eb --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/file_creator.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import jinja2 +import json +import os +from pathlib import Path +from typing import Any, Callable, Union + + +class FileCreator: + def get_opener(self, mode: int) -> Callable[[Union[str, Path], int], int]: + def opener(path_name: Union[str, Path], flags: int) -> int: + return os.open(path_name, os.O_RDWR | os.O_APPEND | os.O_CREAT | flags, mode) + return opener + + def write_to_file(self, file_path: Path, contain: Any, mode: int = 0o644) -> None: + with open(file_path, mode='w+', encoding='utf-8', opener=self.get_opener(mode)) as file: + if file_path.suffix == '.json': + json.dump(contain, file, ensure_ascii=False, indent=4) + else: + file.write(contain) + + def create_ets_files(self, num_files: int, template_path: Path, target_dir: Path) -> list[Path]: + target_dir.mkdir(parents=True, exist_ok=True) + + with open(template_path, 'r', encoding='utf-8') as file: + template_content = file.read() + + template = jinja2.Template(template_content) + ets_files = list() + for i in range(1, num_files + 1): + rendered_content = template.render(file_number=i, files_number=num_files) + file_name = f"file_{i}.ets" + file_path = target_dir.joinpath(file_name) + self.write_to_file(file_path, rendered_content) + ets_files.append(file_path) + return ets_files + + def create_arktsconfig_file(self, out_dir_root: Path, ets_files: list[Path]) -> Path: + out_dir = out_dir_root.joinpath('compiled_abc_files') + out_dir.mkdir(parents=True, exist_ok=True) + filename = 'arktsconfig.json' + file_path = out_dir_root.joinpath(filename) + data = { + "compilerOptions": { + "outDir": str(out_dir) + }, + "files": [str(path) for path in ets_files] + } + self.write_to_file(file_path, data) + return file_path diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/known_failures.kfl b/ets2panda/test/tsconfig/test-compilation-multiple-files/known_failures.kfl new file mode 100644 index 0000000000..444f693b4d --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/known_failures.kfl @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/main.py b/ets2panda/test/tsconfig/test-compilation-multiple-files/main.py new file mode 100644 index 0000000000..e6b8cc0db3 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/main.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import shutil +import sys +from typing import Dict +from pathlib import Path +from parse_options import Parser +from file_creator import FileCreator +from test_runner import Runner +from subprocess import CompletedProcess + + +def run_es2panda( + runner: Runner, + suite_name: str, + files_number: int, + template_path: Path, + generated_ets_files_root: Path + ) -> CompletedProcess: + suite_output_dir = generated_ets_files_root.joinpath(suite_name) + ets_files = FileCreator().create_ets_files(files_number, template_path, suite_output_dir) + arktsconfig_file = FileCreator().create_arktsconfig_file(suite_output_dir, ets_files) + return runner.run_es2panda_test(suite_name, ets_files, arktsconfig_file) + + +def get_result_es2panda_running( + runner: Runner, + template_path: Path, + files_number: int, + generated_ets_files_root: Path + ) -> Dict[str, CompletedProcess]: + result: Dict[str, CompletedProcess] = {} + for template in template_path: + name = Path(template.stem).stem + es2panda_result = run_es2panda( + runner, + name, + files_number, + template.resolve(), + generated_ets_files_root, + ) + result[name] = es2panda_result + return result + + +def load_kfl(kfl: Path) -> list[str]: + lines = [] + with open(kfl, 'r') as file: + for line in file: + lines.append(line.strip()) + return lines + + +def get_new_failures( + result: Dict[str, CompletedProcess], + files_number: int, + kfl_file: Path + ) -> Dict[str, CompletedProcess]: + print('\n📈 Result:') + print(f"\n ℹ️ Number of files to compile: {files_number}\n") + kfl = load_kfl(kfl_file) + new_failures: Dict[str, CompletedProcess] = {} + for suite, process_result in result.items(): + if process_result.returncode == 0: + print(f" 🟢 Suite: {suite}") + print(f" Exit code: {process_result.returncode}\n") + else: + print(f" 🔴 Suite: {suite}") + print(f" Exit code: {process_result.returncode}\n") + if suite not in kfl: + new_failures[suite] = process_result + return new_failures + + +def process_new_failures(new_failures: Dict[str, CompletedProcess], log_files_root: Path) -> None: + if len(new_failures): + print(f"💀 New failures:") + log_files_root.mkdir(parents=True, exist_ok=True) + for suite, process_result in new_failures.items(): + print(f" 🔴 Suite: {suite}") + if process_result.stdout: + FileCreator().write_to_file(log_files_root.joinpath(f"{suite}-stdout.txt"), process_result.stdout) + if process_result.stderr: + FileCreator().write_to_file(log_files_root.joinpath(f"{suite}-stderr.txt"), process_result.stderr) + sys.exit(1) + else: + sys.exit(0) + + +def main() -> None: + args = Parser(argparse.ArgumentParser()).get_parse_args() + + current_dir = Path(__file__).resolve().parent + generated_ets_files_root = current_dir.joinpath('generated_ets_files') + templates_root = current_dir.joinpath('templates') + log_files_root = current_dir.joinpath('logs') + kfl_file = current_dir.joinpath('known_failures.kfl') + + files_number: int = args.files_number + template_path: Path = args.template_path + is_clean_generated_artifacts: bool = args.is_clean_generated_artifacts + build_dir_path: Path = args.build_dir_path + stdlib_path: Path = args.stdlib_path + is_full_log: bool = args.is_full_log + is_qemu_run: bool = args.is_qemu_run + + runner = Runner(build_dir_path, stdlib_path, is_full_log, is_qemu_run) + + result: Dict[str, CompletedProcess] = {} + + if template_path: + result = get_result_es2panda_running(runner, template_path, files_number, generated_ets_files_root) + else: + result = get_result_es2panda_running(runner, templates_root.iterdir(), files_number, generated_ets_files_root) + + if is_clean_generated_artifacts: + shutil.rmtree(generated_ets_files_root) + + new_failures = get_new_failures(result, files_number, kfl_file) + process_new_failures(new_failures, log_files_root) + + +if __name__ == "__main__": + main() diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/parse_options.py b/ets2panda/test/tsconfig/test-compilation-multiple-files/parse_options.py new file mode 100644 index 0000000000..afafcefe34 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/parse_options.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from typing import Any +from pathlib import Path + + +class Parser: + def __init__(self, parser: argparse.ArgumentParser) -> None: + self.parser: argparse.ArgumentParser = parser + + def check_positive_int(self, value: str, min_value: int = 1) -> int: + ivalue = int(value) + if ivalue < min_value: + raise argparse.ArgumentTypeError(f"The value must be an integer greater than or equal to {min_value}") + return ivalue + + def get_parse_args(self) -> Any: + self.parser.add_argument( + '-n', '--files-number', + type=lambda x: self.check_positive_int(x, 2), + required=True, + help='Amount .ets files to create (minimum 2)' + ) + self.parser.add_argument( + '-std', '--stdlib-path', + type=Path, + required=True, + help='Path to build directory' + ) + self.parser.add_argument( + '-b', '--build-dir-path', + type=Path, + required=True, + help='Path to build directory' + ) + self.parser.add_argument( + '-t', '--template-path', + type=Path, + action='append', + help='Path to template of .ets file (default: template.etc.j2)' + ) + self.parser.add_argument( + '-clr', '--is-clean-generated-artifacts', + action='store_true', + help='Remove artifacts (generated by a template .etc files compiled .abc) after executing the script' + ) + self.parser.add_argument( + '-l', '--is-full-log', + action='store_true', + help='Enable more logs' + ) + self.parser.add_argument( + '-qm', '--is-qemu-run', + action='store_true', + help='Run binary files on qemu' + ) + return self.parser.parse_args() diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/cycle-imports-1k-method.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/cycle-imports-1k-method.ets.j2 new file mode 100644 index 0000000000..2fbde02503 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/cycle-imports-1k-method.ets.j2 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% set methods_number = methods_number | default(1000) %} +{% set suffix = suffix | default('') %} + +{# ==================== methods imports ==================== #} +{% for file_idx in range(1, files_number + 1) %} + {# Determining whether to import from this file #} + {% if (file_number > 1 and file_idx < file_number) or + (file_number == 1 and file_idx >= 2) %} + + {# Generating a list of imported methods with aliases #} + {% set current_imports = [] %} + {% for method_idx in range(1, methods_number + 1) %} + {% set method_name = 'method_' ~ method_idx %} + {% set import_alias = 'method_' ~ method_idx ~ '_alias' ~ suffix ~ '_' ~ file_idx %} + {% set _ = current_imports.append(method_name ~ ' as ' ~ import_alias) %} + {% endfor %} + + {# Adding import #} + import { {{ current_imports | join(', ') }} } from './file_{{ file_idx }}'; + {% endif %} +{% endfor %} + +{% for i in range(1, methods_number + 1) %} +export function method_{{ i }}() { +} +{% endfor %} diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-and-first-large.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-and-first-large.ets.j2 new file mode 100644 index 0000000000..219df0664c --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-and-first-large.ets.j2 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% if file_number > 1 -%} +{# Importing all previous files #} +{% for i in range(1, file_number) -%} +import * as file_{{ i }} from './file_{{ i }}.ets'; +{% endfor -%} + +{# Separate import of the first file for special use #} +import * as first_file from './file_1.ets'; +{% endif -%} + +export class Class{{ file_number }} { + constructor() {} + method() {} +} + +{% if file_number > 1 -%} +{# Using the methods from the first file #} +function useFirstFileMethod() { + const inst = new first_file.Class1(); + inst.method(); +} + +{# Using methods from all previous files #} +function usePreviousClasses() { +{% for i in range(1, file_number) -%} + const instance_{{ i }} = new file_{{ i }}.Class{{ i }}(); + instance_{{ i }}.method(); +{% endfor -%} +} +{% endif -%} + + +{% if file_number > 1 -%} +usePreviousClasses(); +useFirstFileMethod(); +{% endif -%} + +{% if file_number == 1 -%} +{# Generating 1000 methods for the first file only #} +{% for i in range(1, 1001) -%} +export function method_{{ i }}() { +} +{% endfor -%} +{% endif -%} diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-in-empty-files.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-in-empty-files.ets.j2 new file mode 100644 index 0000000000..167cf56ed1 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-each-previous-file-in-empty-files.ets.j2 @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% if file_number > 1 -%} +{% for i in range(1, file_number) -%} +import * as file_{{ i }} from './file_{{ i }}.ets' +{% endfor -%} +{% endif -%} diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-type.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-type.ets.j2 new file mode 100644 index 0000000000..5be22d1966 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-type.ets.j2 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% if file_number > 1 -%} +{% for i in range(1, file_number) -%} +import type { Class{{ i }} } from './file_{{ i }}.ets'; +import type { Class{{ i }} as Class_{{ i }} } from './file_{{ i }}.ets'; +import type { Interface{{ i }} } from './file_{{ i }}.ets'; +import type { Interface{{ i }} as Interface_{{ i }} } from './file_{{ i }}.ets'; +{% endfor -%} +{% endif -%} + +export class Class{{ file_number }} { + constructor() {} +} + +export interface Interface{{ file_number }} {} + +{% if file_number > 1 -%} +{% for i in range(1, file_number) -%} +function f1(value: Class{{ i }}): void { +} +function f2(value: Class_{{ i }}): void { +} +{% endfor -%} +{% endif -%} diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-with-alias.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-with-alias.ets.j2 new file mode 100644 index 0000000000..8f48474e60 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/import-with-alias.ets.j2 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% if file_number > 1 -%} +{% for i in range(1, file_number) -%} +import { Class{{ i }} as Class{{ i }} } from './file_{{ i }}.ets'; +{% endfor -%} +{% endif -%} + +export class Class{{ file_number }} { + constructor() {} +} \ No newline at end of file diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-and-alias-import.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-and-alias-import.ets.j2 new file mode 100644 index 0000000000..f9b1eaa8d1 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-and-alias-import.ets.j2 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% if file_number > 1 -%} +{% for i in range(1, file_number) -%} +import { Class{{ i }}, Class{{ i }} as Class{{ i }} } from './file_{{ i }}.ets'; +{% endfor -%} +{% endif -%} + +export class Class{{ file_number }} { + constructor() {} +} \ No newline at end of file diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-named-import.ets.j2 b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-named-import.ets.j2 new file mode 100644 index 0000000000..7d8c45746d --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/templates/simple-named-import.ets.j2 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{% if file_number > 1 -%} +{% for i in range(1, file_number) -%} +import { Class{{ i }} } from './file_{{ i }}.ets'; +import { Interface{{ i }} } from './file_{{ i }}.ets'; +{% endfor -%} +{% endif -%} + +export class Class{{ file_number }} { + constructor() {} +} + +export interface Interface{{ file_number }} {} \ No newline at end of file diff --git a/ets2panda/test/tsconfig/test-compilation-multiple-files/test_runner.py b/ets2panda/test/tsconfig/test-compilation-multiple-files/test_runner.py new file mode 100644 index 0000000000..f237439d69 --- /dev/null +++ b/ets2panda/test/tsconfig/test-compilation-multiple-files/test_runner.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +from pathlib import Path +from datetime import datetime + + +class Runner: + def __init__(self, build_dir_path: Path, stdlib_path: Path, is_full_log: bool, is_qemu_run: bool) -> None: + self.build_dir_path = build_dir_path + self.stdlib_path = stdlib_path + self.es2panda_bin = build_dir_path.joinpath('bin').joinpath('es2panda') + self.is_full_log = is_full_log + self.is_qemu_run = is_qemu_run + + def run_es2panda(self, args: list[str]) -> subprocess.CompletedProcess: + command = [str(self.es2panda_bin)] + if self.is_qemu_run: + command.insert(0, 'qemu-aarch64') + command.extend(args) + result = subprocess.run(command, capture_output=True, text=True) + return result + + def find_compiled_abc_files(self, ets_files: list[Path]) -> tuple[list[Path], list[Path]]: + not_found_files = [] + found_files = [] + for ets_file in ets_files: + file = ( + ets_file.parent + .joinpath('compiled_abc_files') + .joinpath(ets_file.name).with_suffix('.abc') + ) + if not file.is_file(): + not_found_files.append(file) + else: + found_files.append(file) + return not_found_files, found_files + + def process_es2panda(self, ets_files: list[Path], arktsconfig_file: Path) -> tuple: + start_time = datetime.now() + process_result = self.run_es2panda([ + '--arktsconfig', str(arktsconfig_file), + '--stdlib', str(self.stdlib_path) + ]) + finish_time = datetime.now() + duration = (finish_time - start_time).total_seconds() + not_found_files, found_files = self.find_compiled_abc_files(ets_files) + return duration, process_result, not_found_files, found_files + + def log_success( + self, + suite_name: str, + duration: float, + file_count: int, + command_args: list[str] + ) -> None: + print(f" ✅ es2panda compilation for: {suite_name} IS SUCCESSFUL") + print(f"\t⏱️ Execute time: {duration} sec.") + print(f"\t⚒️ Compiled files number: {file_count}") + print(f"\t💻 Command: \n\t {' '.join(command_args)}") + + def log_failure( + self, + suite_name: str, + command_args: list[str], + not_found_files: list[Path] + ) -> None: + print(f" ❌ es2panda compilation for: {suite_name} FAILED") + print(f"\t💻 Command: \n\t {' '.join(command_args)}") + print('\t⚠️ Not found files:') + for file in not_found_files: + print(f"\t 🔴 {file}") + + def log_compilation_result( + self, + suite_name: str, + duration: float, + process_result: subprocess.CompletedProcess, + found_files: list[Path], + not_found_files: list[Path] + ) -> None: + if process_result.returncode == 0 and not not_found_files: + self.log_success(suite_name, duration, len(found_files), process_result.args) + else: + self.log_failure(suite_name, process_result.args, not_found_files) + + def run_es2panda_test( + self, + suite_name: str, + ets_files: list[Path], + arktsconfig_file: Path + ) -> subprocess.CompletedProcess: + duration, process_result, not_found_files, found_files = self.process_es2panda(ets_files, arktsconfig_file) + if self.is_full_log: + self.log_compilation_result(suite_name, duration, process_result, found_files, not_found_files) + return process_result -- Gitee