Skip to content

Commit 6a05aea

Browse files
committed
test(process): cover manager fallback business rules
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 32d2b3d commit 6a05aea

File tree

1 file changed

+134
-28
lines changed

1 file changed

+134
-28
lines changed

tests/php/Unit/Service/Process/ProcessManagerTest.php

Lines changed: 134 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
namespace OCA\Libresign\Tests\Unit\Service\Process;
1010

1111
use OCA\Libresign\AppInfo\Application;
12+
use OCA\Libresign\Service\Process\ListeningPidResolver;
1213
use OCA\Libresign\Service\Process\ProcessManager;
14+
use OCA\Libresign\Service\Process\ProcessSignaler;
1315
use OCA\Libresign\Tests\Unit\TestCase;
1416
use OCP\IAppConfig;
17+
use PHPUnit\Framework\Attributes\DataProvider;
1518
use PHPUnit\Framework\MockObject\MockObject;
1619
use Psr\Log\LoggerInterface;
1720

@@ -29,40 +32,46 @@ public function setUp(): void {
2932
}
3033

3134
/**
32-
* @return array{0: ProcessManager, 1: string}
35+
* @return array{0: ProcessManager, 1: array<string, string>}
3336
*/
3437
private function makeManagerWithStoredRegistry(?callable $factory = null): array {
35-
$stored = '{}';
38+
$storedByKey = [
39+
'process_registry' => '{}',
40+
'process_registry_hints' => '{}',
41+
];
3642
$this->appConfig->method('getValueString')
37-
->willReturnCallback(function (string $_appId, string $_key, string $default) use (&$stored): string {
38-
return $stored ?: $default;
43+
->willReturnCallback(function (string $_appId, string $key, string $default) use (&$storedByKey): string {
44+
return $storedByKey[$key] ?? $default;
3945
});
4046

4147
$this->appConfig->method('setValueString')
42-
->willReturnCallback(function (string $_appId, string $_key, string $value) use (&$stored): bool {
43-
$stored = $value;
48+
->willReturnCallback(function (string $_appId, string $key, string $value) use (&$storedByKey): bool {
49+
$storedByKey[$key] = $value;
4450
return true;
4551
});
4652

4753
$manager = $factory
4854
? $factory($this->appConfig, $this->logger)
4955
: new ProcessManager($this->appConfig, $this->logger);
5056

51-
return [$manager, $stored];
57+
return [$manager, $storedByKey];
5258
}
5359

5460
public function testListRunningPurgesStoppedPids(): void {
55-
$stored = '{}';
61+
$storedByKey = [
62+
'process_registry' => '{}',
63+
'process_registry_hints' => '{}',
64+
];
5665
$this->appConfig->method('getValueString')
57-
->willReturnCallback(function (string $appId, string $key, string $default) use (&$stored): string {
66+
->willReturnCallback(function (string $appId, string $key, string $default) use (&$storedByKey): string {
5867
$this->assertSame(Application::APP_ID, $appId);
59-
$this->assertSame('process_registry', $key);
60-
return $stored ?: $default;
68+
$this->assertContains($key, ['process_registry', 'process_registry_hints']);
69+
return $storedByKey[$key] ?? $default;
6170
});
6271

6372
$this->appConfig->method('setValueString')
64-
->willReturnCallback(function (string $_appId, string $_key, string $value) use (&$stored): bool {
65-
$stored = $value;
73+
->willReturnCallback(function (string $_appId, string $key, string $value) use (&$storedByKey): bool {
74+
$storedByKey[$key] = $value;
6675
return true;
6776
});
6877

@@ -81,19 +90,29 @@ public function isRunning(int $pid): bool {
8190
$this->assertSame(111, $running[0]['pid']);
8291
}
8392

84-
public function testRegisterIgnoresInvalidPid(): void {
93+
#[DataProvider('provideInvalidPids')]
94+
public function testRegisterIgnoresInvalidPid(int $invalidPid): void {
8595
[$manager] = $this->makeManagerWithStoredRegistry(fn (IAppConfig $appConfig, LoggerInterface $logger): ProcessManager => new class($appConfig, $logger) extends ProcessManager {
8696
public function isRunning(int $pid): bool {
8797
return true;
8898
}
8999
});
90100

91-
$manager->register(self::WORKER_SOURCE, 0);
92-
$manager->register(self::WORKER_SOURCE, -9);
101+
$manager->register(self::WORKER_SOURCE, $invalidPid);
93102

94103
$this->assertSame(0, $manager->countRunning(self::WORKER_SOURCE));
95104
}
96105

106+
/**
107+
* @return array<string, array{0: int}>
108+
*/
109+
public static function provideInvalidPids(): array {
110+
return [
111+
'zero' => [0],
112+
'negative' => [-9],
113+
];
114+
}
115+
97116
public function testFindRunningPidReturnsFirstWhenNoFilterProvided(): void {
98117
[$manager] = $this->makeManagerWithStoredRegistry(fn (IAppConfig $appConfig, LoggerInterface $logger): ProcessManager => new class($appConfig, $logger) extends ProcessManager {
99118
public function isRunning(int $pid): bool {
@@ -142,6 +161,49 @@ public function isRunning(int $pid): bool {
142161
$this->assertSame(0, $actual);
143162
}
144163

164+
public function testFindRunningPidHydratesRegistryWhenHintExists(): void {
165+
$resolver = $this->createMock(ListeningPidResolver::class);
166+
$resolver->expects($this->once())
167+
->method('findListeningPids')
168+
->with(8888)
169+
->willReturn([777]);
170+
171+
$signaler = $this->createMock(ProcessSignaler::class);
172+
$signaler->method('isRunning')
173+
->willReturn(true);
174+
175+
[$manager] = $this->makeManagerWithStoredRegistry(
176+
fn (IAppConfig $appConfig, LoggerInterface $logger): ProcessManager
177+
=> new ProcessManager($appConfig, $logger, $signaler, $resolver)
178+
);
179+
180+
$manager->setSourceHint(self::INSTALL_SOURCE, [
181+
'uri' => 'http://127.0.0.1:8888/api/v1/cfssl/',
182+
'port' => 8888,
183+
]);
184+
185+
$actual = $manager->findRunningPid(self::INSTALL_SOURCE);
186+
187+
$this->assertSame(777, $actual);
188+
}
189+
190+
public function testFindRunningPidSkipsFallbackWhenNoHintExists(): void {
191+
$resolver = $this->createMock(ListeningPidResolver::class);
192+
$resolver->expects($this->never())
193+
->method('findListeningPids');
194+
195+
$signaler = $this->createMock(ProcessSignaler::class);
196+
$signaler->method('isRunning')
197+
->willReturn(true);
198+
199+
[$manager] = $this->makeManagerWithStoredRegistry(
200+
fn (IAppConfig $appConfig, LoggerInterface $logger): ProcessManager
201+
=> new ProcessManager($appConfig, $logger, $signaler, $resolver)
202+
);
203+
204+
$this->assertSame(0, $manager->findRunningPid(self::INSTALL_SOURCE));
205+
}
206+
145207
public function testIsRunningReturnsFalseForInvalidPid(): void {
146208
$manager = new ProcessManager($this->appConfig, $this->logger);
147209

@@ -150,15 +212,18 @@ public function testIsRunningReturnsFalseForInvalidPid(): void {
150212
}
151213

152214
public function testStopAllTerminatesAndUnregistersTrackedPids(): void {
153-
$stored = '{}';
215+
$storedByKey = [
216+
'process_registry' => '{}',
217+
'process_registry_hints' => '{}',
218+
];
154219
$this->appConfig->method('getValueString')
155-
->willReturnCallback(function (string $_appId, string $_key, string $default) use (&$stored): string {
156-
return $stored ?: $default;
220+
->willReturnCallback(function (string $_appId, string $key, string $default) use (&$storedByKey): string {
221+
return $storedByKey[$key] ?? $default;
157222
});
158223

159224
$this->appConfig->method('setValueString')
160-
->willReturnCallback(function (string $_appId, string $_key, string $value) use (&$stored): bool {
161-
$stored = $value;
225+
->willReturnCallback(function (string $_appId, string $key, string $value) use (&$storedByKey): bool {
226+
$storedByKey[$key] = $value;
162227
return true;
163228
});
164229

@@ -170,7 +235,7 @@ public function isRunning(int $pid): bool {
170235
return true;
171236
}
172237

173-
protected function terminate(int $pid, int $signal): bool {
238+
public function stopPid(int $pid, int $signal = SIGTERM): bool {
174239
$this->terminated[] = $pid;
175240
return true;
176241
}
@@ -187,15 +252,18 @@ protected function terminate(int $pid, int $signal): bool {
187252
}
188253

189254
public function testStopAllUsesProvidedSignal(): void {
190-
$stored = '{}';
255+
$storedByKey = [
256+
'process_registry' => '{}',
257+
'process_registry_hints' => '{}',
258+
];
191259
$this->appConfig->method('getValueString')
192-
->willReturnCallback(function (string $_appId, string $_key, string $default) use (&$stored): string {
193-
return $stored ?: $default;
260+
->willReturnCallback(function (string $_appId, string $key, string $default) use (&$storedByKey): string {
261+
return $storedByKey[$key] ?? $default;
194262
});
195263

196264
$this->appConfig->method('setValueString')
197-
->willReturnCallback(function (string $_appId, string $_key, string $value) use (&$stored): bool {
198-
$stored = $value;
265+
->willReturnCallback(function (string $_appId, string $key, string $value) use (&$storedByKey): bool {
266+
$storedByKey[$key] = $value;
199267
return true;
200268
});
201269

@@ -207,7 +275,7 @@ public function isRunning(int $pid): bool {
207275
return true;
208276
}
209277

210-
protected function terminate(int $pid, int $signal): bool {
278+
public function stopPid(int $pid, int $signal = SIGTERM): bool {
211279
$this->signals[] = $signal;
212280
return true;
213281
}
@@ -220,4 +288,42 @@ protected function terminate(int $pid, int $signal): bool {
220288

221289
$this->assertSame([SIGKILL, SIGKILL], $manager->signals);
222290
}
291+
292+
public function testFindListeningPidsDelegatesToResolver(): void {
293+
$resolver = $this->createMock(ListeningPidResolver::class);
294+
$resolver->expects($this->once())
295+
->method('findListeningPids')
296+
->with(8888)
297+
->willReturn([111, 222]);
298+
299+
$signaler = $this->createMock(ProcessSignaler::class);
300+
301+
$manager = new ProcessManager($this->appConfig, $this->logger, $signaler, $resolver);
302+
303+
$this->assertSame([111, 222], $manager->findListeningPids(8888));
304+
}
305+
306+
#[DataProvider('provideIsRunningDelegation')]
307+
public function testIsRunningDelegatesToSignaler(int $pid, bool $expected): void {
308+
$resolver = $this->createMock(ListeningPidResolver::class);
309+
$signaler = $this->createMock(ProcessSignaler::class);
310+
$signaler->expects($this->once())
311+
->method('isRunning')
312+
->with($pid)
313+
->willReturn($expected);
314+
315+
$manager = new ProcessManager($this->appConfig, $this->logger, $signaler, $resolver);
316+
317+
$this->assertSame($expected, $manager->isRunning($pid));
318+
}
319+
320+
/**
321+
* @return array<string, array{0: int, 1: bool}>
322+
*/
323+
public static function provideIsRunningDelegation(): array {
324+
return [
325+
'running pid' => [111, true],
326+
'not running pid' => [222, false],
327+
];
328+
}
223329
}

0 commit comments

Comments
 (0)