Skip to content

Commit ac2c348

Browse files
committed
review: introduced ProbeFailureException
1 parent de9e4dd commit ac2c348

11 files changed

Lines changed: 174 additions & 152 deletions

File tree

ext/ldap/tests/skipifbindfailure.inc

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@ require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
55
if ($skip_on_bind_failure) {
66
$configuration = [$uri, $user, $passwd, $protocol_version];
77

8-
$reason = ProbeCache::getFailure('ldap.bind', $configuration, static function () use ($uri, $user, $passwd, $protocol_version): ?string {
9-
$link = ldap_connect($uri);
10-
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
11-
if (!@ldap_bind($link, $user, $passwd)) {
12-
return sprintf("Can't bind to LDAP Server - [%d] %s", ldap_errno($link), ldap_error($link));
13-
}
14-
15-
ldap_unbind($link);
16-
return null;
17-
});
8+
try {
9+
ProbeCache::getFailure('ldap.bind', $configuration, static function () use ($uri, $user, $passwd, $protocol_version): void {
10+
$link = ldap_connect($uri);
11+
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
12+
if (!@ldap_bind($link, $user, $passwd)) {
13+
throw new ProbeFailureException(sprintf("Can't bind to LDAP Server - [%d] %s", ldap_errno($link), ldap_error($link)));
14+
}
1815

19-
if (is_string($reason)) {
20-
die("skip $reason");
16+
ldap_unbind($link);
17+
});
18+
} catch (ProbeFailureException $e) {
19+
die("skip {$e->getMessage()}");
2120
}
2221
}
2322

ext/mysqli/tests/skipifconnectfailure.inc

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,16 @@ require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
44

55
$configuration = [$host, $port, $user, $passwd, $db, $socket, get_environment_connection_flags()];
66

7-
$reason = ProbeCache::getFailure('mysqli', $configuration, static function () use ($host, $user, $passwd, $db, $port, $socket): ?string {
8-
$link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
9-
if (!is_object($link)) {
10-
return sprintf("Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error());
11-
}
7+
try {
8+
ProbeCache::getFailure('mysqli', $configuration, static function () use ($host, $user, $passwd, $db, $port, $socket): void {
9+
$link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
10+
if (!is_object($link)) {
11+
throw new ProbeFailureException(sprintf("Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
12+
}
1213

13-
mysqli_close($link);
14-
return null;
15-
});
16-
17-
if (is_string($reason)) {
18-
die("skip $reason");
14+
mysqli_close($link);
15+
});
16+
} catch (ProbeFailureException $e) {
17+
die("skip {$e->getMessage()}");
1918
}
2019
?>

ext/mysqli/tests/test_setup/test_helpers.inc

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ function mysqli_check_skip_test(): void {
114114
}
115115

116116
function mysqli_connect_or_skip(): mysqli {
117-
$connection = null;
118117
$configuration = [
119118
get_default_host(),
120119
get_default_port(),
@@ -125,20 +124,20 @@ function mysqli_connect_or_skip(): mysqli {
125124
get_environment_connection_flags(),
126125
];
127126

128-
$reason = ProbeCache::getFailure('mysqli', $configuration, static function () use (&$connection): ?string {
129-
try {
130-
$connection = default_mysqli_connect();
131-
return null;
132-
} catch (mysqli_sql_exception $e) {
133-
return sprintf("Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error());
134-
}
135-
});
136-
137-
if (is_string($reason)) {
138-
die("skip $reason");
127+
try {
128+
return ProbeCache::getFailure('mysqli', $configuration, static function (): mysqli {
129+
try {
130+
return default_mysqli_connect();
131+
} catch (mysqli_sql_exception $e) {
132+
throw new ProbeFailureException(
133+
sprintf("Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error()),
134+
$e,
135+
);
136+
}
137+
});
138+
} catch (ProbeFailureException $e) {
139+
die("skip {$e->getMessage()}");
139140
}
140-
141-
return $connection;
142141
}
143142
function have_innodb(mysqli $link): bool {
144143
$res = $link->query("SELECT SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE = 'InnoDB'");

ext/odbc/tests/skipif.inc

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
include 'config.inc';
44
require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
55

6-
$conn = null;
7-
$reason = ProbeCache::getFailure('odbc', [$dsn, $user, $pass], static function () use ($dsn, $user, $pass, &$conn): ?string {
8-
$conn = @odbc_connect($dsn, $user, $pass);
9-
if (!$conn) {
10-
return 'could not connect';
11-
}
6+
try {
7+
$conn = ProbeCache::getFailure('odbc', [$dsn, $user, $pass], static function () use ($dsn, $user, $pass): Odbc\Connection {
8+
$conn = @odbc_connect($dsn, $user, $pass);
9+
if (!$conn) {
10+
throw new ProbeFailureException('could not connect');
11+
}
1212

13-
return null;
14-
});
15-
16-
if (is_string($reason)) {
17-
die("skip $reason");
13+
return $conn;
14+
});
15+
} catch (ProbeFailureException $e) {
16+
die("skip {$e->getMessage()}");
1817
}

ext/pdo/tests/pdo_test.inc

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,19 @@ class PDOTest {
3737
if ($user === false) $user = NULL;
3838
if ($pass === false) $pass = NULL;
3939

40-
if (getenv('TEST_PHP_EVALUATING_SKIPIF') !== '1') {
41-
return self::createConnection($classname, $useConnectMethod, $dsn, $user, $pass, $attributes);
42-
}
43-
44-
$database = null;
4540
$configuration = [$classname, $useConnectMethod, $dsn, $user, $pass, $attributes];
4641

47-
$reason = ProbeCache::getFailure('pdo', $configuration, static function () use (&$database, $classname, $useConnectMethod, $dsn, $user, $pass, $attributes): ?string {
48-
try {
49-
$database = self::createConnection($classname, $useConnectMethod, $dsn, $user, $pass, $attributes);
50-
return null;
51-
} catch (PDOException $e) {
52-
return $e->getMessage();
53-
}
54-
});
55-
56-
if (is_string($reason)) {
57-
throw new PDOException($reason);
42+
try {
43+
return ProbeCache::getFailure('pdo', $configuration, static function () use ($classname, $useConnectMethod, $dsn, $user, $pass, $attributes): PDO {
44+
try {
45+
return self::createConnection($classname, $useConnectMethod, $dsn, $user, $pass, $attributes);
46+
} catch (PDOException $e) {
47+
throw new ProbeFailureException($e);
48+
}
49+
});
50+
} catch (ProbeFailureException $e) {
51+
throw new PDOException($e->getMessage());
5852
}
59-
60-
return $database;
6153
}
6254

6355
static function skip() {

ext/pdo_dblib/tests/config.inc

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,28 +50,21 @@ function getDbConnection(string $class = PDO::class, ?array $attributes = null)
5050
}
5151
[$dsn, $user, $pass] = getCredentials();
5252

53-
$db = null;
54-
$probe = static function () use (&$db, $class, $dsn, $user, $pass, $attributes, $connectionAttributes): ?string {
55-
try {
56-
$db = new $class($dsn, $user, $pass, $connectionAttributes);
57-
if ($attributes === null) {
58-
setAttributes($db);
53+
try {
54+
return ProbeCache::getFailure('pdo', [$class, false, $dsn, $user, $pass, $connectionAttributes], static function () use ($class, $dsn, $user, $pass, $attributes, $connectionAttributes): PDO {
55+
try {
56+
$db = new $class($dsn, $user, $pass, $connectionAttributes);
57+
if ($attributes === null) {
58+
setAttributes($db);
59+
}
60+
return $db;
61+
} catch (PDOException $e) {
62+
throw new ProbeFailureException($e);
5963
}
60-
return null;
61-
} catch (PDOException $e) {
62-
return $e->getMessage();
63-
}
64-
};
65-
66-
$reason = $evaluatingSkipif
67-
? ProbeCache::getFailure('pdo', [$class, false, $dsn, $user, $pass, $connectionAttributes], $probe)
68-
: $probe();
69-
70-
if (is_string($reason)) {
71-
die('skip ' . $reason);
64+
});
65+
} catch (ProbeFailureException $e) {
66+
die('skip ' . $e->getMessage());
7267
}
73-
74-
return $db;
7568
}
7669

7770
function connectToDb() {

ext/pdo_mysql/tests/inc/mysql_pdo_test.inc

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,19 @@ class MySQLPDOTest extends PDOTest {
2020
$attr = is_string($attr) && strlen($attr) ? unserialize($attr) : null;
2121
}
2222

23-
if (getenv('TEST_PHP_EVALUATING_SKIPIF') !== '1') {
24-
return self::createConnection($classname, $useConnectMethod, $dsn, $user, $pass, $attr);
25-
}
26-
27-
$database = null;
2823
$configuration = [$classname, $useConnectMethod, $dsn, $user, $pass, $attr];
2924

30-
$reason = ProbeCache::getFailure('pdo', $configuration, static function () use (&$database, $classname, $useConnectMethod, $dsn, $user, $pass, $attr): ?string {
31-
try {
32-
$database = self::createConnection($classname, $useConnectMethod, $dsn, $user, $pass, $attr);
33-
return null;
34-
} catch (PDOException $e) {
35-
return $e->getMessage();
36-
}
37-
});
38-
39-
if (is_string($reason)) {
40-
throw new PDOException($reason);
25+
try {
26+
return ProbeCache::getFailure('pdo', $configuration, static function () use ($classname, $useConnectMethod, $dsn, $user, $pass, $attr): PDO {
27+
try {
28+
return self::createConnection($classname, $useConnectMethod, $dsn, $user, $pass, $attr);
29+
} catch (PDOException $e) {
30+
throw new ProbeFailureException($e);
31+
}
32+
});
33+
} catch (ProbeFailureException $e) {
34+
throw new PDOException($e->getMessage());
4135
}
42-
43-
return $database;
4436
}
4537

4638
static function factoryWithAttr($attr) {

ext/pgsql/tests/inc/skipif.inc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ if (getenv("SKIP_REPEAT")) {
1515
// We should probably change that, but in the meantime do not allow repetition.
1616
die("skip Cannot repeat pgsql tests");
1717
}
18-
$conn = null;
18+
try {
19+
$conn = ProbeCache::getFailure('pgsql', [$conn_str], static function () use ($conn_str): PgSql\Connection {
20+
$conn = @pg_connect($conn_str);
21+
if (!$conn) {
22+
throw new ProbeFailureException('could not connect');
23+
}
1924

20-
$reason = ProbeCache::getFailure('pgsql', [$conn_str], static function () use (&$conn, $conn_str): ?string {
21-
$conn = @pg_connect($conn_str);
22-
return $conn ? null : 'could not connect';
23-
});
24-
25-
if (is_string($reason)) {
26-
die("skip $reason\n");
25+
return $conn;
26+
});
27+
} catch (ProbeFailureException $e) {
28+
die("skip {$e->getMessage()}\n");
2729
}
2830

2931
function skip_server_version($version, $op = '<')

ext/snmp/tests/skipif.inc

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,17 @@
22
require_once (dirname(__FILE__).'/snmp_include.inc');
33
require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
44

5-
function get_snmp_test_agent_unavailable_reason(): ?string
6-
{
7-
global $hostname, $community, $timeout, $retries;
8-
9-
$probe = static fn(): ?string =>
10-
@snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries) === false
11-
? 'NO SNMPD on this host or community invalid'
12-
: null;
13-
14-
$configuration = [$hostname, $community, $timeout];
15-
16-
return ProbeCache::getFailure('snmp', $configuration, $probe);
17-
}
18-
195
//test server is available
206
// this require snmpget to work ...
217
//snmpget ( string $hostname , string $community ,
228
//string $object_id [, int $timeout [, int $retries ]] )
239

24-
$reason = get_snmp_test_agent_unavailable_reason();
25-
if (is_string($reason)) {
26-
die("skip $reason");
10+
try {
11+
ProbeCache::getFailure('snmp', [$hostname, $community, $timeout], static function () use ($hostname, $community, $timeout, $retries): void {
12+
if (@snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries) === false) {
13+
throw new ProbeFailureException('NO SNMPD on this host or community invalid');
14+
}
15+
});
16+
} catch (ProbeFailureException $e) {
17+
die("skip {$e->getMessage()}");
2718
}

tests/probe_cache.inc

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
11
<?php
22

3+
final class ProbeFailureException extends Exception
4+
{
5+
public function __construct(string|Throwable $failure, ?Throwable $previous = null)
6+
{
7+
if ($failure instanceof Throwable) {
8+
$previous = $failure;
9+
$failure = $failure->getMessage();
10+
}
11+
12+
parent::__construct($failure, 0, $previous);
13+
}
14+
}
15+
316
final class ProbeCache
417
{
518
private const FAILURE_PREFIX = 'failure:';
619

720
/**
8-
* Runs a probe once per configuration for the test run, caching only a
9-
* failure. The callback returns its skip reason, or null on success.
21+
* Runs a probe once per configuration during SKIPIF, caching only failures.
22+
* Outside SKIPIF, the cache is bypassed and wrapped exceptions are rethrown.
1023
*/
11-
public static function getFailure(string $namespace, array $configuration, callable $probe): ?string
24+
public static function getFailure(string $namespace, array $configuration, callable $probe): mixed
1225
{
26+
if (getenv('TEST_PHP_EVALUATING_SKIPIF') !== '1') {
27+
try {
28+
return $probe();
29+
} catch (ProbeFailureException $e) {
30+
throw $e->getPrevious() ?? $e;
31+
}
32+
}
33+
1334
$directory = getenv('TEST_PHP_SHARED_CACHE_DIR');
1435
if (!is_string($directory) || !is_dir($directory)) {
1536
return $probe();
@@ -32,18 +53,18 @@ final class ProbeCache
3253
try {
3354
$cached = stream_get_contents($cache);
3455
if (is_string($cached) && str_starts_with($cached, self::FAILURE_PREFIX)) {
35-
return substr($cached, strlen(self::FAILURE_PREFIX));
56+
throw new ProbeFailureException(substr($cached, strlen(self::FAILURE_PREFIX)));
3657
}
3758

38-
$failure = $probe();
39-
if (is_string($failure)) {
59+
try {
60+
return $probe();
61+
} catch (ProbeFailureException $e) {
4062
rewind($cache);
4163
ftruncate($cache, 0);
42-
fwrite($cache, self::FAILURE_PREFIX . $failure);
64+
fwrite($cache, self::FAILURE_PREFIX . $e->getMessage());
4365
fflush($cache);
66+
throw $e;
4467
}
45-
46-
return $failure;
4768
} finally {
4869
flock($cache, LOCK_UN);
4970
fclose($cache);

0 commit comments

Comments
 (0)