|
1 | 1 | """Test evaluation base."""
|
2 | 2 |
|
3 | 3 | # pylint: disable=import-error,protected-access
|
| 4 | +import errno |
4 | 5 | from os import listdir
|
5 | 6 | from pathlib import Path
|
6 |
| -from unittest.mock import AsyncMock, patch |
| 7 | +from unittest.mock import PropertyMock, patch |
7 | 8 |
|
| 9 | +import pytest |
| 10 | + |
| 11 | +from supervisor.config import CoreConfig |
8 | 12 | from supervisor.coresys import CoreSys
|
9 |
| -from supervisor.resolution.const import ContextType, IssueType, SuggestionType |
| 13 | +from supervisor.exceptions import StoreGitCloneError |
| 14 | +from supervisor.resolution.const import ( |
| 15 | + ContextType, |
| 16 | + IssueType, |
| 17 | + SuggestionType, |
| 18 | + UnhealthyReason, |
| 19 | +) |
10 | 20 | from supervisor.resolution.data import Issue, Suggestion
|
11 | 21 | from supervisor.resolution.fixups.store_execute_reset import FixupStoreExecuteReset
|
| 22 | +from supervisor.store.git import GitRepo |
| 23 | +from supervisor.store.repository import Repository |
12 | 24 |
|
13 | 25 |
|
14 |
| -async def test_fixup(coresys: CoreSys, supervisor_internet, tmp_path): |
15 |
| - """Test fixup.""" |
16 |
| - store_execute_reset = FixupStoreExecuteReset(coresys) |
17 |
| - test_repo = Path(tmp_path, "test_repo") |
| 26 | +@pytest.fixture(name="mock_addons_git", autouse=True) |
| 27 | +async def fixture_mock_addons_git(tmp_supervisor_data: Path) -> None: |
| 28 | + """Mock addons git path.""" |
| 29 | + with patch.object( |
| 30 | + CoreConfig, |
| 31 | + "path_addons_git", |
| 32 | + new=PropertyMock(return_value=tmp_supervisor_data / "addons" / "git"), |
| 33 | + ): |
| 34 | + yield |
18 | 35 |
|
19 |
| - assert store_execute_reset.auto |
20 | 36 |
|
| 37 | +def add_store_reset_suggestion(coresys: CoreSys) -> None: |
| 38 | + """Add suggestion for tests.""" |
21 | 39 | coresys.resolution.add_suggestion(
|
22 |
| - Suggestion(SuggestionType.EXECUTE_RESET, ContextType.STORE, reference="test") |
| 40 | + Suggestion( |
| 41 | + SuggestionType.EXECUTE_RESET, ContextType.STORE, reference="94cfad5a" |
| 42 | + ) |
23 | 43 | )
|
24 | 44 | coresys.resolution.add_issue(
|
25 |
| - Issue(IssueType.CORRUPT_REPOSITORY, ContextType.STORE, reference="test") |
| 45 | + Issue(IssueType.CORRUPT_REPOSITORY, ContextType.STORE, reference="94cfad5a") |
26 | 46 | )
|
27 | 47 |
|
28 |
| - test_repo.mkdir() |
29 |
| - (test_repo / ".git").mkdir() |
| 48 | + |
| 49 | +@pytest.mark.usefixtures("supervisor_internet") |
| 50 | +async def test_fixup(coresys: CoreSys): |
| 51 | + """Test fixup.""" |
| 52 | + store_execute_reset = FixupStoreExecuteReset(coresys) |
| 53 | + test_repo = coresys.config.path_addons_git / "94cfad5a" |
| 54 | + |
| 55 | + assert store_execute_reset.auto |
| 56 | + |
| 57 | + add_store_reset_suggestion(coresys) |
| 58 | + test_repo.mkdir(parents=True) |
| 59 | + good_marker = test_repo / ".git" |
| 60 | + (corrupt_marker := (test_repo / "corrupt")).touch() |
30 | 61 | assert test_repo.exists()
|
| 62 | + assert not good_marker.exists() |
| 63 | + assert corrupt_marker.exists() |
31 | 64 |
|
32 |
| - mock_repositorie = AsyncMock() |
33 |
| - mock_repositorie.git.path = test_repo |
34 |
| - coresys.store.repositories["test"] = mock_repositorie |
35 |
| - assert len(listdir(test_repo)) > 0 |
| 65 | + async def mock_clone(obj: GitRepo, path: Path | None = None): |
| 66 | + """Mock of clone method.""" |
| 67 | + path = path or obj.path |
| 68 | + await coresys.run_in_executor((path / ".git").mkdir) |
36 | 69 |
|
37 |
| - with patch("shutil.disk_usage", return_value=(42, 42, 2 * (1024.0**3))): |
| 70 | + coresys.store.repositories["94cfad5a"] = Repository( |
| 71 | + coresys, "https://github.com/home-assistant/addons-example" |
| 72 | + ) |
| 73 | + with ( |
| 74 | + patch.object(GitRepo, "load"), |
| 75 | + patch.object(GitRepo, "_clone", new=mock_clone), |
| 76 | + patch("shutil.disk_usage", return_value=(42, 42, 2 * (1024.0**3))), |
| 77 | + ): |
38 | 78 | await store_execute_reset()
|
39 | 79 |
|
40 |
| - assert len(listdir(test_repo)) == 0 |
41 |
| - assert mock_repositorie.load.called |
| 80 | + assert test_repo.exists() |
| 81 | + assert good_marker.exists() |
| 82 | + assert not corrupt_marker.exists() |
42 | 83 | assert len(coresys.resolution.suggestions) == 0
|
43 | 84 | assert len(coresys.resolution.issues) == 0
|
| 85 | + assert len(listdir(coresys.config.path_tmp)) == 0 |
| 86 | + |
| 87 | + |
| 88 | +@pytest.mark.usefixtures("supervisor_internet") |
| 89 | +async def test_fixup_clone_fail(coresys: CoreSys): |
| 90 | + """Test fixup does not delete cache when clone fails.""" |
| 91 | + store_execute_reset = FixupStoreExecuteReset(coresys) |
| 92 | + test_repo = coresys.config.path_addons_git / "94cfad5a" |
| 93 | + |
| 94 | + add_store_reset_suggestion(coresys) |
| 95 | + test_repo.mkdir(parents=True) |
| 96 | + (corrupt_marker := (test_repo / "corrupt")).touch() |
| 97 | + assert test_repo.exists() |
| 98 | + assert corrupt_marker.exists() |
| 99 | + |
| 100 | + coresys.store.repositories["94cfad5a"] = Repository( |
| 101 | + coresys, "https://github.com/home-assistant/addons-example" |
| 102 | + ) |
| 103 | + with ( |
| 104 | + patch.object(GitRepo, "load"), |
| 105 | + patch.object(GitRepo, "_clone", side_effect=StoreGitCloneError), |
| 106 | + patch("shutil.disk_usage", return_value=(42, 42, 2 * (1024.0**3))), |
| 107 | + ): |
| 108 | + await store_execute_reset() |
| 109 | + |
| 110 | + assert test_repo.exists() |
| 111 | + assert corrupt_marker.exists() |
| 112 | + assert len(coresys.resolution.suggestions) == 1 |
| 113 | + assert len(coresys.resolution.issues) == 1 |
| 114 | + assert len(listdir(coresys.config.path_tmp)) == 0 |
| 115 | + |
| 116 | + |
| 117 | +@pytest.mark.parametrize( |
| 118 | + ("error_num", "unhealthy"), [(errno.EBUSY, False), (errno.EBADMSG, True)] |
| 119 | +) |
| 120 | +@pytest.mark.usefixtures("supervisor_internet") |
| 121 | +async def test_fixup_move_fail(coresys: CoreSys, error_num: int, unhealthy: bool): |
| 122 | + """Test fixup cleans up clone on move fail. |
| 123 | +
|
| 124 | + This scenario shouldn't really happen unless something is pretty wrong with the system. |
| 125 | + It will leave the user in a bind without the git cache but at least we try to clean up tmp. |
| 126 | + """ |
| 127 | + store_execute_reset = FixupStoreExecuteReset(coresys) |
| 128 | + test_repo = coresys.config.path_addons_git / "94cfad5a" |
| 129 | + |
| 130 | + add_store_reset_suggestion(coresys) |
| 131 | + test_repo.mkdir(parents=True) |
| 132 | + coresys.store.repositories["94cfad5a"] = Repository( |
| 133 | + coresys, "https://github.com/home-assistant/addons-example" |
| 134 | + ) |
| 135 | + with ( |
| 136 | + patch.object(GitRepo, "load"), |
| 137 | + patch.object(GitRepo, "_clone"), |
| 138 | + patch("supervisor.store.git.Path.rename", side_effect=(err := OSError())), |
| 139 | + patch("shutil.disk_usage", return_value=(42, 42, 2 * (1024.0**3))), |
| 140 | + ): |
| 141 | + err.errno = error_num |
| 142 | + await store_execute_reset() |
| 143 | + |
| 144 | + assert len(coresys.resolution.suggestions) == 1 |
| 145 | + assert len(coresys.resolution.issues) == 1 |
| 146 | + assert len(listdir(coresys.config.path_tmp)) == 0 |
| 147 | + assert ( |
| 148 | + UnhealthyReason.OSERROR_BAD_MESSAGE in coresys.resolution.unhealthy |
| 149 | + ) is unhealthy |
0 commit comments