Skip to content

Commit 334ce6f

Browse files
authored
Merge branch 'master' into feature/acceptance-transcript
2 parents 7a6f87b + 2a93274 commit 334ce6f

19 files changed

Lines changed: 196 additions & 226 deletions

.github/workflows/run-test-suite.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
timeout-minutes: ${{ inputs.test-timeout }}
5151
env:
5252
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53+
TEMPORAL_HEADLESS: true
5354
strategy:
5455
fail-fast: ${{ inputs.fail-fast }}
5556
matrix:

phpunit.xml.dist

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,49 +23,47 @@
2323
<testsuite name="Acceptance-Fast">
2424
<directory suffix="Test.php">tests/Acceptance/Extra</directory>
2525
<directory suffix="Test.php">tests/Acceptance/Harness</directory>
26-
<exclude>tests/Acceptance/Harness/Update/SelfTest.php</exclude>
2726
<exclude>tests/Acceptance/Harness/Query/TimeoutDueToNoActiveWorkersTest.php</exclude>
28-
<exclude>tests/Acceptance/Extra/Activity/ActivityPausedTest.php</exclude>
29-
<exclude>tests/Acceptance/Extra/Versioning/DeploymentTest.php</exclude>
3027
<exclude>tests/Acceptance/Harness/EagerWorkflow/SuccessfulStartTest.php</exclude>
31-
<exclude>tests/Acceptance/Harness/Activity/CancelTryCancelTest.php</exclude>
3228
<exclude>tests/Acceptance/Extra/Stability/ResetWorkerTest.php</exclude>
33-
<exclude>tests/Acceptance/Harness/Activity/RetryOnErrorTest.php</exclude>
3429
<exclude>tests/Acceptance/Harness/Update/WorkerRestartTest.php</exclude>
30+
<exclude>tests/Acceptance/Harness/Activity/CancelTryCancelTest.php</exclude>
31+
<exclude>tests/Acceptance/Harness/Activity/RetryOnErrorTest.php</exclude>
32+
<exclude>tests/Acceptance/Extra/Versioning/DeploymentTest.php</exclude>
3533
<exclude>tests/Acceptance/Harness/Schedule/BasicTest.php</exclude>
3634
<exclude>tests/Acceptance/Harness/Update/AsyncAcceptTest.php</exclude>
37-
<exclude>tests/Acceptance/Extra/Workflow/BuiltInPrefixedHandlersTest.php</exclude>
3835
<exclude>tests/Acceptance/Harness/Schedule/TriggerTest.php</exclude>
3936
<exclude>tests/Acceptance/Extra/Workflow/InitMethodTest.php</exclude>
4037
<exclude>tests/Acceptance/Harness/Signal/PreventCloseTest.php</exclude>
4138
<exclude>tests/Acceptance/Extra/Update/UntypedStubTest.php</exclude>
4239
<exclude>tests/Acceptance/Extra/Update/TimeoutTest.php</exclude>
43-
<exclude>tests/Acceptance/Extra/Workflow/DateTimeZoneWorkflowTest.php</exclude>
4440
<exclude>tests/Acceptance/Extra/Schedule/ScheduleUpdateTest.php</exclude>
4541
<exclude>tests/Acceptance/Harness/ChildWorkflow/CancelAbandonTest.php</exclude>
42+
<exclude>tests/Acceptance/Extra/Workflow/DateTimeZoneWorkflowTest.php</exclude>
43+
<exclude>tests/Acceptance/Extra/Workflow/SideEffectTest.php</exclude>
44+
<exclude>tests/Acceptance/Extra/Workflow/WorkflowInfoTest.php</exclude>
4645
<exclude>tests/Acceptance/Harness/ContinueAsNew/ContinueAsSameTest.php</exclude>
4746
</testsuite>
4847
<testsuite name="Acceptance-Slow">
49-
<file>tests/Acceptance/Harness/Update/SelfTest.php</file>
5048
<file>tests/Acceptance/Harness/Query/TimeoutDueToNoActiveWorkersTest.php</file>
51-
<file>tests/Acceptance/Extra/Activity/ActivityPausedTest.php</file>
52-
<file>tests/Acceptance/Extra/Versioning/DeploymentTest.php</file>
5349
<file>tests/Acceptance/Harness/EagerWorkflow/SuccessfulStartTest.php</file>
54-
<file>tests/Acceptance/Harness/Activity/CancelTryCancelTest.php</file>
5550
<file>tests/Acceptance/Extra/Stability/ResetWorkerTest.php</file>
56-
<file>tests/Acceptance/Harness/Activity/RetryOnErrorTest.php</file>
5751
<file>tests/Acceptance/Harness/Update/WorkerRestartTest.php</file>
52+
<file>tests/Acceptance/Harness/Activity/CancelTryCancelTest.php</file>
53+
<file>tests/Acceptance/Harness/Activity/RetryOnErrorTest.php</file>
54+
<file>tests/Acceptance/Extra/Versioning/DeploymentTest.php</file>
5855
<file>tests/Acceptance/Harness/Schedule/BasicTest.php</file>
5956
<file>tests/Acceptance/Harness/Update/AsyncAcceptTest.php</file>
60-
<file>tests/Acceptance/Extra/Workflow/BuiltInPrefixedHandlersTest.php</file>
6157
<file>tests/Acceptance/Harness/Schedule/TriggerTest.php</file>
6258
<file>tests/Acceptance/Extra/Workflow/InitMethodTest.php</file>
6359
<file>tests/Acceptance/Harness/Signal/PreventCloseTest.php</file>
6460
<file>tests/Acceptance/Extra/Update/UntypedStubTest.php</file>
6561
<file>tests/Acceptance/Extra/Update/TimeoutTest.php</file>
66-
<file>tests/Acceptance/Extra/Workflow/DateTimeZoneWorkflowTest.php</file>
6762
<file>tests/Acceptance/Extra/Schedule/ScheduleUpdateTest.php</file>
6863
<file>tests/Acceptance/Harness/ChildWorkflow/CancelAbandonTest.php</file>
64+
<file>tests/Acceptance/Extra/Workflow/DateTimeZoneWorkflowTest.php</file>
65+
<file>tests/Acceptance/Extra/Workflow/SideEffectTest.php</file>
66+
<file>tests/Acceptance/Extra/Workflow/WorkflowInfoTest.php</file>
6967
<file>tests/Acceptance/Harness/ContinueAsNew/ContinueAsSameTest.php</file>
7068
</testsuite>
7169
<testsuite name="Acceptance">

