Skip to content

Commit 5d58876

Browse files
authored
tests: Cache failed service probes (php#22944)
Prevents unavailable optional test services from slowing the suite through repeated connection timeouts. PDO and SNMP availability probes cache the first failure for the duration of one test run, so later SKIPIF checks return immediately. Only failures are cached; successful probes and test connections are unchanged. PDOs one second timeout applies only to the default availability probe. The caches are private, run-scoped and removed afterwards. A service becoming available mid run is detected on the next test-suite run.
1 parent a4be1f5 commit 5d58876

21 files changed

Lines changed: 590 additions & 92 deletions

ext/ldap/tests/skipifbindfailure.inc

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
<?php
22
require_once 'connect.inc';
3+
require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
34

45
if ($skip_on_bind_failure) {
6+
$configuration = [$uri, $user, $passwd, $protocol_version];
7+
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+
}
515

6-
$link = ldap_connect($uri);
7-
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
8-
if (!@ldap_bind($link, $user, $passwd))
9-
die(sprintf("skip Can't bind to LDAP Server - [%d] %s", ldap_errno($link), ldap_error($link)));
10-
11-
ldap_unbind($link);
16+
ldap_unbind($link);
17+
});
18+
} catch (ProbeFailureException $e) {
19+
die("skip {$e->getMessage()}");
20+
}
1221
}
1322

1423
if (isset($require_vendor)) {
Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
<?php
22
require_once 'connect.inc';
3-
$link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
4-
if (!is_object($link))
5-
die(sprintf("skip Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
6-
mysqli_close($link);
3+
require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
4+
5+
$configuration = [$host, $port, $user, $passwd, $db, $socket, get_environment_connection_flags()];
6+
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+
}
13+
14+
mysqli_close($link);
15+
});
16+
} catch (ProbeFailureException $e) {
17+
die("skip {$e->getMessage()}");
18+
}
719
?>

