diff options
| -rw-r--r-- | subcmds/gc.py | 11 | ||||
| -rw-r--r-- | tests/test_subcmds_gc.py | 82 |
2 files changed, 92 insertions, 1 deletions
diff --git a/subcmds/gc.py b/subcmds/gc.py index 4e5bcabff..a23d5e068 100644 --- a/subcmds/gc.py +++ b/subcmds/gc.py | |||
| @@ -284,7 +284,16 @@ class Gc(Command): | |||
| 284 | args, all_manifests=not opt.this_manifest_only | 284 | args, all_manifests=not opt.this_manifest_only |
| 285 | ) | 285 | ) |
| 286 | 286 | ||
| 287 | ret = self.delete_unused_projects(projects, opt) | 287 | # If the user specified projects, fetch the global list separately |
| 288 | # to avoid deleting untargeted projects. | ||
| 289 | if args: | ||
| 290 | all_projects = self.GetProjects( | ||
| 291 | [], all_manifests=not opt.this_manifest_only | ||
| 292 | ) | ||
| 293 | else: | ||
| 294 | all_projects = projects | ||
| 295 | |||
| 296 | ret = self.delete_unused_projects(all_projects, opt) | ||
| 288 | if ret != 0: | 297 | if ret != 0: |
| 289 | return ret | 298 | return ret |
| 290 | 299 | ||
diff --git a/tests/test_subcmds_gc.py b/tests/test_subcmds_gc.py new file mode 100644 index 000000000..708f4a7ec --- /dev/null +++ b/tests/test_subcmds_gc.py | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | # Copyright (C) 2026 The Android Open Source Project | ||
| 2 | # | ||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | # you may not use this file except in compliance with the License. | ||
| 5 | # You may obtain a copy of the License at | ||
| 6 | # | ||
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | # | ||
| 9 | # Unless required by applicable law or agreed to in writing, software | ||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | # See the License for the specific language governing permissions and | ||
| 13 | # limitations under the License. | ||
| 14 | |||
| 15 | """Unittests for the subcmds/gc.py module.""" | ||
| 16 | |||
| 17 | import unittest | ||
| 18 | from unittest import mock | ||
| 19 | |||
| 20 | from subcmds import gc | ||
| 21 | |||
| 22 | |||
| 23 | class GcCommand(unittest.TestCase): | ||
| 24 | """Tests for gc command.""" | ||
| 25 | |||
| 26 | def setUp(self): | ||
| 27 | self.cmd = gc.Gc() | ||
| 28 | self.opt, self.args = self.cmd.OptionParser.parse_args([]) | ||
| 29 | self.opt.this_manifest_only = False | ||
| 30 | self.opt.repack = False | ||
| 31 | |||
| 32 | self.mock_get_projects = mock.patch.object( | ||
| 33 | self.cmd, "GetProjects" | ||
| 34 | ).start() | ||
| 35 | |||
| 36 | self.mock_delete = mock.patch.object( | ||
| 37 | self.cmd, "delete_unused_projects", return_value=0 | ||
| 38 | ).start() | ||
| 39 | |||
| 40 | self.mock_repack = mock.patch.object( | ||
| 41 | self.cmd, "repack_projects", return_value=0 | ||
| 42 | ).start() | ||
| 43 | |||
| 44 | def tearDown(self): | ||
| 45 | mock.patch.stopall() | ||
| 46 | |||
| 47 | def test_gc_no_args(self): | ||
| 48 | """Test gc without specific projects.""" | ||
| 49 | self.mock_get_projects.return_value = ["all_projects"] | ||
| 50 | |||
| 51 | self.cmd.Execute(self.opt, []) | ||
| 52 | |||
| 53 | self.mock_get_projects.assert_called_once_with([], all_manifests=True) | ||
| 54 | self.mock_delete.assert_called_once_with(["all_projects"], self.opt) | ||
| 55 | self.mock_repack.assert_not_called() | ||
| 56 | |||
| 57 | def test_gc_with_args(self): | ||
| 58 | """Test gc with specific projects uses all_projects for delete.""" | ||
| 59 | self.mock_get_projects.side_effect = [["projA"], ["all_projects"]] | ||
| 60 | self.opt.repack = True | ||
| 61 | |||
| 62 | self.cmd.Execute(self.opt, ["projA"]) | ||
| 63 | |||
| 64 | self.mock_get_projects.assert_has_calls( | ||
| 65 | [ | ||
| 66 | mock.call(["projA"], all_manifests=True), | ||
| 67 | mock.call([], all_manifests=True), | ||
| 68 | ] | ||
| 69 | ) | ||
| 70 | |||
| 71 | self.mock_delete.assert_called_once_with(["all_projects"], self.opt) | ||
| 72 | self.mock_repack.assert_called_once_with(["projA"], self.opt) | ||
| 73 | |||
| 74 | def test_gc_exit_on_delete_failure(self): | ||
| 75 | """Test gc exits if delete_unused_projects fails.""" | ||
| 76 | self.mock_get_projects.return_value = ["all_projects"] | ||
| 77 | self.mock_delete.return_value = 1 | ||
| 78 | self.opt.repack = True | ||
| 79 | |||
| 80 | ret = self.cmd.Execute(self.opt, []) | ||
| 81 | self.assertEqual(ret, 1) | ||
| 82 | self.mock_repack.assert_not_called() | ||
