Skip to content

Commit b1517d8

Browse files
Copilotmarcelklehr
andcommitted
test(taskprocessing): fix broken multi-type assertions and add starvation-prevention test
Co-authored-by: marcelklehr <986878+marcelklehr@users.noreply.github.com>
1 parent 549b081 commit b1517d8

1 file changed

Lines changed: 56 additions & 11 deletions

File tree

tests/Core/Command/TaskProcessing/WorkerCommandTest.php

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ private function createProvider(string $id, string $taskTypeId): ISynchronousPro
4545
}
4646

4747
/**
48-
* Helper to create a real Task with a given id.
48+
* Helper to create a real Task with a given id and optional task type.
4949
*/
50-
private function createTask(int $id): Task {
51-
$task = new Task('test_task_type', [], 'testapp', null);
50+
private function createTask(int $id, string $type = 'test_task_type'): Task {
51+
$task = new Task($type, [], 'testapp', null);
5252
$task->setId($id);
5353
return $task;
5454
}
@@ -227,26 +227,31 @@ public function testTimeoutExitsLoop(): void {
227227
$this->assertLessThanOrEqual(5, $elapsed);
228228
}
229229

230-
public function testProcessesFirstMatchingProvider(): void {
230+
public function testProcessesCorrectProviderForReturnedTaskType(): void {
231231
$taskTypeId1 = 'type_a';
232232
$taskTypeId2 = 'type_b';
233233

234234
$provider1 = $this->createProvider('provider_a', $taskTypeId1);
235235
$provider2 = $this->createProvider('provider_b', $taskTypeId2);
236-
$task = $this->createTask(7);
236+
// Task has type_a, so provider1 must be chosen to process it
237+
$task = $this->createTask(7, $taskTypeId1);
237238

238239
$this->manager->expects($this->once())
239240
->method('getProviders')
240241
->willReturn([$provider1, $provider2]);
241242

242-
$this->manager->expects($this->once())
243+
// Both providers are eligible, so getPreferredProvider is called for each
244+
$this->manager->expects($this->exactly(2))
243245
->method('getPreferredProvider')
244-
->with($taskTypeId1)
245-
->willReturn($provider1);
246+
->willReturnMap([
247+
[$taskTypeId1, $provider1],
248+
[$taskTypeId2, $provider2],
249+
]);
246250

251+
// All eligible task types are passed in a single query
247252
$this->manager->expects($this->once())
248253
->method('getNextScheduledTask')
249-
->with([$taskTypeId1])
254+
->with($this->equalTo([$taskTypeId1, $taskTypeId2]))
250255
->willReturn($task);
251256

252257
$this->manager->expects($this->once())
@@ -262,13 +267,53 @@ public function testProcessesFirstMatchingProvider(): void {
262267
$this->assertSame(0, $result);
263268
}
264269

270+
public function testPicksOldestTaskAcrossMultipleEligibleProviders(): void {
271+
$taskTypeId1 = 'type_a';
272+
$taskTypeId2 = 'type_b';
273+
274+
$provider1 = $this->createProvider('provider_a', $taskTypeId1);
275+
$provider2 = $this->createProvider('provider_b', $taskTypeId2);
276+
// getNextScheduledTask returns a type_b task (the globally oldest one)
277+
$task = $this->createTask(3, $taskTypeId2);
278+
279+
$this->manager->expects($this->once())
280+
->method('getProviders')
281+
->willReturn([$provider1, $provider2]);
282+
283+
$this->manager->expects($this->exactly(2))
284+
->method('getPreferredProvider')
285+
->willReturnMap([
286+
[$taskTypeId1, $provider1],
287+
[$taskTypeId2, $provider2],
288+
]);
289+
290+
// Both eligible types are queried together to prevent starvation
291+
$this->manager->expects($this->once())
292+
->method('getNextScheduledTask')
293+
->with($this->equalTo([$taskTypeId1, $taskTypeId2]))
294+
->willReturn($task);
295+
296+
// provider2 must handle the task because the task has type_b
297+
$this->manager->expects($this->once())
298+
->method('processTask')
299+
->with($task, $provider2)
300+
->willReturn(true);
301+
302+
$input = new ArrayInput(['--once' => true], $this->command->getDefinition());
303+
$output = new NullOutput();
304+
305+
$result = $this->command->run($input, $output);
306+
307+
$this->assertSame(0, $result);
308+
}
309+
265310
public function testTaskTypesWhitelistFiltersProviders(): void {
266311
$taskTypeId1 = 'type_a';
267312
$taskTypeId2 = 'type_b';
268313

269314
$provider1 = $this->createProvider('provider_a', $taskTypeId1);
270315
$provider2 = $this->createProvider('provider_b', $taskTypeId2);
271-
$task = $this->createTask(99);
316+
$task = $this->createTask(99, $taskTypeId2);
272317

273318
$this->manager->expects($this->once())
274319
->method('getProviders')
@@ -323,7 +368,7 @@ public function testTaskTypesWhitelistWithNoMatchingProviders(): void {
323368
public function testEmptyTaskTypesAllowsAllProviders(): void {
324369
$taskTypeId = 'type_a';
325370
$provider = $this->createProvider('provider_a', $taskTypeId);
326-
$task = $this->createTask(5);
371+
$task = $this->createTask(5, $taskTypeId);
327372

328373
$this->manager->expects($this->once())
329374
->method('getProviders')

0 commit comments

Comments
 (0)