mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Zend: Add tests for offsets and containers (#12723)
Add various tests showcasing the behavioural variations of different offset types used on various container types in all possible operations: - Read - Write - Read Write - Appending - Unsetting - Existence checks with isset()/empty/null coalesce operator - Behaviour of nesting dimensions (e.g. $container[$offset1][$offset2]) Add a test to ensure compile time and runtime behaviour is identical for offsets. Add an internal class that overloads the dimension object handlers to zend_test
This commit is contained in:
committed by
GitHub
parent
8128d17cc2
commit
a479ed7cc5
132
Zend/tests/offsets/ArrayAccess_container_offset_behaviour.phpt
Normal file
132
Zend/tests/offsets/ArrayAccess_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,132 @@
|
||||
--TEST--
|
||||
ArrayAccess containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT = <<<OUTPUT
|
||||
Read before write:
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
int(5)
|
||||
Write:
|
||||
string(12) "CLASS_NAME::offsetSet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
int(5)
|
||||
Read:
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
int(5)
|
||||
Read-Write:
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(12) "CLASS_NAME::offsetSet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
int(25)
|
||||
isset():
|
||||
string(15) "CLASS_NAME::offsetExists"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
bool(true)
|
||||
empty():
|
||||
string(15) "CLASS_NAME::offsetExists"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
bool(false)
|
||||
null coalesce:
|
||||
string(15) "CLASS_NAME::offsetExists"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
int(5)
|
||||
unset():
|
||||
string(14) "CLASS_NAME::offsetUnset"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
Nested read:
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
|
||||
Warning: Trying to access array offset on int in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
|
||||
Notice: Indirect modification of overloaded element of CLASS_NAME has no effect in %s on line 69
|
||||
Cannot use a scalar value as an array
|
||||
Nested Read-Write:
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
|
||||
Notice: Indirect modification of overloaded element of CLASS_NAME has no effect in %s on line 76
|
||||
Cannot use a scalar value as an array
|
||||
Nested isset():
|
||||
string(15) "CLASS_NAME::offsetExists"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
bool(false)
|
||||
Nested empty():
|
||||
string(15) "CLASS_NAME::offsetExists"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(15) "CLASS_NAME::offsetExists"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
string(12) "CLASS_NAME::offsetGet"
|
||||
VAR_DUMP_OF_OFFSET
|
||||
|
||||
Notice: Indirect modification of overloaded element of CLASS_NAME has no effect in %s on line 102
|
||||
Cannot unset offset in a non-array variable
|
||||
|
||||
OUTPUT;
|
||||
|
||||
ob_start();
|
||||
foreach (['A', 'B'] as $class) {
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = new $class();
|
||||
$error = "(new $class())[" . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
ob_start();
|
||||
var_dump($dimension);
|
||||
$var_dump_output = ob_get_clean();
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
$expected_output = str_replace(
|
||||
["VAR_DUMP_OF_OFFSET\n", "CLASS_NAME"],
|
||||
[$var_dump_output, $class],
|
||||
EXPECTED_OUTPUT
|
||||
);
|
||||
|
||||
if ($varOutput !== $expected_output) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_ArrayAccess_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
314
Zend/tests/offsets/ArrayObject_container_offset_behaviour.phpt
Normal file
314
Zend/tests/offsets/ArrayObject_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,314 @@
|
||||
--TEST--
|
||||
ArrayObject containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT_VALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Undefined array key %s in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
Read:
|
||||
int(5)
|
||||
Read-Write:
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
int(25)
|
||||
unset():
|
||||
Nested read:
|
||||
|
||||
Warning: Undefined array key %s in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
Nested Read-Write:
|
||||
Nested isset():
|
||||
bool(true)
|
||||
Nested empty():
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
int(30)
|
||||
Nested unset():
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_VALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_VALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTF_OUTPUT_FLOAT_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 8
|
||||
|
||||
Warning: Undefined array key %s in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 15
|
||||
Read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 22
|
||||
int(15)
|
||||
Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 29
|
||||
isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 48
|
||||
int(35)
|
||||
unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 62
|
||||
|
||||
Warning: Undefined array key 0 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
int(25)
|
||||
Nested unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
Write:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
Read:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
Read-Write:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
isset():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
empty():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
null coalesce:
|
||||
Cannot access offset of type %s in isset or empty
|
||||
unset():
|
||||
Cannot unset offset of type %s on ArrayObject
|
||||
Nested read:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
Nested write:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
Nested Read-Write:
|
||||
Cannot access offset of type %s on ArrayObject
|
||||
Nested isset():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
Nested empty():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
Nested null coalesce:
|
||||
Cannot access offset of type %s in isset or empty
|
||||
Nested unset():
|
||||
|
||||
Notice: Indirect modification of overloaded element of ArrayObject has no effect in %s on line 102
|
||||
Cannot unset offset of type %s on ArrayObject
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_NULL_OFFSET = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Undefined array key "" in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
Read:
|
||||
|
||||
Warning: Undefined array key "" in %s on line 22
|
||||
NULL
|
||||
Read-Write:
|
||||
|
||||
Warning: Undefined array key "" in %s on line 29
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
string(7) "default"
|
||||
unset():
|
||||
Nested read:
|
||||
|
||||
Warning: Undefined array key "" in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
Nested Read-Write:
|
||||
Nested isset():
|
||||
bool(true)
|
||||
Nested empty():
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
OUTPUT;
|
||||
|
||||
const EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 8
|
||||
|
||||
Warning: Undefined array key 3 in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 22
|
||||
int(5)
|
||||
Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 29
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 29
|
||||
isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 48
|
||||
int(25)
|
||||
unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 62
|
||||
|
||||
Warning: Undefined array key 3 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
ob_start();
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = new ArrayObject();
|
||||
$error = '(new ArrayObject())[' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
ob_start();
|
||||
var_dump($dimension);
|
||||
$var_dump_output = ob_get_clean();
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if (
|
||||
!preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX, $varOutput)
|
||||
&& $varOutput !== EXPECTED_OUTPUT_NULL_OFFSET
|
||||
&& $varOutput !== EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS
|
||||
) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_ArrayObject_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
75
Zend/tests/offsets/appending_containers.phpt
Normal file
75
Zend/tests/offsets/appending_containers.phpt
Normal file
@@ -0,0 +1,75 @@
|
||||
--TEST--
|
||||
Appending containers
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
foreach ($containers as $container) {
|
||||
echo zend_test_var_export($container), " container:\n";
|
||||
try {
|
||||
$container[] = 'value';
|
||||
var_dump($container);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
NULL container:
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(5) "value"
|
||||
}
|
||||
false container:
|
||||
|
||||
Deprecated: Automatic conversion of false to array is deprecated in %s on line %d
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(5) "value"
|
||||
}
|
||||
true container:
|
||||
Cannot use a scalar value as an array
|
||||
4 container:
|
||||
Cannot use a scalar value as an array
|
||||
5.5 container:
|
||||
Cannot use a scalar value as an array
|
||||
'10' container:
|
||||
[] operator not supported for strings
|
||||
'25.5' container:
|
||||
[] operator not supported for strings
|
||||
'string' container:
|
||||
[] operator not supported for strings
|
||||
[] container:
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(5) "value"
|
||||
}
|
||||
STDERR container:
|
||||
Cannot use a scalar value as an array
|
||||
new stdClass() container:
|
||||
Cannot use object of type stdClass as array
|
||||
new ArrayObject() container:
|
||||
object(ArrayObject)#2 (1) {
|
||||
["storage":"ArrayObject":private]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(5) "value"
|
||||
}
|
||||
}
|
||||
new A() container:
|
||||
string(12) "A::offsetSet"
|
||||
NULL
|
||||
string(5) "value"
|
||||
object(A)#3 (0) {
|
||||
}
|
||||
new B() container:
|
||||
string(12) "B::offsetSet"
|
||||
NULL
|
||||
string(5) "value"
|
||||
object(B)#4 (1) {
|
||||
["storage":"ArrayObject":private]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
||||
79
Zend/tests/offsets/appending_containers_in_fetch.phpt
Normal file
79
Zend/tests/offsets/appending_containers_in_fetch.phpt
Normal file
@@ -0,0 +1,79 @@
|
||||
--TEST--
|
||||
Appending containers via a fetch operation $c[][5] = $v;
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
foreach ($containers as $container) {
|
||||
echo zend_test_var_export($container), " container:\n";
|
||||
try {
|
||||
$container[][5] = 'value';
|
||||
var_dump($container);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
NULL container:
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[5]=>
|
||||
string(5) "value"
|
||||
}
|
||||
}
|
||||
false container:
|
||||
|
||||
Deprecated: Automatic conversion of false to array is deprecated in %s on line %d
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[5]=>
|
||||
string(5) "value"
|
||||
}
|
||||
}
|
||||
true container:
|
||||
Error: Cannot use a scalar value as an array
|
||||
4 container:
|
||||
Error: Cannot use a scalar value as an array
|
||||
5.5 container:
|
||||
Error: Cannot use a scalar value as an array
|
||||
'10' container:
|
||||
Error: [] operator not supported for strings
|
||||
'25.5' container:
|
||||
Error: [] operator not supported for strings
|
||||
'string' container:
|
||||
Error: [] operator not supported for strings
|
||||
[] container:
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[5]=>
|
||||
string(5) "value"
|
||||
}
|
||||
}
|
||||
STDERR container:
|
||||
Error: Cannot use a scalar value as an array
|
||||
new stdClass() container:
|
||||
Error: Cannot use object of type stdClass as array
|
||||
new ArrayObject() container:
|
||||
|
||||
Notice: Indirect modification of overloaded element of ArrayObject has no effect in %s on line %d
|
||||
object(ArrayObject)#2 (1) {
|
||||
["storage":"ArrayObject":private]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
||||
new A() container:
|
||||
string(12) "A::offsetGet"
|
||||
NULL
|
||||
|
||||
Notice: Indirect modification of overloaded element of A has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
new B() container:
|
||||
|
||||
Notice: Indirect modification of overloaded element of B has no effect in %s on line %d
|
||||
ArgumentCountError: B::offsetGet(): Argument #1 ($offset) not passed
|
||||
268
Zend/tests/offsets/array_container_offset_behaviour.phpt
Normal file
268
Zend/tests/offsets/array_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,268 @@
|
||||
--TEST--
|
||||
array containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT_VALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Undefined array key %s in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
Read:
|
||||
int(5)
|
||||
Read-Write:
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
int(25)
|
||||
unset():
|
||||
Nested read:
|
||||
|
||||
Warning: Undefined array key %s in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
Nested Read-Write:
|
||||
Nested isset():
|
||||
bool(true)
|
||||
Nested empty():
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
int(30)
|
||||
Nested unset():
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_VALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_VALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTF_OUTPUT_FLOAT_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 8
|
||||
|
||||
Warning: Undefined array key %s in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 15
|
||||
Read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 22
|
||||
int(15)
|
||||
Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 29
|
||||
isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 48
|
||||
int(35)
|
||||
unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 62
|
||||
|
||||
Warning: Undefined array key 0 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
int(25)
|
||||
Nested unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
Cannot access offset of type %s on array
|
||||
Write:
|
||||
Cannot access offset of type %s on array
|
||||
Read:
|
||||
Cannot access offset of type %s on array
|
||||
Read-Write:
|
||||
Cannot access offset of type %s on array
|
||||
isset():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
empty():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
null coalesce:
|
||||
Cannot access offset of type %s on array
|
||||
unset():
|
||||
Cannot unset offset of type %s on array
|
||||
Nested read:
|
||||
Cannot access offset of type %s on array
|
||||
Nested write:
|
||||
Cannot access offset of type %s on array
|
||||
Nested Read-Write:
|
||||
Cannot access offset of type %s on array
|
||||
Nested isset():
|
||||
Cannot access offset of type %s on array
|
||||
Nested empty():
|
||||
Cannot access offset of type %s on array
|
||||
Nested null coalesce:
|
||||
Cannot access offset of type %s on array
|
||||
Nested unset():
|
||||
Cannot access offset of type %s on array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 8
|
||||
|
||||
Warning: Undefined array key 3 in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 22
|
||||
int(5)
|
||||
Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 29
|
||||
isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 48
|
||||
int(25)
|
||||
unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 62
|
||||
|
||||
Warning: Undefined array key 3 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
ob_start();
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = [];
|
||||
$error = '[][' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if (
|
||||
!preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX, $varOutput)
|
||||
&& $varOutput !== EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS
|
||||
) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_array_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
275
Zend/tests/offsets/false_container_offset_behaviour.phpt
Normal file
275
Zend/tests/offsets/false_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,275 @@
|
||||
--TEST--
|
||||
false containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT_VALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on false in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Automatic conversion of false to array is deprecated in %s on line 15
|
||||
Read:
|
||||
int(5)
|
||||
Read-Write:
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
int(25)
|
||||
unset():
|
||||
Nested read:
|
||||
|
||||
Warning: Undefined array key %s in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
Nested Read-Write:
|
||||
Nested isset():
|
||||
bool(true)
|
||||
Nested empty():
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_VALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_VALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTF_OUTPUT_FLOAT_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on false in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Automatic conversion of false to array is deprecated in %s on line 15
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 15
|
||||
Read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 22
|
||||
int(5)
|
||||
Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 29
|
||||
isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 48
|
||||
int(25)
|
||||
unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 62
|
||||
|
||||
Warning: Undefined array key 0 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on false in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Automatic conversion of false to array is deprecated in %s on line 15
|
||||
Cannot access offset of type %s on array
|
||||
Read:
|
||||
Cannot access offset of type %s on array
|
||||
Read-Write:
|
||||
Cannot access offset of type %s on array
|
||||
isset():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
empty():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
null coalesce:
|
||||
Cannot access offset of type %s on array
|
||||
unset():
|
||||
Cannot unset offset of type %s on array
|
||||
Nested read:
|
||||
Cannot access offset of type %s on array
|
||||
Nested write:
|
||||
Cannot access offset of type %s on array
|
||||
Nested Read-Write:
|
||||
Cannot access offset of type %s on array
|
||||
Nested isset():
|
||||
Cannot access offset of type %s on array
|
||||
Nested empty():
|
||||
Cannot access offset of type %s on array
|
||||
Nested null coalesce:
|
||||
Cannot access offset of type %s on array
|
||||
Nested unset():
|
||||
Cannot access offset of type %s on array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on false in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Automatic conversion of false to array is deprecated in %s on line 15
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 22
|
||||
int(5)
|
||||
Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 29
|
||||
isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 48
|
||||
int(25)
|
||||
unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 62
|
||||
|
||||
Warning: Undefined array key 3 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
ob_start();
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = false;
|
||||
$error = 'false[' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if (
|
||||
!preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX, $varOutput)
|
||||
&& $varOutput !== EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS
|
||||
) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_false_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
256
Zend/tests/offsets/internal_handlers.phpt
Normal file
256
Zend/tests/offsets/internal_handlers.phpt
Normal file
@@ -0,0 +1,256 @@
|
||||
--TEST--
|
||||
Internal handlers
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
echo 'read op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$r = $o['foo'];
|
||||
exportObject($o);
|
||||
|
||||
echo 'write op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$o['foo'] = true;
|
||||
exportObject($o);
|
||||
|
||||
echo 'read-write op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$o['foo'] += 10;
|
||||
exportObject($o);
|
||||
|
||||
echo 'isset op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$r = isset($o['foo']);
|
||||
exportObject($o);
|
||||
|
||||
echo 'empty op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$r = empty($o['foo']);
|
||||
exportObject($o);
|
||||
|
||||
echo 'null coalescing op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$r = $o['foo'] ?? 'default';
|
||||
exportObject($o);
|
||||
|
||||
echo 'appending op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$o[] = true;
|
||||
exportObject($o);
|
||||
|
||||
echo 'unset op', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
unset($o['foo']);
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested read', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
$r = $o['foo']['bar'];
|
||||
exportObject($o);
|
||||
|
||||
// Illegal
|
||||
//echo 'nested read: appending then read', PHP_EOL;
|
||||
//$o = new DimensionHandlersNoArrayAccess();
|
||||
//try {
|
||||
// $r = $o[]['bar'];
|
||||
//} catch (\Throwable $e) {
|
||||
// echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
//}
|
||||
|
||||
echo 'nested write', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$o['foo']['bar'] = true;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested write: appending then write', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$o[]['bar'] = true;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested read-write', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$o['foo']['bar'] += 10;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested read-write: appending then write', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$o[]['bar'] += 10;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested isset', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$r = isset($o['foo']['bar']);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
// Illegal
|
||||
//echo 'nested isset: appending then read', PHP_EOL;
|
||||
//try {
|
||||
// $o = new DimensionHandlersNoArrayAccess();
|
||||
// $r = isset($o[]['bar']);
|
||||
//} catch (\Throwable $e) {
|
||||
// echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
//}
|
||||
//exportObject($o);
|
||||
|
||||
echo 'nested empty', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$r = empty($o['foo']['bar']);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
// Illegal
|
||||
//echo 'nested empty: appending then read', PHP_EOL;
|
||||
//try {
|
||||
// $o = new DimensionHandlersNoArrayAccess();
|
||||
// $r = empty($o[]['bar']);
|
||||
//} catch (\Throwable $e) {
|
||||
// echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
//}
|
||||
//exportObject($o);
|
||||
|
||||
echo 'nested null coalescing', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$r = $o['foo']['bar'] ?? 'default';
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
// Illegal
|
||||
//echo 'nested null coalescing: appending then read', PHP_EOL;
|
||||
//try {
|
||||
// $o = new DimensionHandlersNoArrayAccess();
|
||||
// $r = $o[]['bar'] ?? 'default';
|
||||
//} catch (\Throwable $e) {
|
||||
// echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
//}
|
||||
//exportObject($o);
|
||||
|
||||
echo 'nested appending', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$o['foo'][] = true;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested appending: appending then append', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
$o[][] = true;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
echo 'nested unset', PHP_EOL;
|
||||
$o = new DimensionHandlersNoArrayAccess();
|
||||
try {
|
||||
unset($o['foo']['bar']);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
exportObject($o);
|
||||
|
||||
// Illegal
|
||||
//echo 'nested unset: appending then read', PHP_EOL;
|
||||
//try {
|
||||
// $o = new DimensionHandlersNoArrayAccess();
|
||||
// unset($o[]['bar']);
|
||||
//} catch (\Throwable $e) {
|
||||
// echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
//}
|
||||
//exportObject($o);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
read op
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_R, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
write op
|
||||
DimensionHandlersNoArrayAccess, read: false, write: true, has: false, unset: false, readType: uninitialized, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
read-write op
|
||||
DimensionHandlersNoArrayAccess, read: true, write: true, has: false, unset: false, readType: BP_VAR_R, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
isset op
|
||||
DimensionHandlersNoArrayAccess, read: false, write: false, has: true, unset: false, readType: uninitialized, hasOffset: true, checkEmpty: 0, offset: 'foo'
|
||||
empty op
|
||||
DimensionHandlersNoArrayAccess, read: false, write: false, has: true, unset: false, readType: uninitialized, hasOffset: true, checkEmpty: 1, offset: 'foo'
|
||||
null coalescing op
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_IS, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
appending op
|
||||
DimensionHandlersNoArrayAccess, read: false, write: true, has: false, unset: false, readType: uninitialized, hasOffset: false, checkEmpty: uninitialized, offset: uninitialized
|
||||
unset op
|
||||
DimensionHandlersNoArrayAccess, read: false, write: false, has: false, unset: true, readType: uninitialized, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested read
|
||||
|
||||
Warning: Trying to access array offset on true in %s on line %d
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_R, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested write
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_W, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested write: appending then write
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_W, hasOffset: false, checkEmpty: uninitialized, offset: uninitialized
|
||||
nested read-write
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_RW, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested read-write: appending then write
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_RW, hasOffset: false, checkEmpty: uninitialized, offset: uninitialized
|
||||
nested isset
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_IS, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested empty
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_IS, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested null coalescing
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_IS, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested appending
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_W, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
nested appending: appending then append
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot use a scalar value as an array
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_W, hasOffset: false, checkEmpty: uninitialized, offset: uninitialized
|
||||
nested unset
|
||||
|
||||
Notice: Indirect modification of overloaded element of DimensionHandlersNoArrayAccess has no effect in %s on line %d
|
||||
Error: Cannot unset offset in a non-array variable
|
||||
DimensionHandlersNoArrayAccess, read: true, write: false, has: false, unset: false, readType: BP_VAR_UNSET, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
46
Zend/tests/offsets/internal_handlers_extended.phpt
Normal file
46
Zend/tests/offsets/internal_handlers_extended.phpt
Normal file
@@ -0,0 +1,46 @@
|
||||
--TEST--
|
||||
Internal handlers that do not explicitly support userland ArrayAccess
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
class NoImplement extends DimensionHandlersNoArrayAccess {}
|
||||
|
||||
class DoImplement extends DimensionHandlersNoArrayAccess implements ArrayAccess {
|
||||
public function offsetSet($offset, $value): void {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
var_dump($value);
|
||||
}
|
||||
public function offsetGet($offset): mixed {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
return "dummy";
|
||||
}
|
||||
public function offsetUnset($offset): void {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
}
|
||||
public function offsetExists($offset): bool {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$no = new NoImplement();
|
||||
$do = new DoImplement();
|
||||
|
||||
$no['foo'];
|
||||
exportObject($no);
|
||||
|
||||
$do['foo'];
|
||||
exportObject($do);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
NoImplement, read: true, write: false, has: false, unset: false, readType: BP_VAR_R, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
DoImplement, read: true, write: false, has: false, unset: false, readType: BP_VAR_R, hasOffset: true, checkEmpty: uninitialized, offset: 'foo'
|
||||
92
Zend/tests/offsets/invalid_container_offset_behaviour.phpt
Normal file
92
Zend/tests/offsets/invalid_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,92 @@
|
||||
--TEST--
|
||||
Invalid containers with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
$containers = [
|
||||
//false,
|
||||
true,
|
||||
4,
|
||||
5.5,
|
||||
STDERR,
|
||||
//new stdClass(),
|
||||
];
|
||||
|
||||
ob_start();
|
||||
foreach ($containers as $container) {
|
||||
$containerStr = get_zend_debug_type($container);
|
||||
$EXPECTED_OUTPUT = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on $containerStr in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
Cannot use a scalar value as an array
|
||||
Read:
|
||||
|
||||
Warning: Trying to access array offset on $containerStr in %s on line 22
|
||||
NULL
|
||||
Read-Write:
|
||||
Cannot use a scalar value as an array
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
string(7) "default"
|
||||
unset():
|
||||
Cannot unset offset in a non-array variable
|
||||
Nested read:
|
||||
|
||||
Warning: Trying to access array offset on $containerStr in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
Cannot use a scalar value as an array
|
||||
Nested Read-Write:
|
||||
Cannot use a scalar value as an array
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
Cannot unset offset in a non-array variable
|
||||
|
||||
OUTPUT;
|
||||
|
||||
foreach ($offsets as $dimension) {
|
||||
$error = $containerStr . '[' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if ($EXPECTED_OUTPUT !== $varOutput) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_invalid_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
267
Zend/tests/offsets/null_container_offset_behaviour.phpt
Normal file
267
Zend/tests/offsets/null_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,267 @@
|
||||
--TEST--
|
||||
null containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT_VALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
Read:
|
||||
int(5)
|
||||
Read-Write:
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
int(25)
|
||||
unset():
|
||||
Nested read:
|
||||
|
||||
Warning: Undefined array key %s in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
Nested Read-Write:
|
||||
Nested isset():
|
||||
bool(true)
|
||||
Nested empty():
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_VALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_VALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTF_OUTPUT_FLOAT_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 15
|
||||
Read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 22
|
||||
int(5)
|
||||
Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 29
|
||||
isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 48
|
||||
int(25)
|
||||
unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 62
|
||||
|
||||
Warning: Undefined array key 0 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 95
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
Cannot access offset of type %s on array
|
||||
Read:
|
||||
Cannot access offset of type %s on array
|
||||
Read-Write:
|
||||
Cannot access offset of type %s on array
|
||||
isset():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
empty():
|
||||
Cannot access offset of type %s in isset or empty
|
||||
null coalesce:
|
||||
Cannot access offset of type %s on array
|
||||
unset():
|
||||
Cannot unset offset of type %s on array
|
||||
Nested read:
|
||||
Cannot access offset of type %s on array
|
||||
Nested write:
|
||||
Cannot access offset of type %s on array
|
||||
Nested Read-Write:
|
||||
Cannot access offset of type %s on array
|
||||
Nested isset():
|
||||
Cannot access offset of type %s on array
|
||||
Nested empty():
|
||||
Cannot access offset of type %s on array
|
||||
Nested null coalesce:
|
||||
Cannot access offset of type %s on array
|
||||
Nested unset():
|
||||
Cannot access offset of type %s on array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 8
|
||||
NULL
|
||||
Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 22
|
||||
int(5)
|
||||
Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 29
|
||||
isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 48
|
||||
int(25)
|
||||
unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 55
|
||||
Nested read:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 62
|
||||
|
||||
Warning: Undefined array key 3 in %s on line 62
|
||||
|
||||
Warning: Trying to access array offset on null in %s on line 62
|
||||
NULL
|
||||
Nested write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 69
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 76
|
||||
Nested isset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 95
|
||||
int(30)
|
||||
Nested unset():
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
Warning: Resource ID#3 used as offset, casting to integer (3) in %s on line 102
|
||||
|
||||
OUTPUT;
|
||||
|
||||
ob_start();
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = null;
|
||||
$error = 'null[' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if (
|
||||
!preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_FLOAT_OFFSETS_REGEX, $varOutput)
|
||||
&& $varOutput !== EXPECTED_OUTPUT_RESOURCE_STDERR_OFFSETS
|
||||
) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_null_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
72
Zend/tests/offsets/object_container_offset_behaviour.phpt
Normal file
72
Zend/tests/offsets/object_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,72 @@
|
||||
--TEST--
|
||||
object containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT = <<<OUTPUT
|
||||
Read before write:
|
||||
Cannot use object of type stdClass as array
|
||||
Write:
|
||||
Cannot use object of type stdClass as array
|
||||
Read:
|
||||
Cannot use object of type stdClass as array
|
||||
Read-Write:
|
||||
Cannot use object of type stdClass as array
|
||||
isset():
|
||||
Cannot use object of type stdClass as array
|
||||
empty():
|
||||
Cannot use object of type stdClass as array
|
||||
null coalesce:
|
||||
Cannot use object of type stdClass as array
|
||||
unset():
|
||||
Cannot use object of type stdClass as array
|
||||
Nested read:
|
||||
Cannot use object of type stdClass as array
|
||||
Nested write:
|
||||
Cannot use object of type stdClass as array
|
||||
Nested Read-Write:
|
||||
Cannot use object of type stdClass as array
|
||||
Nested isset():
|
||||
Cannot use object of type stdClass as array
|
||||
Nested empty():
|
||||
Cannot use object of type stdClass as array
|
||||
Nested null coalesce:
|
||||
Cannot use object of type stdClass as array
|
||||
Nested unset():
|
||||
Cannot use object of type stdClass as array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
ob_start();
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = new stdClass();
|
||||
$error = '(new stdClass())[' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if ($varOutput !== EXPECTED_OUTPUT) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_object_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
82
Zend/tests/offsets/runtime_compile_time_offset_access.phpt
Normal file
82
Zend/tests/offsets/runtime_compile_time_offset_access.phpt
Normal file
@@ -0,0 +1,82 @@
|
||||
--TEST--
|
||||
Test binary operands exposing the same behavior at compile as at run time
|
||||
--INI--
|
||||
memory_limit=256M
|
||||
opcache.file_update_protection=1
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
function makeTestFile($container, $offset) {
|
||||
$offset_p = zend_test_var_export($offset);
|
||||
$container_p = zend_test_var_export($container);
|
||||
$fileContent = file_get_contents(__DIR__ . '/test_variable_offsets.inc');
|
||||
$fileContent = str_replace('$dimension', $offset_p, $fileContent);
|
||||
return str_replace('//$container var declaration in const generated file', "\$container = $container_p;", $fileContent);
|
||||
}
|
||||
|
||||
function normalize_output(string $output, string $filename): string {
|
||||
$output = str_replace(
|
||||
[$filename],
|
||||
['%s'],
|
||||
$output
|
||||
);
|
||||
|
||||
$output = preg_replace('/\)#\d+ \(/', ')#99 (', $output);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
$const_dim_filename = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_offsets_temp.php';
|
||||
|
||||
ob_start();
|
||||
foreach ($containers as $container_orig) {
|
||||
foreach ($offsets as $offset) {
|
||||
$error = zend_test_var_export($container_orig) . '[' . zend_test_var_export($offset) . '] has different outputs' . "\n";
|
||||
file_put_contents($const_dim_filename, makeTestFile($container_orig, $offset));
|
||||
|
||||
include $const_dim_filename;
|
||||
$constOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$constOutput = normalize_output($constOutput, $const_dim_filename);
|
||||
|
||||
$dimension = $offset;
|
||||
$container = $container_orig;
|
||||
if (is_object($container_orig)) {
|
||||
$container = clone $container_orig;
|
||||
}
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = normalize_output($varOutput, $var_dim_filename);
|
||||
|
||||
if ($constOutput !== $varOutput) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_{$failuresNb}_const.txt", $constOutput);
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_{$failuresNb}_var.txt", $varOutput);
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_{$failuresNb}_test_case.txt", makeTestFile($container_orig, $offset));
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
$fl = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_offsets_temp.php';
|
||||
@unlink($fl);
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
637
Zend/tests/offsets/string_container_offset_behaviour.phpt
Normal file
637
Zend/tests/offsets/string_container_offset_behaviour.phpt
Normal file
@@ -0,0 +1,637 @@
|
||||
--TEST--
|
||||
String containers behaviour with offsets
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'test_offset_helpers.inc';
|
||||
|
||||
const EXPECTED_OUTPUT_VALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
Read:
|
||||
string(1) "5"
|
||||
Read-Write:
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
string(1) "5"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 62
|
||||
string(0) ""
|
||||
Nested write:
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_VALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_VALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_VALID_OFFSETS_OUT_OF_RANGE = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: Illegal string offset %i in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 22
|
||||
string(0) ""
|
||||
Read-Write:
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
string(7) "default"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 62
|
||||
string(0) ""
|
||||
Nested write:
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_VALID_OFFSETS_OUT_OF_RANGE_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_VALID_OFFSETS_OUT_OF_RANGE) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_STRING_CAST_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 22
|
||||
string(1) "5"
|
||||
Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
string(1) "5"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 62
|
||||
string(0) ""
|
||||
Nested write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
|
||||
Warning: String offset cast occurred in %s on line 102
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_STRING_CAST_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_STRING_CAST_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_STRING_CAST_OFFSETS_TO_0 = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset 0 in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 22
|
||||
string(1) "5"
|
||||
Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(true)
|
||||
empty():
|
||||
bool(false)
|
||||
null coalesce:
|
||||
string(1) "5"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
string(1) "5"
|
||||
Nested write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
bool(true)
|
||||
Nested empty():
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
string(1) "5"
|
||||
Nested unset():
|
||||
|
||||
Warning: String offset cast occurred in %s on line 102
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_STRING_CAST_OFFSETS_TO_0_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_STRING_CAST_OFFSETS_TO_0) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_STRING_CAST_OFFSETS_OUT_OF_RANGE = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 15
|
||||
|
||||
Warning: Illegal string offset %i in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 22
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 22
|
||||
string(0) ""
|
||||
Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
string(7) "default"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 62
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 62
|
||||
string(0) ""
|
||||
Nested write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
|
||||
Warning: String offset cast occurred in %s on line 102
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_STRING_CAST_OFFSETS_OUT_OF_RANGE_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_STRING_CAST_OFFSETS_OUT_OF_RANGE) . '$/s';
|
||||
|
||||
const EXPECTF_OUTPUT_FLOAT_OFFSETS_OUT_OF_RANGE = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 15
|
||||
|
||||
Warning: Illegal string offset %i in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 22
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 22
|
||||
string(0) ""
|
||||
Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %f to int loses precision in %s on line 36
|
||||
bool(false)
|
||||
empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %f to int loses precision in %s on line 42
|
||||
bool(true)
|
||||
null coalesce:
|
||||
string(7) "default"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 62
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %i in %s on line 62
|
||||
string(0) ""
|
||||
Nested write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
|
||||
Warning: String offset cast occurred in %s on line 102
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTF_OUTPUT_FLOAT_OFFSETS_OUT_OF_RANGE_REGEX = '/^' . expectf_to_regex(EXPECTF_OUTPUT_FLOAT_OFFSETS_OUT_OF_RANGE) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_FLOAT_INF_NAN_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 22
|
||||
string(1) "5"
|
||||
Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 36
|
||||
bool(true)
|
||||
empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 42
|
||||
bool(false)
|
||||
null coalesce:
|
||||
string(1) "5"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
|
||||
Warning: String offset cast occurred in %s on line 62
|
||||
string(1) "5"
|
||||
Nested write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: String offset cast occurred in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 83
|
||||
bool(true)
|
||||
Nested empty():
|
||||
|
||||
Deprecated: Implicit conversion from float %F to int loses precision in %s on line 89
|
||||
bool(false)
|
||||
Nested null coalesce:
|
||||
string(1) "5"
|
||||
Nested unset():
|
||||
|
||||
Warning: String offset cast occurred in %s on line 102
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_FLOAT_INF_NAN_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_FLOAT_INF_NAN_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS = <<<OUTPUT
|
||||
Read before write:
|
||||
Cannot access offset of type %s on string
|
||||
Write:
|
||||
Cannot access offset of type %s on string
|
||||
Read:
|
||||
Cannot access offset of type %s on string
|
||||
Read-Write:
|
||||
Cannot access offset of type %s on string
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
Cannot access offset of type %s on string
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
Cannot access offset of type %s on string
|
||||
Nested write:
|
||||
Cannot access offset of type %s on string
|
||||
Nested Read-Write:
|
||||
Cannot access offset of type %s on string
|
||||
Nested isset():
|
||||
Cannot access offset of type %s on string
|
||||
Nested empty():
|
||||
Cannot access offset of type %s on string
|
||||
Nested null coalesce:
|
||||
Cannot access offset of type %s on string
|
||||
Nested unset():
|
||||
Cannot unset string offsets
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS_AS_STRINGS = <<<OUTPUT
|
||||
Read before write:
|
||||
Cannot access offset of type string on string
|
||||
Write:
|
||||
Cannot access offset of type string on string
|
||||
Read:
|
||||
Cannot access offset of type string on string
|
||||
Read-Write:
|
||||
Cannot access offset of type string on string
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
string(7) "default"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
Cannot access offset of type string on string
|
||||
Nested write:
|
||||
Cannot access offset of type string on string
|
||||
Nested Read-Write:
|
||||
Cannot access offset of type string on string
|
||||
Nested isset():
|
||||
bool(false)
|
||||
Nested empty():
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
Cannot unset string offsets
|
||||
|
||||
OUTPUT;
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 22
|
||||
string(1) "5"
|
||||
Read-Write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 48
|
||||
string(1) "5"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 62
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 62
|
||||
|
||||
Warning: Uninitialized string offset %d in %s on line 62
|
||||
string(0) ""
|
||||
Nested write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 83
|
||||
bool(false)
|
||||
Nested empty():
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 89
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 95
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 95
|
||||
string(7) "default"
|
||||
Nested unset():
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS) . '$/s';
|
||||
|
||||
const EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS_TO_0 = <<<OUTPUT
|
||||
Read before write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 8
|
||||
|
||||
Warning: Uninitialized string offset 0 in %s on line 8
|
||||
string(0) ""
|
||||
Write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 15
|
||||
Read:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 22
|
||||
string(1) "5"
|
||||
Read-Write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 29
|
||||
Cannot use assign-op operators with string offsets
|
||||
isset():
|
||||
bool(false)
|
||||
empty():
|
||||
bool(true)
|
||||
null coalesce:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 48
|
||||
string(1) "5"
|
||||
unset():
|
||||
Cannot unset string offsets
|
||||
Nested read:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 62
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 62
|
||||
string(1) "5"
|
||||
Nested write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 69
|
||||
Cannot use string offset as an array
|
||||
Nested Read-Write:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 76
|
||||
Cannot use string offset as an array
|
||||
Nested isset():
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 83
|
||||
bool(false)
|
||||
Nested empty():
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 89
|
||||
bool(true)
|
||||
Nested null coalesce:
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 95
|
||||
|
||||
Warning: Illegal string offset %s in %s on line 95
|
||||
string(1) "5"
|
||||
Nested unset():
|
||||
Cannot use string offset as an array
|
||||
|
||||
OUTPUT;
|
||||
|
||||
$EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS_TO_0_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS_TO_0) . '$/s';
|
||||
|
||||
ob_start();
|
||||
foreach ($offsets as $dimension) {
|
||||
$container = '';
|
||||
$error = '""[' . zend_test_var_export($dimension) . '] has different outputs' . "\n";
|
||||
|
||||
include $var_dim_filename;
|
||||
$varOutput = ob_get_contents();
|
||||
ob_clean();
|
||||
$varOutput = str_replace(
|
||||
[$var_dim_filename],
|
||||
['%s'],
|
||||
$varOutput
|
||||
);
|
||||
|
||||
if (
|
||||
!preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_VALID_OFFSETS_OUT_OF_RANGE_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_STRING_CAST_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_STRING_CAST_OFFSETS_TO_0_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_STRING_CAST_OFFSETS_OUT_OF_RANGE_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTF_OUTPUT_FLOAT_OFFSETS_OUT_OF_RANGE_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_FLOAT_INF_NAN_OFFSETS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX, $varOutput)
|
||||
&& $varOutput !== EXPECTED_OUTPUT_INVALID_OFFSETS_AS_STRINGS
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS_REGEX, $varOutput)
|
||||
&& !preg_match($EXPECTED_OUTPUT_INVALID_OFFSETS_AS_LEADING_NUMERIC_STRINGS_TO_0_REGEX, $varOutput)
|
||||
) {
|
||||
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . "debug_string_container_{$failuresNb}.txt", $varOutput);
|
||||
++$failuresNb;
|
||||
$failures[] = $error;
|
||||
}
|
||||
++$testCasesTotal;
|
||||
}
|
||||
ob_end_clean();
|
||||
|
||||
echo "Executed tests\n";
|
||||
if ($failures !== []) {
|
||||
echo "Failures:\n" . implode($failures);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Executed tests
|
||||
204
Zend/tests/offsets/test_offset_helpers.inc
Normal file
204
Zend/tests/offsets/test_offset_helpers.inc
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
function get_zend_debug_type($v) {
|
||||
if ($v === true) {
|
||||
return 'true';
|
||||
}
|
||||
if ($v === false) {
|
||||
return 'false';
|
||||
}
|
||||
if (is_resource($v)) {
|
||||
return 'resource';
|
||||
}
|
||||
return get_debug_type($v);
|
||||
}
|
||||
function zend_test_var_export($value) {
|
||||
if ($value === PHP_INT_MIN) {
|
||||
return "PHP_INT_MIN";
|
||||
}
|
||||
if ($value === PHP_INT_MAX) {
|
||||
return "PHP_INT_MAX";
|
||||
}
|
||||
if (is_array($value)) {
|
||||
return "[]";
|
||||
}
|
||||
if (is_resource($value)) {
|
||||
return "STDERR";
|
||||
}
|
||||
if ($value instanceof stdClass) {
|
||||
return "new stdClass()";
|
||||
}
|
||||
if ($value instanceof B) {
|
||||
return "new B()";
|
||||
}
|
||||
if ($value instanceof A) {
|
||||
return "new A()";
|
||||
}
|
||||
if ($value instanceof ArrayObject) {
|
||||
return "new ArrayObject()";
|
||||
}
|
||||
return var_export($value, true);
|
||||
}
|
||||
|
||||
function exportProp(object $o, string $p) {
|
||||
$rp = new ReflectionProperty($o, $p);
|
||||
|
||||
echo ', ', $p, ': ';
|
||||
if ($rp->isInitialized($o)) {
|
||||
if ($p === 'readType') {
|
||||
echo match($o->$p) {
|
||||
0 => 'BP_VAR_R',
|
||||
1 => 'BP_VAR_W',
|
||||
2 => 'BP_VAR_RW',
|
||||
3 => 'BP_VAR_IS',
|
||||
4 => 'BP_VAR_FUNC_ARG',
|
||||
5 => 'BP_VAR_UNSET',
|
||||
};
|
||||
} else {
|
||||
echo zend_test_var_export($o->$p);
|
||||
}
|
||||
} else {
|
||||
echo 'uninitialized';
|
||||
}
|
||||
}
|
||||
|
||||
function exportObject(object $o) {
|
||||
echo $o::class;
|
||||
foreach (get_class_vars($o::class) as $p => $v) {
|
||||
exportProp($o, $p);
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
/* Taken from run-tests.php */
|
||||
function expectf_to_regex(string $wanted): string
|
||||
{
|
||||
$wanted_re = preg_quote($wanted);
|
||||
return strtr($wanted_re, [
|
||||
'%e' => preg_quote(DIRECTORY_SEPARATOR, '/'),
|
||||
'%s' => '[^\r\n]+',
|
||||
'%S' => '[^\r\n]*',
|
||||
'%a' => '.+',
|
||||
'%A' => '.*',
|
||||
'%w' => '\s*',
|
||||
'%i' => '[+-]?\d+',
|
||||
'%d' => '\d+',
|
||||
'%x' => '[0-9a-fA-F]+',
|
||||
'%f' => '[+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?',
|
||||
'%F' => '([+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?)|(NAN)|(INF)',
|
||||
'%c' => '.',
|
||||
'%0' => '\x00',
|
||||
]);
|
||||
}
|
||||
|
||||
class A implements ArrayAccess {
|
||||
public function offsetSet($offset, $value): void {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
var_dump($value);
|
||||
}
|
||||
public function offsetGet($offset): mixed {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
return 5;
|
||||
}
|
||||
public function offsetUnset($offset): void {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
}
|
||||
public function offsetExists($offset): bool {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends ArrayObject {
|
||||
public function offsetSet($offset, $value): void {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
var_dump($value);
|
||||
}
|
||||
public function offsetGet($offset): mixed {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
return 5;
|
||||
}
|
||||
public function offsetUnset($offset): void {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
}
|
||||
public function offsetExists($offset): bool {
|
||||
var_dump(__METHOD__);
|
||||
var_dump($offset);
|
||||
return true;
|
||||
}
|
||||
public function append(mixed $value) : void{
|
||||
var_dump(__METHOD__);
|
||||
var_dump($value);
|
||||
}
|
||||
}
|
||||
|
||||
$containers = [
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
4,
|
||||
5.5,
|
||||
'10',
|
||||
'25.5',
|
||||
'string',
|
||||
[],
|
||||
STDERR,
|
||||
new stdClass(),
|
||||
new ArrayObject(),
|
||||
new A(),
|
||||
new B(),
|
||||
];
|
||||
|
||||
$offsets = [
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
4,
|
||||
5.5,
|
||||
6.0,
|
||||
-12,
|
||||
-13.5,
|
||||
-14.0,
|
||||
//PHP_INT_MAX,
|
||||
//PHP_INT_MIN,
|
||||
PHP_INT_MAX * 2,
|
||||
PHP_INT_MIN * 2,
|
||||
INF,
|
||||
-INF,
|
||||
NAN,
|
||||
'string',
|
||||
'7',
|
||||
'8.5',
|
||||
'9.0',
|
||||
'2e3',
|
||||
'20a',
|
||||
' 21',
|
||||
'22 ',
|
||||
//"9179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368",
|
||||
//"-9179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368",
|
||||
'0x14',
|
||||
'-15',
|
||||
'-16.5',
|
||||
'-17.0',
|
||||
(string) PHP_INT_MAX * 2,
|
||||
(string) PHP_INT_MIN * 2,
|
||||
[],
|
||||
STDERR,
|
||||
new stdClass(),
|
||||
new ArrayObject(),
|
||||
new A(),
|
||||
new B(),
|
||||
];
|
||||
|
||||
$failures = [];
|
||||
$failuresNb = 0;
|
||||
$testCasesTotal = 0;
|
||||
|
||||
$var_dim_filename = __DIR__ . DIRECTORY_SEPARATOR . 'test_variable_offsets.inc';
|
||||
105
Zend/tests/offsets/test_variable_offsets.inc
Normal file
105
Zend/tests/offsets/test_variable_offsets.inc
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
//$container var declaration in const generated file
|
||||
|
||||
// Read before write
|
||||
try {
|
||||
echo "Read before write:\n";
|
||||
var_dump($container[$dimension]);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Write
|
||||
try {
|
||||
echo "Write:\n";
|
||||
$container[$dimension] = 5;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Read
|
||||
try {
|
||||
echo "Read:\n";
|
||||
var_dump($container[$dimension]);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Read-Write
|
||||
try {
|
||||
echo "Read-Write:\n";
|
||||
$container[$dimension] += 20;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Is
|
||||
try {
|
||||
echo "isset():\n";
|
||||
var_dump(isset($container[$dimension]));
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
echo "empty():\n";
|
||||
var_dump(empty($container[$dimension]));
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
echo "null coalesce:\n";
|
||||
var_dump($container[$dimension] ?? 'default');
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Unset
|
||||
try {
|
||||
echo "unset():\n";
|
||||
unset($container[$dimension]);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Nested read
|
||||
try {
|
||||
echo "Nested read:\n";
|
||||
var_dump($container[$dimension][$dimension]);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Nested write
|
||||
try {
|
||||
echo "Nested write:\n";
|
||||
$container[$dimension][$dimension] = 5;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Nested Read-Write
|
||||
try {
|
||||
echo "Nested Read-Write:\n";
|
||||
$container[$dimension][$dimension] += 25;
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Nested Is
|
||||
try {
|
||||
echo "Nested isset():\n";
|
||||
var_dump(isset($container[$dimension][$dimension]));
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
echo "Nested empty():\n";
|
||||
var_dump(empty($container[$dimension][$dimension]));
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
echo "Nested null coalesce:\n";
|
||||
var_dump($container[$dimension][$dimension] ?? 'default');
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
// Nested unset
|
||||
try {
|
||||
echo "Nested unset():\n";
|
||||
unset($container[$dimension][$dimension]);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
@@ -232,6 +232,52 @@ ZEND_METHOD(NumericCastableNoOperations, __construct)
|
||||
ZVAL_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), n);
|
||||
}
|
||||
|
||||
static zend_class_entry *dimension_handlers_no_ArrayAccess_ce;
|
||||
static zend_object_handlers dimension_handlers_no_ArrayAccess_object_handlers;
|
||||
|
||||
static zend_object* dimension_handlers_no_ArrayAccess_object_create(zend_class_entry* ce) {
|
||||
zend_object *object = zend_objects_new(ce);
|
||||
object_properties_init(object, ce);
|
||||
object->handlers = &dimension_handlers_no_ArrayAccess_object_handlers;
|
||||
return object;
|
||||
}
|
||||
|
||||
static void dimension_common_helper(zend_object *object, zval *offset, int prop_access_type) {
|
||||
ZVAL_BOOL(OBJ_PROP_NUM(object, prop_access_type), true);
|
||||
/* hasOffset */
|
||||
ZVAL_BOOL(OBJ_PROP_NUM(object, 5), offset != NULL);
|
||||
if (offset) {
|
||||
ZVAL_COPY(OBJ_PROP_NUM(object, 7), offset);
|
||||
}
|
||||
}
|
||||
|
||||
static zval* dimension_handlers_no_ArrayAccess_read_dimension(zend_object *object, zval *offset, int type, zval *rv) {
|
||||
dimension_common_helper(object, offset, 0);
|
||||
/* ReadType */
|
||||
ZVAL_LONG(OBJ_PROP_NUM(object, 4), type);
|
||||
|
||||
/* Normal logic */
|
||||
ZVAL_BOOL(rv, true);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void dimension_handlers_no_ArrayAccess_write_dimension(zend_object *object, zval *offset, zval *value) {
|
||||
dimension_common_helper(object, offset, 1);
|
||||
}
|
||||
|
||||
static int dimension_handlers_no_ArrayAccess_has_dimension(zend_object *object, zval *offset, int check_empty) {
|
||||
/* checkEmpty */
|
||||
ZVAL_LONG(OBJ_PROP_NUM(object, 6), check_empty);
|
||||
dimension_common_helper(object, offset, 2);
|
||||
|
||||
/* Normal logic */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dimension_handlers_no_ArrayAccess_unset_dimension(zend_object *object, zval *offset) {
|
||||
dimension_common_helper(object, offset, 3);
|
||||
}
|
||||
|
||||
void zend_test_object_handlers_init(void)
|
||||
{
|
||||
/* DoOperationNoCast class */
|
||||
@@ -255,4 +301,12 @@ void zend_test_object_handlers_init(void)
|
||||
numeric_castable_no_operation_ce->create_object = numeric_castable_no_operation_object_create;
|
||||
memcpy(&numeric_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
numeric_castable_no_operation_object_handlers.cast_object = numeric_castable_no_operation_cast_object;
|
||||
|
||||
dimension_handlers_no_ArrayAccess_ce = register_class_DimensionHandlersNoArrayAccess();
|
||||
dimension_handlers_no_ArrayAccess_ce->create_object = dimension_handlers_no_ArrayAccess_object_create;
|
||||
memcpy(&dimension_handlers_no_ArrayAccess_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
dimension_handlers_no_ArrayAccess_object_handlers.read_dimension = dimension_handlers_no_ArrayAccess_read_dimension;
|
||||
dimension_handlers_no_ArrayAccess_object_handlers.write_dimension = dimension_handlers_no_ArrayAccess_write_dimension;
|
||||
dimension_handlers_no_ArrayAccess_object_handlers.has_dimension = dimension_handlers_no_ArrayAccess_has_dimension;
|
||||
dimension_handlers_no_ArrayAccess_object_handlers.unset_dimension = dimension_handlers_no_ArrayAccess_unset_dimension;
|
||||
}
|
||||
|
||||
@@ -22,3 +22,14 @@ final class NumericCastableNoOperations {
|
||||
private int|float $val;
|
||||
public function __construct(int|float $val) {}
|
||||
}
|
||||
|
||||
class DimensionHandlersNoArrayAccess {
|
||||
public bool $read = false;
|
||||
public bool $write = false;
|
||||
public bool $has = false;
|
||||
public bool $unset = false;
|
||||
public int $readType;
|
||||
public bool $hasOffset = false;
|
||||
public int $checkEmpty;
|
||||
public mixed $offset;
|
||||
}
|
||||
|
||||
65
ext/zend_test/object_handlers_arginfo.h
generated
65
ext/zend_test/object_handlers_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 164cdd464289c8db351f4ec49979a66d44ba3e87 */
|
||||
* Stub hash: 81be60f2c465ffe5c036739d072ab80d9c388907 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DoOperationNoCast___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, val, IS_LONG, 0)
|
||||
@@ -45,6 +45,11 @@ static const zend_function_entry class_NumericCastableNoOperations_methods[] = {
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
|
||||
static const zend_function_entry class_DimensionHandlersNoArrayAccess_methods[] = {
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
static zend_class_entry *register_class_DoOperationNoCast(void)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
@@ -112,3 +117,61 @@ static zend_class_entry *register_class_NumericCastableNoOperations(void)
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_DimensionHandlersNoArrayAccess(void)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "DimensionHandlersNoArrayAccess", class_DimensionHandlersNoArrayAccess_methods);
|
||||
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
||||
|
||||
zval property_read_default_value;
|
||||
ZVAL_FALSE(&property_read_default_value);
|
||||
zend_string *property_read_name = zend_string_init("read", sizeof("read") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_read_name, &property_read_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_read_name);
|
||||
|
||||
zval property_write_default_value;
|
||||
ZVAL_FALSE(&property_write_default_value);
|
||||
zend_string *property_write_name = zend_string_init("write", sizeof("write") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_write_name, &property_write_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_write_name);
|
||||
|
||||
zval property_has_default_value;
|
||||
ZVAL_FALSE(&property_has_default_value);
|
||||
zend_string *property_has_name = zend_string_init("has", sizeof("has") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_has_name, &property_has_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_has_name);
|
||||
|
||||
zval property_unset_default_value;
|
||||
ZVAL_FALSE(&property_unset_default_value);
|
||||
zend_string *property_unset_name = zend_string_init("unset", sizeof("unset") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_unset_name, &property_unset_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_unset_name);
|
||||
|
||||
zval property_readType_default_value;
|
||||
ZVAL_UNDEF(&property_readType_default_value);
|
||||
zend_string *property_readType_name = zend_string_init("readType", sizeof("readType") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_readType_name, &property_readType_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
|
||||
zend_string_release(property_readType_name);
|
||||
|
||||
zval property_hasOffset_default_value;
|
||||
ZVAL_FALSE(&property_hasOffset_default_value);
|
||||
zend_string *property_hasOffset_name = zend_string_init("hasOffset", sizeof("hasOffset") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_hasOffset_name, &property_hasOffset_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
|
||||
zend_string_release(property_hasOffset_name);
|
||||
|
||||
zval property_checkEmpty_default_value;
|
||||
ZVAL_UNDEF(&property_checkEmpty_default_value);
|
||||
zend_string *property_checkEmpty_name = zend_string_init("checkEmpty", sizeof("checkEmpty") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_checkEmpty_name, &property_checkEmpty_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
|
||||
zend_string_release(property_checkEmpty_name);
|
||||
|
||||
zval property_offset_default_value;
|
||||
ZVAL_UNDEF(&property_offset_default_value);
|
||||
zend_string *property_offset_name = zend_string_init("offset", sizeof("offset") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_offset_name, &property_offset_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY));
|
||||
zend_string_release(property_offset_name);
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user