-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_installer.py
More file actions
299 lines (226 loc) · 11.9 KB
/
test_installer.py
File metadata and controls
299 lines (226 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#!/usr/bin/env python3
"""
Unit tests for SSH Operations Hub Installer.
"""
import unittest
from unittest.mock import patch, MagicMock, mock_open
import tempfile
import os
from pathlib import Path
import shutil
import sys
# Add the parent directory to the path to import the module
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from install import SSHOperationsHubInstaller
# Import SSHOperationsHubInstaller from the parent package
from ..install import SSHOperationsHubInstaller
class TestSSHOperationsHubInstaller(unittest.TestCase):
"""Test cases for SSH Operations Hub Installer."""
def setUp(self):
"""Set up test fixture."""
self.installer = SSHOperationsHubInstaller()
# Create temporary directory for testing
self.test_dir = Path(tempfile.mkdtemp())
self.installer.source_script = self.test_dir / "ssh_operations_hub.py"
# Create mock source script
self.installer.source_script.write_text("#!/usr/bin/env python3\nprint('test')")
# Override paths for testing
self.installer.system_bin_dir = self.test_dir / "system_bin"
self.installer.system_config_dir = self.test_dir / "system_config"
self.installer.user_bin_dir = self.test_dir / "user_bin"
self.installer.user_config_dir = self.test_dir / "user_config"
self.installer.system_version_file = self.installer.system_config_dir / "version"
self.installer.user_version_file = self.installer.user_config_dir / "version"
def tearDown(self):
"""Clean up test fixture."""
if self.test_dir.exists():
shutil.rmtree(self.test_dir)
@patch('os.geteuid')
def test_check_sudo_with_root(self, mock_geteuid):
"""Test sudo check when running as root."""
mock_geteuid.return_value = 0
self.assertTrue(self.installer._check_sudo())
@patch('os.geteuid')
def test_check_sudo_without_root(self, mock_geteuid):
"""Test sudo check when not running as root."""
mock_geteuid.return_value = 1000
self.assertFalse(self.installer._check_sudo())
def test_get_current_version_exists(self):
"""Test getting current version when version file exists."""
# Create version file
self.installer.user_config_dir.mkdir(parents=True, exist_ok=True)
self.installer.user_version_file.write_text("1.5.0")
version = self.installer._get_current_version(system_wide=False)
self.assertEqual(version, "1.5.0")
def test_get_current_version_not_exists(self):
"""Test getting current version when version file doesn't exist."""
version = self.installer._get_current_version(system_wide=False)
self.assertIsNone(version)
def test_set_version(self):
"""Test setting version in version file."""
self.installer._set_version(system_wide=False)
self.assertTrue(self.installer.user_version_file.exists())
version = self.installer.user_version_file.read_text().strip()
self.assertEqual(version, self.installer.VERSION)
def test_backup_existing(self):
"""Test backup of existing installation."""
# Create existing file
target = self.test_dir / "existing_file"
target.write_text("existing content")
backup_path = self.installer._backup_existing(target)
self.assertIsNotNone(backup_path)
self.assertTrue(backup_path.exists())
self.assertEqual(backup_path.read_text(), "existing content")
def test_backup_existing_no_file(self):
"""Test backup when no existing file."""
target = self.test_dir / "nonexistent_file"
backup_path = self.installer._backup_existing(target)
self.assertIsNone(backup_path)
def test_copy_config_files(self):
"""Test copying configuration files."""
# Create mock config source
config_source = self.test_dir / "config"
config_source.mkdir()
(config_source / "defaults.conf").write_text("IP_PREFIX=10.0.0")
(config_source / "test.conf").write_text("TEST=value")
# Mock the script directory to include config
self.installer.script_dir = self.test_dir
target_dir = self.test_dir / "target_config"
self.installer._copy_config_files(target_dir)
self.assertTrue(target_dir.exists())
self.assertTrue((target_dir / "defaults.conf").exists())
self.assertTrue((target_dir / "test.conf").exists())
self.assertEqual((target_dir / "defaults.conf").read_text(), "IP_PREFIX=10.0.0")
@patch.object(SSHOperationsHubInstaller, '_check_sudo')
@patch.object(SSHOperationsHubInstaller, '_copy_config_files')
def test_install_user_mode_success(self, mock_copy_config, mock_check_sudo):
"""Test successful user mode installation."""
mock_check_sudo.return_value = False # Not running as sudo
result = self.installer.install(system_wide=False)
self.assertTrue(result)
self.assertTrue(self.installer.user_bin_dir.exists())
self.assertTrue((self.installer.user_bin_dir / self.installer.SCRIPT_NAME).exists())
self.assertTrue(self.installer.user_version_file.exists())
mock_copy_config.assert_called_once()
@patch.object(SSHOperationsHubInstaller, '_check_sudo')
def test_install_system_mode_no_sudo(self, mock_check_sudo):
"""Test system mode installation without sudo."""
mock_check_sudo.return_value = False
result = self.installer.install(system_wide=True)
self.assertFalse(result)
@patch.object(SSHOperationsHubInstaller, '_check_sudo')
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
def test_install_already_installed(self, mock_get_version, mock_check_sudo):
"""Test installation when already installed."""
mock_check_sudo.return_value = False
mock_get_version.return_value = "2.0.0"
result = self.installer.install(system_wide=False, force=False)
self.assertFalse(result)
@patch.object(SSHOperationsHubInstaller, '_check_sudo')
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
def test_install_force_reinstall(self, mock_get_version, mock_check_sudo):
"""Test force reinstallation."""
mock_check_sudo.return_value = False
mock_get_version.return_value = "1.0.0"
result = self.installer.install(system_wide=False, force=True)
self.assertTrue(result)
def test_install_source_not_exists(self):
"""Test installation when source script doesn't exist."""
self.installer.source_script = Path("/nonexistent/script.py")
result = self.installer.install(system_wide=False)
self.assertFalse(result)
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
@patch.object(SSHOperationsHubInstaller, 'install')
def test_update_existing_installation(self, mock_install, mock_get_version):
"""Test updating existing installation."""
mock_get_version.return_value = "1.0.0"
mock_install.return_value = True
result = self.installer.update(system_wide=False)
self.assertTrue(result)
mock_install.assert_called_once_with(False, force=True)
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
def test_update_no_installation(self, mock_get_version):
"""Test update when no existing installation."""
mock_get_version.return_value = None
result = self.installer.update(system_wide=False)
self.assertFalse(result)
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
def test_update_already_current(self, mock_get_version):
"""Test update when already current version."""
mock_get_version.return_value = self.installer.VERSION
result = self.installer.update(system_wide=False)
self.assertTrue(result) # Should return True for "no update needed"
@patch.object(SSHOperationsHubInstaller, '_check_sudo')
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
@patch('builtins.input')
def test_uninstall_success(self, mock_input, mock_get_version, mock_check_sudo):
"""Test successful uninstallation."""
mock_check_sudo.return_value = False
mock_get_version.return_value = "2.0.0"
mock_input.return_value = "y"
# Create files to uninstall
self.installer.user_bin_dir.mkdir(parents=True, exist_ok=True)
script_path = self.installer.user_bin_dir / self.installer.SCRIPT_NAME
script_path.write_text("#!/bin/bash\necho test")
self.installer.user_config_dir.mkdir(parents=True, exist_ok=True)
(self.installer.user_config_dir / "test.conf").write_text("test")
result = self.installer.uninstall(system_wide=False)
self.assertTrue(result)
self.assertFalse(script_path.exists())
@patch.object(SSHOperationsHubInstaller, '_check_sudo')
def test_uninstall_system_no_sudo(self, mock_check_sudo):
"""Test system uninstallation without sudo."""
mock_check_sudo.return_value = False
result = self.installer.uninstall(system_wide=True)
self.assertFalse(result)
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
def test_uninstall_no_installation(self, mock_get_version):
"""Test uninstallation when no installation exists."""
mock_get_version.return_value = None
result = self.installer.uninstall(system_wide=False)
self.assertFalse(result)
@patch.object(SSHOperationsHubInstaller, '_get_current_version')
def test_status(self, mock_get_version):
"""Test status display."""
mock_get_version.side_effect = ["1.0.0", "2.0.0"] # system, then user
# This should not raise any exceptions
self.installer.status()
# Verify both version checks were called
self.assertEqual(mock_get_version.call_count, 2)
class TestInstallerIntegration(unittest.TestCase):
"""Integration tests for the installer."""
def setUp(self):
"""Set up integration test environment."""
self.test_dir = Path(tempfile.mkdtemp())
def tearDown(self):
"""Clean up integration test environment."""
if self.test_dir.exists():
shutil.rmtree(self.test_dir)
def test_full_install_uninstall_cycle(self):
"""Test complete install/uninstall cycle in user mode."""
installer = SSHOperationsHubInstaller()
# Override paths for testing
installer.user_bin_dir = self.test_dir / "bin"
installer.user_config_dir = self.test_dir / "config"
installer.user_version_file = installer.user_config_dir / "version"
# Create mock source script
installer.source_script = self.test_dir / "ssh_operations_hub.py"
installer.source_script.write_text("#!/usr/bin/env python3\nprint('test')")
# Test install
result = installer.install(system_wide=False)
self.assertTrue(result)
# Verify installation
script_path = installer.user_bin_dir / installer.SCRIPT_NAME
self.assertTrue(script_path.exists())
self.assertTrue(installer.user_version_file.exists())
# Test status
version = installer._get_current_version(system_wide=False)
self.assertEqual(version, installer.VERSION)
# Test uninstall
with patch('builtins.input', return_value='n'): # Don't remove config
result = installer.uninstall(system_wide=False)
self.assertTrue(result)
# Verify uninstallation
self.assertFalse(script_path.exists())
if __name__ == '__main__':
unittest.main(verbosity=2)