1--TEST--
2Test debug_zval_dump() function : working on objects
3--SKIPIF--
4<?php
5if (PHP_ZTS) { print "skip only for no-zts build"; }
6?>
7--INI--
8opcache.enable=0
9--FILE--
10<?php
11function zval_dump( $values ) {
12  $counter = 1;
13  foreach( $values as $value ) {
14    echo "-- Iteration $counter --\n";
15    debug_zval_dump( $value );
16    $counter++;
17  }
18}
19
20/* checking on objects type */
21echo "*** Testing debug_zval_dump() on objects ***\n";
22#[AllowDynamicProperties]
23class object_class {
24  var $value1 = 1;
25  private $value2 = 10;
26  protected $value3 = 20;
27  public $value4 = 30;
28
29  private function foo1() {
30    echo "function foo1\n";
31  }
32  protected function foo2() {
33    echo "function foo2\n";
34  }
35  public function foo3() {
36    echo "function foo3\n";
37  }
38  public $array_var  = array( "key1" => 1, "key2 " => 3);
39
40  function __construct () {
41      $this->value1 = 5;
42      $this->object_class1 = $this;
43  }
44}
45
46class no_member_class{
47//no members
48}
49
50/* class with member as object of other class */
51#[AllowDynamicProperties]
52class contains_object_class
53{
54   var       $p = 30;
55   protected $p1 = 40;
56   private   $p2 = 50;
57   var       $class_object1;
58   public    $class_object2;
59   private   $class_object3;
60   protected $class_object4;
61   var       $no_member_class_object;
62
63   public function func() {
64     echo "func() is called \n";
65   }
66
67   function __construct () {
68     $this->class_object1 = new object_class();
69     $this->class_object2 = new object_class();
70     $this->class_object3 = $this->class_object1;
71     $this->class_object4 = $this->class_object2;
72     $this->no_member_class_object = new no_member_class();
73     $this->class_object5 = $this;   //recursive reference
74   }
75}
76
77/* creating new object $obj */
78$obj = new contains_object_class();
79$obj1 = & $obj;  //object $obj1 references object $obj
80$obj2 = & $obj;
81$obj3 = & $obj2;
82
83/* object which is unset */
84$unset_obj = new object_class();
85unset($unset_obj);
86
87$objects = array (
88  new object_class,
89  new no_member_class,
90  $obj,
91  $obj->class_object1,
92  $obj->class_object2,
93  $obj->no_member_class_object,
94  @$temp_class_obj,  //undefined object
95  $obj2->class_object1,
96  $obj3->class_object2,
97  $obj2->class_object1->value4,
98  @$unset_obj
99);
100/* using zval_dump() to dump out the objects and its reference count */
101zval_dump($objects);
102
103$int_var = 500;
104$obj = $int_var;  //$obj is lost, $obj1,$obj2,$obj3,$obj4 = 500
105echo "\n-- Testing debug_zval_dump() on overwritten object variables --\n";
106debug_zval_dump($obj, $obj1, $obj2, $obj3);
107
108echo "\n-- Testing debug_zval_dump() on objects having circular reference --\n";
109$recursion_obj1 = new object_class();
110$recursion_obj2 = new object_class();
111$recursion_obj1->obj = &$recursion_obj2;  //circular reference
112$recursion_obj2->obj = &$recursion_obj1;  //circular reference
113debug_zval_dump($recursion_obj2);
114
115echo "Done\n";
116?>
117--EXPECTF--
118*** Testing debug_zval_dump() on objects ***
119-- Iteration 1 --
120object(object_class)#%d (6) refcount(%d){
121  ["value1"]=>
122  int(5)
123  ["value2":"object_class":private]=>
124  int(10)
125  ["value3":protected]=>
126  int(20)
127  ["value4"]=>
128  int(30)
129  ["array_var"]=>
130  array(2) refcount(%d){
131    ["key1"]=>
132    int(1)
133    ["key2 "]=>
134    int(3)
135  }
136  ["object_class1"]=>
137  *RECURSION*
138}
139-- Iteration 2 --
140object(no_member_class)#%d (0) refcount(%d){
141}
142-- Iteration 3 --
143object(contains_object_class)#%d (9) refcount(%d){
144  ["p"]=>
145  int(30)
146  ["p1":protected]=>
147  int(40)
148  ["p2":"contains_object_class":private]=>
149  int(50)
150  ["class_object1"]=>
151  object(object_class)#%d (6) refcount(%d){
152    ["value1"]=>
153    int(5)
154    ["value2":"object_class":private]=>
155    int(10)
156    ["value3":protected]=>
157    int(20)
158    ["value4"]=>
159    int(30)
160    ["array_var"]=>
161    array(2) refcount(%d){
162      ["key1"]=>
163      int(1)
164      ["key2 "]=>
165      int(3)
166    }
167    ["object_class1"]=>
168    *RECURSION*
169  }
170  ["class_object2"]=>
171  object(object_class)#%d (6) refcount(%d){
172    ["value1"]=>
173    int(5)
174    ["value2":"object_class":private]=>
175    int(10)
176    ["value3":protected]=>
177    int(20)
178    ["value4"]=>
179    int(30)
180    ["array_var"]=>
181    array(2) refcount(%d){
182      ["key1"]=>
183      int(1)
184      ["key2 "]=>
185      int(3)
186    }
187    ["object_class1"]=>
188    *RECURSION*
189  }
190  ["class_object3":"contains_object_class":private]=>
191  object(object_class)#%d (6) refcount(%d){
192    ["value1"]=>
193    int(5)
194    ["value2":"object_class":private]=>
195    int(10)
196    ["value3":protected]=>
197    int(20)
198    ["value4"]=>
199    int(30)
200    ["array_var"]=>
201    array(2) refcount(%d){
202      ["key1"]=>
203      int(1)
204      ["key2 "]=>
205      int(3)
206    }
207    ["object_class1"]=>
208    *RECURSION*
209  }
210  ["class_object4":protected]=>
211  object(object_class)#%d (6) refcount(%d){
212    ["value1"]=>
213    int(5)
214    ["value2":"object_class":private]=>
215    int(10)
216    ["value3":protected]=>
217    int(20)
218    ["value4"]=>
219    int(30)
220    ["array_var"]=>
221    array(2) refcount(%d){
222      ["key1"]=>
223      int(1)
224      ["key2 "]=>
225      int(3)
226    }
227    ["object_class1"]=>
228    *RECURSION*
229  }
230  ["no_member_class_object"]=>
231  object(no_member_class)#%d (0) refcount(%d){
232  }
233  ["class_object5"]=>
234  *RECURSION*
235}
236-- Iteration 4 --
237object(object_class)#%d (6) refcount(%d){
238  ["value1"]=>
239  int(5)
240  ["value2":"object_class":private]=>
241  int(10)
242  ["value3":protected]=>
243  int(20)
244  ["value4"]=>
245  int(30)
246  ["array_var"]=>
247  array(2) refcount(%d){
248    ["key1"]=>
249    int(1)
250    ["key2 "]=>
251    int(3)
252  }
253  ["object_class1"]=>
254  *RECURSION*
255}
256-- Iteration 5 --
257object(object_class)#%d (6) refcount(%d){
258  ["value1"]=>
259  int(5)
260  ["value2":"object_class":private]=>
261  int(10)
262  ["value3":protected]=>
263  int(20)
264  ["value4"]=>
265  int(30)
266  ["array_var"]=>
267  array(2) refcount(%d){
268    ["key1"]=>
269    int(1)
270    ["key2 "]=>
271    int(3)
272  }
273  ["object_class1"]=>
274  *RECURSION*
275}
276-- Iteration 6 --
277object(no_member_class)#%d (0) refcount(%d){
278}
279-- Iteration 7 --
280NULL
281-- Iteration 8 --
282object(object_class)#%d (6) refcount(%d){
283  ["value1"]=>
284  int(5)
285  ["value2":"object_class":private]=>
286  int(10)
287  ["value3":protected]=>
288  int(20)
289  ["value4"]=>
290  int(30)
291  ["array_var"]=>
292  array(2) refcount(%d){
293    ["key1"]=>
294    int(1)
295    ["key2 "]=>
296    int(3)
297  }
298  ["object_class1"]=>
299  *RECURSION*
300}
301-- Iteration 9 --
302object(object_class)#%d (6) refcount(%d){
303  ["value1"]=>
304  int(5)
305  ["value2":"object_class":private]=>
306  int(10)
307  ["value3":protected]=>
308  int(20)
309  ["value4"]=>
310  int(30)
311  ["array_var"]=>
312  array(2) refcount(%d){
313    ["key1"]=>
314    int(1)
315    ["key2 "]=>
316    int(3)
317  }
318  ["object_class1"]=>
319  *RECURSION*
320}
321-- Iteration 10 --
322int(30)
323-- Iteration 11 --
324NULL
325
326-- Testing debug_zval_dump() on overwritten object variables --
327int(500)
328int(500)
329int(500)
330int(500)
331
332-- Testing debug_zval_dump() on objects having circular reference --
333object(object_class)#%d (7) refcount(%d){
334  ["value1"]=>
335  int(5)
336  ["value2":"object_class":private]=>
337  int(10)
338  ["value3":protected]=>
339  int(20)
340  ["value4"]=>
341  int(30)
342  ["array_var"]=>
343  array(2) refcount(%d){
344    ["key1"]=>
345    int(1)
346    ["key2 "]=>
347    int(3)
348  }
349  ["object_class1"]=>
350  *RECURSION*
351  ["obj"]=>
352  reference refcount(2) {
353    object(object_class)#8 (7) refcount(2){
354      ["value1"]=>
355      int(5)
356      ["value2":"object_class":private]=>
357      int(10)
358      ["value3":protected]=>
359      int(20)
360      ["value4"]=>
361      int(30)
362      ["array_var"]=>
363      array(2) refcount(7){
364        ["key1"]=>
365        int(1)
366        ["key2 "]=>
367        int(3)
368      }
369      ["object_class1"]=>
370      *RECURSION*
371      ["obj"]=>
372      reference refcount(2) {
373        *RECURSION*
374      }
375    }
376  }
377}
378Done
379