1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-12-28 09:15:06 -05:00
aprsd/tests/utils/test_trace.py
2025-12-09 17:20:23 -05:00

155 lines
4.5 KiB
Python

import unittest
from unittest import mock
from aprsd.utils import trace
class TestTraceDecorator(unittest.TestCase):
"""Unit tests for the trace() decorator."""
def setUp(self):
"""Set up test fixtures."""
# Enable trace for testing
trace.TRACE_ENABLED = True
def tearDown(self):
"""Clean up after tests."""
trace.TRACE_ENABLED = False
@mock.patch('aprsd.utils.trace.LOG')
def test_trace_decorator_no_debug(self, mock_log):
"""Test trace() decorator when DEBUG is not enabled."""
mock_log.isEnabledFor.return_value = False
@trace.trace
def test_func(x, y):
return x + y
result = test_func(1, 2)
self.assertEqual(result, 3)
# Should not log when DEBUG is disabled
mock_log.debug.assert_not_called()
@mock.patch('aprsd.utils.trace.LOG')
def test_trace_decorator_with_debug(self, mock_log):
"""Test trace() decorator when DEBUG is enabled."""
mock_log.isEnabledFor.return_value = True
@trace.trace
def test_func(x, y):
return x + y
result = test_func(1, 2)
self.assertEqual(result, 3)
# Should log when DEBUG is enabled
self.assertTrue(mock_log.debug.called)
@mock.patch('aprsd.utils.trace.LOG')
def test_trace_decorator_exception(self, mock_log):
"""Test trace() decorator with exception."""
mock_log.isEnabledFor.return_value = True
@trace.trace
def test_func():
raise ValueError('Test error')
with self.assertRaises(ValueError):
test_func()
# Should log exception
self.assertTrue(mock_log.debug.called)
@mock.patch('aprsd.utils.trace.LOG')
def test_trace_decorator_with_filter(self, mock_log):
"""Test trace() decorator with filter function."""
mock_log.isEnabledFor.return_value = True
def filter_func(args):
return args.get('x') > 0
@trace.trace(filter_function=filter_func)
def test_func(x, y):
return x + y
# Should log when filter passes
test_func(1, 2)
self.assertTrue(mock_log.debug.called)
# Reset mock
mock_log.reset_mock()
# Should not log when filter fails
test_func(-1, 2)
# Filter function should prevent logging
# (though function still executes)
def test_trace_decorator_preserves_function(self):
"""Test that trace decorator preserves function metadata."""
@trace.trace
def test_func(x, y):
"""Test function docstring."""
return x + y
self.assertEqual(test_func.__name__, 'test_func')
self.assertIn('docstring', test_func.__doc__)
class TestNoTraceDecorator(unittest.TestCase):
"""Unit tests for the no_trace() decorator."""
def test_no_trace_decorator(self):
"""Test no_trace() decorator."""
@trace.no_trace
def test_func(x, y):
return x + y
result = test_func(1, 2)
self.assertEqual(result, 3)
# Function should work normally
self.assertEqual(test_func.__name__, 'test_func')
class TestTraceWrapperMetaclass(unittest.TestCase):
"""Unit tests for the TraceWrapperMetaclass."""
def test_metaclass_creation(self):
"""Test that TraceWrapperMetaclass creates class correctly."""
class TestClass(metaclass=trace.TraceWrapperMetaclass):
def test_method(self):
return 'test'
instance = TestClass()
self.assertEqual(instance.test_method(), 'test')
def test_metaclass_wraps_methods(self):
"""Test that metaclass wraps methods."""
class TestClass(metaclass=trace.TraceWrapperMetaclass):
def test_method(self):
return 'test'
# Methods should be wrapped
self.assertTrue(
hasattr(TestClass.test_method, '__wrapped__')
or hasattr(TestClass.test_method, '__name__')
)
class TestTraceWrapperWithABCMetaclass(unittest.TestCase):
"""Unit tests for the TraceWrapperWithABCMetaclass."""
def test_metaclass_creation(self):
"""Test that TraceWrapperWithABCMetaclass creates class correctly."""
import abc
class TestAbstractClass(metaclass=trace.TraceWrapperWithABCMetaclass):
@abc.abstractmethod
def test_method(self):
pass
# Should be able to create abstract class
self.assertTrue(hasattr(TestAbstractClass, '__abstractmethods__'))