1
1
"""Tests for the server module."""
2
2
3
+ import os
3
4
from unittest .mock import MagicMock , patch , AsyncMock
4
5
5
6
import pytest
16
17
from src .codegate .codegate_logging import LogLevel , LogFormat
17
18
from uvicorn .config import Config as UvicornConfig
18
19
from click .testing import CliRunner
20
+ from pathlib import Path
19
21
20
22
21
23
@pytest .fixture
@@ -277,7 +279,8 @@ def test_serve_custom_options(cli_runner):
277
279
278
280
# Check if Config object attributes match the expected values
279
281
for key , expected_value in expected_values .items ():
280
- assert getattr (config_arg , key ) == expected_value , f"{ key } does not match expected value"
282
+ assert getattr (config_arg , key ) == expected_value , \
283
+ f"{ key } does not match expected value"
281
284
282
285
283
286
def test_serve_invalid_port (cli_runner ):
@@ -326,7 +329,7 @@ def test_serve_with_config_file(cli_runner, temp_config_file):
326
329
327
330
# Validate that run_servers was called with the expected configuration
328
331
mock_run .assert_called_once ()
329
- config_arg = mock_run .call_args [0 ][0 ] # Assuming Config object is the first positional argument
332
+ config_arg = mock_run .call_args [0 ][0 ]
330
333
331
334
# Define expected values based on the temp_config_file content
332
335
expected_values = {
@@ -339,5 +342,161 @@ def test_serve_with_config_file(cli_runner, temp_config_file):
339
342
340
343
# Check if passed arguments match the expected values
341
344
for key , expected_value in expected_values .items ():
342
- assert getattr (config_arg , key ) == expected_value , f"{ key } does not match expected value"
345
+ assert getattr (config_arg , key ) == expected_value , \
346
+ f"{ key } does not match expected value"
343
347
348
+
349
+ def test_serve_with_nonexistent_config_file (cli_runner : CliRunner ) -> None :
350
+ """Test serve command with nonexistent config file."""
351
+ result = cli_runner .invoke (cli , ["serve" , "--config" , "nonexistent.yaml" ])
352
+ assert result .exit_code == 2
353
+ assert "does not exist" in result .output
354
+
355
+
356
+ def test_serve_priority_resolution (cli_runner : CliRunner , temp_config_file : Path ) -> None :
357
+ """Test serve command respects configuration priority."""
358
+ # Set up environment variables and ensure they get cleaned up after the test
359
+ with patch .dict (os .environ , {'LOG_LEVEL' : 'INFO' , 'PORT' : '9999' }, clear = True ), \
360
+ patch ('src.codegate.cli.run_servers' ) as mock_run , \
361
+ patch ('src.codegate.cli.structlog.get_logger' ) as mock_logging , \
362
+ patch ('src.codegate.cli.setup_logging' ) as mock_setup_logging :
363
+ # Set up mock logger
364
+ logger_instance = MagicMock ()
365
+ mock_logging .return_value = logger_instance
366
+
367
+ # Execute CLI command with specific options overriding environment and config file settings
368
+ result = cli_runner .invoke (
369
+ cli ,
370
+ [
371
+ "serve" ,
372
+ "--config" ,
373
+ str (temp_config_file ),
374
+ "--port" ,
375
+ "8080" ,
376
+ "--host" ,
377
+ "example.com" ,
378
+ "--log-level" ,
379
+ "ERROR" ,
380
+ "--log-format" ,
381
+ "TEXT" ,
382
+ "--certs-dir" ,
383
+ "./cli-certs" ,
384
+ "--ca-cert" ,
385
+ "cli-ca.crt" ,
386
+ "--ca-key" ,
387
+ "cli-ca.key" ,
388
+ "--server-cert" ,
389
+ "cli-server.crt" ,
390
+ "--server-key" ,
391
+ "cli-server.key" ,
392
+ ],
393
+ )
394
+
395
+ # Check the result of the command
396
+ assert result .exit_code == 0
397
+
398
+ # Ensure logging setup was called with the highest priority settings (CLI arguments)
399
+ mock_setup_logging .assert_called_once_with ('ERROR' , 'TEXT' )
400
+ mock_logging .assert_called_with ("codegate" )
401
+
402
+ # Verify that the run_servers was called with the overridden settings
403
+ config_arg = mock_run .call_args [0 ][0 ] # Assuming Config is the first positional arg
404
+
405
+ expected_values = {
406
+ "port" : 8080 ,
407
+ "host" : "example.com" ,
408
+ "log_level" : 'ERROR' ,
409
+ "log_format" : 'TEXT' ,
410
+ "certs_dir" : "./cli-certs" ,
411
+ "ca_cert" : "cli-ca.crt" ,
412
+ "ca_key" : "cli-ca.key" ,
413
+ "server_cert" : "cli-server.crt" ,
414
+ "server_key" : "cli-server.key" ,
415
+ }
416
+
417
+ # Verify if Config object attributes match the expected values from CLI arguments
418
+ for key , expected_value in expected_values .items ():
419
+ assert getattr (config_arg , key ) == expected_value , \
420
+ f"{ key } does not match expected value"
421
+
422
+
423
+ def test_serve_certificate_options (cli_runner : CliRunner ) -> None :
424
+ """Test serve command with certificate options."""
425
+ with patch ('src.codegate.cli.run_servers' ) as mock_run , \
426
+ patch ('src.codegate.cli.structlog.get_logger' ) as mock_logging , \
427
+ patch ('src.codegate.cli.setup_logging' ) as mock_setup_logging :
428
+ # Set up mock logger
429
+ logger_instance = MagicMock ()
430
+ mock_logging .return_value = logger_instance
431
+
432
+ # Execute CLI command with certificate options
433
+ result = cli_runner .invoke (
434
+ cli ,
435
+ [
436
+ "serve" ,
437
+ "--certs-dir" ,
438
+ "./custom-certs" ,
439
+ "--ca-cert" ,
440
+ "custom-ca.crt" ,
441
+ "--ca-key" ,
442
+ "custom-ca.key" ,
443
+ "--server-cert" ,
444
+ "custom-server.crt" ,
445
+ "--server-key" ,
446
+ "custom-server.key" ,
447
+ ],
448
+ )
449
+
450
+ # Check the result of the command
451
+ assert result .exit_code == 0
452
+
453
+ # Ensure logging setup was called with expected arguments
454
+ mock_setup_logging .assert_called_once_with ('INFO' , 'JSON' )
455
+ mock_logging .assert_called_with ("codegate" )
456
+
457
+ # Verify that run_servers was called with the provided certificate options
458
+ config_arg = mock_run .call_args [0 ][0 ] # Assuming Config is the first positional arg
459
+
460
+ expected_values = {
461
+ "certs_dir" : "./custom-certs" ,
462
+ "ca_cert" : "custom-ca.crt" ,
463
+ "ca_key" : "custom-ca.key" ,
464
+ "server_cert" : "custom-server.crt" ,
465
+ "server_key" : "custom-server.key" ,
466
+ }
467
+
468
+ # Check if Config object attributes match the expected values
469
+ for key , expected_value in expected_values .items ():
470
+ assert getattr (config_arg , key ) == expected_value , \
471
+ f"{ key } does not match expected value"
472
+
473
+
474
+ def test_main_function () -> None :
475
+ """Test main function."""
476
+ with patch ("sys.argv" , ["cli" ]), patch ("codegate.cli.cli" ) as mock_cli :
477
+ from codegate .cli import main
478
+ main ()
479
+ mock_cli .assert_called_once ()
480
+
481
+
482
+ @pytest .fixture
483
+ def mock_uvicorn_server ():
484
+ mock_config = MagicMock () # Setup the configuration mock
485
+ mock_server = MagicMock (spec = UvicornServer )
486
+ mock_server .shutdown = AsyncMock () # Ensure shutdown is an async mock
487
+
488
+ uvicorn_server = UvicornServer (config = mock_config , server = mock_server )
489
+ return uvicorn_server
490
+
491
+
492
+ @pytest .mark .asyncio
493
+ async def test_uvicorn_server_cleanup (mock_uvicorn_server ):
494
+ with patch ("asyncio.get_running_loop" ), \
495
+ patch .object (mock_uvicorn_server .server , 'shutdown' , AsyncMock ()):
496
+ # Mock the loop or other components as needed
497
+
498
+ # Start the server or trigger the condition you want to test
499
+ await mock_uvicorn_server .cleanup () # This should now complete without error
500
+
501
+ # Verify that the shutdown was called
502
+ mock_uvicorn_server .server .shutdown .assert_awaited_once ()
0 commit comments