Skip to content

Commit 263b1be

Browse files
committed
Use a local website for testing instead of pecl.php.net
1 parent 8e40b65 commit 263b1be

File tree

28 files changed

+391
-12
lines changed

28 files changed

+391
-12
lines changed

.github/workflows/test.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323
- "7.4"
2424
- "8.0"
2525
runs-on: ${{ matrix.os }}
26+
env:
27+
PICKLE_PECL_TESTSERVER: yes
2628
steps:
2729
- name: Setup PHP
2830
uses: shivammathur/setup-php@v2
@@ -55,6 +57,25 @@ jobs:
5557
env:
5658
PICKLE_BEHAT_PROCESS_TIMEOUT: 0
5759
run: vendor/bin/behat --format=progress
60+
- name: Dump PECL dev server logs
61+
if: always() && startsWith(matrix.os, 'ubuntu')
62+
run: |
63+
rc=0
64+
echo '# 404 errors'
65+
if test -f tests/pecl-website/404.log; then
66+
cat tests/pecl-website/404.log
67+
rc=1
68+
else
69+
echo 'None.'
70+
fi
71+
echo '# 500 errors'
72+
if test -f tests/pecl-website/500.log; then
73+
cat tests/pecl-website/500.log
74+
rc=1
75+
else
76+
echo 'None.'
77+
fi
78+
exit $rc
5879
# We need a new release of Ocular that supports PHP 8 - see https://github.com/scrutinizer-ci/ocular/pull/52
5980
- name: Download Ocular
6081
if: always() && !startsWith(matrix.php-version, '8.')

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/tests/pecl-website/*.log
12
/vendor/
23
/*.phar
34
/.php_cs

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ or via [IRC, EFNet, channel `#pickle`](http://chat.efnet.org/).
158158
Running tests
159159
-------------
160160

161+
You should run the tests by setting the `PICKLE_PECL_TESTSERVER` environment variable to `yes` (or `true` or `1`).
162+
This implies that test are executed using a well-defined environment instead of using a live web server.
163+
164+
```sh
165+
# On Unix-like systems
166+
export PICKLE_PECL_TESTSERVER=yes
167+
# On Windows systems
168+
set PICKLE_PECL_TESTSERVER=yes
169+
```
170+
161171
Unit tests are written using [atoum](https://github.com/atoum/atoum).
162172
You will get atoum, among other dependencies, when running `composer install`.
163173
To run tests, you will need to run the following command:

features/bootstrap/FeatureContext.php

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
use Behat\Behat\Context\SnippetAcceptingContext;
3838
use Behat\Gherkin\Node\PyStringNode;
39+
use Pickle\Base\Pecl\Website;
40+
use Pickle\Base\Pecl\WebsiteFactory;
3941
use Symfony\Component\Process\PhpExecutableFinder;
4042
use Symfony\Component\Process\Process;
4143

@@ -58,15 +60,37 @@ class FeatureContext implements SnippetAcceptingContext
5860

5961
private $process;
6062

63+
/**
64+
* @var Process|null
65+
*/
66+
private static $webserverProcess = null;
67+
6168
public function __construct()
6269
{
6370
$this->assert = new \mageekguy\atoum\asserter\generator();
6471
}
6572

