Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit e1ebd47

Browse files
committed
fix: cs
1 parent 839bb18 commit e1ebd47

File tree

4 files changed

+504
-1
lines changed

4 files changed

+504
-1
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
<?php
2+
3+
namespace Overtrue\LaravelOpenTelemetry\Tests\Hooks\Illuminate\Contracts\Http;
4+
5+
use Mockery;
6+
use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
7+
use Overtrue\LaravelOpenTelemetry\Facades\Measure;
8+
use Overtrue\LaravelOpenTelemetry\Hooks\Illuminate\Contracts\Http\Kernel;
9+
use Overtrue\LaravelOpenTelemetry\Tests\TestCase;
10+
use Symfony\Component\HttpFoundation\Response;
11+
12+
class KernelTest extends TestCase
13+
{
14+
protected function setUp(): void
15+
{
16+
parent::setUp();
17+
}
18+
19+
public function test_adds_trace_id_to_response_header()
20+
{
21+
// Set configuration
22+
config(['otel.response_trace_header_name' => 'X-Trace-Id']);
23+
24+
// Mock trace ID
25+
$expectedTraceId = '12345678901234567890123456789012';
26+
Measure::shouldReceive('traceId')->andReturn($expectedTraceId);
27+
28+
// Create hook
29+
$instrumentation = new CachedInstrumentation('test');
30+
$hook = Kernel::hook($instrumentation);
31+
32+
// Create response
33+
$response = new Response;
34+
35+
// Use reflection to access private method
36+
$reflection = new \ReflectionClass($hook);
37+
$method = $reflection->getMethod('addTraceIdToResponse');
38+
$method->setAccessible(true);
39+
40+
// Execute method
41+
$method->invoke($hook, $response);
42+
43+
// Verify response header is set
44+
$this->assertEquals($expectedTraceId, $response->headers->get('X-Trace-Id'));
45+
}
46+
47+
public function test_does_not_add_header_when_config_is_null()
48+
{
49+
// Set configuration to null
50+
config(['otel.response_trace_header_name' => null]);
51+
52+
// Create hook
53+
$instrumentation = new CachedInstrumentation('test');
54+
$hook = Kernel::hook($instrumentation);
55+
56+
// Create response
57+
$response = new Response;
58+
59+
// Use reflection to access private method
60+
$reflection = new \ReflectionClass($hook);
61+
$method = $reflection->getMethod('addTraceIdToResponse');
62+
$method->setAccessible(true);
63+
64+
// Execute method
65+
$method->invoke($hook, $response);
66+
67+
// Verify response header is not set
68+
$this->assertNull($response->headers->get('X-Trace-Id'));
69+
}
70+
71+
public function test_does_not_add_header_when_config_is_empty()
72+
{
73+
// Set configuration to empty string
74+
config(['otel.response_trace_header_name' => '']);
75+
76+
// Create hook
77+
$instrumentation = new CachedInstrumentation('test');
78+
$hook = Kernel::hook($instrumentation);
79+
80+
// Create response
81+
$response = new Response;
82+
83+
// Use reflection to access private method
84+
$reflection = new \ReflectionClass($hook);
85+
$method = $reflection->getMethod('addTraceIdToResponse');
86+
$method->setAccessible(true);
87+
88+
// Execute method
89+
$method->invoke($hook, $response);
90+
91+
// Verify response header is not set
92+
$this->assertNull($response->headers->get('X-Trace-Id'));
93+
}
94+
95+
public function test_does_not_add_header_when_trace_id_is_empty()
96+
{
97+
// Set configuration
98+
config(['otel.response_trace_header_name' => 'X-Trace-Id']);
99+
100+
// Mock empty trace ID
101+
Measure::shouldReceive('traceId')->andReturn('');
102+
103+
// Create hook
104+
$instrumentation = new CachedInstrumentation('test');
105+
$hook = Kernel::hook($instrumentation);
106+
107+
// Create response
108+
$response = new Response;
109+
110+
// Use reflection to access private method
111+
$reflection = new \ReflectionClass($hook);
112+
$method = $reflection->getMethod('addTraceIdToResponse');
113+
$method->setAccessible(true);
114+
115+
// Execute method
116+
$method->invoke($hook, $response);
117+
118+
// Verify response header is not set
119+
$this->assertNull($response->headers->get('X-Trace-Id'));
120+
}
121+
122+
public function test_does_not_add_header_when_trace_id_is_all_zeros()
123+
{
124+
// Set configuration
125+
config(['otel.response_trace_header_name' => 'X-Trace-Id']);
126+
127+
// Mock all-zeros trace ID (indicates NonRecordingSpan)
128+
$allZerosTraceId = '00000000000000000000000000000000';
129+
Measure::shouldReceive('traceId')->andReturn($allZerosTraceId);
130+
131+
// Create hook
132+
$instrumentation = new CachedInstrumentation('test');
133+
$hook = Kernel::hook($instrumentation);
134+
135+
// Create response
136+
$response = new Response;
137+
138+
// Use reflection to access private method
139+
$reflection = new \ReflectionClass($hook);
140+
$method = $reflection->getMethod('addTraceIdToResponse');
141+
$method->setAccessible(true);
142+
143+
// Execute method
144+
$method->invoke($hook, $response);
145+
146+
// Verify response header is not set
147+
$this->assertNull($response->headers->get('X-Trace-Id'));
148+
}
149+
150+
public function test_handles_exception_gracefully()
151+
{
152+
// Set configuration
153+
config(['otel.response_trace_header_name' => 'X-Trace-Id']);
154+
155+
// Mock Measure::traceId() to throw exception
156+
Measure::shouldReceive('traceId')->andThrow(new \Exception('Test exception'));
157+
158+
// Create hook
159+
$instrumentation = new CachedInstrumentation('test');
160+
$hook = Kernel::hook($instrumentation);
161+
162+
// Create response
163+
$response = new Response;
164+
165+
// Use reflection to access private method
166+
$reflection = new \ReflectionClass($hook);
167+
$method = $reflection->getMethod('addTraceIdToResponse');
168+
$method->setAccessible(true);
169+
170+
// Execute method should not throw exception
171+
$method->invoke($hook, $response);
172+
173+
// Verify response header is not set
174+
$this->assertNull($response->headers->get('X-Trace-Id'));
175+
}
176+
177+
public function test_uses_custom_header_name()
178+
{
179+
// Set custom header name
180+
config(['otel.response_trace_header_name' => 'Custom-Trace-Header']);
181+
182+
// Mock trace ID
183+
$expectedTraceId = '98765432109876543210987654321098';
184+
Measure::shouldReceive('traceId')->andReturn($expectedTraceId);
185+
186+
// Create hook
187+
$instrumentation = new CachedInstrumentation('test');
188+
$hook = Kernel::hook($instrumentation);
189+
190+
// Create response
191+
$response = new Response;
192+
193+
// Use reflection to access private method
194+
$reflection = new \ReflectionClass($hook);
195+
$method = $reflection->getMethod('addTraceIdToResponse');
196+
$method->setAccessible(true);
197+
198+
// Execute method
199+
$method->invoke($hook, $response);
200+
201+
// Verify custom response header is set
202+
$this->assertEquals($expectedTraceId, $response->headers->get('Custom-Trace-Header'));
203+
$this->assertNull($response->headers->get('X-Trace-Id')); // Default header should be empty
204+
}
205+
206+
public function test_instrument_method_registers_hooks()
207+
{
208+
// Create hook
209+
$instrumentation = new CachedInstrumentation('test');
210+
$hook = Kernel::hook($instrumentation);
211+
212+
// Execute instrument method - should not throw exception
213+
$hook->instrument();
214+
215+
// Test passes if no exception is thrown during hook registration
216+
$this->assertTrue(true);
217+
}
218+
219+
public function test_handles_response_with_null_response()
220+
{
221+
// Set configuration
222+
config(['otel.response_trace_header_name' => 'X-Trace-Id']);
223+
224+
// Create hook
225+
$instrumentation = new CachedInstrumentation('test');
226+
$hook = Kernel::hook($instrumentation);
227+
228+
// Test that the post hook handler doesn't crash with null response
229+
// This simulates the post hook callback being called with null response
230+
$reflection = new \ReflectionClass($hook);
231+
$method = $reflection->getMethod('addTraceIdToResponse');
232+
$method->setAccessible(true);
233+
234+
// Should handle gracefully with valid response
235+
$response = new Response;
236+
$method->invoke($hook, $response);
237+
238+
// Test passes if no exception is thrown
239+
$this->assertTrue(true);
240+
}
241+
242+
protected function tearDown(): void
243+
{
244+
Mockery::close();
245+
parent::tearDown();
246+
}
247+
}

0 commit comments

Comments
 (0)