1
0
mirror of https://github.com/php/php-src.git synced 2026-03-26 09:12:14 +01:00
Files
archived-php-src/ext/standard/tests/assert/assert_variation.phpt
Nikita Popov 485d3acfe6 Make zend_call_function() failure handling consistent
This API had rather peculiar behavior in case the provided function
is not callable. For some types of failures, it would silently
return FAILURE (e.g. a function does not exist), while for others
(e.g. a class does not exist) it would generate a warning. Depending
on what the calling code does, this can either result in silent
failure or duplicate errors.

This commit switches the contract such that zend_call_function()
always (*) succeeds, though that success might be in the form of
throwing an exception. Calling a non-callable will now consistently
throw an exception.

There are some rare callers that do want to ignore missing methods,
for legacy APIs that are specific with optional methods. For these
use cases a new zend_call_method_if_exists() API is provided.

Calling code generally does not need to explicitly check for and
report zend_call_function() failures -- it can rely on
zend_call_function() having already done so. However, existing
code that does check for failure should continue to work fine.

(*) The only exception to this is if EG(active) being false during
late engine shutdown. This is not relevant to most code, but code
running in destructors and similar may need to be aware of the
possibility.
2021-09-01 16:09:23 +02:00

141 lines
3.7 KiB
PHP

--TEST--
assert() - variation - test callback options using ini_get/ini_set/assert_options
--INI--
assert.active = 1
assert.warning = 0
assert.callback = f1
assert.bail = 0
assert.exception=0
--FILE--
<?php
function f1()
{
echo "f1 called\n";
}
function f2()
{
echo "f2 called\n";
}
function f3()
{
echo "f3 called\n";
}
class c1
{
static function assert($file, $line, $unused, $desc)
{
echo "Class assertion failed $line, \"$desc\"\n";
}
}
echo "Initial values: assert_options(ASSERT_CALLBACK) => [".assert_options(ASSERT_CALLBACK)."]\n";
echo "Initial values: ini.get(\"assert.callback\") => [".ini_get("assert.callback")."]\n";
var_dump($r2=assert(0 != 0));
echo"\n";
echo "Change callback function using ini.set and test return value \n";
var_dump($rv = ini_set("assert.callback","f2"));
echo "assert_options(ASSERT_CALLBACK) => [".assert_options(ASSERT_CALLBACK)."]\n";
echo "ini.get(\"assert.callback\") => [".ini_get("assert.callback")."]\n";
var_dump($r2=assert(0 != 0));
echo"\n";
echo "Change callback function using assert_options and test return value \n";
var_dump($rv=assert_options(ASSERT_CALLBACK, "f3"));
echo "assert_options(ASSERT_CALLBACK) => [".assert_options(ASSERT_CALLBACK)."]\n";
echo "ini.get(\"assert.callback\") => [".ini_get("assert.callback")."]\n";
var_dump($r2=assert(0 != 0));
echo"\n";
echo "Reset the name of the callback routine to a class method\n";
var_dump($rc=assert_options(ASSERT_CALLBACK, "c1"));
echo "assert_options(ASSERT_CALLBACK) => [".assert_options(ASSERT_CALLBACK)."]\n";
echo "ini.get(\"assert.callback\") => [".ini_get("assert.callback")."]\n";
try {
var_dump($r2=assert(0 != 0));
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
echo"\n";
echo "Reset callback options to use a class method \n";
var_dump($rc = assert_options(ASSERT_CALLBACK,array("c1","assert")));
var_dump($rao=assert_options(ASSERT_CALLBACK));
echo "ini.get(\"assert.callback\") => [".ini_get("assert.callback")."]\n\n";
var_dump($r2=assert(0 != 0));
echo"\n";
echo "Reset callback options to use an object method \n";
$o = new c1();
var_dump($rc=assert_options(ASSERT_CALLBACK,array(&$o,"assert")));
var_dump($rao=assert_options(ASSERT_CALLBACK));
echo "ini.get(\"assert.callback\") => [".ini_get("assert.callback")."]\n\n";
var_dump($r2=assert(0 != 0));
echo"\n";
echo "Set callback to something silly\n";
assert_options(ASSERT_CALLBACK, 3.141);
var_dump($rao = assert_options(ASSERT_CALLBACK));
?>
--EXPECT--
Initial values: assert_options(ASSERT_CALLBACK) => [f1]
Initial values: ini.get("assert.callback") => [f1]
f1 called
bool(false)
Change callback function using ini.set and test return value
string(2) "f1"
assert_options(ASSERT_CALLBACK) => [f2]
ini.get("assert.callback") => [f2]
f2 called
bool(false)
Change callback function using assert_options and test return value
string(2) "f2"
assert_options(ASSERT_CALLBACK) => [f3]
ini.get("assert.callback") => [f2]
f3 called
bool(false)
Reset the name of the callback routine to a class method
string(2) "f3"
assert_options(ASSERT_CALLBACK) => [c1]
ini.get("assert.callback") => [f2]
Invalid callback c1, function "c1" not found or invalid function name
Reset callback options to use a class method
string(2) "c1"
array(2) {
[0]=>
string(2) "c1"
[1]=>
string(6) "assert"
}
ini.get("assert.callback") => [f2]
Class assertion failed 56, "assert(0 != 0)"
bool(false)
Reset callback options to use an object method
array(2) {
[0]=>
string(2) "c1"
[1]=>
string(6) "assert"
}
array(2) {
[0]=>
&object(c1)#2 (0) {
}
[1]=>
string(6) "assert"
}
ini.get("assert.callback") => [f2]
Class assertion failed 64, "assert(0 != 0)"
bool(false)
Set callback to something silly
float(3.141)