psalm-baseline.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,14 @@
14071407
</PossiblyUndefinedStringArrayOffset>
14081408
</file>
14091409
<file src="testing/src/Environment.php">
1410+
<DeprecatedClass>
1411+
<code><![CDATA[new Downloader(new Filesystem(), HttpClient::create([
1412+
'headers' => [
1413+
'authorization' => \is_string($token) ? 'token ' . $token : null,
1414+
],
1415+
]))]]></code>
1416+
<code><![CDATA[private]]></code>
1417+
</DeprecatedClass>
14101418
<PossiblyNullReference>
14111419
<code><![CDATA[stop]]></code>
14121420
<code><![CDATA[stop]]></code>

testing/README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ Also, you can configure java sdk version:
5858
```php
5959
$environment = new Environment(
6060
new ConsoleOutput(),
61-
new Downloader(
62-
new Filesystem(),
63-
HttpClient::create(),
64-
'v1.17.0', // use a specific release tag or `latest` to get the latest version
65-
),
6661
SystemInfo::detect(),
6762
);
6863
```

testing/src/Downloader.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
use Symfony\Component\Filesystem\Filesystem;
88
use Symfony\Contracts\HttpClient\HttpClientInterface;
99

10+
/**
11+
* @deprecated will be removed in the next major release.
12+
* Use dload to get the latest version of the Temporal server or any other ways.
13+
*/
1014
final class Downloader
1115
{
1216
public const TAG_LATEST = 'latest';

testing/src/Environment.php

Lines changed: 81 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,12 @@ public function __construct(
3636
$this->command = $command ?? Command::fromEnv();
3737
}
3838

39-
public static function create(?Command $command = null): self
39+
public static function create(?Command $command = null, ?SystemInfo $systemInfo = null): self
4040
{
4141
$token = \getenv('GITHUB_TOKEN');
4242
$allowExternalTemporalProcess = \getenv('ALLOW_EXTERNAL_TEMPORAL_PROCESS') === 'true';
4343

44-
$systemInfo = SystemInfo::detect();
45-
$roadRunnerBinary = \getenv('ROADRUNNER_BINARY');
46-
if (\is_string($roadRunnerBinary)) {
47-
$systemInfo->rrExecutable = $roadRunnerBinary;
48-
}
44+
$systemInfo ??= SystemInfo::detect();
4945

5046
return new self(
5147
new TestOutputStyle(new ArgvInput(), new ConsoleOutput()),
@@ -60,15 +56,6 @@ public static function create(?Command $command = null): self
6056
);
6157
}
6258

63-
/**
64-
* @param array<string, mixed> $envs
65-
*/
66-
public function start(?array $rrCommand = null, int $commandTimeout = 10, array $envs = [], string $roadRunnerConfigFile = '.rr.yaml'): void
67-
{
68-
$this->startTemporalTestServer($commandTimeout);
69-
$this->startRoadRunner($rrCommand, $commandTimeout, $envs, $roadRunnerConfigFile);
70-
}
71-
7259
/**
7360
* @param list<non-empty-string> $parameters
7461
* @param array<non-empty-string, ValueType|non-empty-string> $searchAttributes Key is the name of the search
@@ -87,7 +74,6 @@ public function startTemporalServer(
8774
$temporalHost = \parse_url($temporalServerAddress, PHP_URL_HOST);
8875
$temporalPort = \parse_url($temporalServerAddress, PHP_URL_PORT);
8976

90-
// Add search attributes
9177
foreach ($searchAttributes as $name => $type) {
9278
$type = \is_string($type) ? ValueType::tryFrom($type) : $type;
9379
if (!$type instanceof ValueType) {
@@ -112,104 +98,75 @@ public function startTemporalServer(
11298
};
11399
}
114100

115-
$this->io->info('Starting Temporal server... ');
116-
$this->temporalServerProcess = new Process(
117-
[
118-
$this->systemInfo->temporalCliExecutable,
119-
"server", "start-dev",
120-
"--port", $temporalPort,
121-
'--log-level', 'error',
122-
'--ip', $temporalHost,
123-
// '--headless',
124-
...$parameters,
125-
],
126-
);
127-
$this->temporalServerProcess->setTimeout($commandTimeout);
128-
$temporalStarted = false;
129-
$this->io->info('Running command: ' . $this->serializeProcess($this->temporalServerProcess));
130-
$this->temporalServerProcess->start();
131-
132-
$deadline = \microtime(true) + (float) $commandTimeout;
133-
while (!$temporalStarted && \microtime(true) < $deadline) {
134-
\usleep(10_000);
101+
$process = new Process([
102+
$this->systemInfo->temporalCliExecutable,
103+
"server", "start-dev",
104+
"--port", $temporalPort,
105+
'--log-level', 'error',
106+
'--ip', $temporalHost,
107+
...$parameters,
108+
]);
109+
$process->setTimeout($commandTimeout);
110+
$this->temporalServerProcess = $process;
111+
112+
$this->runProcess('Temporal', $process, $commandTimeout, function () use ($temporalServerAddress): bool {
135113
$check = new Process([
136114
$this->systemInfo->temporalCliExecutable,
137115
'operator',
138116
'cluster',
139117
'health',
140118
'--address', $temporalServerAddress,
141119
]);
120+
$check->setTimeout(1);
142121
$check->run();
143-
if (\str_contains($check->getOutput(), 'SERVING')) {
144-
$temporalStarted = true;
145-
}
146-
}
147122

148-
if (!$temporalStarted || !$this->temporalServerProcess->isRunning()) {
149-
$errorOutput = $this->temporalServerProcess->getErrorOutput();
123+
return \str_contains($check->getOutput(), 'SERVING');
124+
}, onFailure: function (Process $process): void {
125+
$errorOutput = $process->getErrorOutput();
126+
150127
if (!$this->allowExternalTemporalProcess || !\str_contains($errorOutput, 'address already in use')) {
151128
$this->io->error([
152-
\sprintf(
153-
'Error starting Temporal server: %s.',
154-
!$temporalStarted ? "Health check failed" : $errorOutput,
155-
),
156-
\sprintf(
157-
'Command: `%s`.',
158-
$this->serializeProcess($this->temporalServerProcess),
159-
),
129+
\sprintf('Error starting Temporal server: %s.', $errorOutput ?: "Health check failed"),
130+
\sprintf('Command: `%s`.', $this->serializeProcess($process)),
160131
]);
161132
exit(1);
162133
}
163134
$this->io->warning('Using external Temporal Server');
164-
165135
$this->externalTemporalProcessActive = true;
166-
}
167-
$this->io->info('Temporal server started.');
136+
});
168137
}
169138

170139
public function startTemporalTestServer(int $commandTimeout = 10): void
171140
{
172-
if (!$this->downloader->check($this->systemInfo->temporalServerExecutable)) {
173-
$this->io->info('Download Temporal test server... ');
174-
$this->downloader->download($this->systemInfo);
175-
$this->io->info('Temporal test server downloaded.');
176-
}
177-
178141
$temporalPort = \parse_url((string) $this->command->address, PHP_URL_PORT);
179142

180-
$this->io->info('Starting Temporal test server... ');
181-
$this->temporalTestServerProcess = new Process(
182-
[$this->systemInfo->temporalServerExecutable, $temporalPort, '--enable-time-skipping'],
183-
);
184-
$this->temporalTestServerProcess->setTimeout($commandTimeout);
185-
$this->temporalTestServerProcess->start();
143+
$process = new Process([$this->systemInfo->temporalServerExecutable, $temporalPort, '--enable-time-skipping']);
144+
$process->setTimeout($commandTimeout);
145+
$this->temporalTestServerProcess = $process;
146+
147+
$this->runProcess('Temporal Test', $process, $commandTimeout, static function (): bool {
148+
\sleep(1);
186149

187-
\sleep(1);
150+
return true;
151+
}, onFailure: function (Process $process): void {
152+
$errorOutput = $process->getErrorOutput();
188153

189-
if (!$this->temporalTestServerProcess->isRunning()) {
190-
$errorOutput = $this->temporalTestServerProcess->getErrorOutput();
191154
if (!$this->allowExternalTemporalProcess || !\str_contains($errorOutput, 'address already in use')) {
192155
$this->io->error([
193-
\sprintf(
194-
'Error starting Temporal Test server: %s.',
195-
$errorOutput,
196-
),
197-
\sprintf(
198-
'Command: `%s`.',
199-
$this->serializeProcess($this->temporalTestServerProcess),
200-
),
156+
\sprintf('Error starting Temporal Test server: %s.', $errorOutput),
157+
\sprintf('Command: `%s`.', $this->serializeProcess($process)),
201158
]);
202159
exit(1);
203160
}
204161
$this->io->warning('Using external Temporal Test Server');
205-
}
206-
$this->io->info('Temporal Test server started.');
162+
$this->externalTemporalProcessActive = true;
163+
});
207164
}
208165

209166
/**
210167
* @param array<string, mixed> $envs
211168
*/
212-
public function startRoadRunner(?array $rrCommand = null, int $commandTimeout = 10, array $envs = [], string $configFile = '.rr.yaml'): void
169+
public function startRoadRunner(array $rrCommand, int $commandTimeout = 10, array $envs = [], string $configFile = '.rr.yaml'): void
213170
{
214171
if (!$this->isTemporalRunning() && !$this->isTemporalTestRunning()) {
215172
$this->io->error([
@@ -218,43 +175,21 @@ public function startRoadRunner(?array $rrCommand = null, int $commandTimeout =
218175
exit(1);
219176
}
220177

221-
$this->roadRunnerProcess = new Process(
222-
command: $rrCommand ?? [$this->systemInfo->rrExecutable, 'serve'],
223-
env: $envs,
224-
);
225-
$this->roadRunnerProcess->setTimeout($commandTimeout);
178+
$process = new Process(command: $rrCommand, env: $envs, timeout: $commandTimeout);
179+
$this->roadRunnerProcess = $process;
226180

227-
$this->io->info('Starting RoadRunner... ');
228-
$roadRunnerStarted = false;
229-
$this->io->info('Running command: ' . $this->serializeProcess($this->roadRunnerProcess));
230-
$this->roadRunnerProcess->start();
181+
$this->runProcess('RoadRunner', $process, $commandTimeout, function () use ($process, $configFile) {
182+
$output = $process->getOutput();
183+
if (!\str_contains($output, 'RoadRunner server started')) {
184+
return false;
185+
}
231186

232-
// wait for roadrunner to start
233-
$deadline = \microtime(true) + (float) $commandTimeout;
234-
while (!$roadRunnerStarted && \microtime(true) < $deadline) {
235-
\usleep(10_000);
236187
$check = new Process([$this->systemInfo->rrExecutable, 'workers', '-c', $configFile]);
188+
$check->setTimeout(1);
237189
$check->run();
238-
if (\str_contains($check->getOutput(), 'Workers of')) {
239-
$roadRunnerStarted = true;
240-
}
241-
}
242190

243-
if (!$roadRunnerStarted) {
244-
$this->io->error(\sprintf(
245-
'Failed to start until RoadRunner is ready. Status: "%s". Stderr: "%s". Stdout: "%s".',
246-
$this->roadRunnerProcess->getStatus(),
247-
$this->roadRunnerProcess->getErrorOutput(),
248-
$this->roadRunnerProcess->getOutput(),
249-
));
250-
$this->io->writeln(\sprintf(
251-
"Command: `%s`.",
252-
$this->serializeProcess($this->roadRunnerProcess),
253-
));
254-
exit(1);
255-
}
256-
257-
$this->io->info('RoadRunner server started.');
191+
return \str_contains($check->getOutput(), 'Workers of');
192+
});
258193
}
259194

260195
public function stop(): void
@@ -333,6 +268,41 @@ public function isTemporalTestRunning(): bool
333268
$this->temporalTestServerProcess?->isRunning() === true;
334269
}
335270

271+
private function runProcess(string $name, Process $process, int $commandTimeout, callable $readiness, ?callable $onFailure = null): void
272+
{
273+
$this->io->info(\sprintf("Starting %s server...", $name));
274+
$this->io->info('Running command: ' . $this->serializeProcess($process));
275+
$process->start();
276+
277+
$deadline = \microtime(true) + (float) $commandTimeout;
278+
279+
while ($process->isRunning() && \microtime(true) < $deadline) {
280+
if ($readiness()) {
281+
break;
282+
}
283+
\usleep(10_000);
284+
}
285+
286+
if (!$process->isRunning()) {
287+
($onFailure ?? function (Process $process) use ($name): void {
288+
$this->io->error(\sprintf(
289+
'Failed to start until %s is ready. Status: "%s". Stderr: "%s". Stdout: "%s".',
290+
$name,
291+
$process->getStatus(),
292+
$process->getErrorOutput(),
293+
$process->getOutput(),
294+
));
295+
$this->io->writeln(\sprintf(
296+
"Command: `%s`.",
297+
$this->serializeProcess($process),
298+
));
299+
exit(1);
300+
})($process);
301+
}
302+
303+
$this->io->info(\sprintf("%s server started.", $name));
304+
}
305+
336306
private function stopTemporalTestServerProcess(): void
337307
{
338308
if ($this->externalTemporalProcessActive) {

0 commit comments

Comments
 (0)