123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- #
- # Copyright (c) Contributors to the Open 3D Engine Project.
- # For complete copyright and license terms please see the LICENSE at the root of this distribution.
- #
- # SPDX-License-Identifier: Apache-2.0 OR MIT
- #
- #
- from logging import getLogger
- from typing import Counter
- from test_impact import NativeTestImpact, BaseTestImpact, PythonTestImpact
- from tiaf_driver import SUPPORTED_RUNTIMES
- from tiaf_driver import main
- import pytest
- logging = getLogger("tiaf")
- def assert_list_content_equal(list1, list2):
- assert Counter(list1) == Counter(list2)
- class ConcreteBaseTestImpact(BaseTestImpact):
- """
- Concrete implementation of BaseTestImpact so that we can execute unit tests on the functionality of BaseTestImpact individually.
- """
- _runtime_type = "native"
- _default_sequence_type = "regular"
- @property
- def default_sequence_type(self):
- """
- Returns default sequence type, defaulting to "regular" for this example.
- """
- return self._default_sequence_type
- @property
- def runtime_type(self):
- return self._runtime_type
- class TestTiafDriver():
- def test_run_Tiaf_mars_index_prefix_is_supplied(self, caplog, main_args, skip_if_test_targets_disabled, mock_runtime, mocker):
- # given:
- # Default args + mars_index_prefix being provided,
- # and transmit_report_to_mars is patched to intercept the call.
- main_args['mars_index_prefix'] = "test_prefix"
- mock_mars = mocker.patch("mars_utils.transmit_report_to_mars")
- # when:
- # We run Tiaf through the driver.
- with pytest.raises(SystemExit):
- main(main_args)
- # then:
- # Tiaf should call the transmit function.
- mock_mars.assert_called()
- def test_run_Tiaf_mars_index_prefix_is_not_supplied(self, caplog, main_args, skip_if_test_targets_disabled, mock_runtime, mocker):
- # given:
- # Default_args - mars index is not supplied.
- mock_mars = mocker.patch("mars_utils.transmit_report_to_mars")
- # when:
- # We run tiaf through the driver.
- with pytest.raises(SystemExit):
- main(main_args)
- # then:
- # Tiaf should not call the transmit function.
- mock_mars.assert_not_called()
- @pytest.mark.parametrize("runtime_type,mock_type", [("native", "test_impact.native_test_impact.NativeTestImpact.__init__"), ("python", "test_impact.python_test_impact.PythonTestImpact.__init__")])
- def test_run_Tiaf_driver_runtime_type_selection(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, mocker, runtime_type, mock_type):
- # given:
- # Default args + runtime_type
- tiaf_args['runtime_type'] = runtime_type
- runtime_class = SUPPORTED_RUNTIMES[runtime_type]
- testMock = mocker.patch(mock_type, side_effect=SystemExit)
-
- # when
- # We run tiaf through the driver.
- with pytest.raises(SystemExit):
- main(tiaf_args)
- # then:
- # Tiaf should instantiate a TestImpact object of the correct runtime type
- testMock.assert_called()
- class TestTiafInitialiseStorage():
- def skip_if_test_targets_disabled(skip_if_test_targets_disabled):
- if not skip_if_test_targets_disabled:
- pytest.skip("Test targets are disabled for this runtime, test will be skipped.")
- @pytest.fixture
- def runtime_type(self):
- """
- Override the runtime_type fixture so that only native tests run in this example, as we have hardcoded ConcreteBaseTestImpact to act as a NativeTestImpact object in many cases.
- """
- return "native"
- def to_list(self, input):
- output = []
- for entry in input:
- output.append(entry)
- return output
-
- def test_create_TestImpact_no_s3_bucket_name(self, caplog, tiaf_args, skip_if_test_targets_disabled, config_data, mocker, storage_config):
- # given:
- # Default args.
- expected_storage_args = config_data, tiaf_args['suites'], tiaf_args[
- 'commit'], storage_config['active_workspace'], storage_config['unpacked_coverage_data_file'], storage_config['previous_test_run_data_file'], storage_config['historic_workspace'], storage_config['historic_data_file'], storage_config['temp_workspace']
- mock_local = mocker.patch(
- "persistent_storage.PersistentStorageLocal.__init__", side_effect=SystemError(), return_value=None)
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # PersistentStorageLocal should be called with suites, commit and config data as arguments.
- assert_list_content_equal(self.to_list(mock_local.call_args[0]).pop(), self.to_list(expected_storage_args).pop())
- @pytest.mark.parametrize("bucket_name,top_level_dir,expected_top_level_dir", [("test_bucket", "test_dir", "test_dir/native")])
- def test_create_TestImpact_s3_bucket_name_supplied(self, caplog, tiaf_args, skip_if_test_targets_disabled, mocker, bucket_name, top_level_dir, config_data, expected_top_level_dir, storage_config):
- # given:
- # Default arguments + s3_bucket and s3_top_level_dir being set to the above parameters,
- # and we patch PersistentStorageS3 to intercept the constructor call.
- tiaf_args['s3_bucket'] = bucket_name
- tiaf_args['s3_top_level_dir'] = top_level_dir
- mock_storage = mocker.patch(
- "persistent_storage.PersistentStorageS3.__init__", side_effect=SystemError())
- expected_storage_args = config_data, tiaf_args['suites'], tiaf_args[
- 'commit'], bucket_name, expected_top_level_dir, tiaf_args['src_branch'], storage_config['active_workspace'], storage_config['unpacked_coverage_data_file'], storage_config['previous_test_run_data_file'], storage_config['temp_workspace']
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # PersistentStorageS3 should be called with config data, commit, bucket_name, top_level_dir and src branch as arguments.
- mock_storage.assert_called_with(*expected_storage_args)
- def test_create_TestImpact_s3_bucket_name_not_supplied(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args, mocker, config_data):
- # given:
- # Default arguments + s3_bucket and s3_top_level_dir arguments set to none.
- tiaf_args['s3_bucket'] = None
- tiaf_args['s3_top_level_dir'] = None
- mock_storage = mocker.patch(
- "persistent_storage.PersistentStorageS3.__init__", return_value=None)
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # PersistentStorageS3 should not be called.
- mock_storage.assert_not_called()
- def test_create_TestImpact_s3_top_level_dir_bucket_name_not_supplied(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args, mocker, config_data):
- # given:
- # Default arguments + s3_bucket set to none and s3_top_level_dir is defined.
- tiaf_args['s3_bucket'] = None
- tiaf_args['s3_top_level_dir'] = "test_dir"
- mock_storage = mocker.patch(
- "persistent_storage.PersistentStorageS3.__init__", return_value=None)
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # PersistentStorageS3 should not be called.
- mock_storage.assert_not_called()
- class TestTIAFNativeUnitTests():
- def skip_if_test_targets_disabled(skip_if_test_targets_disabled):
- if not skip_if_test_targets_disabled:
- pytest.skip("Test targets are disabled for this runtime, test will be skipped.")
- @pytest.fixture
- def runtime_type(self):
- """
- Override the runtime_type fixture so that only native versions of the tests run in this example, as we are only testing the NativeTestImpact class.
- """
- return "native"
- @pytest.mark.parametrize("safemode, arg_val", [("on", "on")])
- def test_create_NativeTestImpact_safe_mode_arguments(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, cpp_default_runtime_args, safemode, arg_val):
- # given:
- # Default args + safe_mode set.
- tiaf_args['safe_mode'] = safemode
- cpp_default_runtime_args['safemode'] = "--safemode="+arg_val
- # when:
- # We create a TestImpact object.
- tiaf = NativeTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal expected args.
- assert_list_content_equal(
- tiaf.runtime_args, cpp_default_runtime_args.values())
- def test_create_NativeTestImpact_no_safe_mode(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, cpp_default_runtime_args):
- # given:
- # Default args + safe_mode set.
- # when:
- # We create a TestImpact object.
- tiaf = NativeTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal expected args.
- assert_list_content_equal(
- tiaf.runtime_args, cpp_default_runtime_args.values())
- @pytest.mark.parametrize("bucket_name,top_level_dir,expected_top_level_dir", [("test_bucket", "test_dir", "test_dir/native")])
- def test_create_NativeTestImpact_correct_s3_dir_runtime_type(self, config_data, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, cpp_default_runtime_args, mocker, bucket_name, storage_config, top_level_dir, expected_top_level_dir):
- # given:
- # Default args + s3_bucket and s3_top_level_dir set
- tiaf_args['s3_bucket'] = bucket_name
- tiaf_args['s3_top_level_dir'] = top_level_dir
- mock_storage = mocker.patch(
- "persistent_storage.PersistentStorageS3.__init__", side_effect=SystemError())
- expected_storage_args = config_data, tiaf_args['suites'], tiaf_args[
- 'commit'], bucket_name, expected_top_level_dir, tiaf_args['src_branch'], storage_config['active_workspace'], storage_config['unpacked_coverage_data_file'], storage_config['previous_test_run_data_file'], storage_config['temp_workspace']
- # when:
- # We create a NativeTestImpact object
- tiaf = NativeTestImpact(tiaf_args)
- # then:
- # PersistentStorageS3.__init__ should be called with config data, suites, commit, bucket_name, modified top level dir and src_branch as arguments
- mock_storage.assert_called_with(*expected_storage_args)
- class TestTIAFPythonUnitTests():
- def skip_if_test_targets_disabled(skip_if_test_targets_disabled):
- if not skip_if_test_targets_disabled:
- pytest.skip("Test targets are disabled for this runtime, test will be skipped.")
- @pytest.fixture
- def runtime_type(self):
- """
- Override the runtime_type fixture so that only python versions of the tests run in this example, as we are only testing the PythonTestImpact class.
- """
- return "python"
- #@pytest.mark.skip(reason="To fix before PR")
- @pytest.mark.parametrize("bucket_name,top_level_dir,expected_top_level_dir", [("test_bucket", "test_dir", "test_dir/python")])
- def test_create_PythonTestImpact_correct_s3_dir_runtime_type(self, config_data, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, mocker, bucket_name, top_level_dir, expected_top_level_dir, storage_config):
- # given:
- # Default args + s3_bucket and s3_top_level_dir set
- tiaf_args['s3_bucket'] = bucket_name
- tiaf_args['s3_top_level_dir'] = top_level_dir
- mock_storage = mocker.patch(
- "persistent_storage.PersistentStorageS3.__init__", side_effect=SystemError())
- expected_storage_args = config_data, tiaf_args['suites'], tiaf_args[
- 'commit'], bucket_name, expected_top_level_dir, tiaf_args['src_branch'], storage_config['active_workspace'], storage_config['unpacked_coverage_data_file'], storage_config['previous_test_run_data_file'], storage_config['temp_workspace']
- # when:
- # We create a PythonTestImpact object
- tiaf = PythonTestImpact(tiaf_args)
- # then:
- # PersistentStorageS3.__init__ should be called with config data, suites, commit, bucket_name, modified top level dir and src_branch as arguments
- mock_storage.assert_called_with(*expected_storage_args)
- class TestTIAFBaseUnitTests():
- @pytest.fixture
- def runtime_type(self):
- """
- Override the runtime_type fixture so that only native tests run in this example, as we have hardcoded ConcreteBaseTestImpact to act as a NativeTestImpact object in many cases.
- """
- return "native"
- def test_create_TestImpact_valid_config(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, mocker, default_runtime_args):
- """
- Given default arguments, when we create a TestImpact object, tiaf.runtime_args should be eqaul
- """
- # given:
- # Default arguments.
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal our default_runtime_args values.
- assert_list_content_equal(
- tiaf.runtime_args, default_runtime_args.values())
- def test_create_TestImpact_invalid_config(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, tmp_path_factory, default_runtime_args):
- # given:
- # Invalid config file at invalid_file,
- # and setting tiaf_args.config to that path.
- invalid_file = tmp_path_factory.mktemp("test") / "test_file.txt"
- with open(invalid_file, 'w+') as f:
- f.write("fake json")
- tiaf_args['config'] = invalid_file
- # when:
- # We create a TestImpact object.
- # then:
- # It should raise a SystemError.
- with pytest.raises(SystemError) as exc_info:
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- @ pytest.mark.parametrize("branch_name", ["development", "not_a_real_branch"])
- def test_create_TestImpact_src_branch(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args, branch_name):
- # given:
- # Default args + src_branch set to branch_name.
- tiaf_args['src_branch'] = branch_name
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.source_branch shoudl equal our branch name.
- assert tiaf.source_branch == branch_name
- @ pytest.mark.parametrize("branch_name", ["development", "not_a_real_branch"])
- def test_create_TestImpact_dst_branch(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args, branch_name):
- # given:
- # Default args + dst_branch set to branch_name.
- tiaf_args['dst_branch'] = branch_name
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.destination_branch should equal our branch name parameter.
- assert tiaf.destination_branch == branch_name
- @ pytest.mark.parametrize("commit", ["9a15f038807ba8b987c9e689952d9271ef7fd086", "foobar"])
- def test_create_TestImpact_commit(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args, commit):
- # given:
- # Default args + commit set to commit.
- tiaf_args['commit'] = commit
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.destination_commit should equal our commit parameter.
- assert tiaf.destination_commit == commit
- def test_create_TestImpact_valid_test_suite_name(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args):
- # given:
- # Default args
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal our default_runtime_ars.
- assert_list_content_equal(
- tiaf.runtime_args, default_runtime_args.values())
- def test_create_TestImpact_invalid_test_suite_name(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args):
- # given:
- # Default args + suites defined as "foobar" in given args and expected args.
- tiaf_args['suites'] = "foobar"
- default_runtime_args['suites'] = "--suites=foobar"
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal expected args.
- assert_list_content_equal(
- tiaf.runtime_args, default_runtime_args.values())
- @ pytest.mark.parametrize("policy", ["continue", "abort", "ignore"])
- def test_create_TestImpact_valid_failure_policy(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args, policy):
- # given:
- # Default args + test_failure_policy set to policy parameter.
- tiaf_args['test_failure_policy'] = policy
- default_runtime_args['test_failure_policy'] = "--fpolicy="+policy
- # Set src branch to be different than dst branch so that we can get a regular sequence, otherwise TIAF will default to a see sequence and overwrite our failure policy.
- tiaf_args['src_branch'] = 122
- default_runtime_args['sequence'] = "--sequence=regular"
- default_runtime_args['ipolicy'] = "--ipolicy=continue"
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal expected args.
- assert_list_content_equal(
- tiaf.runtime_args, default_runtime_args.values())
- def test_create_TestImpact_exclude_file_not_supplied(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args):
- # given:
- # Default args.
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal expected args.
- assert_list_content_equal(
- tiaf.runtime_args, default_runtime_args.values())
- def test_create_TestImpact_exclude_file_supplied(self, caplog, tiaf_args, skip_if_test_targets_disabled, mock_runtime, default_runtime_args):
- # given:
- # Default args + exclude_file set.
- tiaf_args['exclude_file'] = "testpath"
- default_runtime_args['exclude'] = "--excluded=testpath"
- # when:
- # We create a TestImpact object.
- tiaf = ConcreteBaseTestImpact(tiaf_args)
- # then:
- # tiaf.runtime_args should equal expected args.
- assert_list_content_equal(
- tiaf.runtime_args, default_runtime_args.values())
|