1
/* Copyright 2002-2004 Elliotte Rusty Harold
3
This library is free software; you can redistribute it and/or modify
4
it under the terms of version 2.1 of the GNU Lesser General Public
5
License as published by the Free Software Foundation.
7
This library is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU Lesser General Public License for more details.
12
You should have received a copy of the GNU Lesser General Public
13
License along with this library; if not, write to the
14
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15
Boston, MA 02111-1307 USA
17
You can contact Elliotte Rusty Harold by sending e-mail to
18
elharo@metalab.unc.edu. Please include the word "XOM" in the
19
subject line. The XOM home page is located at http://www.xom.nu/
24
import nu.xom.Comment;
25
import nu.xom.CycleException;
26
import nu.xom.DocType;
27
import nu.xom.Document;
28
import nu.xom.Element;
29
import nu.xom.IllegalAddException;
30
import nu.xom.MultipleParentException;
31
import nu.xom.NoSuchChildException;
33
import nu.xom.ProcessingInstruction;
39
* Tests adding, removing, and counting children from parent nodes.
42
* @author Elliotte Rusty Harold
46
public class ParentNodeTest extends XOMTestCase {
48
public ParentNodeTest(String name) {
53
private Element empty;
54
private Element notEmpty;
58
protected void setUp() {
59
empty = new Element("Empty");
60
notEmpty = new Element("NotEmpty");
61
child = new Text("Hello");
62
notEmpty.appendChild(child);
66
public void testDetach() {
68
Text text = new Text("This will be attached then detached");
69
empty.appendChild(text);
70
assertEquals(empty, text.getParent());
72
assertNull(text.getParent());
77
public void testAppendChild() {
79
Element child = new Element("test");
80
empty.appendChild(child);
81
assertEquals(1, empty.getChildCount());
82
assertEquals(empty.getChild(0), child);
85
notEmpty.appendChild(child);
86
assertTrue(!notEmpty.getChild(0).equals(child));
87
assertTrue(notEmpty.getChild(1).equals(child));
92
public void testAppendChildToItself() {
94
Element child = new Element("test");
96
child.appendChild(child);
97
fail("Appended node to itself");
99
catch (CycleException success) {
100
assertNotNull(success.getMessage());
106
public void testCycle() {
108
Element a = new Element("test");
109
Element b = new Element("test");
113
fail("Allowed cycle");
115
catch (CycleException success) {
116
assertNotNull(success.getMessage());
121
public void testInsertChild() {
123
Element parent = new Element("parent");
125
// Test insert into empty element
126
Element child1 = new Element("child");
127
parent.insertChild(child1, 0);
128
assertTrue(parent.getChildCount() > 0);
129
assertEquals(0, parent.indexOf(child1));
131
// Test insert at beginning
132
Element child2 = new Element("child2");
133
parent.insertChild(child2, 0);
134
assertEquals(0, parent.indexOf(child2));
135
assertEquals(1, parent.indexOf(child1));
137
// Test insert in middle
138
Element child3 = new Element("child3");
139
parent.insertChild(child3, 1);
140
assertEquals(0, parent.indexOf(child2));
141
assertEquals(1, parent.indexOf(child3));
142
assertEquals(2, parent.indexOf(child1));
144
// Test insert at beginning with children
145
Element child4 = new Element("child4");
146
parent.insertChild(child4, 0);
147
assertEquals(0, parent.indexOf(child4));
148
assertEquals(1, parent.indexOf(child2));
149
assertEquals(2, parent.indexOf(child3));
150
assertEquals(3, parent.indexOf(child1));
152
// Test insert at end with children
153
Element child5 = new Element("child5");
154
parent.insertChild(child5, 4);
155
assertEquals(0, parent.indexOf(child4));
156
assertEquals(1, parent.indexOf(child2));
157
assertEquals(2, parent.indexOf(child3));
158
assertEquals(3, parent.indexOf(child1));
159
assertEquals(4, parent.indexOf(child5));
162
parent.insertChild((Element) null, 0);
163
fail("Inserted null");
165
catch (NullPointerException success) {
166
assertNotNull(success.getMessage());
170
parent.insertChild((Text) null, 0);
171
fail("Inserted null");
173
catch (NullPointerException success) {
174
assertNotNull(success.getMessage());
178
parent.insertChild((Comment) null, 0);
179
fail("Inserted null");
181
catch (NullPointerException success) {
182
assertNotNull(success.getMessage());
186
parent.insertChild((ProcessingInstruction) null, 0);
187
fail("Inserted null");
189
catch (NullPointerException success) {
190
assertNotNull(success.getMessage());
196
public void testAppendChild2() {
199
empty.appendChild(new Document(notEmpty));
200
fail("appended a document to an element");
202
catch (IllegalAddException success) {
203
assertNotNull(success.getMessage());
207
empty.appendChild(child);
208
fail("appended a child twice");
210
catch (MultipleParentException success) {
211
assertNotNull(success.getMessage());
217
public void testReplaceChild() {
219
Element old1 = new Element("old1");
220
Element old2 = new Element("old2");
221
Element old3 = new Element("old3");
222
Element new1 = new Element("new1");
223
Element new2 = new Element("new2");
224
Element new3 = new Element("new3");
226
empty.appendChild(old1);
227
empty.appendChild(old2);
228
empty.appendChild(old3);
230
empty.replaceChild(old1, new1);
231
empty.replaceChild(old3, new3);
232
empty.replaceChild(old2, new2);
234
Node current1 = empty.getChild(0);
235
Node current2 = empty.getChild(1);
236
Node current3 = empty.getChild(2);
238
assertEquals(new1, current1);
239
assertEquals(new2, current2);
240
assertEquals(new3, current3);
243
empty.replaceChild(new1, null);
245
catch (NullPointerException success) {
246
assertNotNull(success.getMessage());
250
empty.replaceChild(null, old1);
252
catch (NullPointerException success) {
253
assertNotNull(success.getMessage());
256
Element new4 = new Element("new4");
259
empty.replaceChild(new4, new Element("test"));
260
fail("Replaced Nonexistent element");
262
catch (NoSuchChildException success) {
263
assertNotNull(success.getMessage());
266
// Test replacing node with itself
267
empty.replaceChild(new1, new1);
268
assertEquals(new1, empty.getChild(0));
269
assertEquals(empty, new1.getParent());
271
// Test replacing node with a sibling
273
empty.replaceChild(new1, new2);
274
fail("replaced a node with its sibling");
276
catch (MultipleParentException success) {
277
assertNotNull(success.getMessage());
284
public void testIndexOf() {
286
Element child1 = new Element("old1");
287
Text child2 = new Text("old2");
288
Comment child3 = new Comment("old3");
290
assertEquals(-1, empty.indexOf(child1));
292
empty.appendChild(child1);
293
empty.appendChild(child2);
294
empty.appendChild(child3);
296
assertEquals(0, empty.indexOf(child1));
297
assertEquals(1, empty.indexOf(child2));
298
assertEquals(2, empty.indexOf(child3));
299
assertEquals(-1, empty.indexOf(empty));
300
assertEquals(-1, empty.indexOf(new Text("test")));
305
public void testGetChild() {
307
Element old1 = new Element("old1");
308
Element old2 = new Element("old2");
309
Element old3 = new Element("old3");
313
fail("No index exception");
315
catch (IndexOutOfBoundsException success) {
317
assertNotNull(success.getMessage());
320
empty.appendChild(old1);
321
empty.appendChild(old2);
322
empty.appendChild(old3);
324
assertEquals(old1, empty.getChild(0));
325
assertEquals(old3, empty.getChild(2));
326
assertEquals(old2, empty.getChild(1));
330
fail("No index exception");
332
catch (IndexOutOfBoundsException success) {
334
assertNotNull(success.getMessage());
340
public void testRemoveChild() {
343
empty.removeChild(0);
344
fail("Removed child from empty element");
346
catch (IndexOutOfBoundsException success) {
347
assertNotNull(success.getMessage());
350
Element old1 = new Element("old1");
351
Element old2 = new Element("old2");
352
Element old3 = new Element("old3");
355
empty.removeChild(old1);
356
fail("Removed non-existent child from empty element");
358
catch (NoSuchChildException success) {
359
assertNotNull(success.getMessage());
362
empty.appendChild(old1);
363
empty.appendChild(old2);
364
empty.appendChild(old3);
366
empty.removeChild(1);
367
assertEquals(old1, empty.getChild(0));
368
assertEquals(old3, empty.getChild(1));
371
empty.removeChild(5);
372
fail("No IndexOutOfBoundsException");
374
catch (IndexOutOfBoundsException success) {
375
assertNotNull(success.getMessage());
378
empty.removeChild(1);
379
empty.removeChild(0);
380
assertNull(old2.getParent());
382
assertEquals(0, empty.getChildCount());
384
empty.appendChild(old1);
385
empty.appendChild(old2);
386
empty.appendChild(old3);
388
assertEquals(3, empty.getChildCount());
390
empty.removeChild(old3);
391
empty.removeChild(old1);
392
empty.removeChild(old2);
394
assertEquals(0, empty.getChildCount());
395
assertNull(old1.getParent());
400
public void testReplaceChildFailures() {
402
Element old1 = new Element("old1");
403
Element old2 = new Element("old2");
404
Element old3 = new Element("old3");
405
Element new1 = new Element("new1");
406
Element new3 = new Element("new3");
408
empty.appendChild(old1);
409
empty.appendChild(old2);
412
empty.replaceChild(old3, new3);
413
fail("Replaced non-existent child");
415
catch (NoSuchChildException success) {
416
assertNotNull(success.getMessage());
420
empty.replaceChild(old1, null);
421
fail("Replaced child with null");
423
catch (NullPointerException success) {
424
assertNotNull(success.getMessage());
428
empty.replaceChild(null, new1);
429
fail("Replaced null");
431
catch (NullPointerException success) {
432
assertNotNull(success.getMessage());
438
public void testReplaceChildInEmptyParent() {
440
Element test1 = new Element("test");
441
Element test2 = new Element("test");
443
empty.replaceChild(test1, test2);
444
fail("Replaced element in empty parent");
446
catch (NoSuchChildException success) {
447
assertNotNull(success.getMessage());
453
// Document that this behavior is intentional
454
// An element cannot be replaced by its sibling unless
455
// the sibling is first detached.
456
public void testReplaceSibling() {
458
Element parent = new Element("parent");
459
Element test1 = new Element("test");
460
Element test2 = new Element("test");
461
parent.appendChild(test1);
462
parent.appendChild(test2);
464
parent.replaceChild(test1, test2);
465
fail("Replaced element without detaching first");
467
catch (IllegalAddException success) {
468
assertNotNull(success.getMessage());
471
assertEquals(2, parent.getChildCount());
472
assertEquals(parent, test1.getParent());
473
assertEquals(parent, test2.getParent());
478
// Similarly, this test documents the conscious decision
479
// that you cannot insert an existing child into its own parent,
480
// even at the same position
481
public void testCantInsertExisitngChild() {
483
Element parent = new Element("parent");
484
Element test1 = new Element("test");
485
Element test2 = new Element("test");
486
parent.appendChild(test1);
487
parent.appendChild(test2);
489
parent.insertChild(test2, 0);
490
fail("Inserted element without detaching first");
492
catch (MultipleParentException success) {
493
assertNotNull(success.getMessage());
497
parent.insertChild(test2, 1);
498
fail("Inserted element without detaching first");
500
catch (MultipleParentException success) {
501
assertNotNull(success.getMessage());
504
assertEquals(2, parent.getChildCount());
505
assertEquals(parent, test1.getParent());
506
assertEquals(parent, test2.getParent());
511
// can't remove when insertion is legal;
512
// succeeed or fail as unit
513
public void testReplaceChildAtomicity() {
515
Element parent = new Element("parent");
516
Text child = new Text("child");
517
parent.appendChild(child);
520
parent.replaceChild(child, new DocType("root"));
521
fail("allowed doctype child of element");
523
catch (IllegalAddException success) {
524
assertEquals(parent, child.getParent());
525
assertEquals(1, parent.getChildCount());
528
Element e = new Element("e");
529
Text child2 = new Text("child2");
530
e.appendChild(child2);
532
parent.replaceChild(child, child2);
533
fail("allowed replacement with existing parent");
535
catch (MultipleParentException success) {
536
assertEquals(e, child2.getParent());
537
assertEquals(parent, child.getParent());
538
assertEquals(1, parent.getChildCount());
539
assertEquals(1, e.getChildCount());