Skip to content

Commit 9269bc6

Browse files
committed
Try fix timeserver
1 parent 2906141 commit 9269bc6

File tree

3 files changed

+96
-61
lines changed

3 files changed

+96
-61
lines changed

composer.lock

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Exercise/TimeServer.php

+90-49
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1111
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1212
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
13-
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
1413
use PhpSchool\PhpWorkshop\Output\OutputInterface;
1514
use PhpSchool\PhpWorkshop\Result\ComparisonFailure;
1615
use PhpSchool\PhpWorkshop\Result\Failure;
@@ -31,71 +30,101 @@ public function getDescription(): string
3130

3231
public function defineListeners(EventDispatcher $eventDispatcher): void
3332
{
34-
$appendArgsListener = function (CliExecuteEvent $event) {
35-
$event->appendArg('127.0.0.1');
36-
$event->appendArg($this->getRandomPort());
37-
};
33+
$referencePort = $this->getRandomPort();
34+
$studentPort = $this->getRandomPort();
35+
36+
$eventDispatcher->listen(
37+
'cli.verify.reference-execute.pre',
38+
function (CliExecuteEvent $event) use ($referencePort) {
39+
$event->appendArg('0.0.0.0');
40+
$event->appendArg((string) $referencePort);
41+
$event->getScenario()->exposePort($referencePort);
42+
}
43+
);
44+
$eventDispatcher->listen(
45+
['cli.verify.student-execute.pre', 'cli.run.student-execute.pre'],
46+
function (CliExecuteEvent $event) use ($studentPort) {
47+
$event->appendArg('0.0.0.0');
48+
$event->appendArg((string) $studentPort);
49+
$event->getScenario()->exposePort($studentPort);
50+
}
51+
);
3852

39-
$eventDispatcher->listen('cli.verify.reference-execute.pre', $appendArgsListener);
40-
$eventDispatcher->listen('cli.verify.student-execute.pre', $appendArgsListener);
41-
$eventDispatcher->listen('cli.run.student-execute.pre', $appendArgsListener);
53+
$eventDispatcher->listen(
54+
'cli.verify.reference.executing',
55+
function (CliExecuteEvent $event) use ($referencePort) {
56+
//wait for server to boot
57+
sleep(1);
4258

43-
$eventDispatcher->listen('cli.verify.reference.executing', function (CliExecuteEvent $event) {
44-
$args = $event->getArgs()->getArrayCopy();
59+
$socket = $this->createSocket();
60+
@socket_connect($socket, '0.0.0.0', $referencePort);
61+
@socket_read($socket, 2048, PHP_NORMAL_READ);
4562

46-
//wait for server to boot
47-
usleep(100000);
63+
socket_close($socket);
4864

49-
$socket = $this->createSocket();
50-
socket_connect($socket, $args[0], (int) $args[1]);
51-
socket_read($socket, 2048, PHP_NORMAL_READ);
65+
//wait for shutdown
66+
usleep(100000);
67+
}
68+
);
5269

53-
//wait for shutdown
54-
usleep(100000);
55-
});
70+
$eventDispatcher->insertVerifier(
71+
'cli.verify.student.executing',
72+
function (CliExecuteEvent $event) use ($studentPort) {
73+
//wait for server to boot
74+
sleep(1);
5675

57-
$eventDispatcher->insertVerifier('cli.verify.student.executing', function (CliExecuteEvent $event) {
58-
$args = $event->getArgs()->getArrayCopy();
76+
$socket = $this->createSocket();
5977

60-
//wait for server to boot
61-
usleep(100000);
78+
$result = @socket_connect($socket, '0.0.0.0', $studentPort);
6279

63-
$socket = $this->createSocket();
64-
$connectResult = @socket_connect($socket, $args[0], (int) $args[1]);
65-
66-
if (!$connectResult) {
67-
return Failure::fromNameAndReason($this->getName(), sprintf(
68-
"Client returns an error (number %d): Connection refused while trying to join tcp://127.0.0.1:%d.",
69-
socket_last_error($socket),
70-
$args[1]
71-
));
72-
}
80+
if (!$result) {
81+
$error = "Client returns an error (number %d): Connection refused ";
82+
$error .= "while trying to join tcp://0.0.0.0:%d.";
7383

74-
$out = (string) socket_read($socket, 2048, PHP_NORMAL_READ);
84+
return Failure::fromNameAndReason($this->getName(), sprintf(
85+
$error,
86+
socket_last_error($socket),
87+
$studentPort
88+
));
89+
}
7590

76-
//wait for shutdown
77-
usleep(100000);
91+
$out = (string) socket_read($socket, 2048, PHP_NORMAL_READ);
92+
93+
socket_close($socket);
7894

79-
$date = new \DateTime();
95+
//wait for shutdown
96+
usleep(100000);
8097

81-
//match the current date but any seconds
82-
//since we can't mock time in PHP easily
83-
if (!preg_match(sprintf('/^%s:([0-5][0-9]|60)\n$/', $date->format('Y-m-d H:i')), $out)) {
84-
return ComparisonFailure::fromNameAndValues($this->getName(), $date->format("Y-m-d H:i:s\n"), $out);
98+
$date = new \DateTime();
99+
100+
//match the current date but any seconds
101+
//since we can't mock time in PHP easily
102+
if (!preg_match(sprintf('/^%s:([0-5][0-9]|60)\n$/', $date->format('Y-m-d H:i')), $out)) {
103+
return ComparisonFailure::fromNameAndValues($this->getName(), $date->format("Y-m-d H:i:s\n"), $out);
104+
}
105+
return new Success($this->getName());
85106
}
86-
return new Success($this->getName());
87-
});
107+
);
88108

89-
$eventDispatcher->listen('cli.run.student.executing', function (CliExecuteEvent $event) {
109+
$eventDispatcher->listen('cli.run.student.executing', function (CliExecuteEvent $event) use ($studentPort) {
90110
/** @var OutputInterface $output */
91111
$output = $event->getParameter('output');
92-
$args = $event->getArgs()->getArrayCopy();
93112

94113
//wait for server to boot
95-
usleep(100000);
114+
sleep(1);
96115

97116
$socket = $this->createSocket();
98-
socket_connect($socket, $args[0], (int) $args[1]);
117+
try {
118+
$connectResult = @socket_connect($socket, '0.0.0.0', $studentPort);
119+
} catch (\ErrorException $e) {
120+
$output->write('Cannot connect');
121+
return;
122+
}
123+
124+
if (false === $connectResult) {
125+
$output->write('Cannot connect');
126+
return;
127+
}
99128
$out = (string) socket_read($socket, 2048, PHP_NORMAL_READ);
100129

101130
//wait for shutdown
@@ -105,9 +134,18 @@ public function defineListeners(EventDispatcher $eventDispatcher): void
105134
});
106135
}
107136

108-
private function getRandomPort(): string
137+
private function getRandomPort(): int
109138
{
110-
return (string) mt_rand(1025, 65535);
139+
$sock = socket_create_listen(0);
140+
141+
if ($sock === false) {
142+
throw new RuntimeException('Cannot create socket');
143+
}
144+
145+
socket_getsockname($sock, $addr, $port);
146+
socket_close($sock);
147+
148+
return $port;
111149
}
112150

113151
public function getType(): ExerciseType
@@ -117,7 +155,8 @@ public function getType(): ExerciseType
117155

118156
public function defineTestScenario(): CliScenario
119157
{
120-
return (new CliScenario())->withExecution();
158+
return (new CliScenario())
159+
->withExecution();
121160
}
122161

123162
private function createSocket(): Socket
@@ -128,6 +167,8 @@ private function createSocket(): Socket
128167
throw new RuntimeException('Cannot create socket');
129168
}
130169

170+
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ["sec" => 5, "usec" => 0]);
171+
131172
return $socket;
132173
}
133174
}

test/Exercise/TimeServerTest.php

+2-8
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,8 @@ public function testFailureWhenCannotConnect(): void
4848

4949
$this->assertVerifyWasNotSuccessful();
5050

51-
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
52-
$reason = '/^Client returns an error \(number \d+\): No connection could be made because';
53-
$reason .= ' the target machine actively refused it\.\r\n';
54-
$reason .= ' while trying to join tcp:\/\/127\.0\.0\.1:\d+\.$/';
55-
} else {
56-
$reason = '/^Client returns an error \(number \d+\): Connection refused';
57-
$reason .= ' while trying to join tcp:\/\/127\.0\.0\.1:\d+\.$/';
58-
}
51+
$reason = '/^Client returns an error \(number \d+\): Connection refused';
52+
$reason .= ' while trying to join tcp:\/\/0\.0\.0\.0:\d+\.$/';
5953

6054
$this->assertResultsHasFailureAndMatches(Failure::class, function (Failure $failure) use ($reason) {
6155
$this->assertMatchesRegularExpression($reason, $failure->getReason());

0 commit comments

Comments
 (0)