# Copyright (C) 2026 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for the main repo script and subcommand routing.""" from unittest import mock import pytest from main import _Repo @pytest.fixture(name="repo") def fixture_repo(): repo = _Repo("repodir") # Overriding the command list here ensures that we are only testing # against a fixed set of commands, reducing fragility to new # subcommands being added to the main repo tool. repo.commands = {"start": None, "sync": None, "smart": None} return repo @pytest.fixture(name="mock_config") def fixture_mock_config(): return mock.MagicMock() @mock.patch("time.sleep") def test_autocorrect_delay(mock_sleep, repo, mock_config): """Test autocorrect with positive delay.""" mock_config.GetString.return_value = "10" res = repo._autocorrect_command_name("tart", mock_config) mock_config.GetString.assert_called_with("help.autocorrect") mock_sleep.assert_called_with(1.0) assert res == "start" @mock.patch("time.sleep") def test_autocorrect_delay_one(mock_sleep, repo, mock_config): """Test autocorrect with '1' (0.1s delay, not immediate).""" mock_config.GetString.return_value = "1" res = repo._autocorrect_command_name("tart", mock_config) mock_sleep.assert_called_with(0.1) assert res == "start" @mock.patch("time.sleep", side_effect=KeyboardInterrupt()) def test_autocorrect_delay_interrupt(mock_sleep, repo, mock_config): """Test autocorrect handles KeyboardInterrupt during delay.""" mock_config.GetString.return_value = "10" res = repo._autocorrect_command_name("tart", mock_config) mock_sleep.assert_called_with(1.0) assert res is None @mock.patch("time.sleep") def test_autocorrect_immediate(mock_sleep, repo, mock_config): """Test autocorrect with immediate/negative delay.""" # Test numeric negative. mock_config.GetString.return_value = "-1" res = repo._autocorrect_command_name("tart", mock_config) mock_sleep.assert_not_called() assert res == "start" # Test string boolean "true". mock_config.GetString.return_value = "true" res = repo._autocorrect_command_name("tart", mock_config) mock_sleep.assert_not_called() assert res == "start" # Test string boolean "yes". mock_config.GetString.return_value = "YES" res = repo._autocorrect_command_name("tart", mock_config) mock_sleep.assert_not_called() assert res == "start" # Test string boolean "immediate". mock_config.GetString.return_value = "Immediate" res = repo._autocorrect_command_name("tart", mock_config) mock_sleep.assert_not_called() assert res == "start" def test_autocorrect_zero_or_show(repo, mock_config): """Test autocorrect with zero delay (suggestions only).""" # Test numeric zero. mock_config.GetString.return_value = "0" res = repo._autocorrect_command_name("tart", mock_config) assert res is None # Test string boolean "false". mock_config.GetString.return_value = "False" res = repo._autocorrect_command_name("tart", mock_config) assert res is None # Test string boolean "show". mock_config.GetString.return_value = "show" res = repo._autocorrect_command_name("tart", mock_config) assert res is None def test_autocorrect_never(repo, mock_config): """Test autocorrect with 'never'.""" mock_config.GetString.return_value = "never" res = repo._autocorrect_command_name("tart", mock_config) assert res is None @mock.patch("builtins.input", return_value="y") def test_autocorrect_prompt_yes(mock_input, repo, mock_config): """Test autocorrect with prompt and user answers yes.""" mock_config.GetString.return_value = "prompt" res = repo._autocorrect_command_name("tart", mock_config) assert res == "start" @mock.patch("builtins.input", return_value="n") def test_autocorrect_prompt_no(mock_input, repo, mock_config): """Test autocorrect with prompt and user answers no.""" mock_config.GetString.return_value = "prompt" res = repo._autocorrect_command_name("tart", mock_config) assert res is None @mock.patch("builtins.input", return_value="y") def test_autocorrect_multiple_candidates(mock_input, repo, mock_config): """Test autocorrect with multiple matches forces a prompt.""" mock_config.GetString.return_value = "10" # Normally just delay # 'snart' matches both 'start' and 'smart' with > 0.7 ratio res = repo._autocorrect_command_name("snart", mock_config) # Because there are multiple candidates, it should prompt mock_input.assert_called_once() assert res == "start" @mock.patch("builtins.input", side_effect=KeyboardInterrupt()) def test_autocorrect_prompt_interrupt(mock_input, repo, mock_config): """Test autocorrect with prompt and user interrupts.""" mock_config.GetString.return_value = "prompt" res = repo._autocorrect_command_name("tart", mock_config) assert res is None