|
1 | 1 | """Tests for trace callback performance optimizations (Issue #115).""" |
2 | 2 |
|
3 | 3 | import sys |
4 | | -import unittest |
5 | | -from unittest.mock import Mock, patch |
| 4 | +from unittest.mock import Mock |
| 5 | + |
| 6 | +import pytest |
6 | 7 |
|
7 | 8 | from crosshair.tracers import ( |
8 | 9 | COMPOSITE_TRACER, |
|
12 | 13 | ) |
13 | 14 |
|
14 | 15 |
|
15 | | -class TestTracingModuleFastPath(unittest.TestCase): |
| 16 | +class TestTracingModuleFastPath: |
16 | 17 | """Test that the TracingModule trace_op fast-path optimizations work correctly.""" |
17 | 18 |
|
18 | | - def test_trace_op_with_none_target_exits_early(self): |
19 | | - """Test that trace_op exits early when target is None.""" |
| 19 | + def test_trace_op_with_nonexistent_opcode_exits_early(self): |
| 20 | + """Test that trace_op exits early when opcode has no handler.""" |
20 | 21 | module = TracingModule() |
21 | 22 |
|
22 | | - # Create a mock frame that would trigger the call handler |
| 23 | + # Create a mock frame |
23 | 24 | mock_frame = Mock() |
24 | | - mock_frame.f_code.co_code = bytes([0, 0]) # Minimal code |
| 25 | + mock_frame.f_code.co_code = bytes([0, 0]) |
25 | 26 | mock_frame.f_lasti = 0 |
26 | 27 |
|
27 | | - # The trace_op should handle None targets gracefully |
28 | | - # (It will try to read from the stack, which might fail, but that's ok) |
29 | | - try: |
30 | | - result = module.trace_op(mock_frame, mock_frame.f_code, 256) # Non-existent opcode |
31 | | - self.assertIsNone(result) |
32 | | - except Exception: |
33 | | - # Some exceptions are expected depending on the mock setup |
34 | | - pass |
35 | | - |
36 | | - def test_trace_op_with_primitive_types_exits_early(self): |
37 | | - """Test that trace_op exits early for primitive types.""" |
| 28 | + # Use a non-existent opcode (256) |
| 29 | + result = module.trace_op(mock_frame, mock_frame.f_code, 256) |
| 30 | + assert result is None |
| 31 | + |
| 32 | + def test_trace_op_fast_path_for_primitives(self): |
| 33 | + """Test that trace_op has fast-path for primitive types.""" |
38 | 34 | module = TracingModule() |
39 | 35 |
|
40 | 36 | # Verify that primitive types are in the fast-path check |
41 | 37 | # This is a white-box test of the optimization |
42 | 38 | fast_path_types = (type(None), int, float, str, bool, list, dict, tuple, set) |
43 | 39 |
|
44 | 40 | for t in fast_path_types: |
45 | | - # The check is: if target_type in fast_path_types: return None |
46 | | - self.assertIn(t, fast_path_types) |
| 41 | + # The check ensures these types exit early |
| 42 | + assert t in fast_path_types |
47 | 43 |
|
48 | 44 |
|
49 | | -class TestCTracerCacheStats(unittest.TestCase): |
| 45 | +class TestCTracerCacheStats: |
50 | 46 | """Test that the C tracer cache statistics work correctly.""" |
51 | 47 |
|
52 | | - @unittest.skipIf( |
53 | | - not hasattr(COMPOSITE_TRACER.ctracer, 'get_cache_stats'), |
54 | | - "Cache stats not available in this build" |
55 | | - ) |
56 | 48 | def test_cache_stats_returns_dict(self): |
57 | 49 | """Test that get_cache_stats returns a dictionary.""" |
58 | 50 | stats = COMPOSITE_TRACER.get_cache_stats() |
59 | | - self.assertIsInstance(stats, dict) |
| 51 | + assert isinstance(stats, dict) |
60 | 52 |
|
61 | | - @unittest.skipIf( |
62 | | - not hasattr(COMPOSITE_TRACER.ctracer, 'get_cache_stats'), |
63 | | - "Cache stats not available in this build" |
64 | | - ) |
65 | 53 | def test_cache_stats_has_expected_keys(self): |
66 | 54 | """Test that cache stats has the expected keys.""" |
67 | 55 | stats = COMPOSITE_TRACER.get_cache_stats() |
68 | 56 | expected_keys = {'cache_hits', 'cache_misses', 'last_opcode'} |
69 | 57 | for key in expected_keys: |
70 | | - self.assertIn(key, stats) |
| 58 | + assert key in stats |
71 | 59 |
|
72 | 60 |
|
73 | | -class TestPerformanceOptimizations(unittest.TestCase): |
| 61 | +class TestPerformanceOptimizations: |
74 | 62 | """Test that performance optimizations don't break functionality.""" |
75 | 63 |
|
76 | 64 | def test_tracing_module_callable(self): |
77 | 65 | """Test that TracingModule instances remain callable.""" |
78 | 66 | module = TracingModule() |
79 | | - self.assertTrue(callable(module)) |
| 67 | + assert callable(module) |
80 | 68 |
|
81 | 69 | def test_composite_tracer_has_cache_stats_method(self): |
82 | 70 | """Test that CompositeTracer has the get_cache_stats method.""" |
83 | | - self.assertTrue(hasattr(COMPOSITE_TRACER, 'get_cache_stats')) |
84 | | - self.assertTrue(callable(COMPOSITE_TRACER.get_cache_stats)) |
| 71 | + assert hasattr(COMPOSITE_TRACER, 'get_cache_stats') |
| 72 | + assert callable(COMPOSITE_TRACER.get_cache_stats) |
85 | 73 |
|
86 | 74 |
|
87 | | -class TestOpcodeFiltering(unittest.TestCase): |
| 75 | +class TestOpcodeFiltering: |
88 | 76 | """Test that opcode filtering works correctly with optimizations.""" |
89 | 77 |
|
90 | 78 | def test_tracing_module_opcodes_wanted(self): |
91 | 79 | """Test that TracingModule has opcodes_wanted attribute.""" |
92 | 80 | module = TracingModule() |
93 | | - self.assertTrue(hasattr(module, 'opcodes_wanted')) |
94 | | - self.assertIsInstance(module.opcodes_wanted, frozenset) |
95 | | - |
96 | | - |
97 | | -if __name__ == '__main__': |
98 | | - unittest.main() |
| 81 | + assert hasattr(module, 'opcodes_wanted') |
| 82 | + assert isinstance(module.opcodes_wanted, frozenset) |
0 commit comments