6673
/**
6774
* @BeforeSuite
75+
*/
76+
public static function beforeSuite(): void
77+
{
78+
self::stopTestWebserver();
79+
if (WebsiteFactory::isTestServer()) {
80+
self::startTestWebserver();
81+
}
82+
self::clean();
83+
}
84+
85+
/**
6886
* @AfterSuite
6987
*/
88+
public static function afterSuite(): void
89+
{
90+
self::stopTestWebserver();
91+
self::clean();
92+
}
93+
7094
public static function clean()
7195
{
7296
if (is_dir(PICKLE_TEST_PATH)) {
@@ -222,7 +246,7 @@ public function JsonfileShouldContain($path, PyStringNode $text)
222246
*/
223247
public function extensionExists($name, $version)
224248
{
225-
$url = 'https://pecl.php.net/get/' . $name . '/' . $version . '?uncompress=1';
249+
$url = WebsiteFactory::getWebsite()->getBaseUrl() . '/get/' . $name . '/' . $version . '?uncompress=1';
226250
$file = $name . '-' . $version . '.tgz';
227251
$dir = $this->workingDir . '/' . $name . '-' . $version;
228252

@@ -307,4 +331,40 @@ private static function clearDirectory($path)
307331

308332
rmdir($path);
309333
}
334+
335+
private static function startTestWebserver(): void
336+
{
337+
self::stopTestWebserver();
338+
$process = new Process(
339+
// $command
340+
[
341+
PHP_BINARY ?: 'php',
342+
'-n',
343+
'-dextension=phar',
344+
'-S', '127.0.0.1:' . Website::TEST_PORT,
345+
],
346+
// $cwd
347+
dirname(__DIR__, 2) . '/tests/pecl-website/web',
348+
// $env
349+
[],
350+
// $input
351+
null,
352+
// $timeout
353+
null
354+
);
355+
$process->start();
356+
usleep((int) (0.5 * 1E6));
357+
if (!$process->isRunning()) {
358+
throw new RuntimeException("Failed to start the test PECL website.\n" . implode("\n", array_filter([$process->getOutput(), $process->getErrorOutput()])));
359+
}
360+
self::$webserverProcess = $process;
361+
}
362+
363+
private static function stopTestWebserver(): void
364+
{
365+
if (self::$webserverProcess !== null) {
366+
self::$webserverProcess->stop(0);
367+
self::$webserverProcess = null;
368+
}
369+
}
310370
}

src/Base/Pecl/Website.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* Pickle
7+
*
8+
*
9+
* @license
10+
*
11+
* New BSD License
12+
*
13+
* Copyright © 2015-2015, Pickle community. All rights reserved.
14+
*
15+
* Redistribution and use in source and binary forms, with or without
16+
* modification, are permitted provided that the following conditions are met:
17+
* * Redistributions of source code must retain the above copyright
18+
* notice, this list of conditions and the following disclaimer.
19+
* * Redistributions in binary form must reproduce the above copyright
20+
* notice, this list of conditions and the following disclaimer in the
21+
* documentation and/or other materials provided with the distribution.
22+
* * Neither the name of the Hoa nor the names of its contributors may be
23+
* used to endorse or promote products derived from this software without
24+
* specific prior written permission.
25+
*
26+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
30+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36+
* POSSIBILITY OF SUCH DAMAGE.
37+
*/
38+
39+
namespace Pickle\Base\Pecl;
40+
41+
class Website
42+
{
43+
/**
44+
* The port to be used for the test web server.
45+
*
46+
* @var int
47+
*/
48+
public const TEST_PORT = 50123;
49+
50+
/**
51+
* The base URL of the PECL website to be used.
52+
*
53+
* @var string
54+
*
55+
* @example 'https://pecl.php.net'
56+
* @example 'https://127.0.0.1:50123'
57+
*/
58+
private $baseUrl;
59+
60+
/**
61+
* Should we allow unsafe connections to the PECL website?
62+
*
63+
* @var bool
64+
*/
65+
private $unsafe;
66+
67+
public function __construct(string $baseUrl, bool $unsafe)
68+
{
69+
$this->baseUrl = $baseUrl;
70+
$this->unsafe = $unsafe;
71+
}
72+
73+
/**
74+
* Get the base URL of the PECL website to be used.
75+
*
76+
* @example 'https://pecl.php.net'
77+
* @example 'https://127.0.0.1:50123'
78+
*/
79+
public function getBaseUrl(): string
80+
{
81+
return $this->baseUrl;
82+
}
83+
84+
/**
85+
* Should we allow unsafe connections to the PECL website?
86+
*/
87+
public function isUnsafe(): bool
88+
{
89+
return $this->unsafe;
90+
}
91+
}
92+
93+
/* vim: set tabstop=4 shiftwidth=4 expandtab: fdm=marker */

src/Base/Pecl/WebsiteFactory.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* Pickle
7+
*
8+
*
9+
* @license
10+
*
11+
* New BSD License
12+
*
13+
* Copyright © 2015-2015, Pickle community. All rights reserved.
14+
*
15+
* Redistribution and use in source and binary forms, with or without
16+
* modification, are permitted provided that the following conditions are met:
17+
* * Redistributions of source code must retain the above copyright
18+
* notice, this list of conditions and the following disclaimer.
19+
* * Redistributions in binary form must reproduce the above copyright
20+
* notice, this list of conditions and the following disclaimer in the
21+
* documentation and/or other materials provided with the distribution.
22+
* * Neither the name of the Hoa nor the names of its contributors may be
23+
* used to endorse or promote products derived from this software without
24+
* specific prior written permission.
25+
*
26+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
30+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36+
* POSSIBILITY OF SUCH DAMAGE.
37+
*/
38+
39+
namespace Pickle\Base\Pecl;
40+
41+
class WebsiteFactory
42+
{
43+
/**
44+
* @var Website|null
45+
*/
46+
private static $website = null;
47+
48+
/**
49+
* Get the PECL website configuration.
50+
*/
51+
public static function getWebsite(): Website
52+
{
53+
if (self::$website === null) {
54+
if (static::isTestServer()) {
55+
self::$website = new Website('http://127.0.0.1:' . Website::TEST_PORT . '/index.php', true);
56+
} else {
57+
$unsafe = static::allowUnsafeConnections();
58+
self::$website = new Website($unsafe ? 'http://pecl.php.net' : 'https://pecl.php.net', $unsafe);
59+
}
60+
}
61+
62+
return self::$website;
63+
}
64+
65+
public static function isTestServer(): bool
66+
{
67+
$v = strtolower(getenv('PICKLE_PECL_TESTSERVER') ?: '');
68+
69+
return in_array($v, ['1', 'true', 'yes'], true);
70+
}
71+
72+
protected static function allowUnsafeConnections(): bool
73+
{
74+
if (static::isTestServer()) {
75+
return true;
76+
}
77+
$v = strtolower(getenv('PICKLE_PECL_UNSAFE') ?: '');
78+
79+
return in_array($v, ['1', 'true', 'yes', 'y', 'ok'], true);
80+
}
81+
}
82+
83+
/* vim: set tabstop=4 shiftwidth=4 expandtab: fdm=marker */

src/Engine/PHP.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ private function getFromConstants()
268268
. 'echo PHP_ZTS . \"\n\"; '
269269
. 'echo PHP_DEBUG . \"\n\"; ';
270270

271-
$cmd = $this->phpCliEscaped . ' -r ' . '"' . str_replace("\n", '', $script) . '"';
271+
$cmd = $this->phpCliEscaped . ' -n -r ' . '"' . str_replace("\n", '', $script) . '"';
272272

273273
$info = null;
274274
exec($cmd, $info);

src/Package/Convey/Command/Git.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,7 @@ protected function fetch($target)
102102
],
103103
]);
104104
$downloader = new GitDownloader($this->io, $config);
105-
if ($downloader !== null) {
106-
$downloader->download($package, $target);
107-
}
105+
$downloader->download($package, $target);
108106
}
109107
}
110108

