|
| 1 | +# type: ignore |
| 2 | + |
| 3 | +import os |
| 4 | +import pathlib |
| 5 | +import tempfile |
| 6 | +from unittest.mock import MagicMock |
| 7 | + |
| 8 | +import pymysql |
| 9 | +import pytest |
| 10 | + |
| 11 | +import mycli.packages.special.utils |
| 12 | +from mycli.packages.special.utils import ( |
| 13 | + CACHED_SSL_VERSION, |
| 14 | + format_uptime, |
| 15 | + get_ssl_version, |
| 16 | + get_uptime, |
| 17 | + get_warning_count, |
| 18 | + handle_cd_command, |
| 19 | +) |
| 20 | +from test.utils import TEMPFILE_PREFIX |
| 21 | + |
| 22 | + |
| 23 | +@pytest.fixture(autouse=True) |
| 24 | +def clear_ssl_cache() -> None: |
| 25 | + CACHED_SSL_VERSION.clear() |
| 26 | + |
| 27 | + |
| 28 | +def test_handle_cd_command_rejects_non_cd_command() -> None: |
| 29 | + handled, message = handle_cd_command(['pwd']) |
| 30 | + |
| 31 | + assert handled is False |
| 32 | + assert message == 'Not a cd command.' |
| 33 | + |
| 34 | + |
| 35 | +def test_handle_cd_command_requires_exactly_one_directory() -> None: |
| 36 | + handled, message = handle_cd_command(['cd']) |
| 37 | + |
| 38 | + assert handled is False |
| 39 | + assert message == 'Exactly one directory name must be provided.' |
| 40 | + |
| 41 | + |
| 42 | +def test_handle_cd_command_changes_directory_and_echoes_cwd(monkeypatch) -> None: |
| 43 | + echoed = [] |
| 44 | + |
| 45 | + monkeypatch.setattr(mycli.packages.special.utils.click, 'echo', lambda message, err=False: echoed.append((message, err))) |
| 46 | + monkeypatch.chdir(os.getcwd()) |
| 47 | + |
| 48 | + # resolve() is needed for mac /private/var arrangement |
| 49 | + with tempfile.TemporaryDirectory(prefix=TEMPFILE_PREFIX) as tempdir: |
| 50 | + tempdir_resolved = str(pathlib.Path(tempdir).resolve()) |
| 51 | + handled, message = handle_cd_command(['cd', tempdir_resolved]) |
| 52 | + assert str(pathlib.Path(os.getcwd()).resolve()) == tempdir_resolved |
| 53 | + assert handled is True |
| 54 | + assert message is None |
| 55 | + assert echoed == [(tempdir_resolved, True)] |
| 56 | + |
| 57 | + |
| 58 | +def test_handle_cd_command_returns_oserror_message(monkeypatch) -> None: |
| 59 | + def raise_oserror(directory: str) -> None: |
| 60 | + raise OSError(2, 'No such file or directory') |
| 61 | + |
| 62 | + monkeypatch.setattr(mycli.packages.special.utils.os, 'chdir', raise_oserror) |
| 63 | + |
| 64 | + handled, message = handle_cd_command(['cd', '/missing']) |
| 65 | + |
| 66 | + assert handled is False |
| 67 | + assert message == 'No such file or directory' |
| 68 | + |
| 69 | + |
| 70 | +def test_format_uptime(): |
| 71 | + seconds = 59 |
| 72 | + assert '59 sec' == format_uptime(seconds) |
| 73 | + |
| 74 | + seconds = 120 |
| 75 | + assert '2 min 0 sec' == format_uptime(seconds) |
| 76 | + |
| 77 | + seconds = 54890 |
| 78 | + assert '15 hours 14 min 50 sec' == format_uptime(seconds) |
| 79 | + |
| 80 | + seconds = 598244 |
| 81 | + assert '6 days 22 hours 10 min 44 sec' == format_uptime(seconds) |
| 82 | + |
| 83 | + seconds = 522600 |
| 84 | + assert '6 days 1 hour 10 min 0 sec' == format_uptime(seconds) |
| 85 | + |
| 86 | + |
| 87 | +def test_format_uptime_uses_singular_units() -> None: |
| 88 | + assert format_uptime('90061') == '1 day 1 hour 1 min 1 sec' |
| 89 | + |
| 90 | + |
| 91 | +def test_get_uptime_returns_value_from_status_row() -> None: |
| 92 | + cur = MagicMock() |
| 93 | + cur.fetchone.return_value = ('Uptime', '15') |
| 94 | + |
| 95 | + uptime = get_uptime(cur) |
| 96 | + |
| 97 | + cur.execute.assert_called_once_with('SHOW STATUS LIKE "Uptime"') |
| 98 | + assert uptime == 15 |
| 99 | + |
| 100 | + |
| 101 | +def test_get_uptime_defaults_to_zero_for_missing_value() -> None: |
| 102 | + cur = MagicMock() |
| 103 | + cur.fetchone.return_value = ('Uptime', None) |
| 104 | + |
| 105 | + assert get_uptime(cur) == 0 |
| 106 | + |
| 107 | + |
| 108 | +def test_get_uptime_ignores_operational_error() -> None: |
| 109 | + cur = MagicMock() |
| 110 | + cur.execute.side_effect = pymysql.err.OperationalError() |
| 111 | + |
| 112 | + assert get_uptime(cur) == 0 |
| 113 | + |
| 114 | + |
| 115 | +def test_get_warning_count_returns_value_from_count_row() -> None: |
| 116 | + cur = MagicMock() |
| 117 | + cur.fetchone.return_value = ('7',) |
| 118 | + |
| 119 | + warning_count = get_warning_count(cur) |
| 120 | + |
| 121 | + cur.execute.assert_called_once_with('SHOW COUNT(*) WARNINGS') |
| 122 | + assert warning_count == 7 |
| 123 | + |
| 124 | + |
| 125 | +def test_get_warning_count_defaults_to_zero_for_missing_value() -> None: |
| 126 | + cur = MagicMock() |
| 127 | + cur.fetchone.return_value = (None,) |
| 128 | + |
| 129 | + assert get_warning_count(cur) == 0 |
| 130 | + |
| 131 | + |
| 132 | +def test_get_warning_count_ignores_operational_error() -> None: |
| 133 | + cur = MagicMock() |
| 134 | + cur.execute.side_effect = pymysql.err.OperationalError() |
| 135 | + |
| 136 | + assert get_warning_count(cur) == 0 |
| 137 | + |
| 138 | + |
| 139 | +def test_get_ssl_version_fetches_and_caches_value() -> None: |
| 140 | + cur = MagicMock() |
| 141 | + cur.connection = MagicMock() |
| 142 | + cur.connection.thread_id.return_value = 42 |
| 143 | + cur.fetchone.return_value = ('Ssl_version', 'TLSv1.3') |
| 144 | + |
| 145 | + first = get_ssl_version(cur) |
| 146 | + second = get_ssl_version(cur) |
| 147 | + |
| 148 | + cur.execute.assert_called_once_with('SHOW STATUS LIKE "Ssl_version"') |
| 149 | + assert first == 'TLSv1.3' |
| 150 | + assert second == 'TLSv1.3' |
| 151 | + |
| 152 | + |
| 153 | +def test_get_ssl_version_caches_missing_row_as_none() -> None: |
| 154 | + cur = MagicMock() |
| 155 | + cur.connection = MagicMock() |
| 156 | + cur.connection.thread_id.return_value = 42 |
| 157 | + cur.fetchone.return_value = None |
| 158 | + |
| 159 | + first = get_ssl_version(cur) |
| 160 | + second = get_ssl_version(cur) |
| 161 | + |
| 162 | + cur.execute.assert_called_once_with('SHOW STATUS LIKE "Ssl_version"') |
| 163 | + assert first is None |
| 164 | + assert second is None |
| 165 | + |
| 166 | + |
| 167 | +def test_get_ssl_version_returns_none_for_empty_value_and_caches_it() -> None: |
| 168 | + cur = MagicMock() |
| 169 | + cur.connection = MagicMock() |
| 170 | + cur.connection.thread_id.return_value = 42 |
| 171 | + cur.fetchone.return_value = ('Ssl_version', '') |
| 172 | + |
| 173 | + first = get_ssl_version(cur) |
| 174 | + second = get_ssl_version(cur) |
| 175 | + |
| 176 | + cur.execute.assert_called_once_with('SHOW STATUS LIKE "Ssl_version"') |
| 177 | + assert first is None |
| 178 | + assert second is None |
| 179 | + |
| 180 | + |
| 181 | +def test_get_ssl_version_ignores_operational_error() -> None: |
| 182 | + cur = MagicMock() |
| 183 | + cur.connection = MagicMock() |
| 184 | + cur.connection.thread_id.return_value = 42 |
| 185 | + cur.execute.side_effect = pymysql.err.OperationalError() |
| 186 | + |
| 187 | + assert get_ssl_version(cur) is None |
0 commit comments