ext/mysqli/tests/test_setup/test_helpers.inc

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
require_once dirname(__DIR__, 4) . '/tests/probe_cache.inc';
4+
35
function get_default_host(): string {
46
static $host = null;
57
if ($host === null) {
@@ -110,11 +112,31 @@ function default_mysqli_connect(): \mysqli{
110112
function mysqli_check_skip_test(): void {
111113
mysqli_connect_or_skip();
112114
}
113-
function mysqli_connect_or_skip() {
115+
116+
function mysqli_connect_or_skip(): mysqli {
117+
$configuration = [
118+
get_default_host(),
119+
get_default_port(),
120+
get_default_user(),
121+
get_default_password(),
122+
get_default_database(),
123+
get_default_socket(),
124+
get_environment_connection_flags(),
125+
];
126+
114127
try {
115-
return default_mysqli_connect();
116-
} catch (\mysqli_sql_exception) {
117-
die(sprintf("skip Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
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()}");
118140
}
119141
}
120142
function have_innodb(mysqli $link): bool {
@@ -123,11 +145,7 @@ function have_innodb(mysqli $link): bool {
123145
return $supported === 'YES' || $supported === 'DEFAULT';
124146
}
125147
function mysqli_check_innodb_support_skip_test(): void {
126-
try {
127-
$link = default_mysqli_connect();
128-
} catch (\mysqli_sql_exception) {
129-
die(sprintf("skip Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
130-
}
148+
$link = mysqli_connect_or_skip();
131149
if (! have_innodb($link)) {
132150
die(sprintf("skip Needs InnoDB support"));
133151
}

ext/odbc/tests/skipif.inc

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
<?php
22

33
include 'config.inc';
4+
require_once dirname(__DIR__, 3) . '/tests/probe_cache.inc';
45

5-
$conn = @odbc_connect($dsn, $user, $pass);
6-
if (!$conn) {
7-
die('skip could not connect');
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+
}
12+
13+
return $conn;
14+
});
15+
} catch (ProbeFailureException $e) {
16+
die("skip {$e->getMessage()}");
817
}

ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_basic.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
7878
$db = PDOTest::factory();
7979
PDOTest::dropTableIfExists($db, "pdo_attr_statement_class_basic");
8080
?>
81-
--EXPECT--
81+
--EXPECTF--
8282
array(1) {
8383
[0]=>
8484
string(12) "PDOStatement"
@@ -89,15 +89,15 @@ StatementWithPublicDestructor::__destruct
8989
Class derived from PDOStatement, with private constructor:
9090
bool(true)
9191
StatementWithPrivateConstructor::__construct
92-
object(StatementWithPrivateConstructor)#2 (1) {
92+
object(StatementWithPrivateConstructor)#%d (1) {
9393
["queryString"]=>
9494
string(68) "SELECT id, label FROM pdo_attr_statement_class_basic ORDER BY id ASC"
9595
}
9696
string(6) "param1"
9797
Class derived from a child of PDOStatement:
9898
bool(true)
9999
StatementWithPrivateConstructor::__construct
100-
object(StatementDerivedFromChild)#2 (1) {
100+
object(StatementDerivedFromChild)#%d (1) {
101101
["queryString"]=>
102102
string(68) "SELECT id, label FROM pdo_attr_statement_class_basic ORDER BY id ASC"
103103
}

ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
4949
$db = PDOTest::factory();
5050
PDOTest::dropTableIfExists($db, "pdo_attr_statement_class_ctor_arg_gc");
5151
?>
52-
--EXPECT--
53-
object(Bar)#1 (1) {
52+
--EXPECTF--
53+
object(Bar)#%d (1) {
5454
["statementClass"]=>
5555
string(3) "Foo"
5656
}

ext/pdo/tests/attr_statement_class/pdo_ATTR_STATEMENT_CLASS_cyclic_ctor_args.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,18 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
4242
$db = PDOTest::factory();
4343
PDOTest::dropTableIfExists($db, "pdo_attr_statement_class_cyclic_ctor_args");
4444
?>
45-
--EXPECT--
45+
--EXPECTF--
4646
array(1) {
4747
[0]=>
4848
string(12) "PDOStatement"
4949
}
5050
bool(true)
51-
object(PDO)#1 (0) {
51+
object(PDO)#%d (0) {
5252
}
53-
object(HoldPdo)#2 (2) {
53+
object(HoldPdo)#%d (2) {
5454
["queryString"]=>
5555
string(79) "SELECT id, label FROM pdo_attr_statement_class_cyclic_ctor_args ORDER BY id ASC"
5656
["v"]=>
57-
object(PDO)#1 (0) {
57+
object(PDO)#%d (0) {
5858
}
5959
}

ext/pdo/tests/attr_statement_class/pdo_prepare_ATTR_STATEMENT_CLASS_ctor_arg_gc.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
5151
$db = PDOTest::factory();
5252
PDOTest::dropTableIfExists($db, "pdo_prepare_attr_statement_class_ctor_arg_gc");
5353
?>
54-
--EXPECT--
55-
object(Bar)#1 (1) {
54+
--EXPECTF--
55+
object(Bar)#%d (1) {
5656
["statementClass"]=>
5757
string(3) "Foo"
5858
}

ext/pdo/tests/pdo_027.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
3636
$db = PDOTest::factory();
3737
PDOTest::dropTableIfExists($db, "test027");
3838
?>
39-
--EXPECT--
40-
object(PDOStatement)#2 (1) {
39+
--EXPECTF--
40+
object(PDOStatement)#%d (1) {
4141
["queryString"]=>
4242
string(21) "SELECT * FROM test027"
4343
}
4444
bool(false)
45-
object(PDORow)#4 (3) {
45+
object(PDORow)#%d (3) {
4646
["queryString"]=>
4747
string(21) "SELECT * FROM test027"
4848
["id"]=>
@@ -52,7 +52,7 @@ object(PDORow)#4 (3) {
5252
}
5353
lazy: 1test1
5454
bool(true)
55-
object(PDORow)#4 (3) {
55+
object(PDORow)#%d (3) {
5656
["queryString"]=>
5757
string(21) "SELECT * FROM test027"
5858
["id"]=>

ext/pdo/tests/pdo_query_fetch_lazy001.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
2929
$db = PDOTest::factory();
3030
PDOTest::dropTableIfExists($db, "pdo_query_fetch_lazy_001");
3131
?>
32-
--EXPECT--
33-
object(PDOStatement)#2 (1) {
32+
--EXPECTF--
33+
object(PDOStatement)#%d (1) {
3434
["queryString"]=>
3535
string(38) "SELECT * FROM pdo_query_fetch_lazy_001"
3636
}

0 commit comments

Comments
 (0)