src/Package/PHP/Command/Install/Windows/Binary.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use DOMDocument;
4040
use Exception;
4141
use Pickle\Base\Archive;
42+
use Pickle\Base\Pecl\WebsiteFactory;
4243
use Pickle\Base\Util;
4344
use Pickle\Base\Util\FileOps;
4445
use Pickle\Engine;
@@ -116,7 +117,7 @@ public function getExtDllPaths()
116117

117118
private function extensionPeclExists()
118119
{
119-
$url = 'https://pecl.php.net/get/' . $this->extName;
120+
$url = WebsiteFactory::getWebsite()->getBaseUrl() . '/get/' . $this->extName;
120121
$headers = get_headers($url, 1);
121122
$status = $headers[0];
122123
if (strpos($status, '404')) {
@@ -311,7 +312,8 @@ private function updateIni()
311312
*/
312313
private function getInfoFromPecl()
313314
{
314-
$url = 'https://pecl.php.net/get/' . $this->extName;
315+
$baseUrl = WebsiteFactory::getWebsite()->getBaseUrl();
316+
$url = $baseUrl . '/get/' . $this->extName;
315317
$headers = get_headers($url);
316318

317319
if (strpos($headers[0], '404') !== false) {
@@ -329,13 +331,13 @@ private function getInfoFromPecl()
329331
}
330332
$m = null;
331333
if (!preg_match('|=(.*)\\.[a-z0-9]{2,3}$|', $headerPkg, $m)) {
332-
throw new Exception('Invalid response from pecl.php.net');
334+
throw new Exception("Invalid response from {$baseUrl}");
333335
}
334336
$packageFullname = $m[1];
335337

336338
[$name, $version] = explode('-', $packageFullname);
337339
if ($name == '' || $version == '') {
338-
throw new Exception('Invalid response from pecl.php.net');
340+
throw new Exception("Invalid response from {$baseUrl}");
339341
}
340342

341343
return [$name, $version];

0 commit comments

Comments
 (0)