123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- """
- 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
- Unit tests for ly_test_tools.cli.codeowners_hint
- """
- import pathlib
- import pytest
- import ly_test_tools.cli.codeowners_hint as hint
- import unittest.mock as mock
- _DUMMY_REPO_PATH = "/home/myuser/github/myrepo"
- _DUMMY_CODEOWNERS_PATH = _DUMMY_REPO_PATH + "/.github/CODEOWNERS"
- _dummy_target_paths = [
- ".",
- "relative/path",
- "/absolute/path",
- "/some/fairly/long/path/which/eventually/ends/in/a/directory/a/s/d/f/g/h/j/k/l",
- "/some/fairly/long/path/which/eventually/ends/in/a/file/a/s/d/f/g/h/j/k/l/dummy.txt"
- "C:\\github\\o3de\\Tools\\LyTestTools\\tests\\unit\\test_codeowners_hint.py",
- "/home/myuser/github/o3de/Tools/LyTestTools/tests/unit/test_codeowners_hint.py",
- ]
- @mock.patch("os.path.exists")
- @pytest.mark.parametrize("target_path", _dummy_target_paths)
- def test_FindCodeowners_MockExistsInRepo_Found(mock_exists, target_path):
- mock_exists.side_effect = [False, True] # found in parent directory
- codeowners_path = hint.find_github_codeowners(target_path)
- assert codeowners_path
- mock_exists.assert_called()
- @mock.patch("os.path.exists")
- @pytest.mark.parametrize("target_path", _dummy_target_paths)
- def test_FindCodeowners_MockNotInRepo_NotFound(mock_exists, target_path):
- mock_exists.return_value = False # never found
- codeowners_path = hint.find_github_codeowners(target_path)
- assert not codeowners_path
- mock_exists.assert_called()
- def _assert_owners_from(target_relative_path, mock_ownership_data, expected_path_match, expected_alias_match):
- """
- :param target_relative_path: string path relative to root of repo, starting with slash
- :param mock_ownership_data: string contents representing a CODEOWNERS file
- :param expected_path_match: expected line's path-value to match
- :param expected_alias_match: expected line's alias-value to match
- """
- with mock.patch('builtins.open', mock.mock_open(read_data=mock_ownership_data)):
- path, alias = hint.get_codeowners_from(pathlib.Path(_DUMMY_REPO_PATH + target_relative_path),
- pathlib.Path(_DUMMY_CODEOWNERS_PATH))
- assert path == expected_path_match
- assert alias == expected_alias_match
- @mock.patch("os.path.isfile", mock.MagicMock(return_value=True))
- @mock.patch("os.path.getsize", mock.MagicMock(return_value=1))
- class TestGetOwnersFrom:
- def test_ExactMatch_OneExactMatch_Matched(self):
- target = "/some/path/to/my/file"
- ownership_data = target + " @alias\n"
- _assert_owners_from(target, ownership_data, target, "@alias")
- @pytest.mark.parametrize("target_path,codeowners_path", [
- (pathlib.PurePosixPath("/some/owned/unix/path"), pathlib.PurePosixPath("/some/.github/CODEOWNERS")),
- (pathlib.PurePosixPath("/some/owned/unix/.dot/path"), pathlib.PurePosixPath("/some/.github/CODEOWNERS")),
- (pathlib.PureWindowsPath("\\some\\owned\\windows\\path"), pathlib.PureWindowsPath("\\some\\.github\\CODEOWNERS")),
- (pathlib.PureWindowsPath("\\some\\owned\\windows\\.dot\\path"), pathlib.PureWindowsPath("\\some\\.github\\CODEOWNERS")),
- ])
- def test_ExactMatch_VariantSystemPaths_Matched(self, target_path, codeowners_path):
- with mock.patch('builtins.open', mock.mock_open(read_data=f"/owned @alias")):
- path, alias = hint.get_codeowners_from(target_path, codeowners_path)
- assert path, "unexpectedly None or empty"
- assert alias, "unexpectedly None or empty"
- def test_NoMatches_MultipleMismatched_Negative(self):
- target = _DUMMY_REPO_PATH + "/does/not/exist"
- ownership_data = \
- "/a/b/c/ @alias\n"\
- "/a/b/d/ @alias2\n"\
- "/a/b/e/ @alias3\n"\
- "/a/b/f/ @alias4\n"
- # warning: negative assertions can easily pass by accident
- _assert_owners_from(target, ownership_data, "", "")
- def test_WildcardMatch_GlobalWildcard_Matches(self):
- target = _DUMMY_REPO_PATH + "/dummy.py"
- ownership_data = "* @alias\n"
- _assert_owners_from(target, ownership_data, "*", "@alias")
- def test_WildcardMatch_GlobalExtensionWildcard_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/dummy.py"
- ownership_data = "*.py @alias\n"
- _assert_owners_from(target, ownership_data, "*.py", "@alias")
- def test_WildcardMismatch_GlobalExtensionWildcard_Negative(self):
- target = _DUMMY_REPO_PATH + "/some/dummy.py"
- ownership_data = "*.txt @alias\n"
- # warning: negative assertions can easily pass by accident
- _assert_owners_from(target, ownership_data, "", "")
- def test_WildcardMatch_RootedExtensionWildcard_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/dummy.py"
- ownership_data = "/some/*.py @alias\n"
- _assert_owners_from(target, ownership_data, "/some/*.py", "@alias")
- def test_WildcardMatch_UnrootedExtensionWildcard_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/other/dummy.py"
- ownership_data = "other/*.py @alias\n"
- _assert_owners_from(target, ownership_data, "other/*.py", "@alias")
- def test_WildcardMatch_RootedQuestionWildcard_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/dummy.py"
- ownership_data = "/some/du?my.py @alias\n"
- _assert_owners_from(target, ownership_data, "/some/du?my.py", "@alias")
- def test_WildcardMatch_UnrootedQuestionWildcard_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/dummy.py"
- ownership_data = "some/du?my.py @alias\n"
- _assert_owners_from(target, ownership_data, "some/du?my.py", "@alias")
- def test_WildcardMatch_ComplexRootedExtension_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/path/to/my/dummy.py"
- ownership_data = "some/pa?h/to/*/*.py @alias\n"
- _assert_owners_from(target, ownership_data, "some/pa?h/to/*/*.py", "@alias")
- def test_WildcardMatch_ComplexRelativePattern_Matches(self):
- target = _DUMMY_REPO_PATH + "/some/path/to/my/dummy.py"
- ownership_data = "path/t?/my/*.py @alias\n"
- _assert_owners_from(target, ownership_data, "path/t?/my/*.py", "@alias")
- def test_PartialMatch_MultipleMatches_FinalMatch(self):
- target = "/some/path/to/my/file"
- ownership_data = \
- "* @alias\n"\
- "/some/path/ @alias2\n"\
- "/some/path/to/my/ @alias3\n"\
- "/some/other/mismatch/ @alias4\n"
- _assert_owners_from(target, ownership_data, "/some/path/to/my/", "@alias3")
- def test_PartialMatch_NonFinalExactMatch_FinalMatched(self):
- target = "/some/path/to/my/file"
- ownership_data = \
- "* @alias\n"\
- "/some/path/ @alias2\n"\
- "/some/path/to/my/file @alias3\n"\
- "/some/path/to/my/ @alias4\n" # expect final matching entry, despite the previous exact match
- _assert_owners_from(target, ownership_data, "/some/path/to/my/", "@alias4")
|