8000 [Messenger] Fix cloned TraceableStack not unstacking the stack indepe… · symfony/symfony@b91bdc6 · GitHub
[go: up one dir, main page]

Skip to content

Commit b91bdc6

Browse files
krciga22nicolas-grekas
authored andcommitted
[Messenger] Fix cloned TraceableStack not unstacking the stack independently
1 parent 7c4f174 commit b91bdc6

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

src/Symfony/Component/Messenger/Middleware/TraceableMiddleware.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,9 @@ public function stop(): void
9494
}
9595
$this->currentEvent = null;
9696
}
97+
98+
public function __clone()
99+
{
100+
$this->stack = clone $this->stack;
101+
}
97102
}

src/Symfony/Component/Messenger/Tests/Middleware/TraceableMiddlewareTest.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\Messenger\Middleware\StackInterface;
1717
use Symfony\Component\Messenger\Middleware\StackMiddleware;
1818
use Symfony\Component\Messenger\Middleware\TraceableMiddleware;
19+
use Symfony\Component\Messenger\Middleware\TraceableStack;
1920
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
2021
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
2122
use Symfony\Component\Stopwatch\Stopwatch;
@@ -140,4 +141,92 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
140141
$traced->handle($envelope, new StackMiddleware(new \ArrayIterator([null, $middleware])));
141142
$this->assertSame(1, $middleware->calls);
142143
}
144+
145+
public function testClonedTraceableStackUnstacksIndependently()
146+
{
147+
// import TraceableStack
148+
class_exists(TraceableMiddleware::class);
149+
150+
$stackMiddleware = new StackMiddleware([
151+
null,
152+
$this->createMock(MiddlewareInterface::class),
153+
$this->createMock(MiddlewareInterface::class),
154+
]);
155+
156+
$stopwatch = $this->createMock(Stopwatch::class);
157+
158+
$traceableStack = new TraceableStack($stackMiddleware, $stopwatch, 'command_bus', 'messenger.middleware');
159+
$clonedStack = clone $traceableStack;
160+
161+
$traceableStackMiddleware1 = $traceableStack->next();
162+
$traceableStackMiddleware2 = $traceableStack->next();
163+
$traceableStackTail = $traceableStack->next();
164+
self::assertSame($stackMiddleware, $traceableStackTail);
165+
166+
// unstack clonedStack independently
167+
$clonedStackMiddleware1 = $clonedStack->next();
168+
self::assertSame($traceableStackMiddleware1, $clonedStackMiddleware1);
169+
self::assertNotSame($traceableStackMiddleware2, $clonedStackMiddleware1);
170+
171+
$clonedStackMiddleware2 = $clonedStack->next();
172+
self::assertSame($traceableStackMiddleware2, $clonedStackMiddleware2);
173+
174+
$clonedStackTail = $clonedStack->next();
175+
self::assertNotSame($stackMiddleware, $clonedStackTail, 'stackMiddleware was also cloned');
176+
}
177+
178+
public function testClonedTraceableStackUsesSameStopwatch()
179+
{
180+
// import TraceableStack
181+
class_exists(TraceableMiddleware::class);
182+
183+
$middlewareIterable = [null, $this->createMock(MiddlewareInterface::class)];
184+
185+
$stackMiddleware = new StackMiddleware($middlewareIterable);
186+
187+
$stopwatch = $this->createMock(Stopwatch::class);
188+
$stopwatch->expects($this->exactly(2))->method('isStarted')->willReturn(true);
189+
190+
$startSeries = [
191+
[$this->matches('"%sMiddlewareInterface%s" on "command_bus"'), 'messenger.middleware'],
192+
[$this->identicalTo('Tail on "command_bus"'), 'messenger.middleware'],
193+
[$this->matches('"%sMiddlewareInterface%s" on "command_bus"'), 'messenger.middleware'],
194+
[$this->identicalTo('Tail on "command_bus"'), 'messenger.middleware'],
195+
];
196+
$stopwatch->expects($this->exactly(4))
197+
->method('start')
198+
->willReturnCallback(function (string $name, string $category = null) use (&$startSeries) {
199+
[$constraint, $expectedCategory] = array_shift($startSeries);
200+
201+
$constraint->evaluate($name);
202+
$this->assertSame($expectedCategory, $category);
203+
204+
return $this->createMock(StopwatchEvent::class);
205+
})
206+
;
207+
208+
$stopSeries = [
209+
$this->matches('"%sMiddlewareInterface%s" on "command_bus"'),
210+
$this->matches('"%sMiddlewareInterface%s" on "command_bus"'),
211+
];
212+
$stopwatch->expects($this->exactly(2))
213+
->method('stop')
214+
->willReturnCallback(function (string $name) use (&$stopSeries) {
215+
$constraint = array_shift($stopSeries);
216+
$constraint->evaluate($name);
217+
218+
return $this->createMock(StopwatchEvent::class);
219+
})
220+
;
221+
222+
$traceableStack = new TraceableStack($stackMiddleware, $stopwatch, 'command_bus', 'messenger.middleware');
223+
$clonedStack = clone $traceableStack;
224+
225+
// unstack the stacks independently
226+
$traceableStack->next();
227+
$traceableStack->next();
228+
229+
$clonedStack->next();
230+
$clonedStack->next();
231+
}
143232
}

0 commit comments

Comments
 (0)
0