Daily bump.
[official-gcc.git] / libgo / go / exp / html / node_test.go
blob471102f3a2218e2d19c882fbc94e0c7d7b1fb046
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package html
7 import (
8 "fmt"
11 // checkTreeConsistency checks that a node and its descendants are all
12 // consistent in their parent/child/sibling relationships.
13 func checkTreeConsistency(n *Node) error {
14 return checkTreeConsistency1(n, 0)
17 func checkTreeConsistency1(n *Node, depth int) error {
18 if depth == 1e4 {
19 return fmt.Errorf("html: tree looks like it contains a cycle")
21 if err := checkNodeConsistency(n); err != nil {
22 return err
24 for c := n.FirstChild; c != nil; c = c.NextSibling {
25 if err := checkTreeConsistency1(c, depth+1); err != nil {
26 return err
29 return nil
32 // checkNodeConsistency checks that a node's parent/child/sibling relationships
33 // are consistent.
34 func checkNodeConsistency(n *Node) error {
35 if n == nil {
36 return nil
39 nParent := 0
40 for p := n.Parent; p != nil; p = p.Parent {
41 nParent++
42 if nParent == 1e4 {
43 return fmt.Errorf("html: parent list looks like an infinite loop")
47 nForward := 0
48 for c := n.FirstChild; c != nil; c = c.NextSibling {
49 nForward++
50 if nForward == 1e6 {
51 return fmt.Errorf("html: forward list of children looks like an infinite loop")
53 if c.Parent != n {
54 return fmt.Errorf("html: inconsistent child/parent relationship")
58 nBackward := 0
59 for c := n.LastChild; c != nil; c = c.PrevSibling {
60 nBackward++
61 if nBackward == 1e6 {
62 return fmt.Errorf("html: backward list of children looks like an infinite loop")
64 if c.Parent != n {
65 return fmt.Errorf("html: inconsistent child/parent relationship")
69 if n.Parent != nil {
70 if n.Parent == n {
71 return fmt.Errorf("html: inconsistent parent relationship")
73 if n.Parent == n.FirstChild {
74 return fmt.Errorf("html: inconsistent parent/first relationship")
76 if n.Parent == n.LastChild {
77 return fmt.Errorf("html: inconsistent parent/last relationship")
79 if n.Parent == n.PrevSibling {
80 return fmt.Errorf("html: inconsistent parent/prev relationship")
82 if n.Parent == n.NextSibling {
83 return fmt.Errorf("html: inconsistent parent/next relationship")
86 parentHasNAsAChild := false
87 for c := n.Parent.FirstChild; c != nil; c = c.NextSibling {
88 if c == n {
89 parentHasNAsAChild = true
90 break
93 if !parentHasNAsAChild {
94 return fmt.Errorf("html: inconsistent parent/child relationship")
98 if n.PrevSibling != nil && n.PrevSibling.NextSibling != n {
99 return fmt.Errorf("html: inconsistent prev/next relationship")
101 if n.NextSibling != nil && n.NextSibling.PrevSibling != n {
102 return fmt.Errorf("html: inconsistent next/prev relationship")
105 if (n.FirstChild == nil) != (n.LastChild == nil) {
106 return fmt.Errorf("html: inconsistent first/last relationship")
108 if n.FirstChild != nil && n.FirstChild == n.LastChild {
109 // We have a sole child.
110 if n.FirstChild.PrevSibling != nil || n.FirstChild.NextSibling != nil {
111 return fmt.Errorf("html: inconsistent sole child's sibling relationship")
115 seen := map[*Node]bool{}
117 var last *Node
118 for c := n.FirstChild; c != nil; c = c.NextSibling {
119 if seen[c] {
120 return fmt.Errorf("html: inconsistent repeated child")
122 seen[c] = true
123 last = c
125 if last != n.LastChild {
126 return fmt.Errorf("html: inconsistent last relationship")
129 var first *Node
130 for c := n.LastChild; c != nil; c = c.PrevSibling {
131 if !seen[c] {
132 return fmt.Errorf("html: inconsistent missing child")
134 delete(seen, c)
135 first = c
137 if first != n.FirstChild {
138 return fmt.Errorf("html: inconsistent first relationship")
141 if len(seen) != 0 {
142 return fmt.Errorf("html: inconsistent forwards/backwards child list")
145 return nil