Skip to content

Commit 106fba9

Browse files
committed
test(cfssl): improve handler unit scenarios
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 9e61cc3 commit 106fba9

File tree

1 file changed

+120
-69
lines changed

1 file changed

+120
-69
lines changed

tests/php/Unit/Handler/CertificateEngine/CfsslHandlerTest.php

Lines changed: 120 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use OCP\IDateTimeFormatter;
2525
use OCP\ITempManager;
2626
use OCP\IURLGenerator;
27+
use PHPUnit\Framework\Attributes\DataProvider;
2728
use PHPUnit\Framework\MockObject\MockObject;
2829
use Psr\Log\LoggerInterface;
2930

@@ -60,25 +61,88 @@ public function testScopedProcessClassIsAvailable(): void {
6061
$this->assertTrue(class_exists(Process::class));
6162
}
6263

63-
public function testCheckBinariesReturnsErrorWhenProcessFails(): void {
64+
public function testStopIfRunningKillsRegisteredAndPortListenerPids(): void {
65+
$unregisteredPids = [];
66+
$stoppedPids = [];
67+
$uri = CfsslHandler::CFSSL_URI;
68+
$port = 8888;
69+
70+
$this->processManager->expects($this->once())
71+
->method('setSourceHint')
72+
->with(self::PROCESS_SOURCE, [
73+
'uri' => $uri,
74+
'port' => $port,
75+
]);
76+
77+
$this->processManager->expects($this->once())
78+
->method('findRunningPid')
79+
->with(self::PROCESS_SOURCE, $this->callback('is_callable'))
80+
->willReturn(321);
81+
82+
$this->processManager->expects($this->once())
83+
->method('listRunning')
84+
->with(self::PROCESS_SOURCE)
85+
->willReturn([
86+
['pid' => 321, 'context' => ['uri' => $uri], 'createdAt' => 1],
87+
['pid' => 654, 'context' => ['uri' => $uri], 'createdAt' => 2],
88+
]);
89+
90+
$this->processManager->expects($this->exactly(2))
91+
->method('unregister')
92+
->willReturnCallback(function (string $source, int $pid) use (&$unregisteredPids): void {
93+
$this->assertSame(self::PROCESS_SOURCE, $source);
94+
$unregisteredPids[] = $pid;
95+
});
96+
97+
$this->processManager->expects($this->exactly(2))
98+
->method('stopPid')
99+
->withAnyParameters()
100+
->willReturnCallback(function (int $pid, int $signal) use (&$stoppedPids): bool {
101+
$this->assertSame(SIGKILL, $signal);
102+
$stoppedPids[] = $pid;
103+
return true;
104+
});
105+
106+
$handler = $this->getMockBuilder(CfsslHandler::class)
107+
->setConstructorArgs($this->getConstructorArgs())
108+
->onlyMethods(['createProcess'])
109+
->getMock();
110+
111+
$handler->method('createProcess')
112+
->willReturn($this->createMock(Process::class));
113+
114+
self::invokePrivate($handler, 'stopIfRunning');
115+
116+
sort($unregisteredPids);
117+
sort($stoppedPids);
118+
$this->assertSame([321, 654], $unregisteredPids);
119+
$this->assertSame([321, 654], $stoppedPids);
120+
}
121+
122+
#[DataProvider('provideCheckBinariesErrorCases')]
123+
public function testCheckBinariesReturnsErrorForInvalidProcessState(
124+
bool $isSuccessful,
125+
string $output,
126+
string $expectedMessage,
127+
): void {
64128
$binary = tempnam(sys_get_temp_dir(), 'cfssl-bin-');
65129
$this->assertNotFalse($binary);
66130

67131
$process = $this->createMock(Process::class);
68132
$process->expects($this->once())
69133
->method('run');
70-
$process->expects($this->once())
71-
->method('getOutput')
72-
->willReturn('');
73134
$process->expects($this->once())
74135
->method('isSuccessful')
75-
->willReturn(false);
136+
->willReturn($isSuccessful);
137+
$process->expects($this->once())
138+
->method('getOutput')
139+
->willReturn($output);
76140

77141
$handler = $this->createHandler($process, (string)$binary);
78142
$result = self::invokePrivate($handler, 'checkBinaries');
79143

80144
$this->assertSame('error', $result[0]->jsonSerialize()['status']);
81-
$this->assertStringContainsString('Failed to run the command', $result[0]->jsonSerialize()['message']);
145+
$this->assertStringContainsString($expectedMessage, $result[0]->jsonSerialize()['message']);
82146

83147
@unlink((string)$binary);
84148
}
@@ -108,53 +172,49 @@ public function testCheckBinariesReturnsSuccessWhenProcessOutputIsValid(): void
108172
@unlink((string)$binary);
109173
}
110174

