init
This commit is contained in:
@@ -0,0 +1,409 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Unit tests for CLI tool
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import tempfile
|
||||
import os
|
||||
import json
|
||||
import shutil
|
||||
from unittest.mock import patch, MagicMock
|
||||
from io import StringIO
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add api directory to path
|
||||
api_dir = Path(__file__).parent.parent / 'api'
|
||||
sys.path.insert(0, str(api_dir))
|
||||
|
||||
# Import from api package instead of tests package
|
||||
try:
|
||||
from cell_cli import api_request, show_status, list_peers, add_peer, remove_peer, show_config, update_config
|
||||
except ImportError:
|
||||
# Fallback for when running from tests directory
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
from api.cell_cli import api_request, show_status, list_peers, add_peer, remove_peer, show_config, update_config
|
||||
|
||||
class TestCLITool(unittest.TestCase):
|
||||
"""Test cases for CLI tool functions"""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test environment"""
|
||||
self.test_dir = tempfile.mkdtemp()
|
||||
self.data_dir = os.path.join(self.test_dir, 'data')
|
||||
os.makedirs(self.data_dir, exist_ok=True)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up test environment"""
|
||||
shutil.rmtree(self.test_dir)
|
||||
|
||||
@patch('requests.get')
|
||||
def test_api_request_get_success(self, mock_get):
|
||||
"""Test successful GET request"""
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {'status': 'success'}
|
||||
mock_response.raise_for_status.return_value = None
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
result = api_request('GET', '/test')
|
||||
self.assertEqual(result, {'status': 'success'})
|
||||
|
||||
@patch('requests.get')
|
||||
def test_api_request_get_failure(self, mock_get):
|
||||
"""Test failed GET request"""
|
||||
import requests
|
||||
mock_get.side_effect = requests.exceptions.RequestException("Connection error")
|
||||
result = api_request('GET', '/test')
|
||||
self.assertIsNone(result)
|
||||
|
||||
@patch('requests.post')
|
||||
def test_api_request_post_success(self, mock_post):
|
||||
"""Test successful POST request"""
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {'message': 'success'}
|
||||
mock_response.raise_for_status.return_value = None
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
result = api_request('POST', '/test', {'data': 'test'})
|
||||
self.assertEqual(result, {'message': 'success'})
|
||||
|
||||
@patch('requests.put')
|
||||
def test_api_request_put_success(self, mock_put):
|
||||
"""Test successful PUT request"""
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {'message': 'updated'}
|
||||
mock_response.raise_for_status.return_value = None
|
||||
mock_put.return_value = mock_response
|
||||
|
||||
result = api_request('PUT', '/test', {'data': 'test'})
|
||||
self.assertEqual(result, {'message': 'updated'})
|
||||
|
||||
@patch('requests.delete')
|
||||
def test_api_request_delete_success(self, mock_delete):
|
||||
"""Test successful DELETE request"""
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {'message': 'deleted'}
|
||||
mock_response.raise_for_status.return_value = None
|
||||
mock_delete.return_value = mock_response
|
||||
|
||||
result = api_request('DELETE', '/test')
|
||||
self.assertEqual(result, {'message': 'deleted'})
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_show_status(self, mock_api_request):
|
||||
"""Test show_status function"""
|
||||
mock_api_request.return_value = {
|
||||
'cell_name': 'testcell',
|
||||
'domain': 'testcell.cell',
|
||||
'peers_count': 2,
|
||||
'uptime': 3600,
|
||||
'services': {
|
||||
'dns': True,
|
||||
'dhcp': True,
|
||||
'ntp': False
|
||||
}
|
||||
}
|
||||
|
||||
# Capture stdout
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
show_status()
|
||||
|
||||
# Restore stdout
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('testcell', output)
|
||||
self.assertIn('2', output)
|
||||
self.assertIn('3600', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_list_peers_empty(self, mock_api_request):
|
||||
"""Test list_peers with empty list"""
|
||||
mock_api_request.return_value = []
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
list_peers()
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('No peers configured', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_list_peers_with_data(self, mock_api_request):
|
||||
"""Test list_peers with peer data"""
|
||||
mock_api_request.return_value = [
|
||||
{
|
||||
'name': 'testpeer',
|
||||
'ip': '192.168.1.100',
|
||||
'public_key': 'testkey123456789',
|
||||
'added_at': '2024-01-01T00:00:00'
|
||||
}
|
||||
]
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
list_peers()
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('testpeer', output)
|
||||
self.assertIn('192.168.1.100', output)
|
||||
self.assertIn('testkey123456789', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_add_peer_success(self, mock_api_request):
|
||||
"""Test add_peer success"""
|
||||
mock_api_request.return_value = {'message': 'Peer added successfully'}
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
add_peer('testpeer', '192.168.1.100', 'testkey123')
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('✅', output)
|
||||
self.assertIn('successfully', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_add_peer_failure(self, mock_api_request):
|
||||
"""Test add_peer failure"""
|
||||
mock_api_request.return_value = None
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
add_peer('testpeer', '192.168.1.100', 'testkey123')
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('❌', output)
|
||||
self.assertIn('Failed', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_remove_peer_success(self, mock_api_request):
|
||||
"""Test remove_peer success"""
|
||||
mock_api_request.return_value = {'message': 'Peer removed successfully'}
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
remove_peer('testpeer')
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('✅', output)
|
||||
self.assertIn('successfully', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_show_config(self, mock_api_request):
|
||||
"""Test show_config function"""
|
||||
mock_api_request.return_value = {
|
||||
'network': {
|
||||
'dns_port': 53,
|
||||
'dhcp_range': '192.168.1.100-200'
|
||||
},
|
||||
'wireguard': {
|
||||
'port': 51820,
|
||||
'address': '10.0.0.1/24'
|
||||
}
|
||||
}
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
show_config()
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('53', output)
|
||||
self.assertIn('51820', output)
|
||||
|
||||
@patch("api.cell_cli.api_request")
|
||||
def test_update_config_success(self, mock_api_request):
|
||||
"""Test update_config success"""
|
||||
mock_api_request.return_value = {'message': 'Configuration updated successfully'}
|
||||
|
||||
captured_output = StringIO()
|
||||
sys.stdout = captured_output
|
||||
|
||||
update_config('network', {'dns_port': 5353})
|
||||
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
output = captured_output.getvalue()
|
||||
self.assertIn('✅', output)
|
||||
self.assertIn('successfully', output)
|
||||
|
||||
class TestEnhancedCLI(unittest.TestCase):
|
||||
"""Test the enhanced CLI functionality"""
|
||||
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.config_file = os.path.join(self.temp_dir, 'cli_config.json')
|
||||
|
||||
# Mock API client
|
||||
self.mock_api_client = MagicMock()
|
||||
self.mock_api_client.get.return_value = {'status': 'ok'}
|
||||
self.mock_api_client.post.return_value = {'success': True}
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
||||
def test_api_client(self):
|
||||
"""Test API client functionality"""
|
||||
with patch('enhanced_cli.requests.get') as mock_get, \
|
||||
patch('enhanced_cli.requests.post') as mock_post:
|
||||
|
||||
mock_get.return_value.json.return_value = {'status': 'ok'}
|
||||
mock_get.return_value.status_code = 200
|
||||
|
||||
mock_post.return_value.json.return_value = {'success': True}
|
||||
mock_post.return_value.status_code = 200
|
||||
|
||||
client = EnhancedCLI('http://localhost:5000')
|
||||
|
||||
# Test GET request
|
||||
response = client.get('/api/status')
|
||||
self.assertEqual(response['status'], 'ok')
|
||||
|
||||
# Test POST request
|
||||
response = client.post('/api/config', {'test': 'data'})
|
||||
self.assertEqual(response['success'], True)
|
||||
|
||||
def test_cli_config_manager(self):
|
||||
"""Test CLI config manager"""
|
||||
config_manager = CLIConfigManager(self.config_file)
|
||||
|
||||
# Test setting and getting config
|
||||
config_manager.set('api_url', 'http://localhost:5000')
|
||||
config_manager.set('timeout', 30)
|
||||
|
||||
self.assertEqual(config_manager.get('api_url'), 'http://localhost:5000')
|
||||
self.assertEqual(config_manager.get('timeout'), 30)
|
||||
|
||||
# Test default values
|
||||
self.assertEqual(config_manager.get('nonexistent', 'default'), 'default')
|
||||
|
||||
# Test saving and loading
|
||||
config_manager.save()
|
||||
|
||||
new_config_manager = CLIConfigManager(self.config_file)
|
||||
self.assertEqual(new_config_manager.get('api_url'), 'http://localhost:5000')
|
||||
|
||||
def test_cli_commands(self):
|
||||
"""Test CLI commands"""
|
||||
with patch('enhanced_cli.APIClient') as mock_client_class:
|
||||
mock_client = MagicMock()
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Mock API responses
|
||||
mock_client.get.return_value = {
|
||||
'status': 'online',
|
||||
'services': ['network', 'wireguard']
|
||||
}
|
||||
mock_client.post.return_value = {'success': True}
|
||||
|
||||
cli = EnhancedCLI('http://localhost:5000')
|
||||
|
||||
# Test status command
|
||||
with patch('builtins.print') as mock_print:
|
||||
cli.show_status()
|
||||
mock_print.assert_called()
|
||||
|
||||
# Test service commands
|
||||
with patch('builtins.print') as mock_print:
|
||||
cli.list_services()
|
||||
mock_print.assert_called()
|
||||
|
||||
# Test configuration commands
|
||||
with patch('builtins.print') as mock_print:
|
||||
cli.show_config()
|
||||
mock_print.assert_called()
|
||||
|
||||
def test_interactive_mode(self):
|
||||
"""Test interactive mode"""
|
||||
with patch('enhanced_cli.APIClient') as mock_client_class:
|
||||
mock_client = MagicMock()
|
||||
mock_client_class.return_value = mock_client
|
||||
mock_client.get.return_value = {'status': 'ok'}
|
||||
|
||||
cli = EnhancedCLI('http://localhost:5000')
|
||||
|
||||
# Test interactive mode setup
|
||||
with patch('builtins.input', return_value='quit'), \
|
||||
patch('builtins.print') as mock_print:
|
||||
cli.interactive_mode()
|
||||
mock_print.assert_called()
|
||||
|
||||
def test_batch_operations(self):
|
||||
"""Test batch operations"""
|
||||
with patch('enhanced_cli.APIClient') as mock_client_class:
|
||||
mock_client = MagicMock()
|
||||
mock_client_class.return_value = mock_client
|
||||
mock_client.post.return_value = {'success': True}
|
||||
|
||||
cli = EnhancedCLI('http://localhost:5000')
|
||||
|
||||
# Test batch service start
|
||||
services = ['network', 'wireguard']
|
||||
with patch('builtins.print') as mock_print:
|
||||
cli.batch_start_services(services)
|
||||
mock_print.assert_called()
|
||||
|
||||
# Test batch service stop
|
||||
with patch('builtins.print') as mock_print:
|
||||
cli.batch_stop_services(services)
|
||||
mock_print.assert_called()
|
||||
|
||||
def test_service_wizards(self):
|
||||
"""Test service wizards"""
|
||||
with patch('enhanced_cli.APIClient') as mock_client_class:
|
||||
mock_client = MagicMock()
|
||||
mock_client_class.return_value = mock_client
|
||||
mock_client.post.return_value = {'success': True}
|
||||
|
||||
cli = EnhancedCLI('http://localhost:5000')
|
||||
|
||||
# Test network setup wizard
|
||||
with patch('builtins.input', side_effect=['192.168.1.1', '255.255.255.0', '53']), \
|
||||
patch('builtins.print') as mock_print:
|
||||
cli.network_setup_wizard()
|
||||
mock_print.assert_called()
|
||||
|
||||
# Test WireGuard setup wizard
|
||||
with patch('builtins.input', side_effect=['51820', '10.0.0.1/24']), \
|
||||
patch('builtins.print') as mock_print:
|
||||
cli.wireguard_setup_wizard()
|
||||
mock_print.assert_called()
|
||||
|
||||
def test_error_handling(self):
|
||||
"""Test error handling"""
|
||||
with patch('enhanced_cli.APIClient') as mock_client_class:
|
||||
mock_client = MagicMock()
|
||||
mock_client_class.return_value = mock_client
|
||||
mock_client.get.side_effect = Exception("Connection failed")
|
||||
|
||||
cli = EnhancedCLI('http://localhost:5000')
|
||||
|
||||
# Test error handling in status command
|
||||
with patch('builtins.print') as mock_print:
|
||||
cli.show_status()
|
||||
# Should handle the exception gracefully
|
||||
mock_print.assert_called()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user