diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 8b78bb6fcc..dd433aadd9 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -32,7 +32,7 @@ jobs: pipenv run flake8 . - name: Run Type Checker run: | - pipenv run mypy src/build_workflow tests/tests_build_workflow src/checkout_workflow tests/tests_checkout_workflow src/run_assemble.py tests/test_run_assemble.py src/assemble_workflow tests/tests_assemble_workflow src/manifests tests/tests_manifests src/paths tests/tests_paths src/system tests/tests_system src/ci_workflow tests/tests_ci_workflow src/manifests_workflow tests/tests_manifests_workflow + pipenv run mypy . - name: Run Tests with Coverage run: | pipenv run coverage run -m pytest --cov=./src --cov-report=xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af024144de..c00fca69cb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: - id: mypy stages: [commit] name: mypy - entry: bash -c 'pipenv run mypy src/build_workflow tests/tests_build_workflow src/checkout_workflow tests/tests_checkout_workflow src/run_assemble.py tests/test_run_assemble.py src/assemble_workflow tests/tests_assemble_workflow src/manifests tests/tests_manifests src/paths tests/tests_paths src/system tests/tests_system src/ci_workflow tests/tests_ci_workflow src/manifests_workflow tests/tests_manifests_workflow' + entry: bash -c 'pipenv run mypy .' language: system - id: pytest stages: [commit] diff --git a/src/build_workflow/build_recorder.py b/src/build_workflow/build_recorder.py index 3e6fcee5e5..d3118a8513 100644 --- a/src/build_workflow/build_recorder.py +++ b/src/build_workflow/build_recorder.py @@ -16,7 +16,7 @@ class BuildRecorder: - def __init__(self, target: BuildTarget): + def __init__(self, target: BuildTarget) -> None: self.build_manifest = self.BuildManifestBuilder(target) self.target = target self.name = target.name @@ -52,7 +52,7 @@ def write_manifest(self) -> None: logging.info(f"Created build manifest {manifest_path}") class BuildManifestBuilder: - def __init__(self, target: BuildTarget): + def __init__(self, target: BuildTarget) -> None: self.data: Dict[str, Any] = {} self.data["build"] = {} self.data["build"]["id"] = target.build_id diff --git a/src/build_workflow/build_target.py b/src/build_workflow/build_target.py index 0c8fda75ca..410f8add23 100644 --- a/src/build_workflow/build_target.py +++ b/src/build_workflow/build_target.py @@ -34,7 +34,7 @@ def __init__( snapshot: bool = True, build_id: str = None, output_dir: str = "artifacts", - ): + ) -> None: self.build_id = os.getenv("BUILD_NUMBER") or build_id or uuid.uuid4().hex self.name = name self.version = version diff --git a/src/build_workflow/builder.py b/src/build_workflow/builder.py index 6a96cb3e17..dd3e70e4df 100644 --- a/src/build_workflow/builder.py +++ b/src/build_workflow/builder.py @@ -12,6 +12,10 @@ class Builder(ABC): + component: Any + target: BuildTarget + output_path: str + def __init__(self, component: Any, target: BuildTarget) -> None: self.output_path = "builds" self.component = component diff --git a/src/ci_workflow/ci_check_list_source.py b/src/ci_workflow/ci_check_list_source.py index 1d9467aba5..a2ada40218 100644 --- a/src/ci_workflow/ci_check_list_source.py +++ b/src/ci_workflow/ci_check_list_source.py @@ -31,7 +31,7 @@ def checkout(self, work_dir: str) -> None: } class InvalidCheckError(Exception): - def __init__(self, check: Any): + def __init__(self, check: Any) -> None: self.check = check super().__init__(f"Invalid check: {check.name}, must be one of {CiCheckListSource.CHECKS.keys()}.") diff --git a/src/manifests/build/build_manifest_1_0.py b/src/manifests/build/build_manifest_1_0.py index 78d4ed0cfe..fc46829fc9 100644 --- a/src/manifests/build/build_manifest_1_0.py +++ b/src/manifests/build/build_manifest_1_0.py @@ -4,8 +4,6 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. -from typing import Any - from manifests.component_manifest import Component, ComponentManifest, Components """ @@ -75,7 +73,7 @@ class BuildManifest_1_0(ComponentManifest['BuildManifest_1_0', 'BuildComponents_ }, } - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.build = self.Build(data["build"]) self.components = BuildComponents_1_0(data.get("components", [])) # type: ignore[assignment] @@ -88,7 +86,7 @@ def __to_dict__(self) -> dict: } class Build: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name: str = data["name"] self.version = data["version"] self.architecture = data["architecture"] @@ -109,12 +107,12 @@ def filename(self) -> str: class BuildComponents_1_0(Components['BuildComponent_1_0']): @classmethod - def __create__(self, data: Any) -> 'BuildComponent_1_0': + def __create__(self, data: dict) -> 'BuildComponent_1_0': return BuildComponent_1_0(data) class BuildComponent_1_0(Component): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.repository = data["repository"] self.ref = data["ref"] diff --git a/src/manifests/build/build_manifest_1_1.py b/src/manifests/build/build_manifest_1_1.py index 586e43f73d..a5512382ca 100644 --- a/src/manifests/build/build_manifest_1_1.py +++ b/src/manifests/build/build_manifest_1_1.py @@ -4,8 +4,6 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. -from typing import Any - from manifests.component_manifest import Component, ComponentManifest, Components """ @@ -76,7 +74,7 @@ class BuildManifest_1_1(ComponentManifest['BuildManifest_1_1', 'BuildComponents_ }, } - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.build = self.Build(data["build"]) self.components = BuildComponents_1_1(data.get("components", [])) # type: ignore[assignment] @@ -89,7 +87,7 @@ def __to_dict__(self) -> dict: } class Build: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name: str = data["name"] self.version = data["version"] self.architecture = data["architecture"] @@ -110,12 +108,12 @@ def filename(self) -> str: class BuildComponents_1_1(Components['BuildComponent_1_1']): @classmethod - def __create__(self, data: Any) -> 'BuildComponent_1_1': + def __create__(self, data: dict) -> 'BuildComponent_1_1': return BuildComponent_1_1(data) class BuildComponent_1_1(Component): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.repository = data["repository"] self.ref = data["ref"] diff --git a/src/manifests/build_manifest.py b/src/manifests/build_manifest.py index 53a9de770a..ed4bdf4202 100644 --- a/src/manifests/build_manifest.py +++ b/src/manifests/build_manifest.py @@ -4,8 +4,6 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. -from typing import Any - from manifests.build.build_manifest_1_0 import BuildManifest_1_0 from manifests.build.build_manifest_1_1 import BuildManifest_1_1 from manifests.component_manifest import Component, ComponentManifest, Components @@ -89,7 +87,7 @@ class BuildManifest(ComponentManifest['BuildManifest', 'BuildComponents']): }, } - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.build = self.Build(data["build"]) self.components = BuildComponents(data.get("components", [])) # type: ignore[assignment] @@ -102,7 +100,7 @@ def __to_dict__(self) -> dict: } class Build: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name: str = data["name"] self.version: str = data["version"] self.platform: str = data["platform"] @@ -127,12 +125,12 @@ def filename(self) -> str: class BuildComponents(Components['BuildComponent']): @classmethod - def __create__(self, data: Any) -> 'BuildComponent': + def __create__(self, data: dict) -> 'BuildComponent': return BuildComponent(data) class BuildComponent(Component): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.repository = data["repository"] self.ref = data["ref"] diff --git a/src/manifests/bundle/bundle_manifest_1_0.py b/src/manifests/bundle/bundle_manifest_1_0.py index 2284f38e0a..1f69378307 100644 --- a/src/manifests/bundle/bundle_manifest_1_0.py +++ b/src/manifests/bundle/bundle_manifest_1_0.py @@ -4,8 +4,6 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. -from typing import Any - from manifests.component_manifest import Component, ComponentManifest, Components @@ -59,7 +57,7 @@ class BundleManifest_1_0(ComponentManifest['BundleManifest_1_0', 'BundleComponen }, } - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.build = self.Build(data["build"]) self.components = BundleComponents_1_0(data.get("components", [])) # type: ignore[assignment] @@ -72,7 +70,7 @@ def __to_dict__(self) -> dict: } class Build: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name = data["name"] self.version = data["version"] self.architecture = data["architecture"] @@ -91,12 +89,12 @@ def __to_dict__(self) -> dict: class BundleComponents_1_0(Components): @classmethod - def __create__(self, data: Any) -> 'BundleComponent_1_0': + def __create__(self, data: dict) -> 'BundleComponent_1_0': return BundleComponent_1_0(data) class BundleComponent_1_0(Component): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.repository = data["repository"] self.ref = data["ref"] diff --git a/src/manifests/bundle_manifest.py b/src/manifests/bundle_manifest.py index 6c3e538eea..68b49d9ba7 100644 --- a/src/manifests/bundle_manifest.py +++ b/src/manifests/bundle_manifest.py @@ -4,7 +4,7 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. -from typing import Any, Dict +from typing import Dict from manifests.bundle.bundle_manifest_1_0 import BundleManifest_1_0 from manifests.component_manifest import Component, ComponentManifest, Components @@ -65,7 +65,7 @@ class BundleManifest(ComponentManifest['BundleManifest', 'BundleComponents']): }, } - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: super().__init__(data) self.build = self.Build(data["build"]) self.components = BundleComponents(data.get("components", [])) # type: ignore[assignment] @@ -78,7 +78,7 @@ def __to_dict__(self) -> dict: } class Build: - def __init__(self, data: Dict[str, str]): + def __init__(self, data: Dict[str, str]) -> None: self.name = data["name"] self.version = data["version"] self.platform = data["platform"] @@ -105,12 +105,12 @@ def filename(self) -> str: class BundleComponents(Components['BundleComponent']): @classmethod - def __create__(self, data: Any) -> 'BundleComponent': + def __create__(self, data: dict) -> 'BundleComponent': return BundleComponent(data) class BundleComponent(Component): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.repository = data["repository"] self.ref = data["ref"] diff --git a/src/manifests/component_manifest.py b/src/manifests/component_manifest.py index 4591f80eb3..453f0863bd 100644 --- a/src/manifests/component_manifest.py +++ b/src/manifests/component_manifest.py @@ -26,7 +26,7 @@ class ComponentManifest(Manifest[ManifestType], Generic[ManifestType, Components } } - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: super().__init__(data) self.components = Components(data.get("components", [])) # type: ignore[assignment] @@ -44,7 +44,7 @@ def __init__(self, data: Dict[Any, Any]) -> None: super().__init__(map(create_component, data)) @classmethod - def __create__(self, data: Any) -> ComponentType: + def __create__(self, data: dict) -> ComponentType: return Component(data) # type: ignore[return-value] def __to_dict__(self) -> List[Dict[Any, Any]]: diff --git a/src/manifests/distribution.py b/src/manifests/distribution.py index e41a763caa..5fc78a5711 100644 --- a/src/manifests/distribution.py +++ b/src/manifests/distribution.py @@ -4,7 +4,7 @@ class DistributionNotFound(Exception): - def __init__(self, urls: List[str]): + def __init__(self, urls: List[str]) -> None: self.urls = urls super().__init__(f"Unable to find a distribution under urls {self.urls}") diff --git a/src/manifests/input_manifest.py b/src/manifests/input_manifest.py index cd232dbc99..2f0fd71b01 100644 --- a/src/manifests/input_manifest.py +++ b/src/manifests/input_manifest.py @@ -39,7 +39,7 @@ import copy import itertools import logging -from typing import Any, Callable, Iterator, List, Optional +from typing import Callable, Iterator, List, Optional from git.git_repository import GitRepository from manifests.component_manifest import Component, ComponentManifest, Components @@ -101,7 +101,7 @@ class InputManifest(ComponentManifest['InputManifest', 'InputComponents']): }, } - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.build = self.Build(data["build"]) @@ -123,14 +123,14 @@ def stable(self) -> 'InputManifest': return manifest class Ci: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.image = None if data is None else self.Image(data.get("image", None)) def __to_dict__(self) -> Optional[dict]: return None if self.image is None else {"image": self.image.__to_dict__()} class Image: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name = data["name"] self.args = data.get("args", None) @@ -141,7 +141,7 @@ def __to_dict__(self) -> dict: } class Build: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name: str = data["name"] self.version = data["version"] self.qualifier = data.get("qualifier", None) @@ -168,7 +168,7 @@ def filename(self) -> str: class InputComponents(Components['InputComponent']): @classmethod - def __create__(self, data: Any) -> 'InputComponent': + def __create__(self, data: dict) -> 'InputComponent': return InputComponent._from(data) # type: ignore[no-any-return] def __stabilize__(self) -> None: @@ -199,13 +199,13 @@ def select(self, focus: List[str] = [], platform: str = None) -> Iterator['Input class InputComponent(Component): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.platforms = data.get("platforms", None) self.checks = list(map(lambda entry: Check(entry), data.get("checks", []))) @classmethod - def _from(self, data: Any) -> 'InputComponent': + def _from(self, data: dict) -> 'InputComponent': if "repository" in data: return InputComponentFromSource(data) elif "dist" in data: @@ -232,7 +232,7 @@ def __stabilize__(self) -> None: class InputComponentFromSource(InputComponent): - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: super().__init__(data) self.repository = data["repository"] self.ref = data["ref"] @@ -255,7 +255,7 @@ def __to_dict__(self) -> dict: class InputComponentFromDist(InputComponent): - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: super().__init__(data) self.dist = data["dist"] @@ -269,7 +269,7 @@ def __to_dict__(self) -> dict: class Check: - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: if isinstance(data, dict): if len(data) != 1: raise ValueError(f"Invalid check format: {data}") diff --git a/src/manifests/manifest.py b/src/manifests/manifest.py index 56c531e862..1079a92fff 100644 --- a/src/manifests/manifest.py +++ b/src/manifests/manifest.py @@ -107,7 +107,7 @@ def to_file(self, path: str) -> None: ) @abstractmethod - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: self.validate(data) self.version = str(data["schema-version"]) @@ -115,7 +115,7 @@ def __init__(self, data: Any) -> None: def schema(self) -> Any: return self.SCHEMA - def validate(self, data: Any) -> None: + def validate(self, data: dict) -> None: v = Validator(self.schema) if not v.validate(data): raise ValueError(f"Invalid manifest schema: {v.errors}") diff --git a/src/manifests/manifests.py b/src/manifests/manifests.py index 3a811b5910..38b5e86314 100644 --- a/src/manifests/manifests.py +++ b/src/manifests/manifests.py @@ -16,7 +16,7 @@ class Manifests(SortedDict, Generic[T]): - def __init__(self, klass: Any, files: List[str]): + def __init__(self, klass: Any, files: List[str]) -> None: super(Manifests, self).__init__() self.klass = klass self.__append__(files) diff --git a/src/manifests/test_manifest.py b/src/manifests/test_manifest.py index df49318b49..0a11f11866 100644 --- a/src/manifests/test_manifest.py +++ b/src/manifests/test_manifest.py @@ -4,7 +4,7 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. -from typing import Any, Optional +from typing import Optional from manifests.component_manifest import Component, ComponentManifest, Components @@ -77,7 +77,7 @@ class TestManifest(ComponentManifest['TestManifest', 'TestComponents']): }, } - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: super().__init__(data) self.name = str(data["name"]) self.ci = self.Ci(data.get("ci", None)) @@ -92,14 +92,14 @@ def __to_dict__(self) -> dict: } class Ci: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.image = None if data is None else self.Image(data.get("image", None)) def __to_dict__(self) -> Optional[dict]: return None if self.image is None else {"image": self.image.__to_dict__()} class Image: - def __init__(self, data: Any): + def __init__(self, data: dict) -> None: self.name = data["name"] self.args = data.get("args", None) @@ -112,12 +112,12 @@ def __to_dict__(self) -> dict: class TestComponents(Components['TestComponent']): @classmethod - def __create__(self, data: Any) -> 'TestComponent': + def __create__(self, data: dict) -> 'TestComponent': return TestComponent(data) class TestComponent(Component): - def __init__(self, data: Any) -> None: + def __init__(self, data: dict) -> None: super().__init__(data) self.working_directory = data.get("working-directory", None) self.integ_test = data.get("integ-test", None) @@ -135,4 +135,5 @@ def __to_dict__(self) -> dict: TestManifest.VERSIONS = {"1.0": TestManifest} +TestComponent.__test__ = False # type: ignore[attr-defined] TestManifest.__test__ = False # type: ignore[attr-defined] diff --git a/src/run_build.py b/src/run_build.py index 923d22434a..694a2fa754 100755 --- a/src/run_build.py +++ b/src/run_build.py @@ -20,7 +20,7 @@ from system.temporary_directory import TemporaryDirectory -def main(): +def main() -> int: args = BuildArgs() console.configure(level=args.logging_level) manifest = InputManifest.from_file(args.manifest) @@ -36,7 +36,7 @@ def main(): else: logging.info(f"Creating {args.ref_manifest}") manifest.to_file(args.ref_manifest) - exit(0) + return 0 output_dir = BuildOutputDir(manifest.build.filename, args.distribution).dir @@ -74,6 +74,7 @@ def main(): build_recorder.write_manifest() logging.info("Done.") + return 0 if __name__ == "__main__": diff --git a/src/run_bwc_test.py b/src/run_bwc_test.py index 6ed4e717f7..190d333e24 100755 --- a/src/run_bwc_test.py +++ b/src/run_bwc_test.py @@ -13,7 +13,7 @@ from test_workflow.test_args import TestArgs -def main(): +def main() -> int: args = TestArgs() # Any logging.info call preceding to next line in the execution chain will make the console output not displaying logs in console. @@ -26,7 +26,9 @@ def main(): all_results.log() if all_results.failed(): - sys.exit(1) + return 1 + else: + return 0 if __name__ == "__main__": diff --git a/src/run_checkout.py b/src/run_checkout.py index 6da2a32a98..aa1cb94d48 100755 --- a/src/run_checkout.py +++ b/src/run_checkout.py @@ -12,12 +12,12 @@ from checkout_workflow.checkout_args import CheckoutArgs from git.git_repository import GitRepository -from manifests.input_manifest import InputManifest +from manifests.input_manifest import InputComponentFromSource, InputManifest from system import console from system.temporary_directory import TemporaryDirectory -def main(): +def main() -> int: args = CheckoutArgs() console.configure(level=args.logging_level) manifest = InputManifest.from_file(args.manifest) @@ -27,16 +27,17 @@ def main(): for component in manifest.components.select(): logging.info(f"Checking out {component.name}") - - with GitRepository( - component.repository, - component.ref, - os.path.join(work_dir.name, component.name), - component.working_directory, - ) as repo: - logging.debug(f"Checked out {component.name} into {repo.dir}") + if type(component) is InputComponentFromSource: + with GitRepository( + component.repository, + component.ref, + os.path.join(work_dir.name, component.name), + component.working_directory, + ) as repo: + logging.debug(f"Checked out {component.name} into {repo.dir}") logging.info(f"Done, checked out into {work_dir.name}.") + return 0 if __name__ == "__main__": diff --git a/src/run_ci.py b/src/run_ci.py index 0c32971a28..4f3c2ab171 100755 --- a/src/run_ci.py +++ b/src/run_ci.py @@ -14,11 +14,11 @@ from system import console -def main(): +def main() -> int: args = CiArgs() console.configure(level=args.logging_level) - CiManifests.from_file(args.manifest, args).check() + return 0 if __name__ == "__main__": diff --git a/src/run_integ_test.py b/src/run_integ_test.py index 75d619e3c8..548f0d24cc 100755 --- a/src/run_integ_test.py +++ b/src/run_integ_test.py @@ -13,7 +13,7 @@ from test_workflow.test_args import TestArgs -def main(): +def main() -> int: args = TestArgs() # Any logging.info call preceding to next line in the execution chain will make the console output not displaying logs in console. @@ -26,7 +26,9 @@ def main(): all_results.log() if all_results.failed(): - sys.exit(1) + return 1 + else: + return 0 if __name__ == "__main__": diff --git a/src/run_manifests.py b/src/run_manifests.py index 7043e28115..0ae79fdfe4 100755 --- a/src/run_manifests.py +++ b/src/run_manifests.py @@ -13,7 +13,7 @@ from system import console -def main(): +def main() -> int: args = ManifestsArgs() console.configure(level=args.logging_level) @@ -26,6 +26,7 @@ def main(): klass().update(keep=args.keep) logging.info("Done.") + return 0 if __name__ == "__main__": diff --git a/src/run_perf_test.py b/src/run_perf_test.py index bc33851fa9..694f5a449f 100644 --- a/src/run_perf_test.py +++ b/src/run_perf_test.py @@ -12,7 +12,7 @@ from test_workflow.perf_test.perf_test_runners import PerfTestRunners -def main(): +def main() -> int: """ Entry point for Performance Test with bundle manifest, config file containing the required arguments for running rally test and the stack name for the cluster. Will call out in test.sh with perf as argument @@ -20,6 +20,7 @@ def main(): perf_args = PerfArgs() manifest = BundleManifest.from_file(perf_args.bundle_manifest) PerfTestRunners.from_args(perf_args, manifest).run() + return 0 if __name__ == "__main__": diff --git a/src/run_sign.py b/src/run_sign.py index b06031fe88..e9716c4d7a 100755 --- a/src/run_sign.py +++ b/src/run_sign.py @@ -14,7 +14,7 @@ from system import console -def main(): +def main() -> int: args = SignArgs() console.configure(level=args.logging_level) @@ -28,6 +28,7 @@ def main(): ) sign.sign() + return 0 if __name__ == "__main__": diff --git a/src/sign_workflow/sign_artifacts.py b/src/sign_workflow/sign_artifacts.py index 2a80b6f5dc..7355926d8b 100644 --- a/src/sign_workflow/sign_artifacts.py +++ b/src/sign_workflow/sign_artifacts.py @@ -10,13 +10,20 @@ import os from abc import abstractmethod from pathlib import Path -from typing import List +from typing import Any, List, Type from manifests.build_manifest import BuildManifest +from sign_workflow.signer import Signer class SignArtifacts: - def __init__(self, target: Path, components: List[str], artifact_type, signature_type, signer): + target: Path + component: str + artifact_type: str + signature_type: str + signer: Signer + + def __init__(self, target: Path, components: List[str], artifact_type: str, signature_type: str, signer: Signer) -> None: self.target = target self.components = components self.artifact_type = artifact_type @@ -24,21 +31,21 @@ def __init__(self, target: Path, components: List[str], artifact_type, signature self.signer = signer @abstractmethod - def __sign__(self): + def __sign__(self) -> None: pass - def sign(self): + def sign(self) -> None: self.__sign__() logging.info("Done.") - def __sign_artifacts__(self, artifacts, basepath): + def __sign_artifacts__(self, artifacts: List[str], basepath: Path) -> None: self.signer.sign_artifacts(artifacts, basepath, self.signature_type) - def __sign_artifact__(self, artifact, basepath): + def __sign_artifact__(self, artifact: str, basepath: Path) -> None: self.signer.sign_artifact(artifact, basepath, self.signature_type) @classmethod - def __signer_class__(self, path: Path): + def __signer_class__(self, path: Path) -> Type[Any]: if path.is_dir(): return SignExistingArtifactsDir elif path.suffix == ".yml": @@ -47,14 +54,13 @@ def __signer_class__(self, path: Path): return SignArtifactsExistingArtifactFile @classmethod - def from_path(self, path: Path, components: List[str], artifact_type, signature_type, signer): + def from_path(self, path: Path, components: List[str], artifact_type: str, signature_type: str, signer: Signer) -> Any: klass = self.__signer_class__(path) return klass(path, components, artifact_type, signature_type, signer) class SignWithBuildManifest(SignArtifacts): - - def __sign__(self): + def __sign__(self) -> None: manifest = BuildManifest.from_file(self.target.open("r")) basepath = self.target.parent for component in manifest.components.select(focus=self.components): @@ -68,15 +74,13 @@ def __sign__(self): class SignArtifactsExistingArtifactFile(SignArtifacts): - - def __sign__(self): + def __sign__(self) -> None: artifacts = self.target.name basename = self.target.parent super().__sign_artifact__(artifacts, basename) class SignExistingArtifactsDir(SignArtifacts): - - def __sign__(self): + def __sign__(self) -> None: for subdir, dirs, files in os.walk(self.target): - super().__sign_artifacts__(files, subdir) + super().__sign_artifacts__(files, Path(subdir)) diff --git a/src/sign_workflow/signer.py b/src/sign_workflow/signer.py index 7652ae17c0..ab9f6e06f0 100644 --- a/src/sign_workflow/signer.py +++ b/src/sign_workflow/signer.py @@ -8,6 +8,8 @@ import logging import os +from pathlib import Path +from typing import List from git.git_repository import GitRepository @@ -18,47 +20,49 @@ class Signer: + git_repo: GitRepository + ACCEPTED_FILE_TYPES = [".zip", ".jar", ".war", ".pom", ".module", ".tar.gz", ".whl", ".crate", ".rpm"] - def __init__(self): + def __init__(self) -> None: self.git_repo = GitRepository(self.get_repo_url(), "HEAD", working_subdirectory="src") self.git_repo.execute("./bootstrap") self.git_repo.execute("rm config.cfg") - def sign_artifact(self, artifact, basepath, signature_type): + def sign_artifact(self, artifact: str, basepath: Path, signature_type: str) -> None: if not self.is_valid_file_type(artifact): logging.info(f"Skipping signing of file {artifact}") return self.generate_signature_and_verify(artifact, basepath, signature_type) - def sign_artifacts(self, artifacts, basepath, signature_type): + def sign_artifacts(self, artifacts: List[str], basepath: Path, signature_type: str) -> None: for artifact in artifacts: if not self.is_valid_file_type(artifact): logging.info(f"Skipping signing of file {artifact}") continue self.generate_signature_and_verify(artifact, basepath, signature_type) - def generate_signature_and_verify(self, artifact, basepath, signature_type): + def generate_signature_and_verify(self, artifact: str, basepath: Path, signature_type: str) -> None: location = os.path.join(basepath, artifact) self.sign(location, signature_type) self.verify(location + signature_type) - def is_valid_file_type(self, file_name): + def is_valid_file_type(self, file_name: str) -> bool: return any( file_name.endswith(x) for x in Signer.ACCEPTED_FILE_TYPES ) - def get_repo_url(self): + def get_repo_url(self) -> str: if "GITHUB_TOKEN" in os.environ: return "https://${GITHUB_TOKEN}@github.com/opensearch-project/opensearch-signer-client.git" return "https://github.com/opensearch-project/opensearch-signer-client.git" - def __remove_existing_signature__(self, signature_file): + def __remove_existing_signature__(self, signature_file: str) -> None: if os.path.exists(signature_file): logging.warning(f"Removing existing signature file {signature_file}") os.remove(signature_file) - def sign(self, filename, signature_type): + def sign(self, filename: str, signature_type: str) -> None: signature_file = filename + signature_type self.__remove_existing_signature__(signature_file) signing_cmd = [ @@ -72,6 +76,6 @@ def sign(self, filename, signature_type): ] self.git_repo.execute(" ".join(signing_cmd)) - def verify(self, filename): + def verify(self, filename: str) -> None: verify_cmd = ["gpg", "--verify-files", filename] self.git_repo.execute(" ".join(verify_cmd)) diff --git a/src/system/temporary_directory.py b/src/system/temporary_directory.py index 5931dc7c95..aff46393d8 100644 --- a/src/system/temporary_directory.py +++ b/src/system/temporary_directory.py @@ -10,6 +10,7 @@ import shutil import stat import tempfile +from pathlib import Path from types import FunctionType from typing import Any @@ -24,7 +25,7 @@ def g__handleRemoveReadonly(func: FunctionType, path: str, exc: Any) -> Any: class TemporaryDirectory: - def __init__(self, keep: bool = False, chdir: bool = False): + def __init__(self, keep: bool = False, chdir: bool = False) -> None: self.keep = keep self.name = tempfile.mkdtemp() if chdir: @@ -33,6 +34,10 @@ def __init__(self, keep: bool = False, chdir: bool = False): else: self.curdir = None + @property + def path(self) -> Path: + return Path(self.name) + def __enter__(self) -> 'TemporaryDirectory': return self diff --git a/src/test_workflow/bwc_test/bwc_test_runner.py b/src/test_workflow/bwc_test/bwc_test_runner.py index 1c851250bb..6cc7409827 100644 --- a/src/test_workflow/bwc_test/bwc_test_runner.py +++ b/src/test_workflow/bwc_test/bwc_test_runner.py @@ -7,29 +7,41 @@ import abc import logging import os +from pathlib import Path +from manifests.build_manifest import BuildComponent, BuildComponents +from manifests.test_manifest import TestComponent, TestManifest from system.temporary_directory import TemporaryDirectory +from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite +from test_workflow.test_args import TestArgs from test_workflow.test_recorder.test_recorder import TestRecorder from test_workflow.test_result.test_suite_results import TestSuiteResults class BwcTestRunner(abc.ABC): - def __init__(self, args, test_manifest): + args: TestArgs + test_manifest: TestManifest + test_dir: str + test_recorder: TestRecorder + components: BuildComponents + + def __init__(self, args: TestArgs, test_manifest: TestManifest, components: BuildComponents) -> None: self.args = args self.test_manifest = test_manifest + self.components = components self.tests_dir = os.path.join(os.getcwd(), "test-results") os.makedirs(self.tests_dir, exist_ok=True) self.test_recorder = TestRecorder(self.args.test_run_id, "bwc-test", self.tests_dir) - def run(self): + def run(self) -> TestSuiteResults: with TemporaryDirectory(keep=self.args.keep, chdir=True) as work_dir: all_results = TestSuiteResults() for component in self.components.select(focus=self.args.components): if component.name in self.test_manifest.components: test_config = self.test_manifest.components[component.name] if test_config.bwc_test: - test_suite = self.__create_test_suite__(component, test_config, work_dir) + test_suite = self.__create_test_suite__(component, test_config, work_dir.path) test_results = test_suite.execute_tests() all_results.append(component.name, test_results) else: @@ -38,3 +50,7 @@ def run(self): logging.info(f"Skipping bwc-tests for {component.name}, as it is currently not declared in the test manifest") return all_results + + @abc.abstractmethod + def __create_test_suite__(self, component: BuildComponent, test_config: TestComponent, work_dir: Path) -> BwcTestSuite: + pass diff --git a/src/test_workflow/bwc_test/bwc_test_runner_opensearch.py b/src/test_workflow/bwc_test/bwc_test_runner_opensearch.py index c4e9d69529..dcf4712ad9 100644 --- a/src/test_workflow/bwc_test/bwc_test_runner_opensearch.py +++ b/src/test_workflow/bwc_test/bwc_test_runner_opensearch.py @@ -6,27 +6,27 @@ import logging import os +from pathlib import Path +from typing import Any -from manifests.test_manifest import TestManifest +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.bwc_test.bwc_test_runner import BwcTestRunner from test_workflow.bwc_test.bwc_test_start_properties_opensearch import BwcTestStartPropertiesOpenSearch +from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite from test_workflow.bwc_test.bwc_test_suite_opensearch import BwcTestSuiteOpenSearch from test_workflow.test_args import TestArgs class BwcTestRunnerOpenSearch(BwcTestRunner): - def __init__(self, args: TestArgs, test_manifest: TestManifest): - super().__init__(args, test_manifest) + def __init__(self, args: TestArgs, test_manifest: TestManifest) -> None: self.properties = BwcTestStartPropertiesOpenSearch(args.paths.get("opensearch", os.getcwd())) - - self.components = self.properties.build_manifest.components - + super().__init__(args, test_manifest, self.properties.build_manifest.components) logging.info("Entering BWC test for OpenSearch") - def __create_test_suite__(self, component, test_config, work_dir): + def __create_test_suite__(self, component: Any, test_config: TestComponent, work_dir: Path) -> BwcTestSuite: return BwcTestSuiteOpenSearch( - work_dir.name, + work_dir, component, test_config, self.test_recorder, diff --git a/src/test_workflow/bwc_test/bwc_test_runner_opensearch_dashboards.py b/src/test_workflow/bwc_test/bwc_test_runner_opensearch_dashboards.py index ba7a8c206d..f4cb51eb77 100644 --- a/src/test_workflow/bwc_test/bwc_test_runner_opensearch_dashboards.py +++ b/src/test_workflow/bwc_test/bwc_test_runner_opensearch_dashboards.py @@ -6,26 +6,27 @@ import logging import os +from pathlib import Path -from manifests.test_manifest import TestManifest +from manifests.build_manifest import BuildComponent +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.bwc_test.bwc_test_runner import BwcTestRunner from test_workflow.bwc_test.bwc_test_start_properties_opensearch_dashboards import BwcTestStartPropertiesOpenSearchDashboards +from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite from test_workflow.bwc_test.bwc_test_suite_opensearch_dashboards import BwcTestSuiteOpenSearchDashboards from test_workflow.test_args import TestArgs class BwcTestRunnerOpenSearchDashboards(BwcTestRunner): - def __init__(self, args: TestArgs, test_manifest: TestManifest): - super().__init__(args, test_manifest) + def __init__(self, args: TestArgs, test_manifest: TestManifest) -> None: self.properties = BwcTestStartPropertiesOpenSearchDashboards(args.paths.get("opensearch-dashboards", os.getcwd())) - - self.components = self.properties.build_manifest.components + super().__init__(args, test_manifest, self.properties.build_manifest.components) logging.info("Entering BWC test for OpenSearch Dashboards") - def __create_test_suite__(self, component, test_config, work_dir): + def __create_test_suite__(self, component: BuildComponent, test_config: TestComponent, work_dir: Path) -> BwcTestSuite: return BwcTestSuiteOpenSearchDashboards( - work_dir.name, + work_dir, component, test_config, self.test_recorder, diff --git a/src/test_workflow/bwc_test/bwc_test_runners.py b/src/test_workflow/bwc_test/bwc_test_runners.py index ba4253220e..5689ce076a 100644 --- a/src/test_workflow/bwc_test/bwc_test_runners.py +++ b/src/test_workflow/bwc_test/bwc_test_runners.py @@ -6,6 +6,7 @@ from manifests.test_manifest import TestManifest +from test_workflow.bwc_test.bwc_test_runner import BwcTestRunner from test_workflow.bwc_test.bwc_test_runner_opensearch import BwcTestRunnerOpenSearch from test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards import BwcTestRunnerOpenSearchDashboards from test_workflow.test_args import TestArgs @@ -18,5 +19,5 @@ class BwcTestRunners: } @classmethod - def from_test_manifest(cls, args: TestArgs, test_manifest: TestManifest): + def from_test_manifest(cls, args: TestArgs, test_manifest: TestManifest) -> BwcTestRunner: return cls.RUNNERS[test_manifest.name](args, test_manifest) diff --git a/src/test_workflow/bwc_test/bwc_test_start_properties.py b/src/test_workflow/bwc_test/bwc_test_start_properties.py index e59ddeb4a6..e6553463df 100644 --- a/src/test_workflow/bwc_test/bwc_test_start_properties.py +++ b/src/test_workflow/bwc_test/bwc_test_start_properties.py @@ -12,7 +12,13 @@ class BwcTestStartProperties(abc.ABC): - def __init__(self, path, build_dir, bundle_dir): + path: str + build_dir: str + bundle_dir: str + build_manifest: BuildManifest + bundle_manifest: BundleManifest + + def __init__(self, path: str, build_dir: str, bundle_dir: str) -> None: self.path = path self.build_dir = build_dir self.bundle_dir = bundle_dir diff --git a/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch.py b/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch.py index fc13494eb6..6fed7bdd7c 100644 --- a/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch.py +++ b/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch.py @@ -8,5 +8,5 @@ class BwcTestStartPropertiesOpenSearch(BwcTestStartProperties): - def __init__(self, path): + def __init__(self, path: str) -> None: super().__init__(path, "builds/opensearch/manifest.yml", "dist/opensearch/manifest.yml") diff --git a/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch_dashboards.py b/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch_dashboards.py index 5820dd6575..237b9393fb 100644 --- a/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch_dashboards.py +++ b/src/test_workflow/bwc_test/bwc_test_start_properties_opensearch_dashboards.py @@ -8,5 +8,5 @@ class BwcTestStartPropertiesOpenSearchDashboards(BwcTestStartProperties): - def __init__(self, path): + def __init__(self, path: str) -> None: super().__init__(path, "builds/opensearch-dashboards/manifest.yml", "dist/opensearch-dashboards/manifest.yml") diff --git a/src/test_workflow/bwc_test/bwc_test_suite.py b/src/test_workflow/bwc_test/bwc_test_suite.py index 293f4285e8..5d196aae19 100644 --- a/src/test_workflow/bwc_test/bwc_test_suite.py +++ b/src/test_workflow/bwc_test/bwc_test_suite.py @@ -10,25 +10,37 @@ import abc import logging import os +from pathlib import Path +from typing import Any from git.git_repository import GitRepository +from manifests.bundle_manifest import BundleManifest from paths.script_finder import ScriptFinder from system.execute import execute +from test_workflow.test_recorder.log_recorder import LogRecorder +from test_workflow.test_recorder.test_recorder import TestRecorder from test_workflow.test_recorder.test_result_data import TestResultData from test_workflow.test_result.test_component_results import TestComponentResults from test_workflow.test_result.test_result import TestResult class BwcTestSuite(abc.ABC): + work_dir: Path + component: Any + test_config: Any + test_recorder: TestRecorder + manifest: BundleManifest + repo: GitRepository + save_logs: LogRecorder def __init__( self, - work_dir, - component, - test_config, - test_recorder, - manifest - ): + work_dir: Path, + component: Any, + test_config: Any, + test_recorder: TestRecorder, + manifest: BundleManifest + ) -> None: self.work_dir = work_dir self.component = component self.test_config = test_config @@ -44,7 +56,7 @@ def __init__( self.save_logs = test_recorder.test_results_logs - def execute_tests(self): + def execute_tests(self) -> TestComponentResults: test_results = TestComponentResults() for config in self.test_config.bwc_test["test-configs"]: @@ -53,13 +65,15 @@ def execute_tests(self): test_results.append(TestResult(self.component.name, config, status)) return test_results - def execute_bwctest_sh(self, config): + def execute_bwctest_sh(self, config: str) -> int: security = self.is_security_enabled(config) script = ScriptFinder.find_bwc_test_script(self.component.name, self.repo.working_directory) if os.path.exists(script): cmd = self.get_cmd(script, security, self.manifest.build.location) self.repo_work_dir = os.path.join( - self.repo.dir, self.test_config.working_directory) if self.test_config.working_directory is not None else self.repo.dir + self.repo.dir, + self.test_config.working_directory + ) if self.test_config.working_directory is not None else self.repo.dir (status, stdout, stderr) = execute(cmd, self.repo_work_dir, True, False) test_result_data = TestResultData( @@ -77,25 +91,26 @@ def execute_bwctest_sh(self, config): return status else: logging.info(f"{script} does not exist. Skipping integ tests for {self.component.name}") + return 0 - def is_security_enabled(self, config): + def is_security_enabled(self, config: str) -> bool: if config in ["with-security", "without-security"]: return True if config == "with-security" else False else: raise InvalidTestConfigError("Unsupported test config: " + config) - def pretty_print_message(self, message): + def pretty_print_message(self, message: str) -> None: logging.info("===============================================") logging.info(message) logging.info("===============================================") @abc.abstractmethod - def get_cmd(self): + def get_cmd(self, script: str, security: bool, manifest_build_location: str) -> str: pass @property @abc.abstractmethod - def test_artifact_files(self): + def test_artifact_files(self) -> dict: pass diff --git a/src/test_workflow/bwc_test/bwc_test_suite_opensearch.py b/src/test_workflow/bwc_test/bwc_test_suite_opensearch.py index 45c8429c46..fa2cd70f5e 100644 --- a/src/test_workflow/bwc_test/bwc_test_suite_opensearch.py +++ b/src/test_workflow/bwc_test/bwc_test_suite_opensearch.py @@ -5,21 +5,25 @@ # compatible open source license. import os +from pathlib import Path +from typing import Any +from manifests.bundle_manifest import BundleManifest +from manifests.test_manifest import TestComponent from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite +from test_workflow.test_recorder.test_recorder import TestRecorder class BwcTestSuiteOpenSearch(BwcTestSuite): def __init__( self, - work_dir, - component, - test_config, - test_recorder, - manifest - ): - + work_dir: Path, + component: Any, + test_config: TestComponent, + test_recorder: TestRecorder, + manifest: BundleManifest + ) -> None: super().__init__( work_dir, component, @@ -29,11 +33,11 @@ def __init__( ) # TODO: enable OpenSearch scripts to accept more arguments - def get_cmd(self, script, security, manifest_build_location): + def get_cmd(self, script: str, security: bool, manifest_build_location: str) -> str: return script @property - def test_artifact_files(self): + def test_artifact_files(self) -> dict: return { "opensearch-bwc-test": os.path.join(self.repo_work_dir, "build", "reports", "tests", "bwcTest") } diff --git a/src/test_workflow/bwc_test/bwc_test_suite_opensearch_dashboards.py b/src/test_workflow/bwc_test/bwc_test_suite_opensearch_dashboards.py index e8dea9fa3d..f2c20befee 100644 --- a/src/test_workflow/bwc_test/bwc_test_suite_opensearch_dashboards.py +++ b/src/test_workflow/bwc_test/bwc_test_suite_opensearch_dashboards.py @@ -5,21 +5,25 @@ # compatible open source license. import os +from pathlib import Path +from manifests.build_manifest import BuildComponent +from manifests.bundle_manifest import BundleManifest +from manifests.test_manifest import TestComponent from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite +from test_workflow.test_recorder.test_recorder import TestRecorder class BwcTestSuiteOpenSearchDashboards(BwcTestSuite): def __init__( self, - work_dir, - component, - test_config, - test_recorder, - manifest - ): - + work_dir: Path, + component: BuildComponent, + test_config: TestComponent, + test_recorder: TestRecorder, + manifest: BundleManifest + ) -> None: super().__init__( work_dir, component, @@ -28,11 +32,11 @@ def __init__( manifest ) - def get_cmd(self, script: str, security: bool, manifest_build_location: any): + def get_cmd(self, script: str, security: bool, manifest_build_location: str) -> str: return f"{script} -s {str(security).lower()} -d {manifest_build_location}" @property - def test_artifact_files(self): + def test_artifact_files(self) -> dict: return { "cypress-videos": os.path.join(self.repo_work_dir, "bwc_tmp", "test", "cypress", "videos"), "cypress-screenshots": os.path.join(self.repo_work_dir, "bwc_tmp", "test", "cypress", "screenshots"), diff --git a/src/test_workflow/dependency_installer.py b/src/test_workflow/dependency_installer.py index b7ad413390..0f1c347d76 100644 --- a/src/test_workflow/dependency_installer.py +++ b/src/test_workflow/dependency_installer.py @@ -10,30 +10,38 @@ import os import shutil import urllib +from typing import List, Tuple import validators # type:ignore +from manifests.build_manifest import BuildManifest +from manifests.bundle_manifest import BundleManifest + class DependencyInstaller(abc.ABC): + root_url: str + build_manifest: BuildManifest + bundle_manifest: BundleManifest + """ Provides a dependency installer for the test suites. """ - def __init__(self, root_url, build_manifest, bundle_manifest): + def __init__(self, root_url: str, build_manifest: BuildManifest, bundle_manifest: BundleManifest) -> None: self.root_url = root_url self.build_manifest = build_manifest self.bundle_manifest = bundle_manifest - def download_dist(self, dest): + def download_dist(self, dest: str) -> str: local_path = os.path.realpath(os.path.join(dest, os.path.basename(self.bundle_manifest.build.location))) return self.download_or_copy(self.bundle_manifest.build.location, local_path) - def __source_dest(self, path, category, dest): + def __source_dest(self, path: str, category: str, dest: str) -> Tuple[str, str]: source = "/".join([self.root_url, category, self.build_manifest.build.filename, path]) dest = os.path.realpath(os.path.join(dest, "/".join(path.split("/")[1:]))) return (source, dest) - def download(self, paths, category, dest): + def download(self, paths: List[str], category: str, dest: str) -> None: logging.info(f"Downloading to {dest} ...") with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor: for result in executor.map( @@ -43,7 +51,7 @@ def download(self, paths, category, dest): ): logging.debug(f"Written {result}") - def download_or_copy(self, source, dest): + def download_or_copy(self, source: str, dest: str) -> str: os.makedirs(os.path.dirname(dest), exist_ok=True) if validators.url(source): logging.info(f"Downloading {source} into {dest} ...") diff --git a/src/test_workflow/dependency_installer_opensearch.py b/src/test_workflow/dependency_installer_opensearch.py index e52a781cd6..0a7c5e9fa2 100644 --- a/src/test_workflow/dependency_installer_opensearch.py +++ b/src/test_workflow/dependency_installer_opensearch.py @@ -6,25 +6,27 @@ import os +from manifests.build_manifest import BuildManifest +from manifests.bundle_manifest import BundleManifest from test_workflow.dependency_installer import DependencyInstaller class DependencyInstallerOpenSearch(DependencyInstaller): - def __init__(self, root_url, build_manifest, bundle_manifest): + def __init__(self, root_url: str, build_manifest: BuildManifest, bundle_manifest: BundleManifest) -> None: super().__init__(root_url, build_manifest, bundle_manifest) @property - def maven_local_path(self): + def maven_local_path(self) -> str: return os.path.join(os.path.expanduser("~"), ".m2", "repository") - def install_maven_dependencies(self): + def install_maven_dependencies(self) -> None: for component in self.build_manifest.components.values(): maven_artifacts = component.artifacts.get("maven", None) if maven_artifacts: self.download(maven_artifacts, "builds", self.maven_local_path) - def install_build_dependencies(self, dependency_dict, dest): + def install_build_dependencies(self, dependency_dict: dict, dest: str) -> None: """ Downloads the build dependencies from S3 and puts them on the given custom path for each dependency in the dependencies. diff --git a/src/test_workflow/dependency_installer_opensearch_dashboards.py b/src/test_workflow/dependency_installer_opensearch_dashboards.py index c9e2615219..fe40b193f4 100644 --- a/src/test_workflow/dependency_installer_opensearch_dashboards.py +++ b/src/test_workflow/dependency_installer_opensearch_dashboards.py @@ -4,10 +4,12 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. +from manifests.build_manifest import BuildManifest +from manifests.bundle_manifest import BundleManifest from test_workflow.dependency_installer import DependencyInstaller class DependencyInstallerOpenSearchDashboards(DependencyInstaller): - def __init__(self, root_url, build_manifest, bundle_manifest): + def __init__(self, root_url: str, build_manifest: BuildManifest, bundle_manifest: BundleManifest) -> None: super().__init__(root_url, build_manifest, bundle_manifest) diff --git a/src/test_workflow/integ_test/distribution.py b/src/test_workflow/integ_test/distribution.py index b047c46f16..f40ad5769b 100644 --- a/src/test_workflow/integ_test/distribution.py +++ b/src/test_workflow/integ_test/distribution.py @@ -26,14 +26,14 @@ def install_dir(self) -> str: @property @abstractmethod - def config_dir(self, bundle_name: str) -> str: + def config_dir(self) -> str: """ Return the config directory for the distribution """ pass @abstractmethod - def install(self) -> None: + def install(self, bundle_name: str) -> None: """ The detailed method to install the distribution before start the service """ diff --git a/src/test_workflow/integ_test/integ_test_runner.py b/src/test_workflow/integ_test/integ_test_runner.py index 832dceebc9..7968267e4f 100644 --- a/src/test_workflow/integ_test/integ_test_runner.py +++ b/src/test_workflow/integ_test/integ_test_runner.py @@ -7,22 +7,34 @@ import abc import logging import os +from pathlib import Path +from manifests.component_manifest import Components +from manifests.test_manifest import TestComponent, TestManifest from system.temporary_directory import TemporaryDirectory +from test_workflow.integ_test.integ_test_suite import IntegTestSuite +from test_workflow.test_args import TestArgs from test_workflow.test_recorder.test_recorder import TestRecorder from test_workflow.test_result.test_suite_results import TestSuiteResults class IntegTestRunner(abc.ABC): - def __init__(self, args, test_manifest): + args: TestArgs + test_manifest: TestManifest + tests_dir: str + test_recorder: TestRecorder + components: Components + + def __init__(self, args: TestArgs, test_manifest: TestManifest, components: Components) -> None: self.args = args self.test_manifest = test_manifest + self.components = components self.tests_dir = os.path.join(os.getcwd(), "test-results") os.makedirs(self.tests_dir, exist_ok=True) self.test_recorder = TestRecorder(self.args.test_run_id, "integ-test", self.tests_dir) - def run(self): + def run(self) -> TestSuiteResults: with TemporaryDirectory(keep=self.args.keep, chdir=True) as work_dir: all_results = TestSuiteResults() @@ -30,7 +42,7 @@ def run(self): if component.name in self.test_manifest.components: test_config = self.test_manifest.components[component.name] if test_config.integ_test: - test_suite = self.__create_test_suite__(component, test_config, work_dir) + test_suite = self.__create_test_suite__(component, test_config, work_dir.path) test_results = test_suite.execute_tests() all_results.append(component.name, test_results) else: @@ -39,3 +51,7 @@ def run(self): logging.info(f"Skipping integ-tests for {component.name}, as it is currently not declared in the test manifest") return all_results + + @abc.abstractmethod + def __create_test_suite__(self, component: TestComponent, test_config: TestComponent, work_dir: Path) -> IntegTestSuite: + pass diff --git a/src/test_workflow/integ_test/integ_test_runner_opensearch.py b/src/test_workflow/integ_test/integ_test_runner_opensearch.py index 81f842e97a..c023ebb62c 100644 --- a/src/test_workflow/integ_test/integ_test_runner_opensearch.py +++ b/src/test_workflow/integ_test/integ_test_runner_opensearch.py @@ -6,8 +6,9 @@ import logging import os +from pathlib import Path -from manifests.test_manifest import TestManifest +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.integ_test.integ_test_runner import IntegTestRunner from test_workflow.integ_test.integ_test_start_properties_opensearch import IntegTestStartPropertiesOpenSearch from test_workflow.integ_test.integ_test_suite_opensearch import IntegTestSuiteOpenSearch @@ -15,24 +16,26 @@ class IntegTestRunnerOpenSearch(IntegTestRunner): + properties: IntegTestStartPropertiesOpenSearch - def __init__(self, args: TestArgs, test_manifest: TestManifest): - super().__init__(args, test_manifest) + def __init__(self, args: TestArgs, test_manifest: TestManifest) -> None: self.properties = IntegTestStartPropertiesOpenSearch(args.paths.get("opensearch", os.getcwd())) - self.properties.dependency_installer.install_maven_dependencies() - - self.components = self.properties.bundle_manifest.components - + super().__init__(args, test_manifest, self.properties.bundle_manifest.components) logging.info("Entering integ test for OpenSearch") - def __create_test_suite__(self, component, test_config, work_dir): + def __create_test_suite__( + self, + component: TestComponent, + test_config: TestComponent, + work_dir: Path + ) -> IntegTestSuiteOpenSearch: return IntegTestSuiteOpenSearch( self.properties.dependency_installer, component, test_config, self.properties.bundle_manifest, self.properties.build_manifest, - work_dir.name, + work_dir, self.test_recorder ) diff --git a/src/test_workflow/integ_test/integ_test_runner_opensearch_dashboards.py b/src/test_workflow/integ_test/integ_test_runner_opensearch_dashboards.py index 96935077d2..8eac303034 100644 --- a/src/test_workflow/integ_test/integ_test_runner_opensearch_dashboards.py +++ b/src/test_workflow/integ_test/integ_test_runner_opensearch_dashboards.py @@ -6,8 +6,9 @@ import logging import os +from pathlib import Path -from manifests.test_manifest import TestManifest +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.integ_test.integ_test_runner import IntegTestRunner from test_workflow.integ_test.integ_test_start_properties_opensearch import IntegTestStartPropertiesOpenSearch from test_workflow.integ_test.integ_test_start_properties_opensearch_dashboards import IntegTestStartPropertiesOpenSearchDashboards @@ -16,19 +17,16 @@ class IntegTestRunnerOpenSearchDashboards(IntegTestRunner): + properties: IntegTestStartPropertiesOpenSearchDashboards + properties_dependency: IntegTestStartPropertiesOpenSearch - def __init__(self, args: TestArgs, test_manifest: TestManifest): - super().__init__(args, test_manifest) - + def __init__(self, args: TestArgs, test_manifest: TestManifest) -> None: self.properties_dependency = IntegTestStartPropertiesOpenSearch(args.paths.get("opensearch", os.getcwd())) self.properties = IntegTestStartPropertiesOpenSearchDashboards(args.paths.get("opensearch-dashboards", os.getcwd())) - - self.components = self.properties.build_manifest.components - + super().__init__(args, test_manifest, self.properties.build_manifest.components) logging.info("Entering integ test for OpenSearch Dashboards") - def __create_test_suite__(self, component, test_config, work_dir): - + def __create_test_suite__(self, component: TestComponent, test_config: TestComponent, work_dir: Path) -> IntegTestSuiteOpenSearchDashboards: return IntegTestSuiteOpenSearchDashboards( self.properties_dependency.dependency_installer, self.properties.dependency_installer, @@ -38,6 +36,6 @@ def __create_test_suite__(self, component, test_config, work_dir): self.properties.bundle_manifest, self.properties_dependency.build_manifest, self.properties.build_manifest, - work_dir.name, + work_dir, self.test_recorder ) diff --git a/src/test_workflow/integ_test/integ_test_runners.py b/src/test_workflow/integ_test/integ_test_runners.py index 0af29881c4..d3389b6dd9 100644 --- a/src/test_workflow/integ_test/integ_test_runners.py +++ b/src/test_workflow/integ_test/integ_test_runners.py @@ -6,6 +6,7 @@ from manifests.test_manifest import TestManifest +from test_workflow.integ_test.integ_test_runner import IntegTestRunner from test_workflow.integ_test.integ_test_runner_opensearch import IntegTestRunnerOpenSearch from test_workflow.integ_test.integ_test_runner_opensearch_dashboards import IntegTestRunnerOpenSearchDashboards from test_workflow.test_args import TestArgs @@ -18,5 +19,5 @@ class IntegTestRunners: } @classmethod - def from_test_manifest(cls, args: TestArgs, test_manifest: TestManifest): + def from_test_manifest(cls, args: TestArgs, test_manifest: TestManifest) -> IntegTestRunner: return cls.RUNNERS[test_manifest.name](args, test_manifest) diff --git a/src/test_workflow/integ_test/integ_test_start_properties.py b/src/test_workflow/integ_test/integ_test_start_properties.py index b51ef658e8..10e430d73d 100644 --- a/src/test_workflow/integ_test/integ_test_start_properties.py +++ b/src/test_workflow/integ_test/integ_test_start_properties.py @@ -12,7 +12,11 @@ class IntegTestStartProperties(abc.ABC): - def __init__(self, path, build_dir, bundle_dir): + path: str + build_dir: str + bundle_dir: str + + def __init__(self, path: str, build_dir: str, bundle_dir: str) -> None: self.path = path self.build_dir = build_dir self.bundle_dir = bundle_dir diff --git a/src/test_workflow/integ_test/integ_test_start_properties_opensearch.py b/src/test_workflow/integ_test/integ_test_start_properties_opensearch.py index 0f4860ddc9..f120a2b7b7 100644 --- a/src/test_workflow/integ_test/integ_test_start_properties_opensearch.py +++ b/src/test_workflow/integ_test/integ_test_start_properties_opensearch.py @@ -9,6 +9,8 @@ class IntegTestStartPropertiesOpenSearch(IntegTestStartProperties): - def __init__(self, path): + dependency_installer: DependencyInstallerOpenSearch + + def __init__(self, path: str) -> None: super().__init__(path, "builds/opensearch/manifest.yml", "dist/opensearch/manifest.yml") self.dependency_installer = DependencyInstallerOpenSearch(self.path, self.build_manifest, self.bundle_manifest) diff --git a/src/test_workflow/integ_test/integ_test_start_properties_opensearch_dashboards.py b/src/test_workflow/integ_test/integ_test_start_properties_opensearch_dashboards.py index 412f43db20..2be077f4fd 100644 --- a/src/test_workflow/integ_test/integ_test_start_properties_opensearch_dashboards.py +++ b/src/test_workflow/integ_test/integ_test_start_properties_opensearch_dashboards.py @@ -9,6 +9,8 @@ class IntegTestStartPropertiesOpenSearchDashboards(IntegTestStartProperties): - def __init__(self, path): + dependency_installer: DependencyInstallerOpenSearchDashboards + + def __init__(self, path: str) -> None: super().__init__(path, "builds/opensearch-dashboards/manifest.yml", "dist/opensearch-dashboards/manifest.yml") self.dependency_installer = DependencyInstallerOpenSearchDashboards(self.path, self.build_manifest, self.bundle_manifest) diff --git a/src/test_workflow/integ_test/integ_test_suite.py b/src/test_workflow/integ_test/integ_test_suite.py index ac0013fb56..8c016ac51b 100644 --- a/src/test_workflow/integ_test/integ_test_suite.py +++ b/src/test_workflow/integ_test/integ_test_suite.py @@ -7,14 +7,33 @@ import abc import logging import os +from pathlib import Path +from typing import Any, Dict from git.git_repository import GitRepository +from manifests.build_manifest import BuildManifest +from manifests.bundle_manifest import BundleManifest from paths.script_finder import ScriptFinder from system.execute import execute +from test_workflow.dependency_installer import DependencyInstaller +from test_workflow.test_recorder.log_recorder import LogRecorder +from test_workflow.test_recorder.test_recorder import TestRecorder from test_workflow.test_recorder.test_result_data import TestResultData +from test_workflow.test_result.test_component_results import TestComponentResults class IntegTestSuite(abc.ABC): + work_dir: Path + component: Any + test_config: Any + test_recorder: TestRecorder + dependency_installer: DependencyInstaller + bundle_manifest: BundleManifest + build_manifest: BuildManifest + repo: GitRepository + save_logs: LogRecorder + additional_cluster_config: dict + """ Kicks off integration tests for a component based on test configurations provided in test_support_matrix.yml @@ -22,14 +41,14 @@ class IntegTestSuite(abc.ABC): def __init__( self, - work_dir, - component, - test_config, - test_recorder, - dependency_installer, - bundle_manifest, - build_manifest - ): + work_dir: Path, + component: Any, + test_config: Any, + test_recorder: TestRecorder, + dependency_installer: DependencyInstaller, + bundle_manifest: BundleManifest, + build_manifest: BuildManifest + ) -> None: self.work_dir = work_dir self.component = component self.test_config = test_config @@ -50,10 +69,10 @@ def __init__( self.additional_cluster_config = None @abc.abstractmethod - def execute_tests(self): + def execute_tests(self) -> TestComponentResults: pass - def execute_integtest_sh(self, endpoint, port, security, test_config): + def execute_integtest_sh(self, endpoint: str, port: int, security: bool, test_config: str) -> int: script = ScriptFinder.find_integ_test_script(self.component.name, self.repo.working_directory) if os.path.exists(script): cmd = f"{script} -b {endpoint} -p {port} -s {str(security).lower()} -v {self.bundle_manifest.build.version}" @@ -76,21 +95,22 @@ def execute_integtest_sh(self, endpoint, port, security, test_config): return status else: logging.info(f"{script} does not exist. Skipping integ tests for {self.component.name}") + return 0 - def is_security_enabled(self, config): + def is_security_enabled(self, config: str) -> bool: if config in ["with-security", "without-security"]: return True if config == "with-security" else False else: raise InvalidTestConfigError("Unsupported test config: " + config) - def pretty_print_message(self, message): + def pretty_print_message(self, message: str) -> None: logging.info("===============================================") logging.info(message) logging.info("===============================================") @property @abc.abstractmethod - def test_artifact_files(self): + def test_artifact_files(self) -> Dict[str, str]: pass diff --git a/src/test_workflow/integ_test/integ_test_suite_opensearch.py b/src/test_workflow/integ_test/integ_test_suite_opensearch.py index 3dee5970f5..3a3fb5c89d 100644 --- a/src/test_workflow/integ_test/integ_test_suite_opensearch.py +++ b/src/test_workflow/integ_test/integ_test_suite_opensearch.py @@ -7,25 +7,32 @@ import glob import logging import os +from pathlib import Path +from typing import Any +from manifests.build_manifest import BuildManifest +from manifests.bundle_manifest import BundleManifest +from test_workflow.dependency_installer_opensearch import DependencyInstallerOpenSearch from test_workflow.integ_test.integ_test_suite import IntegTestSuite, InvalidTestConfigError from test_workflow.integ_test.local_test_cluster import LocalTestCluster +from test_workflow.test_recorder.test_recorder import TestRecorder from test_workflow.test_result.test_component_results import TestComponentResults from test_workflow.test_result.test_result import TestResult class IntegTestSuiteOpenSearch(IntegTestSuite): + dependency_installer: DependencyInstallerOpenSearch def __init__( self, - dependency_installer_opensearch, - component, - test_config, - bundle_manifest_opensearch, - build_manifest_opensearch, - work_dir, - test_recorder - ): + dependency_installer_opensearch: DependencyInstallerOpenSearch, + component: Any, + test_config: Any, + bundle_manifest_opensearch: BundleManifest, + build_manifest_opensearch: BuildManifest, + work_dir: Path, + test_recorder: TestRecorder + ) -> None: super().__init__( work_dir, component, @@ -36,7 +43,7 @@ def __init__( build_manifest_opensearch ) - def execute_tests(self): + def execute_tests(self) -> TestComponentResults: test_results = TestComponentResults() self.__install_build_dependencies() for config in self.test_config.integ_test["test-configs"]: @@ -44,7 +51,7 @@ def execute_tests(self): test_results.append(TestResult(self.component.name, config, status)) return test_results - def __install_build_dependencies(self): + def __install_build_dependencies(self) -> None: if "build-dependencies" in self.test_config.integ_test: dependency_list = self.test_config.integ_test["build-dependencies"] if len(dependency_list) == 1 and "job-scheduler" in dependency_list: @@ -52,14 +59,14 @@ def __install_build_dependencies(self): else: raise InvalidTestConfigError("Integration test job only supports job-scheduler build dependency at present.") - def __copy_job_scheduler_artifact(self): + def __copy_job_scheduler_artifact(self) -> None: custom_local_path = os.path.join(self.repo.dir, "src", "test", "resources", "job-scheduler") for file in glob.glob(os.path.join(custom_local_path, "opensearch-job-scheduler-*.zip")): os.unlink(file) job_scheduler = self.build_manifest.components["job-scheduler"] self.dependency_installer.install_build_dependencies({"opensearch-job-scheduler": job_scheduler.version}, custom_local_path) - def __setup_cluster_and_execute_test_config(self, config): + def __setup_cluster_and_execute_test_config(self, config: str) -> int: security = self.is_security_enabled(config) if "additional-cluster-configs" in self.test_config.integ_test.keys(): self.additional_cluster_config = self.test_config.integ_test.get("additional-cluster-configs") @@ -73,13 +80,13 @@ def __setup_cluster_and_execute_test_config(self, config): security, config, self.test_recorder, - ) as (test_cluster_endpoint, test_cluster_port): + ) as (endpoint, port): self.pretty_print_message("Running integration tests for " + self.component.name) os.chdir(self.work_dir) - return self.execute_integtest_sh(test_cluster_endpoint, test_cluster_port, security, config) + return self.execute_integtest_sh(endpoint, port, security, config) @property - def test_artifact_files(self): + def test_artifact_files(self) -> dict: return { "opensearch-integ-test": os.path.join(self.repo_work_dir, "build", "reports", "tests", "integTest") } diff --git a/src/test_workflow/integ_test/integ_test_suite_opensearch_dashboards.py b/src/test_workflow/integ_test/integ_test_suite_opensearch_dashboards.py index 59e167ee9f..ed6821afa8 100644 --- a/src/test_workflow/integ_test/integ_test_suite_opensearch_dashboards.py +++ b/src/test_workflow/integ_test/integ_test_suite_opensearch_dashboards.py @@ -5,28 +5,38 @@ # compatible open source license. import os +from pathlib import Path +from manifests.build_manifest import BuildManifest +from manifests.bundle_manifest import BundleManifest +from manifests.test_manifest import TestComponent +from test_workflow.dependency_installer_opensearch import DependencyInstallerOpenSearch +from test_workflow.dependency_installer_opensearch_dashboards import DependencyInstallerOpenSearchDashboards from test_workflow.integ_test.integ_test_suite import IntegTestSuite from test_workflow.integ_test.local_test_cluster_opensearch_dashboards import LocalTestClusterOpenSearchDashboards +from test_workflow.test_recorder.test_recorder import TestRecorder from test_workflow.test_result.test_component_results import TestComponentResults from test_workflow.test_result.test_result import TestResult class IntegTestSuiteOpenSearchDashboards(IntegTestSuite): + dependency_installer_opensearch_dashboards: DependencyInstallerOpenSearchDashboards + bundle_manifest_opensearch_dashboards: BundleManifest + build_manifest_opensearch_dashboards: BuildManifest def __init__( self, - dependency_installer_opensearch, - dependency_installer_opensearch_dashboards, - component, - test_config, - bundle_manifest_opensearch, - bundle_manifest_opensearch_dashboards, - build_manifest_opensearch, - build_manifest_opensearch_dashboards, - work_dir, - test_recorder - ): + dependency_installer_opensearch: DependencyInstallerOpenSearch, + dependency_installer_opensearch_dashboards: DependencyInstallerOpenSearchDashboards, + component: TestComponent, + test_config: TestComponent, + bundle_manifest_opensearch: BundleManifest, + bundle_manifest_opensearch_dashboards: BundleManifest, + build_manifest_opensearch: BuildManifest, + build_manifest_opensearch_dashboards: BuildManifest, + work_dir: Path, + test_recorder: TestRecorder + ) -> None: super().__init__( work_dir, @@ -42,7 +52,7 @@ def __init__( self.bundle_manifest_opensearch_dashboards = bundle_manifest_opensearch_dashboards self.build_manifest_opensearch_dashboards = build_manifest_opensearch_dashboards - def execute_tests(self): + def execute_tests(self) -> TestComponentResults: test_results = TestComponentResults() for config in self.test_config.integ_test["test-configs"]: @@ -51,7 +61,7 @@ def execute_tests(self): test_results.append(TestResult(self.component.name, config, status)) return test_results - def __setup_cluster_and_execute_test_config(self, config): + def __setup_cluster_and_execute_test_config(self, config: str) -> int: security = self.is_security_enabled(config) with LocalTestClusterOpenSearchDashboards.create( @@ -65,13 +75,13 @@ def __setup_cluster_and_execute_test_config(self, config): security, config, self.test_recorder, - ) as (test_cluster_endpoint, test_cluster_port): + ) as (endpoint, port): self.pretty_print_message("Running integration tests for " + self.component.name) os.chdir(self.work_dir) - return self.execute_integtest_sh(test_cluster_endpoint, test_cluster_port, security, config) + return self.execute_integtest_sh(endpoint, port, security, config) @property - def test_artifact_files(self): + def test_artifact_files(self) -> dict: return { "cypress-videos": os.path.join(self.repo_work_dir, "cypress", "videos"), "cypress-screenshots": os.path.join(self.repo_work_dir, "cypress", "screenshots"), diff --git a/src/test_workflow/integ_test/local_test_cluster.py b/src/test_workflow/integ_test/local_test_cluster.py index 11b5d7ba6c..ec83bba8e9 100644 --- a/src/test_workflow/integ_test/local_test_cluster.py +++ b/src/test_workflow/integ_test/local_test_cluster.py @@ -5,27 +5,36 @@ # compatible open source license. +from typing import List + +from manifests.bundle_manifest import BundleManifest +from test_workflow.dependency_installer import DependencyInstaller +from test_workflow.integ_test.service import Service from test_workflow.integ_test.service_opensearch import ServiceOpenSearch from test_workflow.test_cluster import TestCluster from test_workflow.test_recorder.test_recorder import TestRecorder class LocalTestCluster(TestCluster): + manifest: BundleManifest + service_opensearch: ServiceOpenSearch + dependency_installer: DependencyInstaller + """ Represents an on-box test cluster. This class downloads a bundle (from a BundleManifest) and runs it as a background process. """ def __init__( self, - dependency_installer, - work_dir, - component_name, - additional_cluster_config, - bundle_manifest, - security_enabled, - component_test_config, + dependency_installer: DependencyInstaller, + work_dir: str, + component_name: str, + additional_cluster_config: dict, + bundle_manifest: BundleManifest, + security_enabled: bool, + component_test_config: str, test_recorder: TestRecorder, - ): + ) -> None: super().__init__( work_dir, component_name, @@ -48,15 +57,13 @@ def __init__( ) @property - def service(self): + def service(self) -> Service: return self.service_opensearch @property - def dependencies(self): + def dependencies(self) -> List[Service]: return [] - def endpoint(self): - return "localhost" - - def port(self): + @property + def port(self) -> int: return 9200 diff --git a/src/test_workflow/integ_test/local_test_cluster_opensearch_dashboards.py b/src/test_workflow/integ_test/local_test_cluster_opensearch_dashboards.py index 23e147e912..02cfd3d69a 100644 --- a/src/test_workflow/integ_test/local_test_cluster_opensearch_dashboards.py +++ b/src/test_workflow/integ_test/local_test_cluster_opensearch_dashboards.py @@ -4,6 +4,12 @@ # this file be licensed under the Apache-2.0 license or a # compatible open source license. +from typing import List + +from manifests.bundle_manifest import BundleManifest +from test_workflow.dependency_installer_opensearch import DependencyInstallerOpenSearch +from test_workflow.dependency_installer_opensearch_dashboards import DependencyInstallerOpenSearchDashboards +from test_workflow.integ_test.service import Service from test_workflow.integ_test.service_opensearch import ServiceOpenSearch from test_workflow.integ_test.service_opensearch_dashboards import ServiceOpenSearchDashboards from test_workflow.test_cluster import TestCluster @@ -11,23 +17,28 @@ class LocalTestClusterOpenSearchDashboards(TestCluster): + manifest_opensearch: BundleManifest + manifest_opensearch_dashboards: BundleManifest + service_opensearch: ServiceOpenSearch + service_opensearch_dashboards: ServiceOpenSearchDashboards + """ Represents an on-box test cluster. This class runs OpenSearchService first and then OpenSearchServiceDashboards service. """ def __init__( self, - dependency_installer_opensearch, - dependency_installer_opensearch_dashboards, - work_dir, - component_name, - additional_cluster_config, - bundle_manifest_opensearch, - bundle_manifest_opensearch_dashboards, - security_enabled, - component_test_config, + dependency_installer_opensearch: DependencyInstallerOpenSearch, + dependency_installer_opensearch_dashboards: DependencyInstallerOpenSearchDashboards, + work_dir: str, + component_name: str, + additional_cluster_config: dict, + bundle_manifest_opensearch: BundleManifest, + bundle_manifest_opensearch_dashboards: BundleManifest, + security_enabled: bool, + component_test_config: str, test_recorder: TestRecorder, - ): + ) -> None: super().__init__( work_dir, component_name, @@ -59,18 +70,20 @@ def __init__( self.dependency_installer_opensearch_dashboards, self.work_dir) - def endpoint(self): + @property + def endpoint(self) -> str: return "localhost" - def port(self): + @property + def port(self) -> int: return 5601 @property - def service(self): + def service(self) -> Service: return self.service_opensearch_dashboards @property - def dependencies(self): + def dependencies(self) -> List[Service]: return [ self.service_opensearch ] diff --git a/src/test_workflow/integ_test/service.py b/src/test_workflow/integ_test/service.py index 67587e0c24..d091be940b 100644 --- a/src/test_workflow/integ_test/service.py +++ b/src/test_workflow/integ_test/service.py @@ -8,19 +8,37 @@ import logging import os import time +from typing import Dict import requests +from requests.models import Response from system.process import Process -from test_workflow.test_cluster import ClusterCreationException +from test_workflow.dependency_installer import DependencyInstaller +from test_workflow.integ_test.service_termination_result import ServiceTerminationResult class Service(abc.ABC): + work_dir: str + version: str + distribution: str + security_enabled: bool + additional_config: dict + dependency_installer: DependencyInstaller + """ Abstract base class for all types of test clusters. """ - def __init__(self, work_dir, version, distribution, security_enabled, additional_config, dependency_installer): + def __init__( + self, + work_dir: str, + version: str, + distribution: str, + security_enabled: bool, + additional_config: dict, + dependency_installer: DependencyInstaller + ) -> None: self.work_dir = work_dir self.version = version self.distribution = distribution @@ -32,48 +50,53 @@ def __init__(self, work_dir, version, distribution, security_enabled, additional self.install_dir = "" @abc.abstractmethod - def start(self): + def start(self) -> None: """ Start a service. """ pass - def terminate(self): + def terminate(self) -> ServiceTerminationResult: if not self.process_handler.started: logging.info("Process is not started") - return + return None self.return_code = self.process_handler.terminate() self.uninstall() - return ServiceTerminationResult(self.return_code, self.process_handler.stdout_data, self.process_handler.stderr_data, self.log_files) + return ServiceTerminationResult( + self.return_code, + self.process_handler.stdout_data, + self.process_handler.stderr_data, + self.log_files + ) - def endpoint(self): + def endpoint(self) -> str: return "localhost" @abc.abstractmethod - def port(self): + def port(self) -> int: """ Get the port that this service is listening on. """ pass @abc.abstractmethod - def get_service_response(self): + def get_service_response(self) -> Response: """ Get response from the service endpoint. """ pass @abc.abstractmethod - def check_service_response_text(self): + def check_service_response_text(self, response_text: str) -> bool: """ Check response text from the service endpoint. """ pass - def service_alive(self): + def service_alive(self) -> bool: response = self.get_service_response() logging.info(f"{response.status_code}: {response.text}") @@ -84,13 +107,13 @@ def service_alive(self): else: return False - def download(self): + def download(self) -> str: logging.info("Downloading bundle artifact") bundle_name = self.dependency_installer.download_dist(self.work_dir) logging.info(f"Downloaded bundle to {os.path.realpath(bundle_name)}") return bundle_name - def wait_for_service(self): + def wait_for_service(self) -> None: logging.info("Waiting for service to become available") for attempt in range(10): @@ -111,13 +134,17 @@ def wait_for_service(self): @property @abc.abstractmethod - def log_files(self): + def log_files(self) -> Dict[str, str]: + pass + + @abc.abstractmethod + def uninstall(self) -> None: pass -class ServiceTerminationResult: - def __init__(self, return_code, stdout_data, stderr_data, log_files): - self.return_code = return_code - self.stdout_data = stdout_data - self.stderr_data = stderr_data - self.log_files = log_files +class ClusterCreationException(Exception): + """ + Indicates that cluster creation failed for some reason. + """ + + pass diff --git a/src/test_workflow/integ_test/service_opensearch.py b/src/test_workflow/integ_test/service_opensearch.py index a8a98ff38b..dbca70a64e 100644 --- a/src/test_workflow/integ_test/service_opensearch.py +++ b/src/test_workflow/integ_test/service_opensearch.py @@ -9,28 +9,37 @@ import requests import yaml +from requests.models import Response +from test_workflow.dependency_installer import DependencyInstaller +from test_workflow.integ_test.distribution import Distribution from test_workflow.integ_test.distributions import Distributions from test_workflow.integ_test.service import Service class ServiceOpenSearch(Service): + dist: Distribution + dependency_installer: DependencyInstaller + install_dir: str + opensearch_yml_dir: str + security_plugin_dir: str + def __init__( self, - version, - distribution, - additional_config, - security_enabled, - dependency_installer, - work_dir - ): + version: str, + distribution: str, + additional_config: dict, + security_enabled: bool, + dependency_installer: DependencyInstaller, + work_dir: str + ) -> None: super().__init__(work_dir, version, distribution, security_enabled, additional_config, dependency_installer) self.dist = Distributions.get_distribution("opensearch", distribution, version, work_dir) self.dependency_installer = dependency_installer self.install_dir = self.dist.install_dir - def start(self): + def start(self) -> None: self.dist.install(self.download()) self.opensearch_yml_dir = os.path.join(self.dist.config_dir, "opensearch.yml") @@ -45,27 +54,27 @@ def start(self): self.process_handler.start(self.dist.start_cmd, self.install_dir) logging.info(f"Started OpenSearch with parent PID {self.process_handler.pid}") - def uninstall(self): + def uninstall(self) -> None: self.dist.uninstall() - def url(self, path=""): + def url(self, path: str = "") -> str: return f'{"https" if self.security_enabled else "http"}://{self.endpoint()}:{self.port()}{path}' - def get_service_response(self): + def get_service_response(self) -> Response: url = self.url("/_cluster/health") logging.info(f"Pinging {url}") return requests.get(url, verify=False, auth=("admin", "admin")) - def __add_plugin_specific_config(self, additional_config): + def __add_plugin_specific_config(self, additional_config: dict) -> None: with open(self.opensearch_yml_dir, "a") as yamlfile: yamlfile.write(yaml.dump(additional_config)) - def port(self): + def port(self) -> int: return 9200 - def check_service_response_text(self, response_text): + def check_service_response_text(self, response_text: str) -> bool: return ('"status":"green"' in response_text) or ('"status":"yellow"' in response_text) @property - def log_files(self): + def log_files(self) -> dict: return {"opensearch-service-logs": os.path.join(self.install_dir, "logs")} diff --git a/src/test_workflow/integ_test/service_opensearch_dashboards.py b/src/test_workflow/integ_test/service_opensearch_dashboards.py index f7569e0a66..359410f591 100644 --- a/src/test_workflow/integ_test/service_opensearch_dashboards.py +++ b/src/test_workflow/integ_test/service_opensearch_dashboards.py @@ -10,26 +10,34 @@ import requests import yaml +from requests.models import Response +from test_workflow.dependency_installer import DependencyInstaller +from test_workflow.integ_test.distribution import Distribution from test_workflow.integ_test.distributions import Distributions from test_workflow.integ_test.service import Service class ServiceOpenSearchDashboards(Service): + dist: Distribution + install_dir: str + opensearch_dashboards_yml_dir: str + executable_dir: str + def __init__( self, - version, - distribution, - additional_config, - security_enabled, - dependency_installer, - work_dir - ): + version: str, + distribution: str, + additional_config: dict, + security_enabled: bool, + dependency_installer: DependencyInstaller, + work_dir: str + ) -> None: super().__init__(work_dir, version, distribution, security_enabled, additional_config, dependency_installer) self.dist = Distributions.get_distribution("opensearch-dashboards", distribution, version, work_dir) self.install_dir = self.dist.install_dir - def start(self): + def start(self) -> None: self.dist.install(self.download()) self.opensearch_dashboards_yml_dir = os.path.join(self.dist.config_dir, "opensearch_dashboards.yml") @@ -46,15 +54,15 @@ def start(self): self.process_handler.start(self.dist.start_cmd, self.executable_dir) logging.info(f"Started OpenSearch Dashboards with parent PID {self.process_handler.pid}") - def uninstall(self): + def uninstall(self) -> None: self.dist.uninstall() - def __set_logging_dest(self): + def __set_logging_dest(self) -> None: self.log_dir = os.path.join(self.install_dir, "logs") os.makedirs(self.log_dir, exist_ok=True) self.additional_config["logging.dest"] = os.path.join(self.log_dir, "opensearch_dashboards.log") - def __remove_security(self): + def __remove_security(self) -> None: self.security_plugin_dir = os.path.join(self.install_dir, "plugins", "securityDashboards") if os.path.isdir(self.security_plugin_dir): subprocess.check_call("./opensearch-dashboards-plugin remove --allow-root securityDashboards", cwd=self.executable_dir, shell=True) @@ -62,24 +70,24 @@ def __remove_security(self): with open(self.opensearch_dashboards_yml_dir, "w") as yamlfile: yamlfile.close() - def url(self, path=""): + def url(self, path: str = "") -> str: return f'http://{self.endpoint()}:{self.port()}{path}' - def get_service_response(self): + def get_service_response(self) -> Response: url = self.url("/api/status") logging.info(f"Pinging {url}") return requests.get(url, verify=False, auth=("admin", "admin") if self.security_enabled else None) - def __add_plugin_specific_config(self, additional_config): + def __add_plugin_specific_config(self, additional_config: dict) -> None: with open(self.opensearch_dashboards_yml_dir, "a") as yamlfile: yamlfile.write(yaml.dump(additional_config)) - def port(self): + def port(self) -> int: return 5601 - def check_service_response_text(self, response_text): + def check_service_response_text(self, response_text: str) -> bool: return ('"state":"green"' in response_text) or ('"state":"yellow"' in response_text) @property - def log_files(self): + def log_files(self) -> dict: return {"opensearch-dashboards-service-logs": os.path.join(self.install_dir, "logs")} diff --git a/src/test_workflow/integ_test/service_termination_result.py b/src/test_workflow/integ_test/service_termination_result.py new file mode 100644 index 0000000000..7b8b2ab7ea --- /dev/null +++ b/src/test_workflow/integ_test/service_termination_result.py @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. + +from typing import Dict + + +class ServiceTerminationResult: + return_code: int + stdout_data: str + stderr_data: str + log_files: Dict[str, str] + + def __init__( + self, + return_code: int, + stdout_data: str, + stderr_data: str, + log_files: Dict[str, str] + ) -> None: + self.return_code = return_code + self.stdout_data = stdout_data + self.stderr_data = stderr_data + self.log_files = log_files diff --git a/src/test_workflow/perf_test/perf_args.py b/src/test_workflow/perf_test/perf_args.py index 8262585c83..147c9b9682 100644 --- a/src/test_workflow/perf_test/perf_args.py +++ b/src/test_workflow/perf_test/perf_args.py @@ -8,11 +8,22 @@ # GitHub history for details. import argparse +from typing import IO # Contains the arguments required to run a perf test. class PerfArgs: - def __init__(self): + bundle_manifest: IO + stack: str + config: IO + keep: bool + workload: str + workload_options: dict + warmup_iters: int + test_iters: int + insecure: bool + + def __init__(self) -> None: parser = argparse.ArgumentParser(description="Test an OpenSearch Bundle") parser.add_argument("--bundle-manifest", type=argparse.FileType("r"), help="Bundle Manifest file.", required=True) parser.add_argument("--stack", dest="stack", help="Stack name for performance test") diff --git a/src/test_workflow/perf_test/perf_multi_node_cluster.py b/src/test_workflow/perf_test/perf_multi_node_cluster.py index 670780c805..27823143db 100644 --- a/src/test_workflow/perf_test/perf_multi_node_cluster.py +++ b/src/test_workflow/perf_test/perf_multi_node_cluster.py @@ -7,28 +7,37 @@ import os +from manifests.bundle_manifest import BundleManifest from test_workflow.perf_test.perf_test_cluster import PerfTestCluster +from test_workflow.perf_test.perf_test_cluster_config import PerfTestClusterConfig class PerfMultiNodeCluster(PerfTestCluster): """ Represents a performance multi node test cluster. This class deploys the opensearch bundle with CDK. """ - def __init__(self, bundle_manifest, config, stack_name, cluster_config, current_workspace): + def __init__( + self, + bundle_manifest: BundleManifest, + config: dict, + stack_name: str, + cluster_config: PerfTestClusterConfig, + current_workspace: str + ) -> None: assert not cluster_config.is_single_node_cluster, "Cluster is a single node configuration" work_dir = os.path.join(current_workspace, "opensearch-cluster", "cdk", "multi-node") super().__init__(bundle_manifest, config, stack_name, cluster_config, current_workspace, work_dir) - def create_endpoint(self, cdk_output): + def create_endpoint(self, cdk_output: dict) -> None: scheme = "https://" if self.cluster_config.security else "http://" host = cdk_output[self.stack_name].get("LoadBalancerEndpoint", None) self.is_endpoint_public = True if host is None: raise RuntimeError("Unable to fetch the cluster endpoint from cdk output") - self.endpoint = host + self.cluster_endpoint = host self.cluster_endpoint_with_port = "".join([scheme, host, ":", str(self.port)]) - def setup_cdk_params(self, config): + def setup_cdk_params(self, config: dict) -> dict: return { "url": self.manifest.build.location, "security_group_id": config["Constants"]["SecurityGroupId"], diff --git a/src/test_workflow/perf_test/perf_single_node_cluster.py b/src/test_workflow/perf_test/perf_single_node_cluster.py index 32dd08444e..cf683be9fb 100644 --- a/src/test_workflow/perf_test/perf_single_node_cluster.py +++ b/src/test_workflow/perf_test/perf_single_node_cluster.py @@ -7,19 +7,28 @@ import os +from manifests.bundle_manifest import BundleManifest from test_workflow.perf_test.perf_test_cluster import PerfTestCluster +from test_workflow.perf_test.perf_test_cluster_config import PerfTestClusterConfig class PerfSingleNodeCluster(PerfTestCluster): """ Represents a performance single node test cluster. This class deploys the opensearch bundle with CDK. """ - def __init__(self, bundle_manifest, config, stack_name, cluster_config, current_workspace): + def __init__( + self, + bundle_manifest: BundleManifest, + config: dict, + stack_name: str, + cluster_config: PerfTestClusterConfig, + current_workspace: str + ) -> None: assert cluster_config.is_single_node_cluster, "Cluster is not a single node cluster" work_dir = os.path.join(current_workspace, "opensearch-cluster", "cdk", "single-node") super().__init__(bundle_manifest, config, stack_name, cluster_config, current_workspace, work_dir) - def create_endpoint(self, cdk_output): + def create_endpoint(self, cdk_output: dict) -> None: scheme = "https://" if self.cluster_config.security else "http://" private_ip = cdk_output[self.stack_name].get("PrivateIp", None) public_ip = cdk_output[self.stack_name].get("PublicIp", None) @@ -27,10 +36,10 @@ def create_endpoint(self, cdk_output): host = public_ip if public_ip is not None else private_ip if host is None: raise RuntimeError("Unable to fetch the cluster endpoint from cdk output") - self.endpoint = host + self.cluster_endpoint = host self.cluster_endpoint_with_port = "".join([scheme, host, ":", str(self.port)]) - def setup_cdk_params(self, config): + def setup_cdk_params(self, config: dict) -> dict: return { "url": self.manifest.build.location, "security_group_id": config["Constants"]["SecurityGroupId"], diff --git a/src/test_workflow/perf_test/perf_test_cluster.py b/src/test_workflow/perf_test/perf_test_cluster.py index 6a8500224b..63ebddd975 100644 --- a/src/test_workflow/perf_test/perf_test_cluster.py +++ b/src/test_workflow/perf_test/perf_test_cluster.py @@ -4,21 +4,44 @@ import os import subprocess from contextlib import contextmanager +from typing import Any, Generator, List import requests from requests.auth import HTTPBasicAuth -from retry.api import retry_call +from retry.api import retry_call # type: ignore +from manifests.bundle_manifest import BundleManifest +from test_workflow.integ_test.service import Service +from test_workflow.perf_test.perf_test_cluster_config import PerfTestClusterConfig from test_workflow.test_cluster import TestCluster class PerfTestCluster(TestCluster): + manifest: BundleManifest + work_dir: str + current_workspace: str + stack_name: str + output_file: str + cluster_config: PerfTestClusterConfig + params: str + is_endpoint_public: bool + cluster_endpoint: str + cluster_endpoint_with_port: str + """ Represents a performance test cluster. This class deploys the opensearch bundle with CDK. Supports both single and multi-node clusters """ - def __init__(self, bundle_manifest, config, stack_name, cluster_config, current_workspace, work_dir): + def __init__( + self, + bundle_manifest: BundleManifest, + config: dict, + stack_name: str, + cluster_config: PerfTestClusterConfig, + current_workspace: str, + work_dir: str + ) -> None: self.manifest = bundle_manifest self.work_dir = work_dir self.current_workspace = current_workspace @@ -36,10 +59,10 @@ def __init__(self, bundle_manifest, config, stack_name, cluster_config, current_ ) self.params = "".join(params_list) + role_params self.is_endpoint_public = False + self.cluster_endpoint = None self.cluster_endpoint_with_port = None - self.endpoint = None - def start(self): + def start(self) -> None: os.chdir(self.work_dir) command = f"cdk deploy {self.params} --outputs-file {self.output_file}" logging.info(f'Executing "{command}" in {os.getcwd()}') @@ -49,30 +72,34 @@ def start(self): self.create_endpoint(load_output) @abc.abstractmethod - def create_endpoint(self, cdk_output): + def create_endpoint(self, cdk_output: dict) -> None: pass @property - def endpoint_with_port(self): + def endpoint(self) -> str: + return self.cluster_endpoint + + @property + def endpoint_with_port(self) -> str: return self.cluster_endpoint_with_port @property - def port(self): + def port(self) -> int: return 443 if self.cluster_config.security else 80 - def terminate(self): + def terminate(self) -> None: os.chdir(self.work_dir) command = f"cdk destroy {self.params} --force" logging.info(f'Executing "{command}" in {os.getcwd()}') subprocess.check_call(command, cwd=os.getcwd(), shell=True) - def service(self): - return [] + def service(self) -> Service: + return None - def dependencies(self): + def dependencies(self) -> List[Service]: return [] - def wait_for_processing(self, tries=3, delay=15, backoff=2): + def wait_for_processing(self, tries: int = 3, delay: int = 15, backoff: int = 2) -> None: # Should be invoked only if the endpoint is public. assert self.is_endpoint_public, "wait_for_processing should be invoked only when cluster is public" logging.info("Waiting for domain to be up") @@ -81,12 +108,12 @@ def wait_for_processing(self, tries=3, delay=15, backoff=2): tries=tries, delay=delay, backoff=backoff) @abc.abstractmethod - def setup_cdk_params(self, config): + def setup_cdk_params(self, config: dict) -> dict: pass @classmethod @contextmanager - def create(cls, *args): + def create(cls, *args: Any) -> Generator[Any, None, None]: """ Set up the cluster. When this method returns, the cluster must be available to take requests. Throws ClusterCreationException if the cluster could not start for some reason. If this exception is thrown, the caller does not need to call "destroy". diff --git a/src/test_workflow/perf_test/perf_test_cluster_config.py b/src/test_workflow/perf_test/perf_test_cluster_config.py index 8715f963b1..3cce942ff7 100644 --- a/src/test_workflow/perf_test/perf_test_cluster_config.py +++ b/src/test_workflow/perf_test/perf_test_cluster_config.py @@ -5,10 +5,17 @@ # compatible open source license. class PerfTestClusterConfig(): + security: bool + data_nodes: int + master_nodes: int + ingest_nodes: int + client_nodes: int + _is_single_node_cluster: bool + """ Maintains the cluster level configuration. """ - def __init__(self, security=False, data_nodes=1, master_nodes=0, ingest_nodes=0, client_nodes=0): + def __init__(self, security: bool = False, data_nodes: int = 1, master_nodes: int = 0, ingest_nodes: int = 0, client_nodes: int = 0) -> None: self.security = security self.data_nodes = data_nodes self.master_nodes = master_nodes @@ -18,5 +25,5 @@ def __init__(self, security=False, data_nodes=1, master_nodes=0, ingest_nodes=0, and self.ingest_nodes == 0 and self.client_nodes == 0) @property - def is_single_node_cluster(self): + def is_single_node_cluster(self) -> bool: return self._is_single_node_cluster diff --git a/src/test_workflow/perf_test/perf_test_runner.py b/src/test_workflow/perf_test/perf_test_runner.py index 8296c4d471..238ce3318b 100644 --- a/src/test_workflow/perf_test/perf_test_runner.py +++ b/src/test_workflow/perf_test/perf_test_runner.py @@ -12,7 +12,12 @@ class PerfTestRunner(abc.ABC): - def __init__(self, args: PerfArgs, test_manifest: BundleManifest): + args: PerfArgs + test_manifest: BundleManifest + security: bool + tests_dir: str + + def __init__(self, args: PerfArgs, test_manifest: BundleManifest) -> None: self.args = args self.test_manifest = test_manifest @@ -20,5 +25,9 @@ def __init__(self, args: PerfArgs, test_manifest: BundleManifest): self.tests_dir = os.path.join(os.getcwd(), "test-results", "perf-test", f"{'with' if self.security else 'without'}-security") os.makedirs(self.tests_dir, exist_ok=True) - def run(self): + @abc.abstractmethod + def run_tests(self) -> None: + pass + + def run(self) -> None: self.run_tests() diff --git a/src/test_workflow/perf_test/perf_test_runner_opensearch.py b/src/test_workflow/perf_test/perf_test_runner_opensearch.py index 5769d683a9..95e48ba877 100644 --- a/src/test_workflow/perf_test/perf_test_runner_opensearch.py +++ b/src/test_workflow/perf_test/perf_test_runner_opensearch.py @@ -8,7 +8,7 @@ import os import yaml -from retry.api import retry_call +from retry.api import retry_call # type: ignore from git.git_repository import GitRepository from manifests.bundle_manifest import BundleManifest @@ -25,16 +25,16 @@ class PerfTestRunnerOpenSearch(PerfTestRunner): """ Runner to execute the performance tests for opensearch. """ - def __init__(self, args: PerfArgs, test_manifest: BundleManifest): + def __init__(self, args: PerfArgs, test_manifest: BundleManifest) -> None: super().__init__(args, test_manifest) logging.info("Running opensearch tests") - def get_infra_repo_url(self): + def get_infra_repo_url(self) -> str: if "GITHUB_TOKEN" in os.environ: return "https://${GITHUB_TOKEN}@github.com/opensearch-project/opensearch-infra.git" return "https://github.com/opensearch-project/opensearch-infra.git" - def run_tests(self): + def run_tests(self) -> None: config = yaml.safe_load(self.args.config) with TemporaryDirectory(keep=self.args.keep, chdir=True) as work_dir: current_workspace = os.path.join(work_dir.name, "infra") diff --git a/src/test_workflow/perf_test/perf_test_runner_opensearch_plugins.py b/src/test_workflow/perf_test/perf_test_runner_opensearch_plugins.py index 53323b147b..29682ac126 100644 --- a/src/test_workflow/perf_test/perf_test_runner_opensearch_plugins.py +++ b/src/test_workflow/perf_test/perf_test_runner_opensearch_plugins.py @@ -16,10 +16,13 @@ class PerfTestRunnerOpenSearchPlugins(PerfTestRunner): + test_dir: str + command: str + """ Runner to execute the performance tests for opensearch plugins. The plugins need to define the test suite """ - def __init__(self, args: PerfArgs, test_manifest: BundleManifest): + def __init__(self, args: PerfArgs, test_manifest: BundleManifest) -> None: super().__init__(args, test_manifest) self.tests_dir = os.path.join(os.getcwd(), "test-results", "perf-test", self.args.component) os.makedirs(self.tests_dir, exist_ok=True) @@ -30,10 +33,10 @@ def __init__(self, args: PerfArgs, test_manifest: BundleManifest): f"--test-result-dir {str(self.tests_dir)} {security_flag}" ) - def get_plugin_repo_url(self): + def get_plugin_repo_url(self) -> str: return f"https://github.com/opensearch-project/{self.args.component}.git" - def run_tests(self): + def run_tests(self) -> None: with TemporaryDirectory(keep=self.args.keep, chdir=True) as work_dir: current_workspace = os.path.join(work_dir.name, self.args.component) with GitRepository(self.get_plugin_repo_url(), "main", current_workspace): diff --git a/src/test_workflow/perf_test/perf_test_runners.py b/src/test_workflow/perf_test/perf_test_runners.py index 26c9f2cbe9..f60b65a7f0 100644 --- a/src/test_workflow/perf_test/perf_test_runners.py +++ b/src/test_workflow/perf_test/perf_test_runners.py @@ -6,6 +6,7 @@ from manifests.bundle_manifest import BundleManifest from test_workflow.perf_test.perf_args import PerfArgs +from test_workflow.perf_test.perf_test_runner import PerfTestRunner from test_workflow.perf_test.perf_test_runner_opensearch import PerfTestRunnerOpenSearch from test_workflow.perf_test.perf_test_runner_opensearch_plugins import PerfTestRunnerOpenSearchPlugins @@ -17,5 +18,5 @@ class PerfTestRunners: } @classmethod - def from_args(cls, args: PerfArgs, test_manifest: BundleManifest): + def from_args(cls, args: PerfArgs, test_manifest: BundleManifest) -> PerfTestRunner: return cls.RUNNERS.get(args.component, PerfTestRunnerOpenSearchPlugins)(args, test_manifest) diff --git a/src/test_workflow/perf_test/perf_test_suite.py b/src/test_workflow/perf_test/perf_test_suite.py index 4016dcf9b2..04fc6a7d0a 100644 --- a/src/test_workflow/perf_test/perf_test_suite.py +++ b/src/test_workflow/perf_test/perf_test_suite.py @@ -1,16 +1,36 @@ import json import os import subprocess +from typing import Any +from manifests.bundle_manifest import BundleManifest from system.working_directory import WorkingDirectory +from test_workflow.perf_test.perf_args import PerfArgs class PerfTestSuite: + manifest: BundleManifest + work_dir: str + endpoint: dict + security: bool + current_workspace: str + args: PerfArgs + command: str + """ Represents a performance test suite. This class runs rally test on the deployed cluster with the provided IP. """ - def __init__(self, bundle_manifest, endpoint, security, current_workspace, test_results_path, args, - owner="opensearch-devops", scenario="DEFAULT"): + def __init__( + self, + bundle_manifest: BundleManifest, + endpoint: Any, + security: bool, + current_workspace: str, + test_results_path: str, + args: PerfArgs, + owner: str = "opensearch-devops", + scenario: str = "DEFAULT" + ) -> None: self.manifest = bundle_manifest self.work_dir = current_workspace + "/mensor/" self.endpoint = endpoint @@ -31,7 +51,7 @@ def __init__(self, bundle_manifest, endpoint, security, current_workspace, test_ f" --scenario-type {scenario} --owner {owner}" ) - def execute(self): + def execute(self) -> None: try: current_workspace = os.path.join(self.current_workspace, self.work_dir) with WorkingDirectory(current_workspace): diff --git a/src/test_workflow/perf_test/test.py b/src/test_workflow/perf_test/test.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/test_workflow/test_args.py b/src/test_workflow/test_args.py index 1e8c338dc5..e649c6e652 100644 --- a/src/test_workflow/test_args.py +++ b/src/test_workflow/test_args.py @@ -17,14 +17,14 @@ class TestArgs: - test_run_id: int + test_run_id: str components: List[str] keep: bool logging_level: int test_manifest_path: str paths: dict - def __init__(self): + def __init__(self) -> None: parser = argparse.ArgumentParser(description="Test an OpenSearch Bundle") parser.add_argument("test_manifest_path", type=TestArgsPathValidator.validate, help="Specify a test manifest path.") parser.add_argument("-p", "--paths", nargs='*', action=TestKwargs, default={}, help="Specify paths for OpenSearch and OpenSearch Dashboards.") diff --git a/src/test_workflow/test_args_path_validator.py b/src/test_workflow/test_args_path_validator.py index 714bfaee1a..8ebf6575b8 100644 --- a/src/test_workflow/test_args_path_validator.py +++ b/src/test_workflow/test_args_path_validator.py @@ -16,5 +16,5 @@ class TestArgsPathValidator: @classmethod - def validate(cls, path): + def validate(cls, path: str) -> str: return path if validators.url(path) else os.path.realpath(path) diff --git a/src/test_workflow/test_cluster.py b/src/test_workflow/test_cluster.py index e87da8de4e..b2874d8864 100644 --- a/src/test_workflow/test_cluster.py +++ b/src/test_workflow/test_cluster.py @@ -7,24 +7,37 @@ import abc import os from contextlib import contextmanager +from typing import Any, Generator, List, Tuple +from test_workflow.integ_test.service import Service +from test_workflow.integ_test.service_termination_result import ServiceTerminationResult +from test_workflow.test_recorder.log_recorder import LogRecorder from test_workflow.test_recorder.test_result_data import TestResultData class TestCluster(abc.ABC): + work_dir: str + component_name: str + component_test_config: str + security_enabled: bool + additional_cluster_config: dict + save_logs: LogRecorder + all_services: List[Service] + termination_result: ServiceTerminationResult + """ Abstract base class for all types of test clusters. """ def __init__( self, - work_dir, - component_name, - component_test_config, - security_enabled, - additional_cluster_config, - save_logs - ): + work_dir: str, + component_name: str, + component_test_config: str, + security_enabled: bool, + additional_cluster_config: dict, + save_logs: LogRecorder + ) -> None: self.work_dir = os.path.join(work_dir, "local-test-cluster") self.component_name = component_name self.component_test_config = component_test_config @@ -37,7 +50,7 @@ def __init__( @classmethod @contextmanager - def create(cls, *args): + def create(cls, *args: Any) -> Generator[Tuple[str, int], None, None]: """ Set up the cluster. When this method returns, the cluster must be available to take requests. Throws ClusterCreationException if the cluster could not start for some reason. If this exception is thrown, the caller does not need to call "destroy". @@ -45,11 +58,11 @@ def create(cls, *args): cluster = cls(*args) try: cluster.start() - yield cluster.endpoint(), cluster.port() + yield cluster.endpoint, cluster.port finally: cluster.terminate() - def start(self): + def start(self) -> None: os.makedirs(self.work_dir, exist_ok=True) self.all_services = [self.service] + self.dependencies @@ -60,7 +73,7 @@ def start(self): for service in self.all_services: service.wait_for_service() - def terminate(self): + def terminate(self) -> None: if self.service: self.termination_result = self.service.terminate() @@ -73,8 +86,7 @@ def terminate(self): self.__save_test_result_data(self.termination_result) - def __save_test_result_data(self, termination_result): - + def __save_test_result_data(self, termination_result: ServiceTerminationResult) -> None: test_result_data = TestResultData( self.component_name, self.component_test_config, @@ -86,43 +98,41 @@ def __save_test_result_data(self, termination_result): self.save_logs.save_test_result_data(test_result_data) - def endpoint(self): + @property + def endpoint(self) -> str: + """ + Get the host that this cluster is listening on. + """ return "localhost" + @property @abc.abstractmethod - def port(self): + def port(self) -> int: """ Get the port that this cluster is listening on. """ pass + @property @abc.abstractproperty - def service(self): + def service(self) -> Service: """ The main service running in this cluster. """ pass @abc.abstractproperty - def dependencies(self): + def dependencies(self) -> List[Service]: """ The dependencies running in this cluster. """ pass -class ClusterCreationException(Exception): - """ - Indicates that cluster creation failed for some reason. - """ - - pass - - class ClusterServiceNotInitializedException(Exception): """ Indicates that the service running in the cluster is not initialized. """ - def __init__(self): + def __init__(self) -> None: super().__init__("Service is not initialized") diff --git a/src/test_workflow/test_component.py b/src/test_workflow/test_component.py index 60f9dcc179..70a1051a84 100644 --- a/src/test_workflow/test_component.py +++ b/src/test_workflow/test_component.py @@ -13,11 +13,11 @@ class TestComponent: repository: str commit_id: str - def __init__(self, respository, commit_id): + def __init__(self, respository: str, commit_id: str) -> None: self.repository = respository self.commit_id = commit_id - def checkout(self, directory): + def checkout(self, directory: str) -> GitRepository: return GitRepository(self.repository, self.commit_id, directory) diff --git a/src/test_workflow/test_kwargs.py b/src/test_workflow/test_kwargs.py index 818336eddd..1dc33477bd 100644 --- a/src/test_workflow/test_kwargs.py +++ b/src/test_workflow/test_kwargs.py @@ -8,12 +8,13 @@ # GitHub history for details. import argparse +from typing import Any, Sequence, Union from test_workflow.test_args_path_validator import TestArgsPathValidator class TestKwargs(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): + def __call__(self, parser: Any, namespace: argparse.Namespace, values: Union[str, Sequence[Any], None], option_string: str = None) -> None: setattr(namespace, self.dest, dict()) for value in values: key, value = value.split('=') diff --git a/src/test_workflow/test_recorder/log_recorder.py b/src/test_workflow/test_recorder/log_recorder.py index f19feaaf2a..051c021687 100644 --- a/src/test_workflow/test_recorder/log_recorder.py +++ b/src/test_workflow/test_recorder/log_recorder.py @@ -9,7 +9,7 @@ class LogRecorder(abc.ABC): """ @abc.abstractmethod - def save_test_result_data(self, test_result_data: TestResultData): + def save_test_result_data(self, test_result_data: TestResultData) -> None: """ Defines how the result data is are recorded """ diff --git a/src/test_workflow/test_recorder/test_recorder.py b/src/test_workflow/test_recorder/test_recorder.py index c57c16c85c..9a1b48af29 100644 --- a/src/test_workflow/test_recorder/test_recorder.py +++ b/src/test_workflow/test_recorder/test_recorder.py @@ -7,6 +7,7 @@ import logging import os import shutil +from typing import Any import yaml @@ -15,28 +16,35 @@ class TestRecorder: - def __init__(self, test_run_id, test_type, tests_dir): + test_run_id: str + test_type: str + location: str + local_cluster_logs: Any + remote_cluster_logs: Any + test_results_logs: Any + + def __init__(self, test_run_id: str, test_type: str, tests_dir: str) -> None: self.test_run_id = test_run_id self.test_type = test_type self.location = os.path.join(tests_dir, str(self.test_run_id), self.test_type) os.makedirs(self.location, exist_ok=True) logging.info(f"TestRecorder recording logs in {self.location}") - self.local_cluster_logs = self.LocalClusterLogs(self) - self.remote_cluster_logs = self.RemoteClusterLogs(self) - self.test_results_logs = self.TestResultsLogs(self) + self.local_cluster_logs = LocalClusterLogs(self) + self.remote_cluster_logs = RemoteClusterLogs(self) + self.test_results_logs = TestResultsLogs(self) - def _create_base_folder_structure(self, component_name, component_test_config): - dest_directory = os.path.join(self.location, str(component_name), str(component_test_config)) + def _create_base_folder_structure(self, component_name: str, component_test_config: str) -> str: + dest_directory = os.path.join(self.location, component_name, component_test_config) os.makedirs(dest_directory, exist_ok=True) return os.path.realpath(dest_directory) - def _generate_std_files(self, stdout, stderr, output_path): + def _generate_std_files(self, stdout: str, stderr: str, output_path: str) -> None: with open(os.path.join(output_path, "stdout.txt"), "w") as stdout_file: stdout_file.write(stdout) with open(os.path.join(output_path, "stderr.txt"), "w") as stderr_file: stderr_file.write(stderr) - def _generate_yml(self, test_result_data: TestResultData, output_path): + def _generate_yml(self, test_result_data: TestResultData, output_path: str) -> str: outcome = { "test_type": self.test_type, "test_run_id": self.test_run_id, @@ -48,59 +56,68 @@ def _generate_yml(self, test_result_data: TestResultData, output_path): yaml.dump(outcome, file) return os.path.realpath("%s.yml" % test_result_data.component_name) - def _copy_log_files(self, log_files, dest_directory): + def _copy_log_files(self, log_files: dict, dest_directory: str) -> None: if log_files: for log_dest_dir_name, source_log_dir in log_files.items(): if os.path.exists(source_log_dir): dest_dir = os.path.join(dest_directory, log_dest_dir_name) shutil.copytree(source_log_dir, dest_dir) - class LocalClusterLogs(LogRecorder): - def __init__(self, parent_class): - self.parent_class = parent_class - - def save_test_result_data(self, test_result_data: TestResultData): - base = self.parent_class._create_base_folder_structure(test_result_data.component_name, test_result_data.component_test_config) - dest_directory = os.path.join(base, "local-cluster-logs") - os.makedirs(dest_directory, exist_ok=True) - logging.info( - f"Recording local cluster logs for {test_result_data.component_name} with test configuration as " - f"{test_result_data.component_test_config} at {os.path.realpath(dest_directory)}" - ) - self.parent_class._generate_std_files( - test_result_data.stdout, - test_result_data.stderr, - os.path.realpath(dest_directory), - ) - - self.parent_class._copy_log_files(test_result_data.log_files, dest_directory) - - class RemoteClusterLogs(LogRecorder): - def __init__(self, parent_class): - self.parent_class = parent_class - - def save_test_result_data(self, test_result_data: TestResultData): - base = self.parent_class._create_base_folder_structure(test_result_data.component_name, test_result_data.component_test_config) - dest_directory = os.path.join(base, "remote-cluster-logs") - os.makedirs(dest_directory, exist_ok=True) - logging.info( - f"Recording remote cluster logs for {test_result_data.component_name} with test configuration as " - f"{test_result_data.component_test_config} at {os.path.realpath(dest_directory)}" - ) - self.parent_class._generate_yml(test_result_data, dest_directory) - - class TestResultsLogs(LogRecorder): - def __init__(self, parent_class): - self.parent_class = parent_class - - def save_test_result_data(self, test_result_data: TestResultData): - base = self.parent_class._create_base_folder_structure(test_result_data.component_name, test_result_data.component_test_config) - dest_directory = os.path.join(base, "test-results") - os.makedirs(dest_directory, exist_ok=False) - logging.info(f"Recording component test results for {test_result_data.component_name} at " f"{os.path.realpath(dest_directory)}") - self.parent_class._generate_std_files(test_result_data.stdout, test_result_data.stderr, dest_directory) - self.parent_class._copy_log_files(test_result_data.log_files, dest_directory) - self.parent_class._generate_yml(test_result_data, dest_directory) + +class LocalClusterLogs(LogRecorder): + parent_class: TestRecorder + + def __init__(self, parent_class: TestRecorder) -> None: + self.parent_class = parent_class + + def save_test_result_data(self, test_result_data: TestResultData) -> None: + base = self.parent_class._create_base_folder_structure(test_result_data.component_name, test_result_data.component_test_config) + dest_directory = os.path.join(base, "local-cluster-logs") + os.makedirs(dest_directory, exist_ok=True) + logging.info( + f"Recording local cluster logs for {test_result_data.component_name} with test configuration as " + f"{test_result_data.component_test_config} at {os.path.realpath(dest_directory)}" + ) + self.parent_class._generate_std_files( + test_result_data.stdout, + test_result_data.stderr, + os.path.realpath(dest_directory), + ) + + self.parent_class._copy_log_files(test_result_data.log_files, dest_directory) + + +class RemoteClusterLogs(LogRecorder): + parent_class: TestRecorder + + def __init__(self, parent_class: TestRecorder) -> None: + self.parent_class = parent_class + + def save_test_result_data(self, test_result_data: TestResultData) -> None: + base = self.parent_class._create_base_folder_structure(test_result_data.component_name, test_result_data.component_test_config) + dest_directory = os.path.join(base, "remote-cluster-logs") + os.makedirs(dest_directory, exist_ok=True) + logging.info( + f"Recording remote cluster logs for {test_result_data.component_name} with test configuration as " + f"{test_result_data.component_test_config} at {os.path.realpath(dest_directory)}" + ) + self.parent_class._generate_yml(test_result_data, dest_directory) + + +class TestResultsLogs(LogRecorder): + parent_class: TestRecorder + + def __init__(self, parent_class: TestRecorder) -> None: + self.parent_class = parent_class + + def save_test_result_data(self, test_result_data: TestResultData) -> None: + base = self.parent_class._create_base_folder_structure(test_result_data.component_name, test_result_data.component_test_config) + dest_directory = os.path.join(base, "test-results") + os.makedirs(dest_directory, exist_ok=False) + logging.info(f"Recording component test results for {test_result_data.component_name} at " f"{os.path.realpath(dest_directory)}") + self.parent_class._generate_std_files(test_result_data.stdout, test_result_data.stderr, dest_directory) + self.parent_class._copy_log_files(test_result_data.log_files, dest_directory) + self.parent_class._generate_yml(test_result_data, dest_directory) TestRecorder.__test__ = False # type:ignore diff --git a/src/test_workflow/test_result/test_component_results.py b/src/test_workflow/test_result/test_component_results.py index 9b17c71910..056df087fd 100644 --- a/src/test_workflow/test_result/test_component_results.py +++ b/src/test_workflow/test_result/test_component_results.py @@ -1,22 +1,24 @@ -from sortedcontainers import SortedDict # type: ignore +from sortedcontainers import SortedDict + +from test_workflow.test_result.test_result import TestResult # type: ignore class TestComponentResults(SortedDict): - def __init__(self): + def __init__(self) -> None: super(TestComponentResults, self).__init__() - def __append__(self, result): + def __append__(self, result: TestResult) -> None: self.__setitem__(result.config, result) - def append(self, result): + def append(self, result: TestResult) -> None: self.__append__(result) - def log(self): + def log(self) -> None: for result in self.values(): result.log(str(result)) @property - def failed(self): + def failed(self) -> bool: for result in self.values(): failed = result.failed if failed: diff --git a/src/test_workflow/test_result/test_result.py b/src/test_workflow/test_result/test_result.py index c906f3d2b3..49dc778406 100644 --- a/src/test_workflow/test_result/test_result.py +++ b/src/test_workflow/test_result/test_result.py @@ -1,28 +1,33 @@ import logging +from typing import Callable class TestResult: - def __init__(self, component, config, status): + component: str + config: dict + status: int + + def __init__(self, component: str, config: dict, status: int) -> None: self.component = component self.config = config self.status = status @property - def __test_result(self): + def __test_result(self) -> str: return "PASS" if self.status == 0 else "FAIL" - def __str__(self): + def __str__(self) -> str: return "| {:20s} | {:20s} | {:5s} | {:4d} |".format(self.component, self.config, self.__test_result, self.status) - def __logger(self): + def __logger(self) -> Callable: return logging.info if self.status == 0 else logging.error - def log(self, result): - log = self.__logger() - log(result) + def log(self, result: str) -> None: + logger = self.__logger() + logger(result) @property - def failed(self): + def failed(self) -> bool: return True if self.status != 0 else False diff --git a/src/test_workflow/test_result/test_suite_results.py b/src/test_workflow/test_result/test_suite_results.py index 2d1bbd9d27..de0f941a81 100644 --- a/src/test_workflow/test_result/test_suite_results.py +++ b/src/test_workflow/test_result/test_suite_results.py @@ -1,21 +1,23 @@ -from sortedcontainers import SortedDict # type: ignore +from sortedcontainers import SortedDict + +from test_workflow.test_result.test_component_results import TestComponentResults # type: ignore class TestSuiteResults(SortedDict): - def __init__(self): + def __init__(self) -> None: super(TestSuiteResults, self).__init__() - def __append__(self, component, test_result_component): + def __append__(self, component: str, test_result_component: TestComponentResults) -> None: self.__setitem__(component, test_result_component) - def append(self, component, test_result_component): + def append(self, component: str, test_result_component: TestComponentResults) -> None: self.__append__(component, test_result_component) - def log(self): + def log(self) -> None: for result in self.values(): result.log() - def failed(self): + def failed(self) -> bool: return any(result.failed for result in self.values()) diff --git a/tests/test_run_build.py b/tests/test_run_build.py index 342623a757..ec45c83261 100644 --- a/tests/test_run_build.py +++ b/tests/test_run_build.py @@ -7,7 +7,8 @@ import os import tempfile import unittest -from unittest.mock import MagicMock, patch +from typing import Any +from unittest.mock import MagicMock, Mock, patch import pytest @@ -17,11 +18,11 @@ class TestRunBuild(unittest.TestCase): @pytest.fixture(autouse=True) - def capfd(self, capfd): + def _capfd(self, capfd: Any) -> None: self.capfd = capfd @patch("argparse._sys.argv", ["run_build.py", "--help"]) - def test_usage(self): + def test_usage(self) -> None: with self.assertRaises(SystemExit): main() @@ -41,7 +42,7 @@ def test_usage(self): @patch("run_build.Builders.builder_from", return_value=MagicMock()) @patch("run_build.BuildRecorder", return_value=MagicMock()) @patch("run_build.TemporaryDirectory") - def test_main_platform_linux(self, mock_temp, mock_recorder, mock_builder, *mocks): + def test_main_platform_linux(self, mock_temp: Mock, mock_recorder: Mock, mock_builder: Mock, *mocks: Any) -> None: mock_temp.return_value.__enter__.return_value.name = tempfile.gettempdir() main() self.assertNotEqual(mock_builder.return_value.build.call_count, 0) @@ -52,7 +53,7 @@ def test_main_platform_linux(self, mock_temp, mock_recorder, mock_builder, *mock @patch("run_build.Builders.builder_from", return_value=MagicMock()) @patch("run_build.BuildRecorder", return_value=MagicMock()) @patch("run_build.TemporaryDirectory") - def test_main_platform_darwin(self, mock_temp, mock_recorder, mock_builder, *mocks): + def test_main_platform_darwin(self, mock_temp: Mock, mock_recorder: Mock, mock_builder: Mock, *mocks: Any) -> None: mock_temp.return_value.__enter__.return_value.name = tempfile.gettempdir() main() self.assertNotEqual(mock_builder.return_value.build.call_count, 0) @@ -63,7 +64,7 @@ def test_main_platform_darwin(self, mock_temp, mock_recorder, mock_builder, *moc @patch("run_build.Builders.builder_from", return_value=MagicMock()) @patch("run_build.BuildRecorder", return_value=MagicMock()) @patch("run_build.TemporaryDirectory") - def test_main_platform_windows(self, mock_temp, mock_recorder, mock_builder, *mocks): + def test_main_platform_windows(self, mock_temp: Mock, mock_recorder: Mock, mock_builder: Mock, *mocks: Any) -> None: mock_temp.return_value.__enter__.return_value.name = tempfile.gettempdir() main() # excludes performance analyzer and k-nn @@ -92,7 +93,7 @@ def test_main_platform_windows(self, mock_temp, mock_recorder, mock_builder, *mo @patch("run_build.Builders.builder_from", return_value=MagicMock()) @patch("run_build.BuildRecorder", return_value=MagicMock()) @patch("run_build.TemporaryDirectory") - def test_main_with_architecture(self, mock_temp, mock_recorder, mock_builder, *mocks): + def test_main_with_architecture(self, mock_temp: Mock, mock_recorder: Mock, mock_builder: Mock, *mocks: Any) -> None: mock_temp.return_value.__enter__.return_value.name = tempfile.gettempdir() main() self.assertEqual(mock_builder.return_value.build.call_count, 11) @@ -100,12 +101,12 @@ def test_main_with_architecture(self, mock_temp, mock_recorder, mock_builder, *m mock_recorder.return_value.write_manifest.assert_called() @patch("argparse._sys.argv", ["run_build.py", OPENSEARCH_DASHBOARDS_MANIFEST, "-p", "invalidplatform", "-a", "x64"]) - def test_main_with_invalid_platform(self, *mocks): + def test_main_with_invalid_platform(self, *mocks: Any) -> None: with self.assertRaises(SystemExit): main() @patch("argparse._sys.argv", ["run_build.py", OPENSEARCH_DASHBOARDS_MANIFEST, "-p", "linux", "-a", "invalidarchitecture"]) - def test_main_with_invalid_architecture(self, *mocks): + def test_main_with_invalid_architecture(self, *mocks: Any) -> None: with self.assertRaises(SystemExit): main() @@ -115,9 +116,8 @@ def test_main_with_invalid_architecture(self, *mocks): @patch("run_build.InputManifest.stable", return_value=InputManifest.from_path(OPENSEARCH_MANIFEST)) @patch("run_build.InputManifest.to_file") @patch("logging.info") - def test_main_manifest_lock_without_changes(self, mock_logging, mock_to_file, mock_stable, *mocks): - with self.assertRaises(SystemExit): - main() + def test_main_manifest_lock_without_changes(self, mock_logging: Mock, mock_to_file: Mock, mock_stable: Mock, *mocks: Any) -> None: + main() mock_stable.assert_called_with() mock_to_file.assert_not_called() mock_logging.assert_called_with(f"No changes since {self.OPENSEARCH_MANIFEST}.lock") @@ -128,9 +128,8 @@ def test_main_manifest_lock_without_changes(self, mock_logging, mock_to_file, mo @patch("run_build.InputManifest.stable", return_value=InputManifest.from_path(OPENSEARCH_MANIFEST_1_2)) @patch("run_build.InputManifest.to_file") @patch("logging.info") - def test_main_manifest_lock_with_changes(self, mock_logging, mock_to_file, mock_stable, *mocks): - with self.assertRaises(SystemExit): - main() + def test_main_manifest_lock_with_changes(self, mock_logging: Mock, mock_to_file: Mock, mock_stable: Mock, *mocks: Any) -> None: + main() mock_stable.assert_called_with() mock_to_file.assert_called_with(self.OPENSEARCH_MANIFEST + ".lock") mock_logging.assert_called_with(f"Updating {self.OPENSEARCH_MANIFEST}.lock") @@ -141,9 +140,8 @@ def test_main_manifest_lock_with_changes(self, mock_logging, mock_to_file, mock_ @patch("run_build.InputManifest.stable", return_value=InputManifest.from_path(OPENSEARCH_MANIFEST_1_2)) @patch("run_build.InputManifest.to_file") @patch("logging.info") - def test_main_manifest_new_lock(self, mock_logging, mock_to_file, mock_stable, *mocks): - with self.assertRaises(SystemExit): - main() + def test_main_manifest_new_lock(self, mock_logging: Mock, mock_to_file: Mock, mock_stable: Mock, *mocks: Any) -> None: + main() mock_stable.assert_called_with() mock_to_file.assert_called_with(self.OPENSEARCH_MANIFEST + ".lock") mock_logging.assert_called_with(f"Creating {self.OPENSEARCH_MANIFEST}.lock") @@ -154,9 +152,8 @@ def test_main_manifest_new_lock(self, mock_logging, mock_to_file, mock_stable, * @patch("run_build.InputManifest.stable", return_value=InputManifest.from_path(OPENSEARCH_MANIFEST_1_2)) @patch("run_build.InputManifest.to_file") @patch("logging.info") - def test_main_manifest_new_lock_with_overrides(self, mock_logging, mock_to_file, mock_stable, *mocks): - with self.assertRaises(SystemExit): - main() + def test_main_manifest_new_lock_with_overrides(self, mock_logging: Mock, mock_to_file: Mock, mock_stable: Mock, *mocks: Any) -> None: + main() mock_stable.assert_called_with() mock_to_file.assert_called_with(self.OPENSEARCH_MANIFEST + ".lock") mock_logging.assert_called_with(f"Creating {self.OPENSEARCH_MANIFEST}.lock") diff --git a/tests/test_run_checkout.py b/tests/test_run_checkout.py index 0efe7d3838..d0fdd2ceb6 100644 --- a/tests/test_run_checkout.py +++ b/tests/test_run_checkout.py @@ -7,7 +7,8 @@ import os import tempfile import unittest -from unittest.mock import MagicMock, call, patch +from typing import Any +from unittest.mock import MagicMock, Mock, call, patch import pytest @@ -16,11 +17,11 @@ class TestRunCheckout(unittest.TestCase): @pytest.fixture(autouse=True) - def capfd(self, capfd): + def _capfd(self, capfd: Any) -> None: self.capfd = capfd @patch("argparse._sys.argv", ["run_checkout.py", "--help"]) - def test_usage(self): + def test_usage(self) -> None: with self.assertRaises(SystemExit): main() @@ -32,7 +33,7 @@ def test_usage(self): @patch("argparse._sys.argv", ["run_checkout.py", OPENSEARCH_MANIFEST]) @patch("run_checkout.GitRepository") @patch("run_checkout.TemporaryDirectory") - def test_main(self, mock_temp, mock_repo): + def test_main(self, mock_temp: Mock, mock_repo: Mock) -> None: mock_temp.return_value.__enter__.return_value.name = tempfile.gettempdir() mock_repo.return_value.__enter__.return_value = MagicMock(working_directory="dummy") diff --git a/tests/test_run_ci.py b/tests/test_run_ci.py index 8342d90cf5..cd313505df 100644 --- a/tests/test_run_ci.py +++ b/tests/test_run_ci.py @@ -7,7 +7,8 @@ import os import tempfile import unittest -from unittest.mock import call, patch +from typing import Any +from unittest.mock import Mock, call, patch import pytest @@ -16,11 +17,11 @@ class TestRunCi(unittest.TestCase): @pytest.fixture(autouse=True) - def capfd(self, capfd): + def _capfd(self, capfd: Any) -> None: self.capfd = capfd @patch("argparse._sys.argv", ["run_ci.py", "--help"]) - def test_usage(self): + def test_usage(self) -> None: with self.assertRaises(SystemExit): main() @@ -32,7 +33,7 @@ def test_usage(self): @patch("argparse._sys.argv", ["run_ci.py", OPENSEARCH_MANIFEST]) @patch("ci_workflow.ci_input_manifest.TemporaryDirectory") @patch("ci_workflow.ci_input_manifest.CiCheckLists.from_component") - def test_main(self, mock_lists, mock_temp, *mocks): + def test_main(self, mock_lists: Mock, mock_temp: Mock, *mocks: Any) -> None: mock_temp.return_value.__enter__.return_value.name = tempfile.gettempdir() main() self.assertNotEqual(mock_lists.call_count, 0) @@ -43,7 +44,7 @@ def test_main(self, mock_lists, mock_temp, *mocks): @patch("argparse._sys.argv", ["run_ci.py", OPENSEARCH_TEST_MANIFEST]) @patch("logging.info") - def test_main_test_manifest(self, mock_logging, *mocks): + def test_main_test_manifest(self, mock_logging: Mock, *mocks: Any) -> None: main() mock_logging.assert_has_calls([ call("TestManifest schema validation succeeded"), @@ -53,6 +54,6 @@ def test_main_test_manifest(self, mock_logging, *mocks): OPENSEARCH_TEST_MANIFEST_NOT_EXIST = os.path.realpath(os.path.join(os.path.dirname(__file__), "../manifests/1.4.0/opensearch-1.3.0-test.yml")) @patch("argparse._sys.argv", ["run_ci.py", OPENSEARCH_TEST_MANIFEST_NOT_EXIST]) - def test_main_test_manifest_empty(self, *mocks): + def test_main_test_manifest_empty(self, *mocks: Any) -> None: with self.assertRaises(SystemExit): main() diff --git a/tests/test_run_manifests.py b/tests/test_run_manifests.py index a830c00f95..d3d8fb711c 100644 --- a/tests/test_run_manifests.py +++ b/tests/test_run_manifests.py @@ -5,7 +5,8 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, call, patch +from typing import Any +from unittest.mock import MagicMock, Mock, call, patch import pytest @@ -14,11 +15,11 @@ class TestRunManifests(unittest.TestCase): @pytest.fixture(autouse=True) - def capfd(self, capfd): + def _capfd(self, capfd: Any) -> None: self.capfd = capfd @patch("argparse._sys.argv", ["run_manifests.py", "--help"]) - def test_usage(self): + def test_usage(self) -> None: with self.assertRaises(SystemExit): main() @@ -27,7 +28,7 @@ def test_usage(self): @patch("argparse._sys.argv", ["run_manifests.py", "list"]) @patch("run_manifests.logging", return_value=MagicMock()) - def test_main_list(self, mock_logging, *mocks): + def test_main_list(self, mock_logging: Mock, *mocks: Any) -> None: main() mock_logging.info.assert_has_calls([ @@ -52,7 +53,7 @@ def test_main_list(self, mock_logging, *mocks): @patch("argparse._sys.argv", ["run_manifests.py", "update"]) @patch("manifests_workflow.manifests_args.InputManifestsOpenSearch", return_value=MagicMock()) @patch("manifests_workflow.manifests_args.InputManifestsOpenSearchDashboards", return_value=MagicMock()) - def test_main_update(self, mock_manifests_opensearch_dashboards, mock_manifests_opensearch, *mocks): + def test_main_update(self, mock_manifests_opensearch_dashboards: Mock, mock_manifests_opensearch: Mock, *mocks: Any) -> None: main() mock_manifests_opensearch_dashboards.return_value.update.assert_called() mock_manifests_opensearch.return_value.update.assert_called() diff --git a/tests/test_run_perf_test.py b/tests/test_run_perf_test.py index 474fa64a4b..006e1aa635 100644 --- a/tests/test_run_perf_test.py +++ b/tests/test_run_perf_test.py @@ -6,7 +6,8 @@ import os import unittest -from unittest.mock import patch +from typing import Any +from unittest.mock import Mock, patch import pytest @@ -15,11 +16,11 @@ class TestRunPerfTest(unittest.TestCase): @pytest.fixture(autouse=True) - def capfd(self, capfd): + def _capfd(self, capfd: Any) -> None: self.capfd = capfd @patch("argparse._sys.argv", ["run_perf_test.py", "--help"]) - def test_usage(self): + def test_usage(self) -> None: with self.assertRaises(SystemExit): main() @@ -43,6 +44,6 @@ def test_usage(self): @patch("argparse._sys.argv", ["run_perf_test.py", "--bundle-manifest", OPENSEARCH_BUNDLE_MANIFEST, "--stack", "test-stack", "--config", PERF_TEST_CONFIG]) @patch("run_perf_test.PerfTestRunners.from_args") - def test_default_execute_perf_test(self, mock_runner, *mocks): + def test_default_execute_perf_test(self, mock_runner: Mock, *mocks: Any) -> None: main() self.assertEqual(1, mock_runner.call_count) diff --git a/tests/test_run_sign.py b/tests/test_run_sign.py index 69c5f24596..89e3186e74 100644 --- a/tests/test_run_sign.py +++ b/tests/test_run_sign.py @@ -6,7 +6,8 @@ import os import unittest -from unittest.mock import patch +from typing import Any +from unittest.mock import Mock, patch import pytest @@ -15,11 +16,11 @@ class TestRunSign(unittest.TestCase): @pytest.fixture(autouse=True) - def capfd(self, capfd): + def _capfd(self, capfd: Any) -> None: self.capfd = capfd @patch("argparse._sys.argv", ["run_sign.py", "--help"]) - def test_usage(self, *mocks): + def test_usage(self, *mocks: Any) -> None: with self.assertRaises(SystemExit): main() @@ -33,7 +34,7 @@ def test_usage(self, *mocks): @patch("argparse._sys.argv", ["run_sign.py", BUILD_MANIFEST]) @patch("run_sign.SignArtifacts") @patch("run_sign.Signer") - def test_main(self, mock_signer, mock_sign_artifacts, *mocks): + def test_main(self, mock_signer: Mock, mock_sign_artifacts: Mock, *mocks: Any) -> None: main() mock_sign_artifacts.from_path.assert_called_once() diff --git a/tests/tests_git/test_git_repository.py b/tests/tests_git/test_git_repository.py index fe42903985..4e47a39aa4 100644 --- a/tests/tests_git/test_git_repository.py +++ b/tests/tests_git/test_git_repository.py @@ -7,20 +7,21 @@ import os import subprocess import unittest -from unittest.mock import patch +from typing import Any +from unittest.mock import Mock, patch from git.git_repository import GitRepository from system.temporary_directory import TemporaryDirectory class TestGitRepository(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.repo = GitRepository( url="https://github.com/opensearch-project/.github", ref="8ac515431bf24caf92fea9d9b0af3b8f10b88453", ) - def test_checkout(self): + def test_checkout(self) -> None: self.assertEqual(self.repo.url, "https://github.com/opensearch-project/.github") self.assertEqual(self.repo.ref, "8ac515431bf24caf92fea9d9b0af3b8f10b88453") self.assertEqual(self.repo.sha, "8ac515431bf24caf92fea9d9b0af3b8f10b88453") @@ -30,19 +31,19 @@ def test_checkout(self): # was added in the next commit self.assertFalse(os.path.exists(os.path.join(self.repo.dir, "CONTRIBUTING.md"))) - def test_execute(self): + def test_execute(self) -> None: self.repo.execute("echo $PWD > created.txt") self.assertTrue(os.path.isfile(os.path.join(self.repo.dir, "created.txt"))) - def test_execute_in_dir(self): + def test_execute_in_dir(self) -> None: self.repo.execute("echo $PWD > created.txt", os.path.join(self.repo.dir, "ISSUE_TEMPLATE")) self.assertFalse(os.path.isfile(os.path.join(self.repo.dir, "created.txt"))) self.assertTrue(os.path.isfile(os.path.join(self.repo.dir, "ISSUE_TEMPLATE", "created.txt"))) @patch("subprocess.check_call") - def test_execute_silent(self, mock_subprocess): + def test_execute_silent(self, mock_subprocess: Mock) -> None: self.repo.execute_silent("echo .") - subprocess.check_call.assert_called_with( + mock_subprocess.assert_called_with( "echo .", cwd=self.repo.dir, shell=True, @@ -51,13 +52,13 @@ def test_execute_silent(self, mock_subprocess): ) @patch("subprocess.check_output") - def test_output(self, mock_subprocess): + def test_output(self, mock_subprocess: Any) -> None: self.repo.output("echo hello") - subprocess.check_output.assert_called_with("echo hello", cwd=self.repo.dir, shell=True) + mock_subprocess.assert_called_with("echo hello", cwd=self.repo.dir, shell=True) class TestGitRepositoryDir(unittest.TestCase): - def test_checkout_into_dir(self): + def test_checkout_into_dir(self) -> None: with TemporaryDirectory() as tmpdir: subdir = os.path.join(tmpdir.name, ".github") repo = GitRepository( @@ -75,7 +76,7 @@ def test_checkout_into_dir(self): class TestGitRepositoryWithWorkingDir(unittest.TestCase): - def test_checkout_into_dir(self): + def test_checkout_into_dir(self) -> None: with GitRepository( url="https://github.com/opensearch-project/.github", ref="163b5acaf6c7d220f800684801bbf2e12f99c797", @@ -89,14 +90,14 @@ def test_checkout_into_dir(self): class TestGitRepositoryClassMethods(unittest.TestCase): @patch("subprocess.check_output") - def test_stable_ref(self, mock_output): + def test_stable_ref(self, mock_output: Mock) -> None: mock_output.return_value.decode.return_value = "sha\tHEAD" ref, name = GitRepository.stable_ref("https://github.com/opensearch-project/OpenSearch", "sha") self.assertEqual(ref, "sha") self.assertEqual(name, "HEAD") @patch("subprocess.check_output") - def test_stable_ref_none(self, mock_output): + def test_stable_ref_none(self, mock_output: Mock) -> None: mock_output.return_value.decode.return_value = "" ref, name = GitRepository.stable_ref("https://github.com/opensearch-project/OpenSearch", "sha") self.assertEqual(ref, "sha") diff --git a/tests/tests_manifests/test_input_manifest.py b/tests/tests_manifests/test_input_manifest.py index 8d3f5a9ffe..39daa36ac1 100644 --- a/tests/tests_manifests/test_input_manifest.py +++ b/tests/tests_manifests/test_input_manifest.py @@ -157,9 +157,9 @@ def test_component___matches_platform__(self) -> None: data = {"name": "x", "repository": "", "ref": ""} self.assertTrue(InputComponent(data).__matches__(platform=None)) self.assertTrue(InputComponent(data).__matches__(platform="x")) - self.assertTrue(InputComponent({**data, "platforms": ["linux"]}).__matches__(platform="linux")) - self.assertTrue(InputComponent({**data, "platforms": ["linux", "windows"]}).__matches__(platform="linux")) - self.assertFalse(InputComponent({**data, "platforms": ["linux"]}).__matches__(platform="x")) + self.assertTrue(InputComponent({**data, "platforms": ["linux"]}).__matches__(platform="linux")) # type: ignore + self.assertTrue(InputComponent({**data, "platforms": ["linux", "windows"]}).__matches__(platform="linux")) # type: ignore + self.assertFalse(InputComponent({**data, "platforms": ["linux"]}).__matches__(platform="x")) # type: ignore def test_component___matches_focus__(self) -> None: component = InputComponent({"name": "x", "repository": "", "ref": ""}) diff --git a/tests/tests_paths/test_tree_walker.py b/tests/tests_paths/test_tree_walker.py index 5152bd32c3..da171312cc 100644 --- a/tests/tests_paths/test_tree_walker.py +++ b/tests/tests_paths/test_tree_walker.py @@ -17,7 +17,7 @@ def setUp(self) -> None: self.data_path = os.path.realpath(os.path.join(os.path.dirname(__file__), "data")) def test_walk(self) -> None: - paths = sorted(list(itertools.chain(walk(self.data_path))), key=lambda path: path[0]) + paths = sorted(list(itertools.chain(walk(self.data_path))), key=lambda path: path[0]) # type: ignore self.assertTrue(len(paths), 7) self.assertEqual( paths[0][1], diff --git a/tests/tests_sign_workflow/test_sign_artifacts.py b/tests/tests_sign_workflow/test_sign_artifacts.py index 317207b17f..0f37d07d1b 100644 --- a/tests/tests_sign_workflow/test_sign_artifacts.py +++ b/tests/tests_sign_workflow/test_sign_artifacts.py @@ -1,7 +1,8 @@ import os import unittest from pathlib import Path -from unittest.mock import MagicMock, patch +from typing import Any +from unittest.mock import MagicMock, Mock, patch from sign_workflow.sign_artifacts import SignArtifacts, SignArtifactsExistingArtifactFile, SignExistingArtifactsDir, SignWithBuildManifest @@ -10,7 +11,7 @@ class TestSignArtifacts(unittest.TestCase): @patch("sign_workflow.signer.GitRepository") @patch("sign_workflow.signer.Signer", return_value=MagicMock()) - def test_from_path_method(self, mock_signer, *mocks): + def test_from_path_method(self, mock_signer: Mock, *mocks: Any) -> None: components = ['maven'] artifact_type = 'dummy' sigtype = '.asc' @@ -24,7 +25,7 @@ def test_from_path_method(self, mock_signer, *mocks): klass = SignArtifacts.from_path(Path(r"/dummy/path/artifact.tar.gz"), components, artifact_type, sigtype, mock_signer) self.assertEqual(type(SignArtifactsExistingArtifactFile), type(klass.__class__)) - def test_signer_class(self): + def test_signer_class(self) -> None: self.assertIs(SignArtifacts.__signer_class__( Path(r"/dummy/path/manifest.yml")), SignWithBuildManifest) @@ -37,7 +38,7 @@ def test_signer_class(self): Path(r"/dummy/path/artifact.tar.gz")), SignArtifactsExistingArtifactFile) - def test_sign_with_build_manifest(self): + def test_sign_with_build_manifest(self) -> None: manifest = Path(os.path.join(os.path.dirname(__file__), "data", "opensearch-build-1.1.0.yml")) sigtype = '.asc' signer = MagicMock() @@ -59,7 +60,7 @@ def test_sign_with_build_manifest(self): ] signer.sign_artifacts.assert_called_with(expected, manifest.parent, sigtype) - def test_sign_existing_artifacts_file(self): + def test_sign_existing_artifacts_file(self) -> None: path = Path(r"/dummy/path/file.tar.gz") sigtype = '.sig' signer = MagicMock() @@ -74,7 +75,7 @@ def test_sign_existing_artifacts_file(self): signer.sign_artifact.assert_called_with("file.tar.gz", path.parent, sigtype) @patch('os.walk') - def test_sign_existing_artifacts_folder(self, mock_os_walk): + def test_sign_existing_artifacts_folder(self, mock_os_walk: Mock) -> None: mock_os_walk.return_value = [ ('dummy', (), ['tar_dummy_artifact_1.0.0.tar.gz', 'zip_dummy_artifact_1.1.0.zip']) ] @@ -90,4 +91,4 @@ def test_sign_existing_artifacts_folder(self, mock_os_walk): ) signer_with_manifest.sign() expected = ["tar_dummy_artifact_1.0.0.tar.gz", "zip_dummy_artifact_1.1.0.zip"] - signer.sign_artifacts.assert_called_with(expected, str(path), sigtype) + signer.sign_artifacts.assert_called_with(expected, path, sigtype) diff --git a/tests/tests_sign_workflow/test_signer.py b/tests/tests_sign_workflow/test_signer.py index f85b5d8893..c1a83826ce 100644 --- a/tests/tests_sign_workflow/test_signer.py +++ b/tests/tests_sign_workflow/test_signer.py @@ -1,13 +1,14 @@ import os import unittest -from unittest.mock import MagicMock, call, patch +from pathlib import Path +from unittest.mock import MagicMock, Mock, call, patch from sign_workflow.signer import Signer class TestSigner(unittest.TestCase): @patch("sign_workflow.signer.GitRepository") - def test_accepted_file_types_asc(self, git_repo): + def test_accepted_file_types_asc(self, git_repo: Mock) -> None: artifacts = [ "bad-xml.xml", "the-jar.jar", @@ -33,12 +34,12 @@ def test_accepted_file_types_asc(self, git_repo): call(os.path.join("path", "something-1.0.0.0.jar"), ".asc"), ] signer = Signer() - signer.sign = MagicMock() - signer.sign_artifacts(artifacts, "path", ".asc") + signer.sign = MagicMock() # type: ignore + signer.sign_artifacts(artifacts, Path("path"), ".asc") self.assertEqual(signer.sign.call_args_list, expected) @patch("sign_workflow.signer.GitRepository") - def test_accepted_file_types_sig(self, git_repo): + def test_accepted_file_types_sig(self, git_repo: Mock) -> None: artifacts = [ "bad-xml.xml", "the-jar.jar", @@ -68,8 +69,8 @@ def test_accepted_file_types_sig(self, git_repo): call(os.path.join("path", "cratefile.crate"), ".sig") ] signer = Signer() - signer.sign = MagicMock() - signer.sign_artifacts(artifacts, "path", ".sig") + signer.sign = MagicMock() # type: ignore + signer.sign_artifacts(artifacts, Path("path"), ".sig") self.assertEqual(signer.sign.call_args_list, expected) @patch( @@ -77,60 +78,60 @@ def test_accepted_file_types_sig(self, git_repo): return_value="https://github.com/opensearch-project/.github", ) @patch("sign_workflow.signer.GitRepository.execute") - def test_signer_checks_out_tool(self, mock_execute, mock_signer): + def test_signer_checks_out_tool(self, mock_execute: Mock, mock_signer: Mock) -> None: Signer() self.assertEqual(mock_execute.call_count, 2) mock_execute.assert_has_calls([call("./bootstrap"), call("rm config.cfg")]) @patch("sign_workflow.signer.GitRepository") - def test_signer_verify_asc(self, mock_repo): + def test_signer_verify_asc(self, mock_repo: Mock) -> None: signer = Signer() signer.verify("/path/the-jar.jar.asc") mock_repo.assert_has_calls([call().execute("gpg --verify-files /path/the-jar.jar.asc")]) @patch("sign_workflow.signer.GitRepository") - def test_signer_verify_sig(self, mock_repo): + def test_signer_verify_sig(self, mock_repo: Mock) -> None: signer = Signer() signer.verify("/path/the-jar.jar.sig") mock_repo.assert_has_calls([call().execute("gpg --verify-files /path/the-jar.jar.sig")]) @patch("sign_workflow.signer.GitRepository") - def test_signer_sign_asc(self, mock_repo): + def test_signer_sign_asc(self, mock_repo: Mock) -> None: signer = Signer() signer.sign("/path/the-jar.jar", ".asc") mock_repo.assert_has_calls( [call().execute("./opensearch-signer-client -i /path/the-jar.jar -o /path/the-jar.jar.asc -p pgp")]) @patch("sign_workflow.signer.GitRepository") - def test_signer_sign_sig(self, mock_repo): + def test_signer_sign_sig(self, mock_repo: Mock) -> None: signer = Signer() signer.sign("/path/the-jar.jar", ".sig") mock_repo.assert_has_calls( [call().execute("./opensearch-signer-client -i /path/the-jar.jar -o /path/the-jar.jar.sig -p pgp")]) @patch("sign_workflow.signer.GitRepository") - def test_sign_artifact_not_called(self, mock_repo): + def test_sign_artifact_not_called(self, mock_repo: Mock) -> None: signer = Signer() - signer.generate_signature_and_verify = MagicMock() - signer.sign_artifact("the-jar.notvalid", "/path", ".sig") + signer.generate_signature_and_verify = MagicMock() # type: ignore + signer.sign_artifact("the-jar.notvalid", Path("/path"), ".sig") signer.generate_signature_and_verify.assert_not_called() @patch("sign_workflow.signer.GitRepository") - def test_sign_artifact_called(self, mock_repo): + def test_sign_artifact_called(self, mock_repo: Mock) -> None: signer = Signer() - signer.generate_signature_and_verify = MagicMock() - signer.sign_artifact("the-jar.zip", "/path", ".sig") - signer.generate_signature_and_verify.assert_called_with("the-jar.zip", "/path", ".sig") + signer.generate_signature_and_verify = MagicMock() # type: ignore + signer.sign_artifact("the-jar.zip", Path("/path"), ".sig") + signer.generate_signature_and_verify.assert_called_with("the-jar.zip", Path("/path"), ".sig") @patch("sign_workflow.signer.GitRepository") - def test_remove_existing_signature_found(self, mock_repo): + def test_remove_existing_signature_found(self, mock_repo: Mock) -> None: signer = Signer() os.remove = MagicMock() signer.sign("tests/tests_sign_workflow/data/signature/tar_dummy_artifact_1.0.0.tar.gz", ".sig") os.remove.assert_called_with("tests/tests_sign_workflow/data/signature/tar_dummy_artifact_1.0.0.tar.gz.sig") @patch("sign_workflow.signer.GitRepository") - def test_remove_existing_signature_not_found(self, mock_repo): + def test_remove_existing_signature_not_found(self, mock_repo: Mock) -> None: signer = Signer() os.remove = MagicMock() signer.sign("tests/tests_sign_workflow/data/signature/not_found.tar.gz", ".sig") diff --git a/tests/tests_system/test_temporary_directory.py b/tests/tests_system/test_temporary_directory.py index de317b66fd..1907c20dfd 100644 --- a/tests/tests_system/test_temporary_directory.py +++ b/tests/tests_system/test_temporary_directory.py @@ -7,6 +7,7 @@ import os import stat import unittest +from pathlib import Path from system.temporary_directory import TemporaryDirectory @@ -44,3 +45,8 @@ def test_chdir_false(self) -> None: with TemporaryDirectory(): self.assertEqual(before_dir, os.getcwd()) self.assertEqual(before_dir, os.getcwd()) + + def test_path(self) -> None: + with TemporaryDirectory() as work_dir: + self.assertIsInstance(work_dir.path, Path) + self.assertTrue(work_dir.path.exists()) diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch.py index 4d512e92c7..2bbad28dbc 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch.py @@ -5,13 +5,13 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.bwc_test.bwc_test_runner_opensearch import BwcTestRunnerOpenSearch class TestBwcTestRunnerOpenSearch(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.args = MagicMock() self.args.paths = {"opensearch": "test-path"} self.args.component = "sql" @@ -23,7 +23,7 @@ def setUp(self): @patch("test_workflow.bwc_test.bwc_test_runner_opensearch.BwcTestSuiteOpenSearch") @patch("test_workflow.bwc_test.bwc_test_runner.TestRecorder") @patch("test_workflow.bwc_test.bwc_test_runner.TemporaryDirectory") - def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_properties): + def test_with_bwc_test(self, mock_temp: Mock, mock_test_recorder: Mock, mock_suite: Mock, mock_properties: Mock) -> None: mock_test_config = MagicMock() mock_test_config.bwc_test = MagicMock() self.test_manifest.components = {"sql": mock_test_config} @@ -48,7 +48,8 @@ def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_pro mock_suite_object.execute_tests.return_value = mock_test_results mock_suite.return_value = mock_suite_object - mock_temp.return_value.__enter__.return_value.name = "temp-name" + mock_path = MagicMock() + mock_temp.return_value.__enter__.return_value.path = mock_path mock_test_recorder_object = MagicMock() mock_test_recorder.return_value = mock_test_recorder_object @@ -60,7 +61,7 @@ def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_pro self.assertEqual(results["sql"], mock_test_results) mock_suite.assert_called_once_with( - "temp-name", + mock_path, mock_component, mock_test_config, mock_test_recorder_object, @@ -69,7 +70,7 @@ def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_pro @patch("test_workflow.bwc_test.bwc_test_runner_opensearch.BwcTestStartPropertiesOpenSearch") @patch("test_workflow.bwc_test.bwc_test_runner_opensearch.BwcTestSuiteOpenSearch") - def test_without_bwc_test(self, mock_suite, mock_properties): + def test_without_bwc_test(self, mock_suite: Mock, mock_properties: Mock) -> None: mock_test_config = MagicMock() mock_test_config.bwc_test = None self.test_manifest.components = {"sql": mock_test_config} @@ -99,7 +100,7 @@ def test_without_bwc_test(self, mock_suite, mock_properties): @patch("test_workflow.bwc_test.bwc_test_runner_opensearch.BwcTestStartPropertiesOpenSearch") @patch("test_workflow.bwc_test.bwc_test_runner_opensearch.BwcTestSuiteOpenSearch") - def test_component_not_in_test_manifest(self, mock_suite, mock_properties): + def test_component_not_in_test_manifest(self, mock_suite: Mock, mock_properties: Mock) -> None: mock_test_config = MagicMock() mock_test_config.bwc_test = MagicMock() self.test_manifest.components = {"alerting": mock_test_config} diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch_dashboards.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch_dashboards.py index badbd88d33..75a5100dae 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runner_opensearch_dashboards.py @@ -5,13 +5,13 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards import BwcTestRunnerOpenSearchDashboards class TestBwcTestRunnerOpenSearchDashboards(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.args = MagicMock() self.args.paths = {"opensearch-dashboards": "test-path"} self.args.component = "sql" @@ -23,7 +23,7 @@ def setUp(self): @patch("test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards.BwcTestSuiteOpenSearchDashboards") @patch("test_workflow.bwc_test.bwc_test_runner.TestRecorder") @patch("test_workflow.bwc_test.bwc_test_runner.TemporaryDirectory") - def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_properties): + def test_with_bwc_test(self, mock_temp: Mock, mock_test_recorder: Mock, mock_suite: Mock, mock_properties: Mock) -> None: mock_test_config = MagicMock() mock_test_config.bwc_test = MagicMock() self.test_manifest.components = {"sql": mock_test_config} @@ -48,7 +48,8 @@ def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_pro mock_suite_object.execute_tests.return_value = mock_test_results mock_suite.return_value = mock_suite_object - mock_temp.return_value.__enter__.return_value.name = "temp-name" + mock_path = MagicMock() + mock_temp.return_value.__enter__.return_value.path = mock_path mock_test_recorder_object = MagicMock() mock_test_recorder.return_value = mock_test_recorder_object @@ -60,7 +61,7 @@ def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_pro self.assertEqual(results["sql"], mock_test_results) mock_suite.assert_called_once_with( - "temp-name", + mock_path, mock_component, mock_test_config, mock_test_recorder_object, @@ -69,7 +70,7 @@ def test_with_bwc_test(self, mock_temp, mock_test_recorder, mock_suite, mock_pro @patch("test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards.BwcTestStartPropertiesOpenSearchDashboards") @patch("test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards.BwcTestSuiteOpenSearchDashboards") - def test_without_bwc_test(self, mock_suite, mock_properties): + def test_without_bwc_test(self, mock_suite: Mock, mock_properties: Mock) -> None: mock_test_config = MagicMock() mock_test_config.bwc_test = None self.test_manifest.components = {"sql": mock_test_config} @@ -99,7 +100,7 @@ def test_without_bwc_test(self, mock_suite, mock_properties): @patch("test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards.BwcTestStartPropertiesOpenSearchDashboards") @patch("test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards.BwcTestSuiteOpenSearchDashboards") - def test_component_not_in_test_manifest(self, mock_suite, mock_properties): + def test_component_not_in_test_manifest(self, mock_suite: Mock, mock_properties: Mock) -> None: mock_test_config = MagicMock() mock_test_config.bwc_test = MagicMock() self.test_manifest.components = {"alerting": mock_test_config} diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runners.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runners.py index 74fa7d929d..f69a792179 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runners.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_runners.py @@ -12,7 +12,7 @@ class TestBwcTestRunners(unittest.TestCase): - def test_opensearch(self): + def test_opensearch(self) -> None: mock_args = MagicMock() mock_test_manifest = MagicMock() @@ -34,7 +34,7 @@ def test_opensearch(self): mock_opensearch_runner.assert_called_once_with(mock_args, mock_test_manifest) - def test_opensearch_dashboards(self): + def test_opensearch_dashboards(self) -> None: mock_args = MagicMock() mock_test_manifest = MagicMock() diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch.py index 7ec2b60d2e..2fab01759a 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch.py @@ -5,7 +5,7 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.bwc_test.bwc_test_start_properties_opensearch import BwcTestStartPropertiesOpenSearch @@ -14,7 +14,7 @@ class TestBwcTestStartPropertiesOpenSearch(unittest.TestCase): @patch("test_workflow.bwc_test.bwc_test_start_properties.BundleManifest") @patch("test_workflow.bwc_test.bwc_test_start_properties.BuildManifest") - def test(self, mock_build, mock_bundle): + def test(self, mock_build: Mock, mock_bundle: Mock) -> None: path = "test-path" mock_bundle_object = MagicMock() diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch_dashboards.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch_dashboards.py index d76515fb35..fd8317d769 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_start_properties_opensearch_dashboards.py @@ -5,7 +5,7 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.bwc_test.bwc_test_start_properties_opensearch_dashboards import BwcTestStartPropertiesOpenSearchDashboards @@ -14,7 +14,7 @@ class TestBwcTestStartPropertiesOpenSearchDashboards(unittest.TestCase): @patch("test_workflow.bwc_test.bwc_test_start_properties.BundleManifest") @patch("test_workflow.bwc_test.bwc_test_start_properties.BuildManifest") - def test(self, mock_build, mock_bundle): + def test(self, mock_build: Mock, mock_bundle: Mock) -> None: path = "test-path" mock_bundle_object = MagicMock() diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch.py index 2ae71854db..7d34c851a6 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch.py @@ -6,12 +6,14 @@ import os import unittest -from unittest.mock import MagicMock, call, patch +from pathlib import Path +from typing import Any, Tuple +from unittest.mock import MagicMock, Mock, call, patch from git.git_repository import GitRepository from manifests.build_manifest import BuildManifest -from manifests.bundle_manifest import BundleManifest -from manifests.test_manifest import TestManifest +from manifests.bundle_manifest import BundleComponent, BundleManifest +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.bwc_test.bwc_test_suite import InvalidTestConfigError, ScriptFinder from test_workflow.bwc_test.bwc_test_suite_opensearch import BwcTestSuiteOpenSearch @@ -25,18 +27,18 @@ class TestBwcSuiteOpenSearch(unittest.TestCase): BUNDLE_MANIFEST = os.path.join(DATA, "bundle_manifest.yml") TEST_MANIFEST = os.path.join(DATA, "test_manifest.yml") - def setUp(self): + def setUp(self) -> None: os.chdir(os.path.dirname(__file__)) self.bundle_manifest = BundleManifest.from_path(self.BUNDLE_MANIFEST) self.build_manifest = BuildManifest.from_path(self.BUILD_MANIFEST) self.test_manifest = TestManifest.from_path(self.TEST_MANIFEST) - self.work_dir = "test_dir" + self.work_dir = Path("test_dir") self.test_recorder = MagicMock() self.save_logs = MagicMock() self.test_recorder.test_results_logs = self.save_logs @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute(self, mock_test_recorder, *mock): + def test_execute(self, mock_test_recorder: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("index-management") bwc_test_suite = BwcTestSuiteOpenSearch( self.work_dir, @@ -48,7 +50,7 @@ def test_execute(self, mock_test_recorder, *mock): mock_execute_bwctest_sh = MagicMock() mock_execute_bwctest_sh.return_value = "success" - bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh + bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh # type: ignore bwc_test_suite.execute_tests() @@ -59,7 +61,7 @@ def test_execute(self, mock_test_recorder, *mock): @patch("os.path.exists", return_value=True) @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_multiple_test_configs(self, mock_test_recorder, *mock): + def test_execute_with_multiple_test_configs(self, mock_test_recorder: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("job-scheduler") bwc_test_suite = BwcTestSuiteOpenSearch( self.work_dir, @@ -70,7 +72,7 @@ def test_execute_with_multiple_test_configs(self, mock_test_recorder, *mock): ) mock_execute_bwctest_sh = MagicMock() mock_execute_bwctest_sh.return_value = "success" - bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh + bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh # type: ignore test_results = bwc_test_suite.execute_tests() self.assertEqual(len(test_results), 2) @@ -84,7 +86,7 @@ def test_execute_with_multiple_test_configs(self, mock_test_recorder, *mock): @patch("os.path.exists", return_value=True) @patch.object(ScriptFinder, "find_bwc_test_script") @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_working_directory(self, mock_test_recorder, mock_script_finder, *mock): + def test_execute_with_working_directory(self, mock_test_recorder: Mock, mock_script_finder: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") bwc_test_suite = BwcTestSuiteOpenSearch( self.work_dir, @@ -98,7 +100,7 @@ def test_execute_with_working_directory(self, mock_test_recorder, mock_script_fi mock_execute_bwctest_sh = MagicMock() mock_execute_bwctest_sh.return_value = "success" - bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh + bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh # type: ignore bwc_test_suite.execute_tests() @@ -109,13 +111,13 @@ def test_execute_with_working_directory(self, mock_test_recorder, mock_script_fi @patch("test_workflow.bwc_test.bwc_test_suite.TestResultData") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") @patch("test_workflow.bwc_test.bwc_test_suite.execute", return_value=True) - def test_execute_bwctest_sh(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists, *mock): + def test_execute_bwctest_sh(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "dir" @@ -163,12 +165,12 @@ def test_execute_bwctest_sh(self, mock_execute, mock_git, mock_test_result_data, @patch("test_workflow.bwc_test.bwc_test_suite.TestResultData") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") @patch("test_workflow.bwc_test.bwc_test_suite.execute", return_value=True) - def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists, *mock): + def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -187,7 +189,7 @@ def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute, mock_git, mo # call the test target status = suite.execute_bwctest_sh("with-security") - self.assertIsNone(status) + self.assertEqual(0, status) mock_execute.assert_not_called() mock_test_result_data.assert_not_called() @@ -195,12 +197,12 @@ def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute, mock_git, mo @patch("os.path.exists") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") - def test_is_security_enabled(self, mock_git, mock_path_exists, *mock): + def test_is_security_enabled(self, mock_git: Mock, mock_path_exists: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -227,13 +229,13 @@ def test_is_security_enabled(self, mock_git, mock_path_exists, *mock): @patch("test_workflow.bwc_test.bwc_test_suite.logging") @patch("os.path.exists") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") - def test_pretty_print_message(self, mock_git, mock_path_exists, mock_logging, *mock): + def test_pretty_print_message(self, mock_git: Mock, mock_path_exists: Mock, mock_logging: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -257,7 +259,7 @@ def test_pretty_print_message(self, mock_git, mock_path_exists, mock_logging, *m call("==============================================="), ]) - def __get_test_config_and_bundle_component(self, component_name): + def __get_test_config_and_bundle_component(self, component_name: str) -> Tuple[TestComponent, BundleComponent]: component = self.bundle_manifest.components[component_name] test_config = self.test_manifest.components[component.name] return test_config, component diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch_dashboards.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch_dashboards.py index 10c65aaf53..cd7b0bf045 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_bwc_test_suite_opensearch_dashboards.py @@ -7,12 +7,14 @@ import logging import os import unittest -from unittest.mock import MagicMock, call, patch +from pathlib import Path +from typing import Any, Tuple +from unittest.mock import MagicMock, Mock, call, patch from git.git_repository import GitRepository from manifests.build_manifest import BuildManifest from manifests.bundle_manifest import BundleManifest -from manifests.test_manifest import TestManifest +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.bwc_test.bwc_test_suite import InvalidTestConfigError, ScriptFinder from test_workflow.bwc_test.bwc_test_suite_opensearch_dashboards import BwcTestSuiteOpenSearchDashboards @@ -26,19 +28,19 @@ class TestBwcSuiteOpenSearchDashboards(unittest.TestCase): BUNDLE_MANIFEST = os.path.join(DATA, "bundle_manifest.yml") TEST_MANIFEST = os.path.join(DATA, "test_manifest.yml") - def setUp(self): + def setUp(self) -> None: os.chdir(os.path.dirname(__file__)) self.bundle_manifest = BundleManifest.from_path(self.BUNDLE_MANIFEST) self.build_manifest = BuildManifest.from_path(self.BUILD_MANIFEST) self.test_manifest = TestManifest.from_path(self.TEST_MANIFEST) - self.work_dir = "test_dir" + self.work_dir = Path("test_dir") self.test_recorder = MagicMock() self.save_logs = MagicMock() self.test_recorder.test_results_logs = self.save_logs @patch("test_workflow.bwc_test.bwc_test_suite.TestResultData") @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute(self, mock_test_recorder, mock_test_result_data, *mock): + def test_execute(self, mock_test_recorder: Mock, mock_test_result_data: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("index-management") bwc_test_suite = BwcTestSuiteOpenSearchDashboards( self.work_dir, @@ -49,7 +51,7 @@ def test_execute(self, mock_test_recorder, mock_test_result_data, *mock): ) mock_execute_bwctest_sh = MagicMock() - bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh + bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh # type: ignore mock_execute_bwctest_sh.return_value = "success" mock_test_result_data_object = MagicMock() @@ -64,7 +66,7 @@ def test_execute(self, mock_test_recorder, mock_test_result_data, *mock): @patch("os.path.exists", return_value=True) @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_multiple_test_configs(self, mock_test_recorder, *mock): + def test_execute_with_multiple_test_configs(self, mock_test_recorder: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("job-scheduler") bwc_test_suite = BwcTestSuiteOpenSearchDashboards( self.work_dir, @@ -75,7 +77,7 @@ def test_execute_with_multiple_test_configs(self, mock_test_recorder, *mock): ) mock_execute_bwctest_sh = MagicMock() mock_execute_bwctest_sh.return_value = "success" - bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh + bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh # type: ignore test_results = bwc_test_suite.execute_tests() @@ -90,7 +92,7 @@ def test_execute_with_multiple_test_configs(self, mock_test_recorder, *mock): @patch("os.path.exists", return_value=True) @patch.object(ScriptFinder, "find_bwc_test_script") @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_working_directory(self, mock_test_recorder, mock_script_finder, *mock): + def test_execute_with_working_directory(self, mock_test_recorder: Mock, mock_script_finder: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") bwc_test_suite = BwcTestSuiteOpenSearchDashboards( self.work_dir, @@ -104,7 +106,7 @@ def test_execute_with_working_directory(self, mock_test_recorder, mock_script_fi mock_execute_bwctest_sh = MagicMock() mock_execute_bwctest_sh.return_value = "success" - bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh + bwc_test_suite.execute_bwctest_sh = mock_execute_bwctest_sh # type: ignore bwc_test_suite.execute_tests() @@ -115,14 +117,14 @@ def test_execute_with_working_directory(self, mock_test_recorder, mock_script_fi @patch("test_workflow.bwc_test.bwc_test_suite.TestResultData") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") @patch("test_workflow.bwc_test.bwc_test_suite.execute", return_value=True) - def test_execute_bwctest_sh(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists, *mock): + def test_execute_bwctest_sh(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") logging.info(locals()) mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "dir" @@ -172,12 +174,12 @@ def test_execute_bwctest_sh(self, mock_execute, mock_git, mock_test_result_data, @patch("test_workflow.bwc_test.bwc_test_suite.TestResultData") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") @patch("test_workflow.bwc_test.bwc_test_suite.execute", return_value=True) - def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists, *mock): + def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -196,7 +198,7 @@ def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute, mock_git, mo # call the test target status = suite.execute_bwctest_sh("with-security") - self.assertIsNone(status) + self.assertEqual(0, status) mock_execute.assert_not_called() mock_test_result_data.assert_not_called() @@ -204,12 +206,12 @@ def test_execute_bwctest_sh_script_do_not_exist(self, mock_execute, mock_git, mo @patch("os.path.exists") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") - def test_is_security_enabled(self, mock_git, mock_path_exists, *mock): + def test_is_security_enabled(self, mock_git: Mock, mock_path_exists: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -236,13 +238,13 @@ def test_is_security_enabled(self, mock_git, mock_path_exists, *mock): @patch("test_workflow.bwc_test.bwc_test_suite.logging") @patch("os.path.exists") @patch("test_workflow.bwc_test.bwc_test_suite.GitRepository") - def test_pretty_print_message(self, mock_git, mock_path_exists, mock_logging, *mock): + def test_pretty_print_message(self, mock_git: Mock, mock_path_exists: Mock, mock_logging: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") mock_find = MagicMock() mock_find.return_value = "./bwctest.sh" - ScriptFinder.find_bwc_test_script = mock_find + ScriptFinder.find_bwc_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -266,7 +268,7 @@ def test_pretty_print_message(self, mock_git, mock_path_exists, mock_logging, *m call("==============================================="), ]) - def __get_test_config_and_bundle_component(self, component_name): + def __get_test_config_and_bundle_component(self, component_name: str) -> Tuple[TestComponent, Any]: component = self.bundle_manifest.components[component_name] test_config = self.test_manifest.components[component.name] return test_config, component diff --git a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_run_bwc_test.py b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_run_bwc_test.py index a061d8bce9..ed62ae5488 100644 --- a/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_run_bwc_test.py +++ b/tests/tests_test_workflow/test_bwc_workflow/bwc_test/test_run_bwc_test.py @@ -6,6 +6,7 @@ import os import unittest +from typing import Any from unittest.mock import MagicMock, patch from manifests.test_manifest import TestManifest @@ -23,7 +24,7 @@ class TestRunBwcTest(unittest.TestCase): "--paths", "opensearch=" + os.path.join(os.path.dirname(__file__), "..", "..", "data", "remote") ]) - def test_run_bwc_test(self, *mock): + def test_run_bwc_test(self, *mock: Any) -> None: mock_runner = MagicMock() mock_result = MagicMock() @@ -32,7 +33,7 @@ def test_run_bwc_test(self, *mock): mock_runner.run.return_value = mock_result mock_from_test_manifest = MagicMock() mock_from_test_manifest.return_value = mock_runner - BwcTestRunners.from_test_manifest = mock_from_test_manifest + BwcTestRunners.from_test_manifest = mock_from_test_manifest # type: ignore main() diff --git a/tests/tests_test_workflow/test_dependency_installer_opensearch.py b/tests/tests_test_workflow/test_dependency_installer_opensearch.py index 04159aff18..8bdbcea593 100644 --- a/tests/tests_test_workflow/test_dependency_installer_opensearch.py +++ b/tests/tests_test_workflow/test_dependency_installer_opensearch.py @@ -1,6 +1,6 @@ import os import unittest -from unittest.mock import call, patch +from unittest.mock import Mock, call, patch from urllib.error import HTTPError from manifests.build_manifest import BuildManifest @@ -18,7 +18,7 @@ class DependencyInstallerOpenSearchTests(unittest.TestCase): @patch("os.makedirs") @patch("shutil.copyfile") @patch("urllib.request.urlretrieve") - def test_install_maven_dependencies_local(self, mock_request, mock_copyfile, mock_makedirs): + def test_install_maven_dependencies_local(self, mock_request: Mock, mock_copyfile: Mock, mock_makedirs: Mock) -> None: counter = ThreadSafeCounter() mock_copyfile.side_effect = counter.thread_safe_count @@ -50,7 +50,7 @@ def test_install_maven_dependencies_local(self, mock_request, mock_copyfile, moc @patch("os.makedirs") @patch("shutil.copyfile") @patch("urllib.request.urlretrieve") - def test_install_maven_dependencies_remote(self, mock_request, mock_copyfile, mock_makedirs): + def test_install_maven_dependencies_remote(self, mock_request: Mock, mock_copyfile: Mock, mock_makedirs: Mock) -> None: counter = ThreadSafeCounter() mock_request.side_effect = counter.thread_safe_count dependency_installer = DependencyInstallerOpenSearch( @@ -81,9 +81,9 @@ def test_install_maven_dependencies_remote(self, mock_request, mock_copyfile, mo @patch("os.makedirs") @patch("shutil.copyfile") @patch("urllib.request.urlretrieve") - def test_install_maven_dependencies_remote_failure(self, mock_request, mock_copyfile, mock_makedirs): - def mock_retrieve(source, dest): - raise HTTPError(url=source, hdrs={}, fp=None, msg="Not Found", code=404) + def test_install_maven_dependencies_remote_failure(self, mock_request: Mock, mock_copyfile: Mock, mock_makedirs: Mock) -> None: + def mock_retrieve(source: str, dest: str) -> str: + raise HTTPError(url=source, hdrs=None, fp=None, msg="Not Found", code=404) mock_request.side_effect = mock_retrieve @@ -100,7 +100,7 @@ def mock_retrieve(source, dest): @patch("os.makedirs") @patch("shutil.copyfile") @patch("urllib.request.urlretrieve") - def test_install_build_dependencies_local(self, mock_request, mock_copyfile, mock_makedirs): + def test_install_build_dependencies_local(self, mock_request: Mock, mock_copyfile: Mock, mock_makedirs: Mock) -> None: dependency_installer = DependencyInstallerOpenSearch( self.DATA, BuildManifest.from_path(self.BUILD_MANIFEST), @@ -118,7 +118,7 @@ def test_install_build_dependencies_local(self, mock_request, mock_copyfile, moc @patch("os.makedirs") @patch("shutil.copyfile") @patch("urllib.request.urlretrieve") - def test_install_build_dependencies_remote(self, mock_request, mock_copyfile, mock_makedirs): + def test_install_build_dependencies_remote(self, mock_request: Mock, mock_copyfile: Mock, mock_makedirs: Mock) -> None: dependency_installer = DependencyInstallerOpenSearch( "https://ci.opensearch.org/x/y", BuildManifest.from_path(self.BUILD_MANIFEST), BundleManifest.from_path(self.DIST_MANIFEST_REMOTE) ) diff --git a/tests/tests_test_workflow/test_dependency_installer_opensearch_dashboards.py b/tests/tests_test_workflow/test_dependency_installer_opensearch_dashboards.py index e68f08ab06..25e515cfbc 100644 --- a/tests/tests_test_workflow/test_dependency_installer_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_dependency_installer_opensearch_dashboards.py @@ -6,7 +6,7 @@ class DependencyInstallerOpenSearchDashboardsTests(unittest.TestCase): - def test(self): + def test(self) -> None: mock_root_url = MagicMock() mock_build_manifest = MagicMock() mock_bundle_manifest = MagicMock() diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch.py index edfe80c3c1..538468aa9c 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch.py @@ -5,13 +5,13 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.integ_test.integ_test_runner_opensearch import IntegTestRunnerOpenSearch class TestIntegTestRunnerOpenSearch(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.args = MagicMock() self.test_manifest = MagicMock() @@ -19,7 +19,7 @@ def setUp(self): @patch("test_workflow.integ_test.integ_test_runner_opensearch.IntegTestSuiteOpenSearch") @patch("test_workflow.integ_test.integ_test_runner.TestRecorder") @patch("test_workflow.integ_test.integ_test_runner.TemporaryDirectory") - def test_with_integ_test(self, mock_temp, mock_test_recorder, mock_suite, mock_properties): + def test_with_integ_test(self, mock_temp: Mock, mock_test_recorder: Mock, mock_suite: Mock, mock_properties: Mock) -> None: self.args.paths = {"opensearch": "test-path"} self.args.component = "sql" self.args.test_run_id = "12345" @@ -52,7 +52,8 @@ def test_with_integ_test(self, mock_temp, mock_test_recorder, mock_suite, mock_p mock_suite.return_value = mock_suite_object - mock_temp.return_value.__enter__.return_value.name = "temp-name" + mock_path = MagicMock() + mock_temp.return_value.__enter__.return_value.path = mock_path mock_test_recorder_object = MagicMock() mock_test_recorder.return_value = mock_test_recorder_object @@ -70,13 +71,13 @@ def test_with_integ_test(self, mock_temp, mock_test_recorder, mock_suite, mock_p mock_test_config, mock_properties_object.bundle_manifest, mock_properties_object.build_manifest, - "temp-name", + mock_path, mock_test_recorder_object ) @patch("test_workflow.integ_test.integ_test_runner_opensearch.IntegTestStartPropertiesOpenSearch") @patch("test_workflow.integ_test.integ_test_runner_opensearch.IntegTestSuiteOpenSearch") - def test_without_integ_test(self, mock_suite, mock_properties): + def test_without_integ_test(self, mock_suite: Mock, mock_properties: Mock) -> None: self.args.paths = {"opensearch": "test-path"} self.args.component = "sql" self.args.test_run_id = "12345" @@ -112,7 +113,7 @@ def test_without_integ_test(self, mock_suite, mock_properties): @patch("test_workflow.integ_test.integ_test_runner_opensearch.IntegTestStartPropertiesOpenSearch") @patch("test_workflow.integ_test.integ_test_runner_opensearch.IntegTestSuiteOpenSearch") - def test_component_not_in_test_manifest(self, mock_suite, mock_properties): + def test_component_not_in_test_manifest(self, mock_suite: Mock, mock_properties: Mock) -> None: self.args.paths = {"opensearch": "test-path"} self.args.component = "sql" self.args.test_run_id = "12345" diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch_dashboards.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch_dashboards.py index a5eb966a09..2e0026db3c 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runner_opensearch_dashboards.py @@ -5,13 +5,13 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.integ_test.integ_test_runner_opensearch_dashboards import IntegTestRunnerOpenSearchDashboards class TestIntegTestRunnerOpenSearchDashboards(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.args = MagicMock() self.test_manifest = MagicMock() @@ -20,7 +20,7 @@ def setUp(self): @patch("test_workflow.integ_test.integ_test_runner_opensearch_dashboards.IntegTestSuiteOpenSearchDashboards") @patch("test_workflow.integ_test.integ_test_runner.TestRecorder") @patch("test_workflow.integ_test.integ_test_runner.TemporaryDirectory") - def test_with_integ_test(self, mock_temp, mock_test_recorder, mock_suite, mock_properties, mock_properties_dependency): + def test_with_integ_test(self, mock_temp: Mock, mock_test_recorder: Mock, mock_suite: Mock, mock_properties: Mock, mock_properties_dependency: Mock) -> None: self.args.paths = {"opensearch-dashboards": "test-path"} self.args.component = "sql" self.args.test_run_id = "12345" @@ -59,7 +59,8 @@ def test_with_integ_test(self, mock_temp, mock_test_recorder, mock_suite, mock_p mock_suite.return_value = mock_suite_object - mock_temp.return_value.__enter__.return_value.name = "temp-name" + mock_path = MagicMock() + mock_temp.return_value.__enter__.return_value.path = mock_path mock_test_recorder_object = MagicMock() mock_test_recorder.return_value = mock_test_recorder_object @@ -80,6 +81,6 @@ def test_with_integ_test(self, mock_temp, mock_test_recorder, mock_suite, mock_p mock_properties_object.bundle_manifest, mock_properties_dependency_object.build_manifest, mock_properties_object.build_manifest, - "temp-name", + mock_path, mock_test_recorder_object ) diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runners.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runners.py index 1a67005942..d550eb1794 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runners.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_runners.py @@ -12,7 +12,7 @@ class TestIntegTestRunners(unittest.TestCase): - def test_opensearch(self): + def test_opensearch(self) -> None: mock_args = MagicMock() mock_test_manifest = MagicMock() @@ -29,12 +29,10 @@ def test_opensearch(self): "OpenSearch Dashboards": mock_opensearch_dashboards_runner, }): runner = IntegTestRunners.from_test_manifest(mock_args, mock_test_manifest) - self.assertEqual(runner, mock_opensearch_runner_object) - mock_opensearch_runner.assert_called_once_with(mock_args, mock_test_manifest) - def test_opensearch_dashboards(self): + def test_opensearch_dashboards(self) -> None: mock_args = MagicMock() mock_test_manifest = MagicMock() @@ -51,6 +49,5 @@ def test_opensearch_dashboards(self): "OpenSearch Dashboards": mock_opensearch_dashboards_runner, }): runner = IntegTestRunners.from_test_manifest(mock_args, mock_test_manifest) - self.assertEqual(runner, mock_opensearch_dashboards_runner_object) mock_opensearch_dashboards_runner.assert_called_once_with(mock_args, mock_test_manifest) diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch.py index c1cf5b16e7..a53d2a1d32 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch.py @@ -5,7 +5,7 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.integ_test.integ_test_start_properties_opensearch import IntegTestStartPropertiesOpenSearch @@ -15,7 +15,7 @@ class TestIntegTestStartPropertiesOpenSearch(unittest.TestCase): @patch("test_workflow.integ_test.integ_test_start_properties.BundleManifest") @patch("test_workflow.integ_test.integ_test_start_properties.BuildManifest") @patch("test_workflow.integ_test.integ_test_start_properties_opensearch.DependencyInstallerOpenSearch") - def test(self, mock_installer, mock_build, mock_bundle): + def test(self, mock_installer: Mock, mock_build: Mock, mock_bundle: Mock) -> None: path = "test-path" mock_bundle_object = MagicMock() diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch_dashboards.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch_dashboards.py index 3844e8ee3f..54d538a4ca 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_start_properties_opensearch_dashboards.py @@ -5,7 +5,7 @@ # compatible open source license. import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.integ_test.integ_test_start_properties_opensearch_dashboards import IntegTestStartPropertiesOpenSearchDashboards @@ -15,7 +15,7 @@ class TestIntegTestStartPropertiesOpenSearchDashboards(unittest.TestCase): @patch("test_workflow.integ_test.integ_test_start_properties.BundleManifest") @patch("test_workflow.integ_test.integ_test_start_properties.BuildManifest") @patch("test_workflow.integ_test.integ_test_start_properties_opensearch_dashboards.DependencyInstallerOpenSearchDashboards") - def test(self, mock_installer, mock_build, mock_bundle): + def test(self, mock_installer: Mock, mock_build: Mock, mock_bundle: Mock) -> None: path = "test-path" mock_bundle_object = MagicMock() diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch.py index 70efb4305a..adc617af8b 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch.py @@ -6,12 +6,14 @@ import os import unittest -from unittest.mock import MagicMock, call, patch +from pathlib import Path +from typing import Any, Tuple +from unittest.mock import MagicMock, Mock, call, patch from git.git_repository import GitRepository from manifests.build_manifest import BuildManifest -from manifests.bundle_manifest import BundleManifest -from manifests.test_manifest import TestManifest +from manifests.bundle_manifest import BundleComponent, BundleManifest +from manifests.test_manifest import TestComponent, TestManifest from test_workflow.integ_test.integ_test_suite import InvalidTestConfigError, ScriptFinder from test_workflow.integ_test.integ_test_suite_opensearch import IntegTestSuiteOpenSearch, LocalTestCluster @@ -25,23 +27,31 @@ class TestIntegSuiteOpenSearch(unittest.TestCase): BUNDLE_MANIFEST = os.path.join(DATA, "bundle_manifest.yml") TEST_MANIFEST = os.path.join(DATA, "test_manifest.yml") - def setUp(self): + def setUp(self) -> None: os.chdir(os.path.dirname(__file__)) self.bundle_manifest = BundleManifest.from_path(self.BUNDLE_MANIFEST) self.build_manifest = BuildManifest.from_path(self.BUILD_MANIFEST) self.test_manifest = TestManifest.from_path(self.TEST_MANIFEST) + self.work_dir = Path("test_dir") @patch("os.path.exists", return_value=True) @patch("test_workflow.integ_test.integ_test_suite_opensearch.LocalTestCluster") @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_multiple_test_configs(self, mock_test_recorder, mock_local_test_cluster, *mock): + def test_execute_with_multiple_test_configs(self, mock_test_recorder: Mock, mock_local_test_cluster: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("job-scheduler") dependency_installer = MagicMock() - integ_test_suite = IntegTestSuiteOpenSearch(dependency_installer, component, test_config, - self.bundle_manifest, self.build_manifest, "tmpdir", mock_test_recorder) + integ_test_suite = IntegTestSuiteOpenSearch( + dependency_installer, + component, + test_config, + self.bundle_manifest, + self.build_manifest, + self.work_dir, + mock_test_recorder + ) mock_local_test_cluster.create().__enter__.return_value = "localhost", 9200 mock_execute_integtest_sh = MagicMock() - IntegTestSuiteOpenSearch.execute_integtest_sh = mock_execute_integtest_sh + IntegTestSuiteOpenSearch.execute_integtest_sh = mock_execute_integtest_sh # type: ignore mock_execute_integtest_sh.return_value = "success" test_results = integ_test_suite.execute_tests() @@ -55,21 +65,28 @@ def test_execute_with_multiple_test_configs(self, mock_test_recorder, mock_local @patch("test_workflow.integ_test.integ_test_suite_opensearch.LocalTestCluster") @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_build_dependencies(self, mock_test_recorder, mock_local_test_cluster, *mock): + def test_execute_with_build_dependencies(self, mock_test_recorder: Mock, mock_local_test_cluster: Mock, *mock: Any) -> None: dependency_installer = MagicMock() test_config, component = self.__get_test_config_and_bundle_component("index-management") - integ_test_suite = IntegTestSuiteOpenSearch(dependency_installer, component, test_config, - self.bundle_manifest, self.build_manifest, "tmpdir", mock_test_recorder) + integ_test_suite = IntegTestSuiteOpenSearch( + dependency_installer, + component, + test_config, + self.bundle_manifest, + self.build_manifest, + self.work_dir, + mock_test_recorder + ) mock_local_test_cluster.create().__enter__.return_value = "localhost", 9200 mock_execute_integtest_sh = MagicMock() - IntegTestSuiteOpenSearch.execute_integtest_sh = mock_execute_integtest_sh + IntegTestSuiteOpenSearch.execute_integtest_sh = mock_execute_integtest_sh # type: ignore mock_execute_integtest_sh.return_value = "success" integ_test_suite.execute_tests() dependency_installer.install_build_dependencies.assert_called_with( - {"opensearch-job-scheduler": "1.1.0.0"}, os.path.join("tmpdir", "index-management", "src", "test", "resources", "job-scheduler") + {"opensearch-job-scheduler": "1.1.0.0"}, os.path.join(self.work_dir, "index-management", "src", "test", "resources", "job-scheduler") ) mock_execute_integtest_sh.assert_has_calls([ @@ -79,7 +96,7 @@ def test_execute_with_build_dependencies(self, mock_test_recorder, mock_local_te @patch("test_workflow.test_recorder.test_recorder.TestRecorder") @patch("test_workflow.integ_test.integ_test_suite.execute") - def test_execute_without_build_dependencies(self, mock_execute, *mock): + def test_execute_without_build_dependencies(self, mock_execute: Mock, *mock: Any) -> None: dependency_installer = MagicMock() test_config, component = self.__get_test_config_and_bundle_component("job-scheduler") mock_test_recorder = MagicMock() @@ -89,7 +106,7 @@ def test_execute_without_build_dependencies(self, mock_execute, *mock): mock_create = MagicMock() mock_create.return_value.__enter__.return_value = ("test_endpoint", 1234) - LocalTestCluster.create = mock_create + LocalTestCluster.create = mock_create # type: ignore mock_execute.return_value = ("test_status", "test_stdout", "") @@ -99,7 +116,7 @@ def test_execute_without_build_dependencies(self, mock_execute, *mock): test_config, self.bundle_manifest, self.build_manifest, - "tmpdir", + self.work_dir, mock_test_recorder) integ_test_suite.execute_tests() @@ -107,22 +124,29 @@ def test_execute_without_build_dependencies(self, mock_execute, *mock): dependency_installer.install_build_dependencies.assert_not_called() @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_unsupported_build_dependencies(self, mock_test_recorder, *mock): + def test_execute_with_unsupported_build_dependencies(self, mock_test_recorder: Mock, *mock: Any) -> None: dependency_installer = MagicMock() test_config, component = self.__get_test_config_and_bundle_component("anomaly-detection") - integ_test_suite = IntegTestSuiteOpenSearch(dependency_installer, component, test_config, - self.bundle_manifest, self.build_manifest, "tmpdir", mock_test_recorder) + integ_test_suite = IntegTestSuiteOpenSearch( + dependency_installer, + component, + test_config, + self.bundle_manifest, + self.build_manifest, + self.work_dir, + mock_test_recorder + ) with self.assertRaises(InvalidTestConfigError): integ_test_suite.execute_tests() dependency_installer.install_build_dependencies.assert_not_called() @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_missing_job_scheduler(self, mock_test_recorder, mock_install_build_dependencies, *mock): + def test_execute_with_missing_job_scheduler(self, mock_test_recorder: Mock, mock_install_build_dependencies: Mock, *mock: Any) -> None: invalid_build_manifest = BuildManifest.from_path("data/build_manifest_missing_components.yml") test_config, component = self.__get_test_config_and_bundle_component("index-management") dependency_installer = MagicMock() integ_test_suite = IntegTestSuiteOpenSearch( - dependency_installer, component, test_config, self.bundle_manifest, invalid_build_manifest, "tmpdir", mock_test_recorder + dependency_installer, component, test_config, self.bundle_manifest, invalid_build_manifest, self.work_dir, mock_test_recorder ) with self.assertRaises(KeyError) as ctx: integ_test_suite.execute_tests() @@ -130,7 +154,7 @@ def test_execute_with_missing_job_scheduler(self, mock_test_recorder, mock_insta self.assertEqual(str(ctx.exception), "'job-scheduler'") dependency_installer.install_build_dependencies.assert_not_called() - def __get_test_config_and_bundle_component(self, component_name): + def __get_test_config_and_bundle_component(self, component_name: str) -> Tuple[TestComponent, BundleComponent]: component = self.bundle_manifest.components[component_name] test_config = self.test_manifest.components[component.name] return test_config, component @@ -139,7 +163,7 @@ def __get_test_config_and_bundle_component(self, component_name): @patch.object(ScriptFinder, "find_integ_test_script") @patch("test_workflow.integ_test.integ_test_suite_opensearch.LocalTestCluster") @patch("test_workflow.test_recorder.test_recorder.TestRecorder") - def test_execute_with_working_directory(self, mock_test_recorder, mock_local_test_cluster, mock_script_finder, *mock): + def test_execute_with_working_directory(self, mock_test_recorder: Mock, mock_local_test_cluster: Mock, mock_script_finder: Mock, *mock: Any) -> None: test_config, component = self.__get_test_config_and_bundle_component("dashboards-reports") dependency_installer = MagicMock() integ_test_suite = IntegTestSuiteOpenSearch( @@ -148,7 +172,7 @@ def test_execute_with_working_directory(self, mock_test_recorder, mock_local_tes test_config, self.bundle_manifest, self.build_manifest, - "tmpdir", + self.work_dir, mock_test_recorder ) @@ -156,7 +180,7 @@ def test_execute_with_working_directory(self, mock_test_recorder, mock_local_tes mock_script_finder.return_value = "integtest.sh" mock_execute_integtest_sh = MagicMock() - IntegTestSuiteOpenSearch.execute_integtest_sh = mock_execute_integtest_sh + IntegTestSuiteOpenSearch.execute_integtest_sh = mock_execute_integtest_sh # type: ignore mock_execute_integtest_sh.return_value = "success" integ_test_suite.execute_tests() diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch_dashboards.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch_dashboards.py index 0d1b78627d..92417b101f 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_integ_test_suite_opensearch_dashboards.py @@ -2,7 +2,8 @@ import logging import os import unittest -from unittest.mock import MagicMock, call, patch +from pathlib import Path +from unittest.mock import MagicMock, Mock, call, patch from paths.script_finder import ScriptFinder from test_workflow.integ_test.integ_test_suite import InvalidTestConfigError @@ -12,7 +13,7 @@ class TestIntegSuiteOpenSearchDashboards(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.dependency_installer_opensearch = MagicMock() self.dependency_installer_opensearch_dashboards = MagicMock() @@ -29,7 +30,7 @@ def setUp(self): self.bundle_manifest_opensearch_dashboards = MagicMock() self.build_manifest_opensearch = MagicMock() self.build_manifest_opensearch_dashboards = MagicMock() - self.work_dir = "test_dir" + self.work_dir = Path("test_dir") self.test_recorder = MagicMock() self.save_logs = MagicMock() @@ -40,12 +41,12 @@ def setUp(self): @patch("test_workflow.integ_test.integ_test_suite.TestResultData") @patch("test_workflow.integ_test.integ_test_suite.GitRepository") @patch("test_workflow.integ_test.integ_test_suite.execute", return_value=True) - def test_execute_tests(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists, mock_chdir): + def test_execute_tests(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock, mock_chdir: Mock) -> None: mock_find = MagicMock() mock_find.return_value = "./integtest.sh" - ScriptFinder.find_integ_test_script = mock_find + ScriptFinder.find_integ_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -60,7 +61,7 @@ def test_execute_tests(self, mock_execute, mock_git, mock_test_result_data, mock mock_create = MagicMock() mock_create.return_value.__enter__.return_value = ("test_endpoint", 1234) - LocalTestClusterOpenSearchDashboards.create = mock_create + LocalTestClusterOpenSearchDashboards.create = mock_create # type: ignore suite = IntegTestSuiteOpenSearchDashboards( self.dependency_installer_opensearch, @@ -76,7 +77,7 @@ def test_execute_tests(self, mock_execute, mock_git, mock_test_result_data, mock ) mock_execute_integtest_sh = MagicMock() - suite.execute_integtest_sh = mock_execute_integtest_sh + suite.execute_integtest_sh = mock_execute_integtest_sh # type: ignore # call the test target suite.execute_tests() @@ -92,13 +93,13 @@ def test_execute_tests(self, mock_execute, mock_git, mock_test_result_data, mock @patch("test_workflow.integ_test.integ_test_suite.TestResultData") @patch("test_workflow.integ_test.integ_test_suite.GitRepository") @patch("test_workflow.integ_test.integ_test_suite.execute", return_value=True) - def test_execute_integtest_sh(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists): + def test_execute_integtest_sh(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock) -> None: logging.info(locals()) mock_find = MagicMock() mock_find.return_value = "./integtest.sh" - ScriptFinder.find_integ_test_script = mock_find + ScriptFinder.find_integ_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "dir" @@ -125,7 +126,7 @@ def test_execute_integtest_sh(self, mock_execute, mock_git, mock_test_result_dat ) # call the test target - status = suite.execute_integtest_sh("test_endpoint", 1234, True, ["with-security", "without-security"]) + status = suite.execute_integtest_sh("test_endpoint", 1234, True, "with-security") self.assertEqual(status, "test_status") mock_execute.assert_called_once_with('./integtest.sh -b test_endpoint -p 1234 -s true -v 1.2.0', @@ -133,7 +134,7 @@ def test_execute_integtest_sh(self, mock_execute, mock_git, mock_test_result_dat mock_test_result_data.assert_called_once_with( "sql", - ["with-security", "without-security"], + "with-security", "test_status", "test_stdout", "", @@ -149,11 +150,11 @@ def test_execute_integtest_sh(self, mock_execute, mock_git, mock_test_result_dat @patch("test_workflow.integ_test.integ_test_suite.TestResultData") @patch("test_workflow.integ_test.integ_test_suite.GitRepository") @patch("test_workflow.integ_test.integ_test_suite.execute", return_value=True) - def test_execute_integtest_sh_script_do_not_exist(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists): + def test_execute_integtest_sh_script_do_not_exist(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock) -> None: mock_find = MagicMock() mock_find.return_value = "./integtest.sh" - ScriptFinder.find_integ_test_script = mock_find + ScriptFinder.find_integ_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -175,9 +176,9 @@ def test_execute_integtest_sh_script_do_not_exist(self, mock_execute, mock_git, ) # call the test target - status = suite.execute_integtest_sh("test_endpoint", 1234, True, ["with-security", "without-security"]) + status = suite.execute_integtest_sh("test_endpoint", 1234, True, "without-security") - self.assertIsNone(status) + self.assertEqual(0, status) mock_execute.assert_not_called() mock_test_result_data.assert_not_called() @@ -187,11 +188,11 @@ def test_execute_integtest_sh_script_do_not_exist(self, mock_execute, mock_git, @patch("test_workflow.integ_test.integ_test_suite.TestResultData") @patch("test_workflow.integ_test.integ_test_suite.GitRepository") @patch("test_workflow.integ_test.integ_test_suite.execute", return_value=True) - def test_is_security_enabled(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists): + def test_is_security_enabled(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock) -> None: mock_find = MagicMock() mock_find.return_value = "./integtest.sh" - ScriptFinder.find_integ_test_script = mock_find + ScriptFinder.find_integ_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" @@ -225,12 +226,12 @@ def test_is_security_enabled(self, mock_execute, mock_git, mock_test_result_data @patch("test_workflow.integ_test.integ_test_suite.TestResultData") @patch("test_workflow.integ_test.integ_test_suite.GitRepository") @patch("test_workflow.integ_test.integ_test_suite.execute", return_value=True) - def test_pretty_print_message(self, mock_execute, mock_git, mock_test_result_data, mock_path_exists, mock_logging): + def test_pretty_print_message(self, mock_execute: Mock, mock_git: Mock, mock_test_result_data: Mock, mock_path_exists: Mock, mock_logging: Mock) -> None: mock_find = MagicMock() mock_find.return_value = "./integtest.sh" - ScriptFinder.find_integ_test_script = mock_find + ScriptFinder.find_integ_test_script = mock_find # type: ignore mock_git_object = MagicMock() mock_git_object.dir = "https://test.github.com" diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster.py index 392c453e39..f46c25bf97 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster.py @@ -6,7 +6,7 @@ import os import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, Mock, patch from test_workflow.integ_test.local_test_cluster import LocalTestCluster from test_workflow.integ_test.service import ServiceTerminationResult @@ -15,7 +15,7 @@ class LocalTestClusterTests(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: mock_manifest = MagicMock() mock_manifest.build.version = "1.1.0" mock_manifest.build.distribution = "tar" @@ -28,11 +28,11 @@ def setUp(self): self.component_test_config = "test_config" self.additional_cluster_config = {"script.context.field.max_compilations_rate": "1000/1m"} self.save_logs = "" - self.dependency_installer = "" - self.test_recorder = "" + self.dependency_installer = None + self.test_recorder = None @patch("test_workflow.integ_test.local_test_cluster.ServiceOpenSearch") - def test_start(self, mock_service): + def test_start(self, mock_service: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -67,7 +67,7 @@ def test_start(self, mock_service): @patch("test_workflow.integ_test.local_test_cluster.ServiceOpenSearch") @patch("test_workflow.test_cluster.TestResultData") - def test_terminate(self, mock_test_result_data, mock_service): + def test_terminate(self, mock_test_result_data: Mock, mock_service: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -88,7 +88,12 @@ def test_terminate(self, mock_test_result_data, mock_service): mock_log_files = MagicMock() - mock_service_object.terminate.return_value = ServiceTerminationResult(123, "test stdout_data", "test stderr_data", mock_log_files) + mock_service_object.terminate.return_value = ServiceTerminationResult( + 123, + "test stdout_data", + "test stderr_data", + mock_log_files + ) mock_test_result_data_object = MagicMock() mock_test_result_data.return_value = mock_test_result_data_object @@ -109,7 +114,7 @@ def test_terminate(self, mock_test_result_data, mock_service): mock_local_cluster_logs.save_test_result_data.assert_called_once_with(mock_test_result_data_object) @patch("test_workflow.integ_test.local_test_cluster.ServiceOpenSearch") - def test_terminate_service_not_initialized(self, mock_service): + def test_terminate_service_not_initialized(self, mock_service: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -133,7 +138,7 @@ def test_terminate_service_not_initialized(self, mock_service): self.assertEqual(str(ctx.exception), "Service is not initialized") @patch("test_workflow.integ_test.local_test_cluster.ServiceOpenSearch") - def test_endpoint_port(self, mock_service): + def test_endpoint_port(self, mock_service: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -152,5 +157,5 @@ def test_endpoint_port(self, mock_service): mock_test_recorder ) - self.assertEqual(cluster.endpoint(), "localhost") - self.assertEqual(cluster.port(), 9200) + self.assertEqual(cluster.endpoint, "localhost") + self.assertEqual(cluster.port, 9200) diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster_opensearch_dashboards.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster_opensearch_dashboards.py index 39f2447e39..ec626f905f 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_local_test_cluster_opensearch_dashboards.py @@ -6,7 +6,7 @@ import os import unittest -from unittest.mock import MagicMock, call, patch +from unittest.mock import MagicMock, Mock, call, patch from test_workflow.integ_test.local_test_cluster_opensearch_dashboards import LocalTestClusterOpenSearchDashboards from test_workflow.integ_test.service import ServiceTerminationResult @@ -15,7 +15,7 @@ class LocalTestClusterOpenSearchDashboardsTests(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: mock_bundle_manifest_opensearch = MagicMock() mock_bundle_manifest_opensearch.build.version = "1.1.0" mock_bundle_manifest_opensearch.build.distribution = "tar" @@ -44,7 +44,7 @@ def setUp(self): @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearch") @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearchDashboards") - def test_start(self, mock_service_opensearch_dashboards, mock_service_opensearch): + def test_start(self, mock_service_opensearch_dashboards: Mock, mock_service_opensearch: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -97,7 +97,7 @@ def test_start(self, mock_service_opensearch_dashboards, mock_service_opensearch @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearch") @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearchDashboards") @patch("test_workflow.test_cluster.TestResultData") - def test_terminate(self, mock_test_result_data, mock_service_opensearch_dashboards, mock_service_opensearch): + def test_terminate(self, mock_test_result_data: Mock, mock_service_opensearch_dashboards: Mock, mock_service_opensearch: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -158,7 +158,7 @@ def test_terminate(self, mock_test_result_data, mock_service_opensearch_dashboar @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearch") @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearchDashboards") - def test_terminate_service_not_initialized(self, mock_service_opensearch_dashboards, mock_service_opensearch): + def test_terminate_service_not_initialized(self, mock_service_opensearch_dashboards: Mock, mock_service_opensearch: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -190,7 +190,7 @@ def test_terminate_service_not_initialized(self, mock_service_opensearch_dashboa @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearch") @patch("test_workflow.integ_test.local_test_cluster_opensearch_dashboards.ServiceOpenSearchDashboards") - def test_endpoint_port(self, mock_service_opensearch_dashboards, mock_service_opensearch): + def test_endpoint_port(self, mock_service_opensearch_dashboards: Mock, mock_service_opensearch: Mock) -> None: mock_test_recorder = MagicMock() mock_local_cluster_logs = MagicMock() mock_test_recorder.local_cluster_logs = mock_local_cluster_logs @@ -214,5 +214,5 @@ def test_endpoint_port(self, mock_service_opensearch_dashboards, mock_service_op mock_test_recorder ) - self.assertEqual(cluster.endpoint(), "localhost") - self.assertEqual(cluster.port(), 5601) + self.assertEqual(cluster.endpoint, "localhost") + self.assertEqual(cluster.port, 5601) diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_run_integ_test.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_run_integ_test.py index f14b36cc66..36cbbd36b9 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_run_integ_test.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_run_integ_test.py @@ -6,6 +6,7 @@ import os import unittest +from typing import Any from unittest.mock import MagicMock, patch from manifests.test_manifest import TestManifest @@ -23,7 +24,7 @@ class TestRunIntegTest(unittest.TestCase): "--paths", "opensearch=" + os.path.join(os.path.dirname(__file__), "..", "..", "data", "remote") ]) - def test_run_integ_test(self, *mock): + def test_run_integ_test(self, *mock: Any) -> None: mock_runner = MagicMock() mock_result = MagicMock() @@ -32,7 +33,7 @@ def test_run_integ_test(self, *mock): mock_runner.run.return_value = mock_result mock_from_test_manifest = MagicMock() mock_from_test_manifest.return_value = mock_runner - IntegTestRunners.from_test_manifest = mock_from_test_manifest + IntegTestRunners.from_test_manifest = mock_from_test_manifest # type: ignore main() diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch.py index 3900558c35..6a0496667f 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch.py @@ -6,21 +6,30 @@ import os import unittest -from unittest.mock import MagicMock, PropertyMock, call, mock_open, patch +from typing import Any +from unittest.mock import MagicMock, Mock, PropertyMock, call, mock_open, patch import requests +from test_workflow.dependency_installer import DependencyInstaller +from test_workflow.integ_test.service import ClusterCreationException from test_workflow.integ_test.service_opensearch import ServiceOpenSearch -from test_workflow.test_cluster import ClusterCreationException class ServiceOpenSearchTests(unittest.TestCase): - def setUp(self): + version: str + distribution: str + work_dir: str + additional_config: dict + dependency_installer: DependencyInstaller + save_logs: str + + def setUp(self) -> None: self.version = "1.1.0" self.distribution = "tar" self.work_dir = "test_work_dir" self.additional_config = {"script.context.field.max_compilations_rate": "1000/1m"} - self.dependency_installer = "" + self.dependency_installer = None self.save_logs = "" @patch("test_workflow.integ_test.service.Process.start") @@ -28,7 +37,7 @@ def setUp(self): @patch("builtins.open", new_callable=mock_open) @patch("yaml.dump") @patch("tarfile.open") - def test_start(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_process): + def test_start(self, mock_tarfile_open: Mock, mock_dump: Mock, mock_file: Mock, mock_pid: Mock, mock_process: Mock) -> None: dependency_installer = MagicMock() @@ -72,7 +81,7 @@ def test_start(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_pro @patch("builtins.open", new_callable=mock_open) @patch("yaml.dump") @patch("tarfile.open") - def test_start_security_disabled(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_process, mock_os_isdir): + def test_start_security_disabled(self, mock_tarfile_open: Mock, mock_dump: Mock, mock_file: Any, mock_pid: Mock, mock_process: Mock, mock_os_isdir: Mock) -> None: dependency_installer = MagicMock() @@ -122,7 +131,7 @@ def test_start_security_disabled(self, mock_tarfile_open, mock_dump, mock_file, @patch("builtins.open", new_callable=mock_open) @patch("yaml.dump") @patch("tarfile.open") - def test_start_security_disabled_and_not_installed(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_process, mock_os_isdir): + def test_start_security_disabled_and_not_installed(self, mock_tarfile_open: Mock, mock_dump: Mock, mock_file: Any, mock_pid: Mock, mock_process: Mock, mock_os_isdir: Mock) -> None: dependency_installer = MagicMock() @@ -171,11 +180,11 @@ def test_start_security_disabled_and_not_installed(self, mock_tarfile_open, mock @patch('test_workflow.integ_test.service.Process.stderr_data', new_callable=PropertyMock, return_value="test stderr_data") def test_terminate( self, - mock_process_stderr_data, - mock_process_stdout_data, - mock_process_started, - mock_process_terminate - ): + mock_process_stderr_data: Mock, + mock_process_stdout_data: Mock, + mock_process_started: Mock, + mock_process_terminate: Mock + ) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -196,7 +205,7 @@ def test_terminate( @patch("test_workflow.integ_test.service.Process.terminate") @patch('test_workflow.integ_test.service.Process.started', new_callable=PropertyMock, return_value=False) - def test_terminate_process_not_started(self, mock_process_started, mock_process_terminate): + def test_terminate_process_not_started(self, mock_process_started: Mock, mock_process_terminate: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -211,7 +220,7 @@ def test_terminate_process_not_started(self, mock_process_started, mock_process_ mock_process_terminate.assert_not_called() mock_process_started.assert_called_once() - def test_endpoint_port(self): + def test_endpoint_port(self) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -224,7 +233,7 @@ def test_endpoint_port(self): self.assertEqual(service.endpoint(), "localhost") self.assertEqual(service.port(), 9200) - def test_url_security_enabled(self): + def test_url_security_enabled(self) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -236,7 +245,7 @@ def test_url_security_enabled(self): self.assertEqual(service.url(), "https://localhost:9200") - def test_url_security_disabled(self): + def test_url_security_disabled(self) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -250,7 +259,7 @@ def test_url_security_disabled(self): @patch("requests.get") @patch.object(ServiceOpenSearch, "url") - def test_get_service_response(self, mock_url, mock_requests_get): + def test_get_service_response(self, mock_url: Mock, mock_requests_get: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -274,7 +283,7 @@ def test_get_service_response(self, mock_url, mock_requests_get): @patch.object(ServiceOpenSearch, "service_alive", return_value=True) @patch('test_workflow.integ_test.service.Process.stdout_data', new_callable=PropertyMock, return_value="test stdout_data") @patch('test_workflow.integ_test.service.Process.stderr_data', new_callable=PropertyMock, return_value="test stderr_data") - def test_wait_for_service_succeed_on_first_attemp(self, mock_process_stderr_data, mock_process_stdout_data, mock_service_alive, mock_time_sleep): + def test_wait_for_service_succeed_on_first_attemp(self, mock_process_stderr_data: Mock, mock_process_stdout_data: Mock, mock_service_alive: Mock, mock_time_sleep: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -297,11 +306,11 @@ def test_wait_for_service_succeed_on_first_attemp(self, mock_process_stderr_data @patch('test_workflow.integ_test.service.Process.stderr_data', new_callable=PropertyMock, return_value="test stderr_data") def test_wait_for_service_always_fail_without_exception( self, - mock_process_stderr_data, - mock_process_stdout_data, - mock_service_alive, - mock_time_sleep - ): + mock_process_stderr_data: Mock, + mock_process_stdout_data: Mock, + mock_service_alive: Mock, + mock_time_sleep: Mock + ) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -327,11 +336,11 @@ def test_wait_for_service_always_fail_without_exception( @patch('test_workflow.integ_test.service.Process.stderr_data', new_callable=PropertyMock, return_value="test stderr_data") def test_wait_for_service_always_fail_with_exception( self, - mock_process_stderr_data, - mock_process_stdout_data, - mock_service_alive, - mock_time_sleep - ): + mock_process_stderr_data: Mock, + mock_process_stdout_data: Mock, + mock_service_alive: Mock, + mock_time_sleep: Mock + ) -> None: service = ServiceOpenSearch( self.version, @@ -361,11 +370,11 @@ def test_wait_for_service_always_fail_with_exception( @patch('test_workflow.integ_test.service.Process.stderr_data', new_callable=PropertyMock, return_value="test stderr_data") def test_wait_for_service_suceed_on_third_attempt( self, - mock_process_stderr_data, - mock_process_stdout_data, - mock_service_alive, - mock_time_sleep - ): + mock_process_stderr_data: Mock, + mock_process_stdout_data: Mock, + mock_service_alive: Mock, + mock_time_sleep: Mock + ) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -383,7 +392,7 @@ def test_wait_for_service_suceed_on_third_attempt( self.assertEqual(mock_process_stderr_data.call_count, 2) @patch.object(ServiceOpenSearch, "get_service_response") - def test_service_alive_green_available(self, mock_get_service_response): + def test_service_alive_green_available(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -403,7 +412,7 @@ def test_service_alive_green_available(self, mock_get_service_response): self.assertTrue(service.service_alive()) @patch.object(ServiceOpenSearch, "get_service_response") - def test_service_alive_yellow_available(self, mock_get_service_response): + def test_service_alive_yellow_available(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -423,7 +432,7 @@ def test_service_alive_yellow_available(self, mock_get_service_response): self.assertTrue(service.service_alive()) @patch.object(ServiceOpenSearch, "get_service_response") - def test_service_alive_red_unavailable(self, mock_get_service_response): + def test_service_alive_red_unavailable(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, @@ -443,7 +452,7 @@ def test_service_alive_red_unavailable(self, mock_get_service_response): self.assertFalse(service.service_alive()) @patch.object(ServiceOpenSearch, "get_service_response") - def test_service_alive_unavailable(self, mock_get_service_response): + def test_service_alive_unavailable(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearch( self.version, self.distribution, diff --git a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch_dashboards.py b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch_dashboards.py index c1967614cc..3c32eed6fb 100644 --- a/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch_dashboards.py +++ b/tests/tests_test_workflow/test_integ_workflow/integ_test/test_service_opensearch_dashboards.py @@ -6,26 +6,33 @@ import os import unittest -from unittest.mock import MagicMock, PropertyMock, call, mock_open, patch +from typing import Any +from unittest.mock import MagicMock, Mock, PropertyMock, call, mock_open, patch +from test_workflow.dependency_installer import DependencyInstaller from test_workflow.integ_test.service_opensearch_dashboards import ServiceOpenSearchDashboards class ServiceOpenSearchDashboardsTests(unittest.TestCase): + version: str + distribution: str + work_dir: str + additional_config: dict + dependency_installer: DependencyInstaller - def setUp(self): + def setUp(self) -> None: self.version = "1.1.0" self.distribution = "tar" self.work_dir = "test_work_dir" self.additional_config = {"script.context.field.max_compilations_rate": "1000/1m"} - self.dependency_installer = "" + self.dependency_installer = None @patch("test_workflow.integ_test.service.Process.start") @patch('test_workflow.integ_test.service.Process.pid', new_callable=PropertyMock, return_value=12345) @patch("builtins.open", new_callable=mock_open) @patch("yaml.dump") @patch("tarfile.open") - def test_start(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_process): + def test_start(self, mock_tarfile_open: Mock, mock_dump: Mock, mock_file: Mock, mock_pid: Mock, mock_process: Mock) -> None: mock_dependency_installer = MagicMock() @@ -73,7 +80,7 @@ def test_start(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_pro @patch("builtins.open", new_callable=mock_open) @patch("yaml.dump") @patch("tarfile.open") - def test_start_without_security(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_process, mock_check_call, mock_os_isdir): + def test_start_without_security(self, mock_tarfile_open: Mock, mock_dump: Mock, mock_file: Any, mock_pid: Mock, mock_process: Mock, mock_check_call: Mock, mock_os_isdir: Mock) -> None: mock_dependency_installer = MagicMock() @@ -130,7 +137,16 @@ def test_start_without_security(self, mock_tarfile_open, mock_dump, mock_file, m @patch("builtins.open", new_callable=mock_open) @patch("yaml.dump") @patch("tarfile.open") - def test_start_without_security_and_not_installed(self, mock_tarfile_open, mock_dump, mock_file, mock_pid, mock_process, mock_check_call, mock_os_isdir): + def test_start_without_security_and_not_installed( + self, + mock_tarfile_open: Mock, + mock_dump: Mock, + mock_file: Any, + mock_pid: Mock, + mock_process: Mock, + mock_check_call: Mock, + mock_os_isdir: Mock + ) -> None: mock_dependency_installer = MagicMock() @@ -176,7 +192,7 @@ def test_start_without_security_and_not_installed(self, mock_tarfile_open, mock_ mock_file_handler_for_security.close.assert_called_once() mock_file_handler_for_additional_config.write.assert_called_once_with(mock_dump_result) - def test_endpoint_port_url(self): + def test_endpoint_port_url(self) -> None: service = ServiceOpenSearchDashboards( self.version, self.distribution, @@ -192,7 +208,7 @@ def test_endpoint_port_url(self): @patch("requests.get") @patch.object(ServiceOpenSearchDashboards, "url") - def test_get_service_response_with_security(self, mock_url, mock_requests_get): + def test_get_service_response_with_security(self, mock_url: Mock, mock_requests_get: Mock) -> None: service = ServiceOpenSearchDashboards( self.version, self.distribution, @@ -212,7 +228,7 @@ def test_get_service_response_with_security(self, mock_url, mock_requests_get): @patch("requests.get") @patch.object(ServiceOpenSearchDashboards, "url") - def test_get_service_response_without_security(self, mock_url, mock_requests_get): + def test_get_service_response_without_security(self, mock_url: Mock, mock_requests_get: Mock) -> None: service = ServiceOpenSearchDashboards( self.version, self.distribution, @@ -231,7 +247,7 @@ def test_get_service_response_without_security(self, mock_url, mock_requests_get mock_requests_get.assert_called_once_with(mock_url_result, auth=None, verify=False) @patch.object(ServiceOpenSearchDashboards, "get_service_response") - def test_service_alive_green_available(self, mock_get_service_response): + def test_service_alive_green_available(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearchDashboards( self.version, self.distribution, @@ -251,7 +267,7 @@ def test_service_alive_green_available(self, mock_get_service_response): self.assertTrue(service.service_alive()) @patch.object(ServiceOpenSearchDashboards, "get_service_response") - def test_service_alive_yellow_available(self, mock_get_service_response): + def test_service_alive_yellow_available(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearchDashboards( self.version, self.distribution, @@ -271,7 +287,7 @@ def test_service_alive_yellow_available(self, mock_get_service_response): self.assertTrue(service.service_alive()) @patch.object(ServiceOpenSearchDashboards, "get_service_response") - def test_service_alive_red_unavailable(self, mock_get_service_response): + def test_service_alive_red_unavailable(self, mock_get_service_response: Mock) -> None: service = ServiceOpenSearchDashboards( self.version, self.distribution, diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_multi_node_cluster.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_multi_node_cluster.py index 003dc3fbb7..a886e38505 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_multi_node_cluster.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_multi_node_cluster.py @@ -16,13 +16,13 @@ class TestPerfMultiNodeCluster(unittest.TestCase): DATA = os.path.join(os.path.dirname(__file__), "data") BUNDLE_MANIFEST = os.path.join(DATA, "bundle_manifest.yml") - def setUp(self): + def setUp(self) -> None: self.manifest = BundleManifest.from_path(self.BUNDLE_MANIFEST) self.stack_name = "stack" self.config = {"Constants": {"SecurityGroupId": "sg-00000000", "VpcId": "vpc-12345", "AccountId": "12345678", "Region": "us-west-2", "Role": "role-arn"}} - def test_multi_node_cluster(self): + def test_multi_node_cluster(self) -> None: test_cluster = PerfMultiNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 2, 3, 0, 0), current_workspace="current_workspace") @@ -34,13 +34,13 @@ def test_multi_node_cluster(self): self.assertTrue("client_node_count=0" in test_cluster.params) self.assertTrue("ingest_node_count=0" in test_cluster.params) - def test_multi_node_cluster_invalid_configuration(self): + def test_multi_node_cluster_invalid_configuration(self) -> None: self.assertRaises( AssertionError, PerfMultiNodeCluster, bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(False, 1, 0, 0, 0), current_workspace="current_workspace") - def test_multi_node_cluster_without_security(self): + def test_multi_node_cluster_without_security(self) -> None: test_cluster = PerfMultiNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(False, 1, 1, 0, 0), current_workspace="current_workspace") @@ -55,7 +55,7 @@ def test_multi_node_cluster_without_security(self): self.assertTrue(test_cluster.is_endpoint_public) self.assertEqual(test_cluster.endpoint, "abc") - def test_multi_node_cluster_with_security(self): + def test_multi_node_cluster_with_security(self) -> None: test_cluster = PerfMultiNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 1, 1, 0, 0), current_workspace="current_workspace") @@ -70,10 +70,9 @@ def test_multi_node_cluster_with_security(self): self.assertTrue(test_cluster.is_endpoint_public) self.assertEqual(test_cluster.endpoint, "abc") - def test_cdk_failure_scenarios(self): + def test_cdk_failure_scenarios(self) -> None: test_cluster = PerfMultiNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 1, 1, 0, 0), current_workspace="current_workspace") - cdk_output = {self.stack_name: {}} - self.assertRaises(RuntimeError, test_cluster.create_endpoint, cdk_output) + self.assertRaises(RuntimeError, test_cluster.create_endpoint, {self.stack_name: {}}) diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_single_node_cluster.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_single_node_cluster.py index 508a8b6953..97c55fd0df 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_single_node_cluster.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_single_node_cluster.py @@ -16,13 +16,13 @@ class TestPerfSingleNodeCluster(unittest.TestCase): DATA = os.path.join(os.path.dirname(__file__), "data") BUNDLE_MANIFEST = os.path.join(DATA, "bundle_manifest.yml") - def setUp(self): + def setUp(self) -> None: self.manifest = BundleManifest.from_path(self.BUNDLE_MANIFEST) self.stack_name = "stack" self.config = {"Constants": {"SecurityGroupId": "sg-00000000", "VpcId": "vpc-12345", "AccountId": "12345678", "Region": "us-west-2", "Role": "role-arn"}} - def test_single_node_cluster(self): + def test_single_node_cluster(self) -> None: test_cluster = PerfSingleNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 1, 0, 0, 0), current_workspace="current_workspace") @@ -31,13 +31,13 @@ def test_single_node_cluster(self): self.assertTrue("stack_name" in test_cluster.params) self.assertTrue("data_node_count" not in test_cluster.params) - def test_single_node_cluster_invalid_configuration(self): + def test_single_node_cluster_invalid_configuration(self) -> None: self.assertRaises( AssertionError, PerfSingleNodeCluster, bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 1, 1, 0, 0), current_workspace="current_workspace") - def test_single_node_cluster_public_ip(self): + def test_single_node_cluster_public_ip(self) -> None: test_cluster = PerfSingleNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(False, 1, 0, 0, 0), current_workspace="current_workspace") @@ -53,7 +53,7 @@ def test_single_node_cluster_public_ip(self): self.assertTrue(test_cluster.is_endpoint_public) self.assertEqual(test_cluster.endpoint, "3.0.0.0") - def test_single_node_cluster_private_ip(self): + def test_single_node_cluster_private_ip(self) -> None: test_cluster = PerfSingleNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 1, 0, 0, 0), current_workspace="current_workspace") @@ -68,10 +68,9 @@ def test_single_node_cluster_private_ip(self): self.assertFalse(test_cluster.is_endpoint_public) self.assertEqual(test_cluster.endpoint, "127.0.0.1") - def test_cdk_failure_scenarios(self): + def test_cdk_failure_scenarios(self) -> None: test_cluster = PerfSingleNodeCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(True, 1, 0, 0, 0), current_workspace="current_workspace") - cdk_output = {self.stack_name: {}} - self.assertRaises(RuntimeError, test_cluster.create_endpoint, cdk_output) + self.assertRaises(RuntimeError, test_cluster.create_endpoint, {self.stack_name: {}}) diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster.py index 69d4b900d5..4d3e0b525c 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster.py @@ -17,16 +17,16 @@ class TestPerfTestCluster(unittest.TestCase): DATA = os.path.join(os.path.dirname(__file__), "data") BUNDLE_MANIFEST = os.path.join(DATA, "bundle_manifest.yml") - def setUp(self): + def setUp(self) -> None: self.manifest = BundleManifest.from_path(self.BUNDLE_MANIFEST) self.stack_name = "stack" - self.security = "disable" + self.security = True self.config = {"Constants": {"SecurityGroupId": "sg-00000000", "VpcId": "vpc-12345", "AccountId": "12345678", "Region": "us-west-2", "Role": "role-arn"}} self.perf_test_cluster = DummyPerfTestCluster( bundle_manifest=self.manifest, config=self.config, stack_name=self.stack_name, cluster_config=PerfTestClusterConfig(self.security), current_workspace="current_workspace") - def test_create(self): + def test_create(self) -> None: mock_file = MagicMock(side_effect=[{"stack": {"PrivateIp": "10.10.10.10"}}]) with patch("test_workflow.perf_test.perf_test_cluster.os.chdir") as mock_chdir: with patch("subprocess.check_call") as mock_check_call: @@ -36,13 +36,13 @@ def test_create(self): mock_chdir.assert_called_once_with(os.path.join(self.perf_test_cluster.current_workspace, "test_dir")) self.assertEqual(mock_check_call.call_count, 1) - def test_endpoint(self): + def test_endpoint(self) -> None: self.assertEqual(self.perf_test_cluster.endpoint_with_port, None) - def test_port(self): + def test_port(self) -> None: self.assertEqual(self.perf_test_cluster.port, 443) - def test_terminate(self): + def test_terminate(self) -> None: with patch("test_workflow.perf_test.perf_test_cluster.os.chdir") as mock_chdir: with patch("subprocess.check_call") as mock_check_call: self.perf_test_cluster.terminate() @@ -51,12 +51,19 @@ def test_terminate(self): class DummyPerfTestCluster(PerfTestCluster): - def __init__(self, bundle_manifest, config, stack_name, cluster_config, current_workspace): + def __init__( + self, + bundle_manifest: BundleManifest, + config: dict, + stack_name: str, + cluster_config: PerfTestClusterConfig, + current_workspace: str + ): work_dir = os.path.join(current_workspace, "test_dir") super().__init__(bundle_manifest, config, stack_name, cluster_config, current_workspace, work_dir) - def create_endpoint(self, cdk_output): + def create_endpoint(self, cdk_output: dict) -> None: pass - def setup_cdk_params(self, config): + def setup_cdk_params(self, config: dict) -> dict: return {} diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster_config.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster_config.py index 988470e65d..300bdac006 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster_config.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_cluster_config.py @@ -11,7 +11,7 @@ class TestPerfTestClusterConfig(unittest.TestCase): - def test_default_args(self): + def test_default_args(self) -> None: config = PerfTestClusterConfig() self.assertEqual(config.security, False) self.assertEqual(config.data_nodes, 1) @@ -20,7 +20,7 @@ def test_default_args(self): self.assertEqual(config.client_nodes, 0) self.assertEqual(config.is_single_node_cluster, True) - def test_non_default_args(self): + def test_non_default_args(self) -> None: config = PerfTestClusterConfig(True, 1, 2, 3, 4) self.assertEqual(config.security, True) self.assertEqual(config.data_nodes, 1) diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch.py index 8b0c28567b..c4be499e46 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch.py @@ -6,7 +6,8 @@ import os import tempfile import unittest -from unittest.mock import patch +from typing import Any +from unittest.mock import Mock, patch from manifests.bundle_manifest import BundleManifest from test_workflow.perf_test.perf_args import PerfArgs @@ -38,7 +39,7 @@ class TestPerfTestRunnerOpenSearch(unittest.TestCase): @patch("test_workflow.perf_test.perf_test_runner_opensearch.GitRepository") @patch("test_workflow.perf_test.perf_test_runner_opensearch.PerfSingleNodeCluster.create") @patch("test_workflow.perf_test.perf_test_runner_opensearch.PerfTestSuite") - def test_run(self, mock_suite, mock_cluster, mock_git, mock_temp_directory, *mocks): + def test_run(self, mock_suite: Mock, mock_cluster: Mock, mock_git: Mock, mock_temp_directory: Mock, *mocks: Any) -> None: mock_temp_directory.return_value.__enter__.return_value.name = tempfile.gettempdir() mock_cluster.return_value.__enter__.return_value = mock_cluster diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch_plugins.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch_plugins.py index b6c7917543..98e3bdcdd0 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch_plugins.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_runner_opensearch_plugins.py @@ -7,7 +7,8 @@ import os import tempfile import unittest -from unittest.mock import patch +from typing import Any +from unittest.mock import Mock, patch from manifests.bundle_manifest import BundleManifest from test_workflow.perf_test.perf_args import PerfArgs @@ -40,7 +41,7 @@ class PerfTestRunnerOpenSearchPlugins(unittest.TestCase): @patch('test_workflow.perf_test.perf_test_runner_opensearch_plugins.subprocess') @patch("test_workflow.perf_test.perf_test_runner_opensearch_plugins.TemporaryDirectory") @patch("test_workflow.perf_test.perf_test_runner_opensearch_plugins.GitRepository") - def test_run(self, mock_git, mock_temp_directory, *mocks): + def test_run(self, mock_git: Mock, mock_temp_directory: Mock, *mocks: Any) -> None: mock_temp_directory.return_value.__enter__.return_value.name = tempfile.gettempdir() perf_args = PerfArgs() diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_suite.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_suite.py index 31bca03635..f8ff3b1ed5 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_suite.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_perf_test_suite.py @@ -13,7 +13,7 @@ class TestPerfTestSuite(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.args = Mock() self.args.workload = "nyc_taxis" self.args.workload_options = "{}" @@ -28,7 +28,7 @@ def setUp(self): current_workspace="current_workspace", test_results_path="test/results/", args=self.args) - def test_execute_default(self): + def test_execute_default(self) -> None: perf_test_suite = PerfTestSuite(bundle_manifest=self.manifest, endpoint=self.endpoint, security=False, current_workspace="current_workspace", test_results_path="test/results/", args=self.args) with patch("test_workflow.perf_test.perf_test_suite.os.chdir"): @@ -40,7 +40,7 @@ def test_execute_default(self): " -b 41d5ae25183d4e699e92debfbe3f83bd -a x64 -p test/results/ --workload nyc_taxis" " --workload-options '{}' --warmup-iters 0 --test-iters 1 --scenario-type DEFAULT --owner opensearch-devops") - def test_execute_different_owner_and_scenario(self): + def test_execute_different_owner_and_scenario(self) -> None: perf_test_suite = PerfTestSuite(bundle_manifest=self.manifest, endpoint=self.endpoint, security=False, current_workspace="current_workspace", test_results_path="test/results/", args=self.args, owner="test-owner", scenario="CROSS_CLUSTER_REPLICATION") @@ -54,13 +54,21 @@ def test_execute_different_owner_and_scenario(self): " --workload-options '{}' --warmup-iters 0 --test-iters 1 --scenario-type CROSS_CLUSTER_REPLICATION" " --owner test-owner") - def test_execute_with_dict_endpoint(self): + def test_execute_with_dict_endpoint(self) -> None: endpoint = { "default": ["cluster-1"], "second_cluster": ["cluster-2"] } - perf_test_suite = PerfTestSuite(bundle_manifest=self.manifest, endpoint=endpoint, security=False, - current_workspace="current_workspace", test_results_path="test/results/", args=self.args) + + perf_test_suite = PerfTestSuite( + bundle_manifest=self.manifest, + endpoint=endpoint, + security=False, + current_workspace="current_workspace", + test_results_path="test/results/", + args=self.args + ) + with patch("test_workflow.perf_test.perf_test_suite.os.chdir"): with patch("subprocess.check_call") as mock_check_call: perf_test_suite.execute() diff --git a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_run_perf_test.py b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_run_perf_test.py index d5b4627e4e..58a8636bda 100644 --- a/tests/tests_test_workflow/test_perf_workflow/perf_test/test_run_perf_test.py +++ b/tests/tests_test_workflow/test_perf_workflow/perf_test/test_run_perf_test.py @@ -6,7 +6,8 @@ import os import unittest -from unittest.mock import patch +from typing import Any +from unittest.mock import Mock, patch from run_perf_test import main @@ -32,7 +33,7 @@ class TestRunPerfTest(unittest.TestCase): ) @patch("test_workflow.perf_test.perf_test_runners.PerfTestRunnerOpenSearchPlugins.run_tests") @patch("test_workflow.perf_test.perf_test_runners.PerfTestRunnerOpenSearch.run_tests") - def test_run_perf_test(self, os_mock_runner, plugin_mock_runner, *mock): + def test_run_perf_test(self, os_mock_runner: Mock, plugin_mock_runner: Mock, *mock: Any) -> None: main() self.assertEqual(1, os_mock_runner.call_count) self.assertEqual(0, plugin_mock_runner.call_count) @@ -59,7 +60,7 @@ def test_run_perf_test(self, os_mock_runner, plugin_mock_runner, *mock): ) @patch("test_workflow.perf_test.perf_test_runners.PerfTestRunnerOpenSearchPlugins.run_tests") @patch("test_workflow.perf_test.perf_test_runners.PerfTestRunnerOpenSearch.run_tests") - def test_run_perf_test_plugins(self, os_mock_runner, plugin_mock_runner, *mock): + def test_run_perf_test_plugins(self, os_mock_runner: Mock, plugin_mock_runner: Mock, *mock: Any) -> None: main() self.assertEqual(0, os_mock_runner.call_count) self.assertEqual(1, plugin_mock_runner.call_count) diff --git a/tests/tests_test_workflow/test_recorder/test_local_cluster_logs.py b/tests/tests_test_workflow/test_recorder/test_local_cluster_logs.py index 064186c130..15ddafbe2e 100644 --- a/tests/tests_test_workflow/test_recorder/test_local_cluster_logs.py +++ b/tests/tests_test_workflow/test_recorder/test_local_cluster_logs.py @@ -9,19 +9,19 @@ import unittest from unittest.mock import MagicMock -from test_workflow.test_recorder.test_recorder import TestRecorder +from test_workflow.test_recorder.test_recorder import LocalClusterLogs class TestLocalClusterLogs(unittest.TestCase): - def test(self): + def test(self) -> None: mock_parent_class = MagicMock() mock_parent_class._create_base_folder_structure.return_value = "test_base" mock_parent_class._copy_log_files = MagicMock() - logs = TestRecorder.LocalClusterLogs(mock_parent_class) + logs = LocalClusterLogs(mock_parent_class) mock_test_result_data = MagicMock() diff --git a/tests/tests_test_workflow/test_test_args.py b/tests/tests_test_workflow/test_test_args.py index 7fc3c40748..15c2b74f03 100644 --- a/tests/tests_test_workflow/test_test_args.py +++ b/tests/tests_test_workflow/test_test_args.py @@ -27,7 +27,7 @@ class TestTestArgs(unittest.TestCase): ) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_PATH]) - def test_opensearch_default_with_opensearch_test_manifest(self): + def test_opensearch_default_with_opensearch_test_manifest(self) -> None: test_args = TestArgs() self.assertFalse(hasattr(test_args, "opensearch")) self.assertFalse(hasattr(test_args, "opensearch-dashboards")) @@ -39,12 +39,12 @@ def test_opensearch_default_with_opensearch_test_manifest(self): self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_PATH) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_PATH, "--component", "foo", "bar"]) - def test_components(self): + def test_components(self) -> None: test_args = TestArgs() self.assertEqual(test_args.components, ["foo", "bar"]) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_PATH, "--paths", "opensearch=" + TEST_MANIFEST_PATH]) - def test_opensearch_file_with_opensearch_test_manifest(self): + def test_opensearch_file_with_opensearch_test_manifest(self) -> None: test_args = TestArgs() self.assertEqual(test_args.paths.get("opensearch"), os.path.realpath(self.TEST_MANIFEST_PATH)) self.assertFalse(hasattr(test_args.paths, "opensearch-dashboards")) @@ -56,7 +56,7 @@ def test_opensearch_file_with_opensearch_test_manifest(self): self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_PATH) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_PATH, "--paths", "opensearch=https://ci.opensearch.org/x/y", "--verbose"]) - def test_opensearch_url_with_opensearch_test_manifest(self): + def test_opensearch_url_with_opensearch_test_manifest(self) -> None: test_args = TestArgs() self.assertEqual(test_args.paths.get("opensearch"), "https://ci.opensearch.org/x/y") self.assertFalse(hasattr(test_args.paths, "opensearch-dashboards")) @@ -68,7 +68,7 @@ def test_opensearch_url_with_opensearch_test_manifest(self): self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_PATH) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_OPENSEARCH_DASHBOARDS_PATH, "--paths", "opensearch=" + TEST_MANIFEST_PATH]) - def test_opensearch_dashboards_default_with_opensearch_dashboards_test_manifest(self): + def test_opensearch_dashboards_default_with_opensearch_dashboards_test_manifest(self) -> None: test_args = TestArgs() self.assertFalse(hasattr(test_args.paths, "opensearch-dashboards")) self.assertEqual(test_args.paths.get("opensearch"), self.TEST_MANIFEST_PATH) @@ -89,7 +89,7 @@ def test_opensearch_dashboards_default_with_opensearch_dashboards_test_manifest( "opensearch=" + TEST_MANIFEST_PATH ] ) - def test_opensearch_dashboards_file_with_opensearch_dashboards_test_manifest(self): + def test_opensearch_dashboards_file_with_opensearch_dashboards_test_manifest(self) -> None: test_args = TestArgs() self.assertEqual(test_args.paths.get("opensearch-dashboards"), self.TEST_MANIFEST_OPENSEARCH_DASHBOARDS_PATH) self.assertEqual(test_args.paths.get("opensearch"), self.TEST_MANIFEST_PATH) @@ -101,7 +101,7 @@ def test_opensearch_dashboards_file_with_opensearch_dashboards_test_manifest(sel self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_OPENSEARCH_DASHBOARDS_PATH) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_OPENSEARCH_DASHBOARDS_PATH, "--paths", "opensearch-dashboards=https://ci.opensearch.org/x/y", "opensearch=" + TEST_MANIFEST_PATH]) - def test_opensearch_dashboards_url_with_opensearch_dashboards_test_manifest(self): + def test_opensearch_dashboards_url_with_opensearch_dashboards_test_manifest(self) -> None: test_args = TestArgs() self.assertEqual(test_args.paths.get("opensearch-dashboards"), "https://ci.opensearch.org/x/y") self.assertEqual(test_args.paths.get("opensearch"), self.TEST_MANIFEST_PATH) @@ -123,20 +123,20 @@ def test_opensearch_dashboards_url_with_opensearch_dashboards_test_manifest(self "--verbose" ] ) - def test_opensearch_url_opensearch_dashboards_url_with_opensearch_dashboards_test_manifest(self): + def test_opensearch_url_opensearch_dashboards_url_with_opensearch_dashboards_test_manifest(self) -> None: test_args = TestArgs() self.assertEqual(test_args.paths.get("opensearch"), "https://ci.opensearch.org/x/y") self.assertEqual(test_args.paths.get("opensearch-dashboards"), "https://ci.opensearch.org/x/y/dashboards") self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_OPENSEARCH_DASHBOARDS_PATH) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_PATH, "--paths", "opensearch=" + TEST_MANIFEST_PATH, "--test-run-id", "6"]) - def test_run_id(self): + def test_run_id(self) -> None: test_args = TestArgs() self.assertEqual(test_args.test_run_id, 6) self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_PATH) @patch("argparse._sys.argv", [ARGS_PY, TEST_MANIFEST_PATH, "--paths", "opensearch=" + TEST_MANIFEST_PATH, "--verbose"]) - def test_verbose(self): + def test_verbose(self) -> None: test_args = TestArgs() self.assertEqual(test_args.logging_level, logging.DEBUG) self.assertEqual(test_args.test_manifest_path, self.TEST_MANIFEST_PATH) diff --git a/tests/tests_test_workflow/test_test_args_path_validator.py b/tests/tests_test_workflow/test_test_args_path_validator.py index 7952a8b7f5..249ffbb383 100644 --- a/tests/tests_test_workflow/test_test_args_path_validator.py +++ b/tests/tests_test_workflow/test_test_args_path_validator.py @@ -12,7 +12,7 @@ class TestTestArgsPathValidator(unittest.TestCase): - def test(self): + def test(self) -> None: self.assertEqual( TestArgsPathValidator.validate("https://ci.opensearch.org/ci/dbc/bundle-build-dashboards/1.2.0/428"), "https://ci.opensearch.org/ci/dbc/bundle-build-dashboards/1.2.0/428" diff --git a/tests/tests_test_workflow/test_test_component.py b/tests/tests_test_workflow/test_test_component.py index ab9ddb9e5e..bcde2afcd4 100644 --- a/tests/tests_test_workflow/test_test_component.py +++ b/tests/tests_test_workflow/test_test_component.py @@ -6,13 +6,13 @@ class TestTestComponent(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.test_component = TestComponent( "https://github.com/opensearch-project/.github", "8ac515431bf24caf92fea9d9b0af3b8f10b88453", ) - def test_checkout(self): + def test_checkout(self) -> None: with TemporaryDirectory() as tmpdir: subdir = os.path.join(tmpdir.name, ".github") repo = self.test_component.checkout(subdir) diff --git a/tests/tests_test_workflow/test_test_kwargs.py b/tests/tests_test_workflow/test_test_kwargs.py index 7bfc57e795..0c540fb8ff 100644 --- a/tests/tests_test_workflow/test_test_kwargs.py +++ b/tests/tests_test_workflow/test_test_kwargs.py @@ -14,13 +14,13 @@ class TestTestKwargs(unittest.TestCase): - def test(self): + def test(self) -> None: kwargs = TestKwargs(dest="test", option_strings=[]) mock_parser = MagicMock() namespace = SimpleNamespace() values = ["key1=value1", "key2=value2"] - kwargs.__call__(parser=mock_parser, namespace=namespace, values=values) + kwargs.__call__(parser=mock_parser, namespace=namespace, values=values) # type: ignore self.assertEqual( namespace.__getattribute__("test"), diff --git a/tests/tests_test_workflow/test_test_result/test_test_component_results.py b/tests/tests_test_workflow/test_test_result/test_test_component_results.py index 5d25b7b5ee..98c4de0299 100644 --- a/tests/tests_test_workflow/test_test_result/test_test_component_results.py +++ b/tests/tests_test_workflow/test_test_result/test_test_component_results.py @@ -4,10 +4,10 @@ class TestTestResultsComponent(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.test_test_results_component = TestComponentResults() - def test_test_status(self): + def test_test_status(self) -> None: test_failed = self.test_test_results_component.failed self.assertFalse(test_failed) diff --git a/tests/tests_test_workflow/test_test_result/test_test_result.py b/tests/tests_test_workflow/test_test_result/test_test_result.py index 0f662cea21..79d3496938 100644 --- a/tests/tests_test_workflow/test_test_result/test_test_result.py +++ b/tests/tests_test_workflow/test_test_result/test_test_result.py @@ -5,14 +5,16 @@ class TestTestResult(unittest.TestCase): - def setUp(self): - self.test_result = TestResult("sql", "with-security", 0) + test_result: TestResult - def test_failed(self): + def setUp(self) -> None: + self.test_result = TestResult("sql", {"with-security": {}}, 0) + + def test_failed(self) -> None: failed = self.test_result.failed self.assertFalse(failed) - def test_log(self): + def test_log(self) -> None: result = MagicMock() with self.assertLogs() as captured: self.test_result.log(result) diff --git a/tests/tests_test_workflow/test_test_result/test_test_suite_results.py b/tests/tests_test_workflow/test_test_result/test_test_suite_results.py index a5356d2ef0..80ca1945b3 100644 --- a/tests/tests_test_workflow/test_test_result/test_test_suite_results.py +++ b/tests/tests_test_workflow/test_test_result/test_test_suite_results.py @@ -4,9 +4,9 @@ class TestTestResultsSuite(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.test_test_results_suite = TestSuiteResults() - def test_status(self): + def test_status(self) -> None: test_failed = self.test_test_results_suite.failed() self.assertFalse(test_failed)