xref: /php-src/ext/dom/tests/gh13863.phpt (revision 6e7adb3c)
1--TEST--
2GH-13863 (Removal during NodeList iteration breaks loop)
3--EXTENSIONS--
4dom
5--FILE--
6<?php
7
8enum DomType {
9    case Legacy;
10    case Modern;
11}
12
13function createTestDoc(DomType $type) {
14    $xml = <<<EOXML
15    <x>
16        <item1 />
17        <item2 />
18        <item3 />
19        <item4 />
20        <item5 />
21    </x>
22    EOXML;
23
24    if ($type === DomType::Legacy) {
25        $doc = new DOMDocument();
26        $doc->preserveWhiteSpace = false;
27        $doc->loadXML($xml);
28    } else {
29        $doc = Dom\XMLDocument::createFromString($xml, LIBXML_NOBLANKS);
30    }
31
32    return $doc;
33}
34
35foreach ([DomType::Legacy, DomType::Modern] as $case) {
36    $name = match ($case) {
37        DomType::Legacy => 'Legacy',
38        DomType::Modern => 'Modern',
39    };
40
41    echo "--- $name test remove index 2 at index 2 ---\n";
42
43    $doc = createTestDoc($case);
44
45    foreach ($doc->documentElement->childNodes as $i => $node) {
46        var_dump($doc->documentElement->childNodes->item($i) === $node);
47        var_dump($i, $node->localName);
48        if ($i === 2) {
49            $node->remove();
50        }
51    }
52
53    echo $doc->saveXML(), "\n";
54
55    echo "--- $name test remove index 1 at index 2 ---\n";
56
57    $doc = createTestDoc($case);
58
59    foreach ($doc->documentElement->childNodes as $i => $node) {
60        var_dump($doc->documentElement->childNodes->item($i) === $node);
61        var_dump($i, $node->localName);
62        if ($i === 2) {
63            $doc->documentElement->childNodes[1]->remove();
64        }
65    }
66
67    echo $doc->saveXML(), "\n";
68
69    echo "--- $name test remove all ---\n";
70
71    $doc = createTestDoc($case);
72
73    foreach ($doc->documentElement->childNodes as $i => $node) {
74        var_dump($doc->documentElement->childNodes->item($i) === $node);
75        var_dump($i, $node->localName);
76        $node->remove();
77    }
78
79    echo $doc->saveXML(), "\n";
80}
81
82?>
83--EXPECT--
84--- Legacy test remove index 2 at index 2 ---
85bool(true)
86int(0)
87string(5) "item1"
88bool(true)
89int(1)
90string(5) "item2"
91bool(true)
92int(2)
93string(5) "item3"
94<?xml version="1.0"?>
95<x><item1/><item2/><item4/><item5/></x>
96
97--- Legacy test remove index 1 at index 2 ---
98bool(true)
99int(0)
100string(5) "item1"
101bool(true)
102int(1)
103string(5) "item2"
104bool(true)
105int(2)
106string(5) "item3"
107bool(false)
108int(3)
109string(5) "item4"
110bool(false)
111int(4)
112string(5) "item5"
113<?xml version="1.0"?>
114<x><item1/><item3/><item4/><item5/></x>
115
116--- Legacy test remove all ---
117bool(true)
118int(0)
119string(5) "item1"
120<?xml version="1.0"?>
121<x><item2/><item3/><item4/><item5/></x>
122
123--- Modern test remove index 2 at index 2 ---
124bool(true)
125int(0)
126string(5) "item1"
127bool(true)
128int(1)
129string(5) "item2"
130bool(true)
131int(2)
132string(5) "item3"
133bool(true)
134int(3)
135string(5) "item5"
136<?xml version="1.0" encoding="UTF-8"?>
137<x><item1/><item2/><item4/><item5/></x>
138--- Modern test remove index 1 at index 2 ---
139bool(true)
140int(0)
141string(5) "item1"
142bool(true)
143int(1)
144string(5) "item2"
145bool(true)
146int(2)
147string(5) "item3"
148bool(true)
149int(3)
150string(5) "item5"
151<?xml version="1.0" encoding="UTF-8"?>
152<x><item1/><item3/><item4/><item5/></x>
153--- Modern test remove all ---
154bool(true)
155int(0)
156string(5) "item1"
157bool(true)
158int(1)
159string(5) "item3"
160bool(true)
161int(2)
162string(5) "item5"
163<?xml version="1.0" encoding="UTF-8"?>
164<x><item2/><item4/></x>
165