mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
import expect
This commit is contained in:
parent
f08e8772a7
commit
3892eba2bf
37 changed files with 526 additions and 39 deletions
12
Zend/tests/assert/expect_001.phpt
Normal file
12
Zend/tests/assert/expect_001.phpt
Normal file
|
@ -0,0 +1,12 @@
|
|||
--TEST--
|
||||
test passing assertion
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
assert(true);
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
16
Zend/tests/assert/expect_002.phpt
Normal file
16
Zend/tests/assert/expect_002.phpt
Normal file
|
@ -0,0 +1,16 @@
|
|||
--TEST--
|
||||
test failing assertion
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
assert(false);
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'AssertionException' with message 'assert(false)' in %sexpect_002.php:%d
|
||||
Stack trace:
|
||||
#0 %sexpect_002.php(%d): assert(false, 'assert(false)')
|
||||
#1 {main}
|
||||
thrown in %sexpect_002.php on line %d
|
15
Zend/tests/assert/expect_003.phpt
Normal file
15
Zend/tests/assert/expect_003.phpt
Normal file
|
@ -0,0 +1,15 @@
|
|||
--TEST--
|
||||
test catching failed assertion
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
try {
|
||||
assert(false);
|
||||
} catch (AssertionException $ex) {
|
||||
var_dump($ex->getMessage());
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
string(13) "assert(false)"
|
15
Zend/tests/assert/expect_004.phpt
Normal file
15
Zend/tests/assert/expect_004.phpt
Normal file
|
@ -0,0 +1,15 @@
|
|||
--TEST--
|
||||
test providing reason (fail)
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
try {
|
||||
assert(false, "I require this to succeed");
|
||||
} catch (AssertionException $ex) {
|
||||
var_dump($ex->getMessage());
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
string(25) "I require this to succeed"
|
17
Zend/tests/assert/expect_005.phpt
Normal file
17
Zend/tests/assert/expect_005.phpt
Normal file
|
@ -0,0 +1,17 @@
|
|||
--TEST--
|
||||
test providing reason (pass)
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
try {
|
||||
/* by passing we test there are no leaks upon success */
|
||||
assert(true, "I require this to succeed");
|
||||
} catch (AssertionException $ex) {
|
||||
var_dump($ex->getMessage());
|
||||
}
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
14
Zend/tests/assert/expect_006.phpt
Normal file
14
Zend/tests/assert/expect_006.phpt
Normal file
|
@ -0,0 +1,14 @@
|
|||
--TEST--
|
||||
test looping assert (pass)
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
for($i=0; $i<100000; $i++) {
|
||||
assert ($i < 100000, "The universe should make sense");
|
||||
}
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
22
Zend/tests/assert/expect_007.phpt
Normal file
22
Zend/tests/assert/expect_007.phpt
Normal file
|
@ -0,0 +1,22 @@
|
|||
--TEST--
|
||||
test compiled reason
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
$next = 1;
|
||||
$data = array(
|
||||
"key" => "X-HTTP ",
|
||||
"value" => "testing"
|
||||
);
|
||||
|
||||
class HeaderMalfunctionException extends AssertionException {}
|
||||
|
||||
assert (preg_match("~^([a-zA-Z0-9-]+)$~", $data["key"]), new HeaderMalfunctionException("malformed key found at {$next} \"{$data["key"]}\""));
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'HeaderMalfunctionException' with message 'malformed key found at 1 "X-HTTP "' in %sexpect_007.php:10
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %sexpect_007.php on line 10
|
34
Zend/tests/assert/expect_008.phpt
Normal file
34
Zend/tests/assert/expect_008.phpt
Normal file
|
@ -0,0 +1,34 @@
|
|||
--TEST--
|
||||
test disabled expectations have no ill side effects
|
||||
--INI--
|
||||
zend.assertions=0
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
class One {
|
||||
public function __construct() {
|
||||
assert($this || 0);
|
||||
}
|
||||
}
|
||||
class Two extends One {}
|
||||
|
||||
class OdEar extends AssertionException {}
|
||||
|
||||
function blah(){ return 1; }
|
||||
|
||||
$variable = 1;
|
||||
assert(true, "constant message");
|
||||
assert(($variable && $variable) || php_sapi_name(), new OdEar("constant message"));
|
||||
assert(false);
|
||||
assert(blah(), blah());
|
||||
|
||||
new Two();
|
||||
new Two();
|
||||
new Two();
|
||||
|
||||
assert (blah() || blah() || blah(), blah() || blah() || blah() || blah());
|
||||
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
26
Zend/tests/assert/expect_009.phpt
Normal file
26
Zend/tests/assert/expect_009.phpt
Normal file
|
@ -0,0 +1,26 @@
|
|||
--TEST--
|
||||
test stack trace is correct from failed exception in extended class
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
class One {
|
||||
public function __construct() {
|
||||
|
||||
}
|
||||
}
|
||||
class Two extends One {
|
||||
public function __construct() {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
new Two();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'AssertionException' with message 'assert(false)' in %sexpect_009.php:%d
|
||||
Stack trace:
|
||||
#0 %sexpect_009.php(%d): assert(false, 'assert(false)')
|
||||
#1 %sexpect_009.php(%d): Two->__construct()
|
||||
#2 {main}
|
||||
thrown in %sexpect_009.php on line %d
|
23
Zend/tests/assert/expect_010.phpt
Normal file
23
Zend/tests/assert/expect_010.phpt
Normal file
|
@ -0,0 +1,23 @@
|
|||
--TEST--
|
||||
test stack trace is correct from failed exception in extended class (parent implementing constructor)
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
class One {
|
||||
public function __construct() {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
class Two extends One {}
|
||||
|
||||
new Two();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'AssertionException' with message 'assert(false)' in %sexpect_010.php:%d
|
||||
Stack trace:
|
||||
#0 %sexpect_010.php(%d): assert(false, 'assert(false)')
|
||||
#1 %sexpect_010.php(%d): One->__construct()
|
||||
#2 {main}
|
||||
thrown in %sexpect_010.php on line %d
|
30
Zend/tests/assert/expect_011.phpt
Normal file
30
Zend/tests/assert/expect_011.phpt
Normal file
|
@ -0,0 +1,30 @@
|
|||
--TEST--
|
||||
test overloaded __toString on custom exception
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
class MyExpectations extends AssertionException {
|
||||
public function __toString() {
|
||||
return sprintf(
|
||||
"[Message]: %s", __CLASS__);
|
||||
}
|
||||
}
|
||||
|
||||
class One {
|
||||
public function __construct() {
|
||||
assert(false, (string) new MyExpectations());
|
||||
}
|
||||
}
|
||||
class Two extends One {}
|
||||
|
||||
new Two();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'AssertionException' with message '[Message]: MyExpectations' in %sexpect_011.php:%d
|
||||
Stack trace:
|
||||
#0 %sexpect_011.php(%d): assert(false, '[Message]: MyEx...')
|
||||
#1 %sexpect_011.php(%d): One->__construct()
|
||||
#2 {main}
|
||||
thrown in %sexpect_011.php on line %d
|
21
Zend/tests/assert/expect_012.phpt
Normal file
21
Zend/tests/assert/expect_012.phpt
Normal file
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
test enable/disable assertions at runtime
|
||||
--INI--
|
||||
zend.assertions=1
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump((integer)ini_get("zend.assertions"));
|
||||
ini_set("zend.assertions", 0);
|
||||
var_dump((integer)ini_get("zend.assertions"));
|
||||
assert(false);
|
||||
ini_set("zend.assertions", 1);
|
||||
var_dump((integer)ini_get("zend.assertions"));
|
||||
assert(true);
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(0)
|
||||
int(1)
|
||||
bool(true)
|
11
Zend/tests/assert/expect_013.phpt
Normal file
11
Zend/tests/assert/expect_013.phpt
Normal file
|
@ -0,0 +1,11 @@
|
|||
--TEST--
|
||||
test failing assertion when disabled (with return value)
|
||||
--INI--
|
||||
zend.assertions=0
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(assert(false));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
12
Zend/tests/assert/expect_014.phpt
Normal file
12
Zend/tests/assert/expect_014.phpt
Normal file
|
@ -0,0 +1,12 @@
|
|||
--TEST--
|
||||
test failing assertion when disabled
|
||||
--INI--
|
||||
zend.assertions=0
|
||||
assert.exception=1
|
||||
--FILE--
|
||||
<?php
|
||||
assert(false);
|
||||
var_dump(true);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
|
@ -101,6 +101,7 @@ static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */
|
|||
|
||||
ZEND_INI_BEGIN()
|
||||
ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
|
||||
STD_ZEND_INI_BOOLEAN("zend.assertions", "1", ZEND_INI_SYSTEM, OnUpdateBool, assertions, zend_executor_globals, executor_globals)
|
||||
STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)
|
||||
STD_ZEND_INI_BOOLEAN("zend.multibyte", "0", ZEND_INI_PERDIR, OnUpdateBool, multibyte, zend_compiler_globals, compiler_globals)
|
||||
ZEND_INI_ENTRY("zend.script_encoding", NULL, ZEND_INI_ALL, OnUpdateScriptEncoding)
|
||||
|
|
|
@ -1969,6 +1969,22 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
|
|||
}
|
||||
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant));
|
||||
|
||||
if (Z_STRLEN(function_name->u.constant) == sizeof("assert")-1 &&
|
||||
memcmp(lcname, "assert", sizeof("assert")-1) == 0) {
|
||||
|
||||
int op_number = get_next_op_number(CG(active_op_array));
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
opline->opcode = ZEND_ASSERT_CHECK;
|
||||
opline->extended_value = 0;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op2.ptr = (void*)LANG_SCNG(yy_text);
|
||||
|
||||
function_name->EA = op_number;
|
||||
}
|
||||
|
||||
if ((zend_hash_find(CG(function_table), lcname, Z_STRLEN(function_name->u.constant)+1, (void **) &function)==FAILURE) ||
|
||||
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
|
||||
(function->type == ZEND_INTERNAL_FUNCTION))) {
|
||||
|
@ -2538,19 +2554,85 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static inline void zend_copy_assertion_text(zval *target, const char *start_statement, const char *end_statement TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *str;
|
||||
const char *statement = start_statement;
|
||||
size_t statement_length = end_statement - start_statement;
|
||||
|
||||
while (statement && isspace(*statement)) {
|
||||
statement_length--;
|
||||
statement++;
|
||||
}
|
||||
|
||||
while (end_statement && isspace(*end_statement)) {
|
||||
statement_length--;
|
||||
end_statement--;
|
||||
}
|
||||
|
||||
str = emalloc(sizeof("assert") + statement_length + 1);
|
||||
memcpy(str, "assert", sizeof("assert") - 1);
|
||||
memcpy(str + sizeof("assert") - 1, statement, statement_length + 1);
|
||||
str[sizeof("assert") + statement_length] = 0;
|
||||
ZVAL_STRINGL(target, str, sizeof("assert") + statement_length, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
long arg_num = Z_LVAL(argument_list->u.constant);
|
||||
|
||||
if (is_method && function_name && function_name->op_type == IS_UNUSED) {
|
||||
/* clone */
|
||||
if (Z_LVAL(argument_list->u.constant) != 0) {
|
||||
if (arg_num != 0) {
|
||||
zend_error(E_WARNING, "Clone method does not require arguments");
|
||||
}
|
||||
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
|
||||
} else {
|
||||
zend_function **function_ptr_ptr;
|
||||
zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
|
||||
|
||||
if (!is_method &&
|
||||
function_name->op_type==IS_CONST &&
|
||||
Z_STRLEN(function_name->u.constant) == sizeof("assert")-1 &&
|
||||
memcmp(Z_STRVAL(function_name->u.constant), "assert", sizeof("assert")-1) == 0) {
|
||||
|
||||
int assert_op_number = function_name->EA;
|
||||
|
||||
if (arg_num == 1) {
|
||||
int last_op_number = get_next_op_number(CG(active_op_array));
|
||||
zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
|
||||
|
||||
if (last_op->opcode != ZEND_SEND_VAL ||
|
||||
last_op->op1_type != IS_CONST ||
|
||||
Z_TYPE(CONSTANT(last_op->op1.constant)) != IS_STRING) {
|
||||
|
||||
zval message;
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_SEND_VAL;
|
||||
|
||||
zend_copy_assertion_text(
|
||||
&message,
|
||||
(const char*)CG(active_op_array)->opcodes[assert_op_number].op2.ptr,
|
||||
(const char*)LANG_SCNG(yy_text) TSRMLS_CC);
|
||||
opline->op1_type = IS_CONST;
|
||||
opline->op1.constant = zend_add_literal(CG(active_op_array), &message TSRMLS_CC);
|
||||
CALCULATE_LITERAL_HASH(opline->op1.constant);
|
||||
opline->op2.opline_num = 2;
|
||||
opline->extended_value = !is_dynamic_fcall ? ZEND_DO_FCALL : ZEND_DO_FCALL_BY_NAME;
|
||||
SET_UNUSED(opline->op2);
|
||||
arg_num = 2;
|
||||
CG(context).used_stack++;
|
||||
}
|
||||
}
|
||||
|
||||
CG(active_op_array)->opcodes[assert_op_number].op1.opline_num =
|
||||
get_next_op_number(CG(active_op_array)) + 1;
|
||||
CG(active_op_array)->opcodes[assert_op_number].op2.ptr =
|
||||
NULL;
|
||||
}
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
if (*function_ptr_ptr) {
|
||||
|
@ -2580,12 +2662,12 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
|
|||
GET_NODE(result, opline->result);
|
||||
|
||||
zend_stack_del_top(&CG(function_call_stack));
|
||||
opline->extended_value = Z_LVAL(argument_list->u.constant);
|
||||
opline->extended_value = arg_num;
|
||||
|
||||
if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack + 1;
|
||||
}
|
||||
CG(context).used_stack -= Z_LVAL(argument_list->u.constant);
|
||||
CG(context).used_stack -= arg_num;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -1299,6 +1299,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
|
|||
}
|
||||
/* break omitted intentionally */
|
||||
case ZEND_JMP:
|
||||
case ZEND_ASSERT_CHECK:
|
||||
opline->op1.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.opline_num];
|
||||
break;
|
||||
case ZEND_JMPZ:
|
||||
|
|
|
@ -256,6 +256,7 @@ struct _zend_executor_globals {
|
|||
zend_property_info std_property_info;
|
||||
|
||||
zend_bool active;
|
||||
zend_bool assertions;
|
||||
|
||||
zend_op *start_op;
|
||||
|
||||
|
|
|
@ -699,6 +699,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
|||
}
|
||||
/* break omitted intentionally */
|
||||
case ZEND_JMP:
|
||||
case ZEND_ASSERT_CHECK:
|
||||
case ZEND_FAST_CALL:
|
||||
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
|
||||
break;
|
||||
|
|
|
@ -5659,4 +5659,24 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
|
|||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(166, ZEND_ASSERT_CHECK, ANY, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
if (!EG(assertions)) {
|
||||
if (RETURN_VALUE_USED((opline->op1.jmp_addr-1))) {
|
||||
zval *ret;
|
||||
|
||||
MAKE_STD_ZVAL(ret);
|
||||
Z_SET_REFCOUNT_P(ret, 0);
|
||||
ZVAL_BOOL(ret, 1);
|
||||
PZVAL_LOCK(ret);
|
||||
AI_SET_PTR(&EX_T((opline->op1.jmp_addr-1)->result.var), ret);
|
||||
}
|
||||
ZEND_VM_JMP(opline->op1.jmp_addr);
|
||||
} else {
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
|
||||
|
|
|
@ -1383,6 +1383,26 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|||
}
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
if (!EG(assertions)) {
|
||||
if (RETURN_VALUE_USED((opline->op1.jmp_addr-1))) {
|
||||
zval *ret;
|
||||
|
||||
MAKE_STD_ZVAL(ret);
|
||||
Z_SET_REFCOUNT_P(ret, 0);
|
||||
ZVAL_BOOL(ret, 1);
|
||||
PZVAL_LOCK(ret);
|
||||
AI_SET_PTR(&EX_T((opline->op1.jmp_addr-1)->result.var), ret);
|
||||
}
|
||||
ZEND_VM_JMP(opline->op1.jmp_addr);
|
||||
} else {
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
@ -45078,6 +45098,31 @@ void zend_init_opcodes_handlers(void)
|
|||
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
||||
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
||||
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_ASSERT_CHECK_SPEC_HANDLER,
|
||||
ZEND_NULL_HANDLER
|
||||
};
|
||||
zend_opcode_handlers = (opcode_handler_t*)labels;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <stdio.h>
|
||||
#include <zend.h>
|
||||
|
||||
const char *zend_vm_opcodes_map[166] = {
|
||||
const char *zend_vm_opcodes_map[167] = {
|
||||
"ZEND_NOP",
|
||||
"ZEND_ADD",
|
||||
"ZEND_SUB",
|
||||
|
@ -188,6 +188,7 @@ const char *zend_vm_opcodes_map[166] = {
|
|||
"ZEND_FAST_RET",
|
||||
"ZEND_RECV_VARIADIC",
|
||||
"ZEND_SEND_UNPACK",
|
||||
"ZEND_ASSERT_CHECK",
|
||||
};
|
||||
|
||||
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
|
||||
|
|
|
@ -171,5 +171,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
|
|||
#define ZEND_FAST_RET 163
|
||||
#define ZEND_RECV_VARIADIC 164
|
||||
#define ZEND_SEND_UNPACK 165
|
||||
#define ZEND_ASSERT_CHECK 166
|
||||
|
||||
#endif
|
||||
|
|
|
@ -118,6 +118,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
|
|||
}
|
||||
START_BLOCK_OP(opno + 1);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
START_BLOCK_OP(ZEND_OP1(opline).opline_num);
|
||||
START_BLOCK_OP(opno + 1);
|
||||
break;
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
START_BLOCK_OP(ZEND_OP1(opline).opline_num);
|
||||
|
@ -268,6 +274,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
|
|||
cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
|
||||
cur_block->follow_to = &blocks[opno];
|
||||
break;
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
|
||||
|
|
|
@ -57,6 +57,9 @@ static void nop_removal(zend_op_array *op_array)
|
|||
/* update JMPs */
|
||||
for (opline = op_array->opcodes; opline<end; opline++) {
|
||||
switch (opline->opcode) {
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
|
||||
case ZEND_GOTO:
|
||||
|
|
|
@ -485,6 +485,9 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
|
|||
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
|
||||
case ZEND_FAST_CALL:
|
||||
case ZEND_FAST_RET:
|
||||
#endif
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
case ZEND_JMPZNZ:
|
||||
|
|
|
@ -474,6 +474,9 @@ static void zend_accel_optimize(zend_op_array *op_array,
|
|||
}
|
||||
#endif
|
||||
switch (opline->opcode) {
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
|
||||
case ZEND_GOTO:
|
||||
|
@ -515,6 +518,9 @@ static void zend_accel_optimize(zend_op_array *op_array,
|
|||
}
|
||||
#endif
|
||||
switch (opline->opcode) {
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
|
||||
case ZEND_GOTO:
|
||||
|
|
|
@ -345,6 +345,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
|||
if (ZEND_DONE_PASS_TWO(op_array)) {
|
||||
/* fix jumps to point to new array */
|
||||
switch (opline->opcode) {
|
||||
#ifdef ZEND_ASSERT_CHECK
|
||||
case ZEND_ASSERT_CHECK:
|
||||
#endif
|
||||
case ZEND_JMP:
|
||||
case ZEND_GOTO:
|
||||
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
|
||||
|
|
|
@ -9,12 +9,14 @@ var_dump($standard->getClassNames());
|
|||
?>
|
||||
==DONE==
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
array(4) {
|
||||
[0]=>
|
||||
%s(22) "__PHP_Incomplete_Class"
|
||||
[1]=>
|
||||
%s(15) "php_user_filter"
|
||||
[2]=>
|
||||
%s(9) "Directory"
|
||||
[3]=>
|
||||
%s(18) "AssertionException"
|
||||
}
|
||||
==DONE==
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "php.h"
|
||||
#include "php_assert.h"
|
||||
#include "php_ini.h"
|
||||
#include "zend_exceptions.h"
|
||||
/* }}} */
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(assert)
|
||||
|
@ -29,12 +30,15 @@ ZEND_BEGIN_MODULE_GLOBALS(assert)
|
|||
long bail;
|
||||
long warning;
|
||||
long quiet_eval;
|
||||
long exception;
|
||||
zval *callback;
|
||||
char *cb;
|
||||
ZEND_END_MODULE_GLOBALS(assert)
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(assert)
|
||||
|
||||
static zend_class_entry *assertion_exception_ce;
|
||||
|
||||
#ifdef ZTS
|
||||
#define ASSERTG(v) TSRMG(assert_globals_id, zend_assert_globals *, v)
|
||||
#else
|
||||
|
@ -48,7 +52,8 @@ enum {
|
|||
ASSERT_CALLBACK,
|
||||
ASSERT_BAIL,
|
||||
ASSERT_WARNING,
|
||||
ASSERT_QUIET_EVAL
|
||||
ASSERT_QUIET_EVAL,
|
||||
ASSERT_EXCEPTION
|
||||
};
|
||||
|
||||
static PHP_INI_MH(OnChangeCallback) /* {{{ */
|
||||
|
@ -84,6 +89,7 @@ PHP_INI_BEGIN()
|
|||
STD_PHP_INI_ENTRY("assert.warning", "1", PHP_INI_ALL, OnUpdateLong, warning, zend_assert_globals, assert_globals)
|
||||
PHP_INI_ENTRY("assert.callback", NULL, PHP_INI_ALL, OnChangeCallback)
|
||||
STD_PHP_INI_ENTRY("assert.quiet_eval", "0", PHP_INI_ALL, OnUpdateLong, quiet_eval, zend_assert_globals, assert_globals)
|
||||
STD_PHP_INI_ENTRY("assert.exception", "0", PHP_INI_ALL, OnUpdateLong, exception, zend_assert_globals, assert_globals)
|
||||
PHP_INI_END()
|
||||
|
||||
static void php_assert_init_globals(zend_assert_globals *assert_globals_p TSRMLS_DC) /* {{{ */
|
||||
|
@ -95,6 +101,8 @@ static void php_assert_init_globals(zend_assert_globals *assert_globals_p TSRMLS
|
|||
|
||||
PHP_MINIT_FUNCTION(assert) /* {{{ */
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
ZEND_INIT_MODULE_GLOBALS(assert, php_assert_init_globals, NULL);
|
||||
|
||||
REGISTER_INI_ENTRIES();
|
||||
|
@ -104,6 +112,10 @@ PHP_MINIT_FUNCTION(assert) /* {{{ */
|
|||
REGISTER_LONG_CONSTANT("ASSERT_BAIL", ASSERT_BAIL, CONST_CS|CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("ASSERT_WARNING", ASSERT_WARNING, CONST_CS|CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("ASSERT_QUIET_EVAL", ASSERT_QUIET_EVAL, CONST_CS|CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("ASSERT_EXCEPTION", ASSERT_EXCEPTION, CONST_CS|CONST_PERSISTENT);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "AssertionException", NULL);
|
||||
assertion_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
@ -140,24 +152,25 @@ PHP_MINFO_FUNCTION(assert) /* {{{ */
|
|||
Checks if assertion is false */
|
||||
PHP_FUNCTION(assert)
|
||||
{
|
||||
zval **assertion;
|
||||
int val, description_len = 0;
|
||||
zval *assertion;
|
||||
zval *description = NULL;
|
||||
int val;
|
||||
char *myeval = NULL;
|
||||
char *compiled_string_description, *description = NULL;
|
||||
char *compiled_string_description;
|
||||
|
||||
if (! ASSERTG(active)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|s", &assertion, &description, &description_len) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &assertion, &description) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Z_TYPE_PP(assertion) == IS_STRING) {
|
||||
if (Z_TYPE_P(assertion) == IS_STRING) {
|
||||
zval retval;
|
||||
int old_error_reporting = 0; /* shut up gcc! */
|
||||
|
||||
myeval = Z_STRVAL_PP(assertion);
|
||||
myeval = Z_STRVAL_P(assertion);
|
||||
|
||||
if (ASSERTG(quiet_eval)) {
|
||||
old_error_reporting = EG(error_reporting);
|
||||
|
@ -165,12 +178,13 @@ PHP_FUNCTION(assert)
|
|||
}
|
||||
|
||||
compiled_string_description = zend_make_compiled_string_description("assert code" TSRMLS_CC);
|
||||
if (zend_eval_stringl(myeval, Z_STRLEN_PP(assertion), &retval, compiled_string_description TSRMLS_CC) == FAILURE) {
|
||||
if (zend_eval_stringl(myeval, Z_STRLEN_P(assertion), &retval, compiled_string_description TSRMLS_CC) == FAILURE) {
|
||||
efree(compiled_string_description);
|
||||
if (description_len == 0) {
|
||||
if (!description) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s", PHP_EOL, myeval);
|
||||
} else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s:\"%s\"", PHP_EOL, description, myeval);
|
||||
convert_to_string(description);
|
||||
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s:\"%s\"", PHP_EOL, Z_STRVAL_P(description), myeval);
|
||||
}
|
||||
if (ASSERTG(bail)) {
|
||||
zend_bailout();
|
||||
|
@ -186,8 +200,11 @@ PHP_FUNCTION(assert)
|
|||
convert_to_boolean(&retval);
|
||||
val = Z_LVAL(retval);
|
||||
} else {
|
||||
convert_to_boolean_ex(assertion);
|
||||
val = Z_LVAL_PP(assertion);
|
||||
#if PHP_VERSION_ID >= 50700
|
||||
val = zend_is_true(assertion TSRMLS_CC);
|
||||
#else
|
||||
val = zend_is_true(assertion);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (val) {
|
||||
|
@ -200,7 +217,7 @@ PHP_FUNCTION(assert)
|
|||
}
|
||||
|
||||
if (ASSERTG(callback)) {
|
||||
zval **args = safe_emalloc(description_len == 0 ? 3 : 4, sizeof(zval *), 0);
|
||||
zval **args = safe_emalloc(!description ? 3 : 4, sizeof(zval *), 0);
|
||||
zval *retval;
|
||||
int i;
|
||||
uint lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
|
@ -218,14 +235,15 @@ PHP_FUNCTION(assert)
|
|||
ZVAL_FALSE(retval);
|
||||
|
||||
/* XXX do we want to check for error here? */
|
||||
if (description_len == 0) {
|
||||
if (!description) {
|
||||
call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 3, args TSRMLS_CC);
|
||||
for (i = 0; i <= 2; i++) {
|
||||
zval_ptr_dtor(&(args[i]));
|
||||
}
|
||||
} else {
|
||||
MAKE_STD_ZVAL(args[3]);
|
||||
ZVAL_STRINGL(args[3], SAFE_STRING(description), description_len, 1);
|
||||
convert_to_string(description);
|
||||
Z_ADDREF_P(description);
|
||||
args[3] = description;
|
||||
|
||||
call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 4, args TSRMLS_CC);
|
||||
for (i = 0; i <= 3; i++) {
|
||||
|
@ -237,18 +255,30 @@ PHP_FUNCTION(assert)
|
|||
zval_ptr_dtor(&retval);
|
||||
}
|
||||
|
||||
if (ASSERTG(warning)) {
|
||||
if (description_len == 0) {
|
||||
if (ASSERTG(exception)) {
|
||||
if (!description) {
|
||||
zend_throw_exception(assertion_exception_ce, NULL, E_ERROR TSRMLS_CC);
|
||||
} else if (Z_TYPE_P(description) == IS_OBJECT &&
|
||||
instanceof_function(Z_OBJCE_P(description), assertion_exception_ce TSRMLS_CC)) {
|
||||
Z_ADDREF_P(description);
|
||||
zend_throw_exception_object(description TSRMLS_CC);
|
||||
} else {
|
||||
convert_to_string(description);
|
||||
zend_throw_exception(assertion_exception_ce, Z_STRVAL_P(description), E_ERROR TSRMLS_CC);
|
||||
}
|
||||
} else if (ASSERTG(warning)) {
|
||||
if (!description) {
|
||||
if (myeval) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion \"%s\" failed", myeval);
|
||||
} else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion failed");
|
||||
}
|
||||
} else {
|
||||
convert_to_string(description);
|
||||
if (myeval) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: \"%s\" failed", description, myeval);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: \"%s\" failed", Z_STRVAL_P(description), myeval);
|
||||
} else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s failed", description);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s failed", Z_STRVAL_P(description));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -327,6 +357,15 @@ PHP_FUNCTION(assert_options)
|
|||
return;
|
||||
break;
|
||||
|
||||
case ASSERT_EXCEPTION:
|
||||
oldint = ASSERTG(exception);
|
||||
if (ac == 2) {
|
||||
convert_to_string_ex(value);
|
||||
zend_alter_ini_entry_ex("assert.exception", sizeof("assert.exception"), Z_STRVAL_PP(value), Z_STRLEN_PP(value), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
|
||||
}
|
||||
RETURN_LONG(oldint);
|
||||
break;
|
||||
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value %ld", what);
|
||||
break;
|
||||
|
|
|
@ -42,7 +42,7 @@ Warning: assert_options() expects at most 2 parameters, 3 given in %s on line %d
|
|||
|
||||
Warning: assert_options() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d
|
||||
|
||||
Warning: assert(): Assertion failed in %s on line %d
|
||||
Warning: assert(): assert(0) failed in %s on line %d
|
||||
|
||||
Warning: assert(): Assertion failed in %s on line %d
|
||||
Warning: assert(): assert(0) failed in %s on line %d
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ assert(0);
|
|||
string(2) "f1"
|
||||
f1 called
|
||||
|
||||
Warning: assert(): Assertion failed in %s on line 13
|
||||
Warning: assert(): assert(0) failed in %s on line 13
|
||||
string(2) "f1"
|
||||
string(2) "f2"
|
||||
f2 called
|
||||
|
||||
Warning: assert(): Assertion failed in %s on line 17
|
||||
Warning: assert(): assert(0) failed in %s on line 17
|
||||
|
|
|
@ -22,4 +22,4 @@ echo "If this is printed BAIL hasn't worked";
|
|||
int(0)
|
||||
f1 called
|
||||
|
||||
Warning: assert(): Assertion "0 != 0" failed in %s on line 10
|
||||
Warning: assert(): assert($sa): "0 != 0" failed in %s on line 10
|
||||
|
|
|
@ -26,7 +26,7 @@ var_dump($rao=assert_options(ASSERT_WARNING, 0));
|
|||
int(0)
|
||||
f1 called
|
||||
|
||||
Warning: assert(): Assertion "0 != 0" failed in %s on line 10
|
||||
Warning: assert(): assert($sa): "0 != 0" failed in %s on line 10
|
||||
NULL
|
||||
bool(true)
|
||||
int(1)
|
||||
|
|
|
@ -13,4 +13,4 @@ assert(0);
|
|||
--EXPECTF--
|
||||
Hello World!
|
||||
|
||||
Warning: assert(): Assertion failed in %s on line %d
|
||||
Warning: assert(): assert(0) failed in %s on line %d
|
||||
|
|
|
@ -17,8 +17,7 @@ function f1($script, $line, $message, $user_message)
|
|||
|
||||
//bail out on error
|
||||
var_dump($rao = assert_options(ASSERT_BAIL, 1));
|
||||
$sa = "0 != 0";
|
||||
var_dump($r2 = assert($sa));
|
||||
var_dump($r2 = assert("0 != 0"));
|
||||
echo "If this is printed BAIL hasn't worked";
|
||||
--EXPECTF--
|
||||
int(0)
|
||||
|
@ -26,5 +25,5 @@ int(0)
|
|||
Warning: Missing argument 4 for f1() in %s on line 2
|
||||
f1 called
|
||||
|
||||
Warning: assert(): Assertion "0 != 0" failed in %s on line 10
|
||||
Warning: assert(): Assertion "0 != 0" failed in %s on line 9
|
||||
|
||||
|
|
|
@ -10,12 +10,11 @@ error_reporting = -1
|
|||
display_errors = 1
|
||||
--FILE--
|
||||
<?php
|
||||
$sa = "0 $ 0";
|
||||
var_dump($r2 = assert($sa));
|
||||
var_dump($r2 = assert("0 $ 0"));
|
||||
--EXPECTF--
|
||||
|
||||
Parse error: syntax error, unexpected '$' in %s(3) : assert code on line 1
|
||||
Parse error: syntax error, unexpected '$' in %s(2) : assert code on line 1
|
||||
|
||||
Catchable fatal error: assert(): Failure evaluating code:
|
||||
0 $ 0 in %s on line 3
|
||||
0 $ 0 in %s on line 2
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue