adding test server (#982)
Some checks failed
Functional & Unit Tests / Functional & Unit Tests (push) Failing after 4m2s
Functional & Unit Tests / Generate Coverage Badge (push) Has been skipped

Signed-off-by: Paige Patton <prubenda@redhat.com>
This commit is contained in:
Paige Patton
2025-12-02 14:10:05 -05:00
committed by GitHub
parent eecdeed73c
commit 197ce43f9a
4 changed files with 426 additions and 4 deletions

385
tests/test_server.py Normal file
View File

@@ -0,0 +1,385 @@
#!/usr/bin/env python3
"""
Test suite for SimpleHTTPRequestHandler class
Usage:
python -m coverage run -a -m unittest tests/test_server.py -v
Assisted By: Claude Code
"""
import unittest
from unittest.mock import Mock, patch, MagicMock
from io import BytesIO
import server
from server import SimpleHTTPRequestHandler
class TestSimpleHTTPRequestHandler(unittest.TestCase):
def setUp(self):
"""
Set up test fixtures for SimpleHTTPRequestHandler
"""
# Reset the global server_status before each test
server.server_status = ""
# Reset the requests_served counter
SimpleHTTPRequestHandler.requests_served = 0
# Create a mock request
self.mock_request = MagicMock()
self.mock_client_address = ('127.0.0.1', 12345)
self.mock_server = MagicMock()
def _create_handler(self, method='GET', path='/'):
"""
Helper method to create a handler instance with mocked request
"""
# Create a mock request with proper attributes
mock_request = MagicMock()
mock_request.makefile.return_value = BytesIO(
f"{method} {path} HTTP/1.1\r\n\r\n".encode('utf-8')
)
# Create handler
handler = SimpleHTTPRequestHandler(
mock_request,
self.mock_client_address,
self.mock_server
)
# Mock the wfile (write file) for response
handler.wfile = BytesIO()
return handler
def test_do_GET_root_path_calls_do_status(self):
"""
Test do_GET with root path calls do_status
"""
handler = self._create_handler('GET', '/')
with patch.object(handler, 'do_status') as mock_do_status:
handler.do_GET()
mock_do_status.assert_called_once()
def test_do_GET_non_root_path_does_nothing(self):
"""
Test do_GET with non-root path does not call do_status
"""
handler = self._create_handler('GET', '/other')
with patch.object(handler, 'do_status') as mock_do_status:
handler.do_GET()
mock_do_status.assert_not_called()
def test_do_status_sends_200_response(self):
"""
Test do_status sends 200 status code
"""
server.server_status = "TEST_STATUS"
handler = self._create_handler()
with patch.object(handler, 'send_response') as mock_send_response:
with patch.object(handler, 'end_headers'):
handler.do_status()
mock_send_response.assert_called_once_with(200)
def test_do_status_writes_server_status(self):
"""
Test do_status writes server_status to response
"""
server.server_status = "RUNNING"
handler = self._create_handler()
with patch.object(handler, 'send_response'):
with patch.object(handler, 'end_headers'):
handler.do_status()
# Check that the status was written to wfile
response_content = handler.wfile.getvalue().decode('utf-8')
self.assertEqual(response_content, "RUNNING")
def test_do_status_increments_requests_served(self):
"""
Test do_status increments requests_served counter
"""
# Note: Creating a handler increments the counter by 1
# Then do_status increments it again
SimpleHTTPRequestHandler.requests_served = 0
handler = self._create_handler()
initial_count = SimpleHTTPRequestHandler.requests_served
with patch.object(handler, 'send_response'):
with patch.object(handler, 'end_headers'):
handler.do_status()
self.assertEqual(
SimpleHTTPRequestHandler.requests_served,
initial_count + 1
)
def test_do_status_multiple_requests_increment_counter(self):
"""
Test multiple do_status calls increment counter correctly
"""
SimpleHTTPRequestHandler.requests_served = 0
for i in range(5):
handler = self._create_handler()
with patch.object(handler, 'send_response'):
with patch.object(handler, 'end_headers'):
handler.do_status()
# Each iteration: handler creation increments by 1, do_status increments by 1
# Total: 5 * 2 = 10
self.assertEqual(SimpleHTTPRequestHandler.requests_served, 10)
def test_do_POST_STOP_path_calls_set_stop(self):
"""
Test do_POST with /STOP path calls set_stop
"""
handler = self._create_handler('POST', '/STOP')
with patch.object(handler, 'set_stop') as mock_set_stop:
handler.do_POST()
mock_set_stop.assert_called_once()
def test_do_POST_RUN_path_calls_set_run(self):
"""
Test do_POST with /RUN path calls set_run
"""
handler = self._create_handler('POST', '/RUN')
with patch.object(handler, 'set_run') as mock_set_run:
handler.do_POST()
mock_set_run.assert_called_once()
def test_do_POST_PAUSE_path_calls_set_pause(self):
"""
Test do_POST with /PAUSE path calls set_pause
"""
handler = self._create_handler('POST', '/PAUSE')
with patch.object(handler, 'set_pause') as mock_set_pause:
handler.do_POST()
mock_set_pause.assert_called_once()
def test_do_POST_unknown_path_does_nothing(self):
"""
Test do_POST with unknown path does not call any setter
"""
handler = self._create_handler('POST', '/UNKNOWN')
with patch.object(handler, 'set_stop') as mock_set_stop:
with patch.object(handler, 'set_run') as mock_set_run:
with patch.object(handler, 'set_pause') as mock_set_pause:
handler.do_POST()
mock_set_stop.assert_not_called()
mock_set_run.assert_not_called()
mock_set_pause.assert_not_called()
def test_set_run_sets_status_to_RUN(self):
"""
Test set_run sets global server_status to 'RUN'
"""
handler = self._create_handler()
with patch.object(handler, 'send_response'):
with patch.object(handler, 'end_headers'):
handler.set_run()
self.assertEqual(server.server_status, 'RUN')
def test_set_run_sends_200_response(self):
"""
Test set_run sends 200 status code
"""
handler = self._create_handler()
with patch.object(handler, 'send_response') as mock_send_response:
with patch.object(handler, 'end_headers'):
handler.set_run()
mock_send_response.assert_called_once_with(200)
def test_set_stop_sets_status_to_STOP(self):
"""
Test set_stop sets global server_status to 'STOP'
"""
handler = self._create_handler()
with patch.object(handler, 'send_response'):
with patch.object(handler, 'end_headers'):
handler.set_stop()
self.assertEqual(server.server_status, 'STOP')
def test_set_stop_sends_200_response(self):
"""
Test set_stop sends 200 status code
"""
handler = self._create_handler()
with patch.object(handler, 'send_response') as mock_send_response:
with patch.object(handler, 'end_headers'):
handler.set_stop()
mock_send_response.assert_called_once_with(200)
def test_set_pause_sets_status_to_PAUSE(self):
"""
Test set_pause sets global server_status to 'PAUSE'
"""
handler = self._create_handler()
with patch.object(handler, 'send_response'):
with patch.object(handler, 'end_headers'):
handler.set_pause()
self.assertEqual(server.server_status, 'PAUSE')
def test_set_pause_sends_200_response(self):
"""
Test set_pause sends 200 status code
"""
handler = self._create_handler()
with patch.object(handler, 'send_response') as mock_send_response:
with patch.object(handler, 'end_headers'):
handler.set_pause()
mock_send_response.assert_called_once_with(200)
def test_requests_served_is_class_variable(self):
"""
Test requests_served is shared across all instances
"""
SimpleHTTPRequestHandler.requests_served = 0
handler1 = self._create_handler() # Increments to 1
handler2 = self._create_handler() # Increments to 2
with patch.object(handler1, 'send_response'):
with patch.object(handler1, 'end_headers'):
handler1.do_status() # Increments to 3
with patch.object(handler2, 'send_response'):
with patch.object(handler2, 'end_headers'):
handler2.do_status() # Increments to 4
# Both handlers should see the same counter
# 2 handler creations + 2 do_status calls = 4
self.assertEqual(handler1.requests_served, 4)
self.assertEqual(handler2.requests_served, 4)
self.assertEqual(SimpleHTTPRequestHandler.requests_served, 4)
class TestServerModuleFunctions(unittest.TestCase):
def setUp(self):
"""
Set up test fixtures for server module functions
"""
server.server_status = ""
def test_publish_kraken_status_sets_server_status(self):
"""
Test publish_kraken_status sets global server_status
"""
server.publish_kraken_status("NEW_STATUS")
self.assertEqual(server.server_status, "NEW_STATUS")
def test_publish_kraken_status_overwrites_existing_status(self):
"""
Test publish_kraken_status overwrites existing status
"""
server.server_status = "OLD_STATUS"
server.publish_kraken_status("NEW_STATUS")
self.assertEqual(server.server_status, "NEW_STATUS")
@patch('server.HTTPServer')
@patch('server._thread')
def test_start_server_creates_http_server(self, mock_thread, mock_http_server):
"""
Test start_server creates HTTPServer with correct address
"""
address = ("localhost", 8080)
mock_server_instance = MagicMock()
mock_http_server.return_value = mock_server_instance
server.start_server(address, "RUNNING")
mock_http_server.assert_called_once_with(
address,
SimpleHTTPRequestHandler
)
@patch('server.HTTPServer')
@patch('server._thread')
def test_start_server_starts_thread(self, mock_thread, mock_http_server):
"""
Test start_server starts a new thread for serve_forever
"""
address = ("localhost", 8080)
mock_server_instance = MagicMock()
mock_http_server.return_value = mock_server_instance
server.start_server(address, "RUNNING")
mock_thread.start_new_thread.assert_called_once()
# Check that serve_forever was passed to the thread
args = mock_thread.start_new_thread.call_args[0]
self.assertEqual(args[0], mock_server_instance.serve_forever)
@patch('server.HTTPServer')
@patch('server._thread')
def test_start_server_publishes_status(self, mock_thread, mock_http_server):
"""
Test start_server publishes the provided status
"""
address = ("localhost", 8080)
mock_server_instance = MagicMock()
mock_http_server.return_value = mock_server_instance
server.start_server(address, "INITIAL_STATUS")
self.assertEqual(server.server_status, "INITIAL_STATUS")
@patch('server.HTTPConnection')
def test_get_status_makes_http_request(self, mock_http_connection):
"""
Test get_status makes HTTP GET request to root path
"""
address = ("localhost", 8080)
mock_connection = MagicMock()
mock_response = MagicMock()
mock_response.read.return_value = b"TEST_STATUS"
mock_connection.getresponse.return_value = mock_response
mock_http_connection.return_value = mock_connection
result = server.get_status(address)
mock_http_connection.assert_called_once_with("localhost", 8080)
mock_connection.request.assert_called_once_with("GET", "/")
self.assertEqual(result, "TEST_STATUS")
@patch('server.HTTPConnection')
def test_get_status_returns_decoded_response(self, mock_http_connection):
"""
Test get_status returns decoded response string
"""
address = ("localhost", 8080)
mock_connection = MagicMock()
mock_response = MagicMock()
mock_response.read.return_value = b"RUNNING"
mock_connection.getresponse.return_value = mock_response
mock_http_connection.return_value = mock_connection
result = server.get_status(address)
self.assertEqual(result, "RUNNING")
self.assertIsInstance(result, str)
if __name__ == "__main__":
unittest.main()