111-
public function testCheckBinariesReturnsErrorWhenVersionOutputFormatIsInvalid(): void {
112-
$binary = tempnam(sys_get_temp_dir(), 'cfssl-bin-');
113-
$this->assertNotFalse($binary);
114175

115-
$process = $this->createMock(Process::class);
116-
$process->expects($this->once())
117-
->method('run');
118-
$process->expects($this->once())
119-
->method('isSuccessful')
120-
->willReturn(true);
121-
$process->expects($this->once())
122-
->method('getOutput')
123-
->willReturn('cfssl version output without expected separators');
124-
125-
$handler = $this->createHandler($process, (string)$binary);
126-
$result = self::invokePrivate($handler, 'checkBinaries');
127-
128-
$this->assertSame('error', $result[0]->jsonSerialize()['status']);
129-
$this->assertStringContainsString('Failed to identify cfssl version', $result[0]->jsonSerialize()['message']);
130-
131-
@unlink((string)$binary);
176+
/**
177+
* @return array<string, array{0: bool, 1: string, 2: string}>
178+
*/
179+
public static function provideCheckBinariesErrorCases(): array {
180+
return [
181+
'process failure without output' => [
182+
false,
183+
'',
184+
'Failed to run the command',
185+
],
186+
'invalid version output format' => [
187+
true,
188+
'cfssl version output without expected separators',
189+
'Failed to identify cfssl version',
190+
],
191+
'version mismatch' => [
192+
true,
193+
"Version: 0.0.1\nRuntime: go1.22\n",
194+
'Invalid version. Expected:',
195+
],
196+
];
132197
}
133198

134-
public function testCheckBinariesReturnsErrorWhenCfsslVersionDoesNotMatchExpected(): void {
135-
$binary = tempnam(sys_get_temp_dir(), 'cfssl-bin-');
136-
$this->assertNotFalse($binary);
137-
138-
$process = $this->createMock(Process::class);
139-
$process->expects($this->once())
140-
->method('run');
141-
$process->expects($this->once())
142-
->method('isSuccessful')
143-
->willReturn(true);
144-
$process->expects($this->once())
145-
->method('getOutput')
146-
->willReturn("Version: 0.0.1\nRuntime: go1.22\n");
199+
private function createHandler(?Process $process = null, ?string $binary = null): CfsslHandler {
200+
$constructorArgs = $this->getConstructorArgs($binary);
201+
$process ??= $this->createMock(Process::class);
147202

148-
$handler = $this->createHandler($process, (string)$binary);
149-
$result = self::invokePrivate($handler, 'checkBinaries');
203+
$handler = $this->getMockBuilder(CfsslHandler::class)
204+
->setConstructorArgs($constructorArgs)
205+
->onlyMethods(['createProcess'])
206+
->getMock();
150207

151-
$this->assertSame('error', $result[0]->jsonSerialize()['status']);
152-
$this->assertStringContainsString('Invalid version. Expected:', $result[0]->jsonSerialize()['message']);
208+
$handler->method('createProcess')
209+
->willReturn($process);
153210

154-
@unlink((string)$binary);
211+
return $handler;
155212
}
156213

157-
private function createHandler(?Process $process = null, ?string $binary = null): CfsslHandler {
214+
/**
215+
* @return array<int, mixed>
216+
*/
217+
private function getConstructorArgs(?string $binary = null): array {
158218
$config = \OCP\Server::get(IConfig::class);
159219
$appConfig = $this->getMockAppConfigWithReset();
160220
if ($binary !== null) {
@@ -180,30 +240,21 @@ private function createHandler(?Process $process = null, ?string $binary = null)
180240
$cfsslServerHandler = $this->createMock(CfsslServerHandler::class);
181241
$cfsslServerHandler->expects($this->once())
182242
->method('configCallback');
183-
$process ??= $this->createMock(Process::class);
184-
185-
$handler = $this->getMockBuilder(CfsslHandler::class)
186-
->setConstructorArgs([
187-
$config,
188-
$appConfig,
189-
$appDataFactory,
190-
$dateTimeFormatter,
191-
$tempManager,
192-
$cfsslServerHandler,
193-
$certificatePolicyService,
194-
$urlGenerator,
195-
$caIdentifierService,
196-
$crlMapper,
197-
$logger,
198-
$crlRevocationChecker,
199-
$this->processManager,
200-
])
201-
->onlyMethods(['createProcess'])
202-
->getMock();
203243

204-
$handler->method('createProcess')
205-
->willReturn($process);
206-
207-
return $handler;
244+
return [
245+
$config,
246+
$appConfig,
247+
$appDataFactory,
248+
$dateTimeFormatter,
249+
$tempManager,
250+
$cfsslServerHandler,
251+
$certificatePolicyService,
252+
$urlGenerator,
253+
$caIdentifierService,
254+
$crlMapper,
255+
$logger,
256+
$crlRevocationChecker,
257+
$this->processManager,
258+
];
208259
}
209260
}

0 commit comments

Comments
 (0)