OLD | NEW |
1 package utils | 1 package utils |
2 | 2 |
3 import ( | 3 import ( |
4 "bytes" | 4 "bytes" |
5 "fmt" | 5 "fmt" |
6 "strings" | 6 "strings" |
7 "testing" | 7 "testing" |
8 ) | 8 ) |
9 | 9 |
10 //////////////////////////////////////////////////// | 10 //////////////////////////////////////////////////// |
11 // SimpleNode type | 11 // SimpleNode type |
12 //////////////////////////////////////////////////// | 12 //////////////////////////////////////////////////// |
13 | 13 |
14 // SimpleNode is a simple implementation of the |Node| interface used | 14 // SimpleNode is a simple implementation of the |Node| interface used |
15 // for testing. | 15 // for testing. |
16 type SimpleNode struct { | 16 type SimpleNode struct { |
17 // The value of this node | 17 // The value of this node |
18 value int | 18 value int |
19 | 19 |
20 // Is this node a square node? | 20 // Is this node a square node? |
21 isSquare bool | 21 isSquare bool |
22 | 22 |
23 » // The list of out-edges. The elements will be *SimpleNodes. | 23 » // The list of out-edges. |
24 » edges []Node | 24 » edges []OutEdge |
25 | 25 |
26 // Cache the fact that |SetKnownWellFounded| has been invoked. | 26 // Cache the fact that |SetKnownWellFounded| has been invoked. |
27 knownWellFounded bool | 27 knownWellFounded bool |
28 } | 28 } |
29 | 29 |
30 func (node *SimpleNode) DebugName() string { | 30 func (node *SimpleNode) Name() string { |
31 return fmt.Sprintf("Node%d", node.value) | 31 return fmt.Sprintf("Node%d", node.value) |
32 } | 32 } |
33 | 33 |
34 func (node *SimpleNode) OutEdges() []Node { | 34 func (node *SimpleNode) OutEdges() []OutEdge { |
35 return node.edges | 35 return node.edges |
36 } | 36 } |
37 | 37 |
38 func (node *SimpleNode) IsSquare() bool { | 38 func (node *SimpleNode) IsSquare() bool { |
39 return node.isSquare | 39 return node.isSquare |
40 } | 40 } |
41 | 41 |
42 func (node *SimpleNode) KnownWellFounded() bool { | 42 func (node *SimpleNode) KnownWellFounded() bool { |
43 return node.knownWellFounded | 43 return node.knownWellFounded |
44 } | 44 } |
45 | 45 |
46 func (node *SimpleNode) SetKnownWellFounded() { | 46 func (node *SimpleNode) SetKnownWellFounded() { |
47 if node.knownWellFounded { | 47 if node.knownWellFounded { |
48 » » panic(fmt.Sprintf("SetKnownWellFounded invoked twice on %s", nod
e.DebugName())) | 48 » » panic(fmt.Sprintf("SetKnownWellFounded invoked twice on %s", nod
e.Name())) |
49 } | 49 } |
50 node.knownWellFounded = true | 50 node.knownWellFounded = true |
51 } | 51 } |
52 | 52 |
53 //Creates a new SimpleNode. | 53 //Creates a new SimpleNode. |
54 func NewNode(value, numEdges int, isSquare bool) *SimpleNode { | 54 func NewNode(value, numEdges int, isSquare bool) *SimpleNode { |
55 node := new(SimpleNode) | 55 node := new(SimpleNode) |
56 node.value = value | 56 node.value = value |
57 » node.edges = make([]Node, numEdges) | 57 » node.edges = make([]OutEdge, numEdges) |
58 node.isSquare = isSquare | 58 node.isSquare = isSquare |
59 return node | 59 return node |
60 } | 60 } |
61 | 61 |
62 //////////////////////////////////////////////////// | 62 //////////////////////////////////////////////////// |
63 // Test Utilities | 63 // Test Utilities |
64 //////////////////////////////////////////////////// | 64 //////////////////////////////////////////////////// |
65 | 65 |
66 // Builds a test graph containing only circle nodes. | 66 // Builds a test graph containing only circle nodes. |
67 // The connection matrix should have the following form: | 67 // The connection matrix should have the following form: |
(...skipping 14 matching lines...) Expand all Loading... |
82 squareMap[n] = true | 82 squareMap[n] = true |
83 } | 83 } |
84 } | 84 } |
85 nodes = make([]*SimpleNode, len(connectionMatrix)) | 85 nodes = make([]*SimpleNode, len(connectionMatrix)) |
86 for index, connectionList := range connectionMatrix { | 86 for index, connectionList := range connectionMatrix { |
87 _, isSquare := squareMap[index] | 87 _, isSquare := squareMap[index] |
88 nodes[index] = NewNode(index, len(connectionList), isSquare) | 88 nodes[index] = NewNode(index, len(connectionList), isSquare) |
89 } | 89 } |
90 for index, connectionList := range connectionMatrix { | 90 for index, connectionList := range connectionMatrix { |
91 for i, target := range connectionList { | 91 for i, target := range connectionList { |
92 » » » nodes[index].edges[i] = nodes[target] | 92 » » » nodes[index].edges[i] = OutEdge{"", nodes[target]} |
93 } | 93 } |
94 } | 94 } |
95 return | 95 return |
96 } | 96 } |
97 | 97 |
98 // expectedDebugData is used to store an expectation for the value of the |debug
Data| populated | 98 // expectedDebugData is used to store an expectation for the value of the |debug
Data| populated |
99 // by the ethod |checkWellFounded|. This data captures the result of phase 1 of
the algorithm. | 99 // by the ethod |checkWellFounded|. This data captures the result of phase 1 of
the algorithm. |
100 type expectedDebugData struct { | 100 type expectedDebugData struct { |
101 initialPendingSet []string | 101 initialPendingSet []string |
102 initialFoundationSet []string | 102 initialFoundationSet []string |
(...skipping 10 matching lines...) Expand all Loading... |
113 return compareNodeSlice(expected.initialFoundationSet, actual.initialFou
ndationSet, "initialFoundationSet") | 113 return compareNodeSlice(expected.initialFoundationSet, actual.initialFou
ndationSet, "initialFoundationSet") |
114 } | 114 } |
115 | 115 |
116 func compareNodeSlice(expected []string, actual []Node, name string) error { | 116 func compareNodeSlice(expected []string, actual []Node, name string) error { |
117 expectedMap := make(map[string]bool) | 117 expectedMap := make(map[string]bool) |
118 actualMap := make(map[string]bool) | 118 actualMap := make(map[string]bool) |
119 for _, n := range expected { | 119 for _, n := range expected { |
120 expectedMap[n] = true | 120 expectedMap[n] = true |
121 } | 121 } |
122 for _, n := range actual { | 122 for _, n := range actual { |
123 » » actualMap[n.DebugName()] = true | 123 » » actualMap[n.Name()] = true |
124 } | 124 } |
125 for _, n := range expected { | 125 for _, n := range expected { |
126 if _, ok := actualMap[n]; !ok { | 126 if _, ok := actualMap[n]; !ok { |
127 return fmt.Errorf("%s: missing %s, actual: %s", name, n,
NodeSliceToString(actual)) | 127 return fmt.Errorf("%s: missing %s, actual: %s", name, n,
NodeSliceToString(actual)) |
128 } | 128 } |
129 } | 129 } |
130 for _, n := range actual { | 130 for _, n := range actual { |
131 » » if _, ok := expectedMap[n.DebugName()]; !ok { | 131 » » if _, ok := expectedMap[n.Name()]; !ok { |
132 » » » return fmt.Errorf("%s: unexpected: %s, expected: %v, act
ual: %s", name, n.DebugName(), expected, NodeSliceToString(actual)) | 132 » » » return fmt.Errorf("%s: unexpected: %s, expected: %v, act
ual: %s", name, n.Name(), expected, NodeSliceToString(actual)) |
133 } | 133 } |
134 } | 134 } |
135 return nil | 135 return nil |
136 } | 136 } |
137 | 137 |
138 func NodeSliceToString(nodeSlice []Node) string { | 138 func NodeSliceToString(nodeSlice []Node) string { |
139 var buffer bytes.Buffer | 139 var buffer bytes.Buffer |
140 fmt.Fprintf(&buffer, "[") | 140 fmt.Fprintf(&buffer, "[") |
141 first := true | 141 first := true |
142 for _, n := range nodeSlice { | 142 for _, n := range nodeSlice { |
143 if !first { | 143 if !first { |
144 fmt.Fprintf(&buffer, ", ") | 144 fmt.Fprintf(&buffer, ", ") |
145 } | 145 } |
146 » » fmt.Fprintf(&buffer, "%s", n.DebugName()) | 146 » » fmt.Fprintf(&buffer, "%s", n.Name()) |
147 first = false | 147 first = false |
148 } | 148 } |
149 fmt.Fprintln(&buffer, "]") | 149 fmt.Fprintln(&buffer, "]") |
150 return buffer.String() | 150 return buffer.String() |
151 } | 151 } |
152 | 152 |
153 //////////////////////////////////////////////////// | 153 //////////////////////////////////////////////////// |
154 // Tests | 154 // Tests |
155 //////////////////////////////////////////////////// | 155 //////////////////////////////////////////////////// |
156 | 156 |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 } | 451 } |
452 if len(c.expectedPathA) == 0 { | 452 if len(c.expectedPathA) == 0 { |
453 if cycleDescription != nil { | 453 if cycleDescription != nil { |
454 t.Fatalf("Case %dA: Detected a cycle: %s", i, cy
cleDescription) | 454 t.Fatalf("Case %dA: Detected a cycle: %s", i, cy
cleDescription) |
455 } | 455 } |
456 } else { | 456 } else { |
457 if cycleDescription == nil { | 457 if cycleDescription == nil { |
458 t.Fatalf("Case %d: Expected a cycle.", i) | 458 t.Fatalf("Case %d: Expected a cycle.", i) |
459 } | 459 } |
460 if !strings.Contains(cycleDescription.String(), fmt.Spri
ntf("first:%s", c.expectedFirstA)) { | 460 if !strings.Contains(cycleDescription.String(), fmt.Spri
ntf("first:%s", c.expectedFirstA)) { |
461 » » » » t.Fatalf("Case %d: got=%s expectedFirst=%q", i,
cycleDescription.String(), c.expectedFirstA) | 461 » » » » t.Fatalf("Case %d: got=%s expectedFirstA=%q", i,
cycleDescription.String(), c.expectedFirstA) |
462 } | 462 } |
463 if !strings.Contains(cycleDescription.String(), fmt.Spri
ntf("last:%s", c.expectedLastA)) { | 463 if !strings.Contains(cycleDescription.String(), fmt.Spri
ntf("last:%s", c.expectedLastA)) { |
464 » » » » t.Fatalf("Case %d: got=%s expectedLast=%q", i, c
ycleDescription.String(), c.expectedLastA) | 464 » » » » t.Fatalf("Case %d: got=%s expectedLastA=%q", i,
cycleDescription.String(), c.expectedLastA) |
465 } | 465 } |
466 if !strings.Contains(cycleDescription.String(), fmt.Spri
ntf("{%s}", c.expectedPathA)) { | 466 if !strings.Contains(cycleDescription.String(), fmt.Spri
ntf("{%s}", c.expectedPathA)) { |
467 » » » » t.Fatalf("Case %d: got=%s expectedPath=%q", i, c
ycleDescription.String(), c.expectedPathA) | 467 » » » » t.Fatalf("Case %d: got=%s expectedPathA=%q", i,
cycleDescription.String(), c.expectedPathA) |
468 } | 468 } |
469 } | 469 } |
470 | 470 |
471 // Test from root=Node1 | 471 // Test from root=Node1 |
472 if len(graph) > 1 { | 472 if len(graph) > 1 { |
473 dbgData := debugData{} | 473 dbgData := debugData{} |
474 cycleDescription := checkWellFounded(graph[1], &dbgData) | 474 cycleDescription := checkWellFounded(graph[1], &dbgData) |
475 if err := compareDebugData(&c.expectedDebugDataB, &dbgDa
ta); err != nil { | 475 if err := compareDebugData(&c.expectedDebugDataB, &dbgDa
ta); err != nil { |
476 t.Fatalf("Case %dB: %s", i, err.Error()) | 476 t.Fatalf("Case %dB: %s", i, err.Error()) |
477 } | 477 } |
478 if len(c.expectedPathB) == 0 { | 478 if len(c.expectedPathB) == 0 { |
479 if cycleDescription != nil { | 479 if cycleDescription != nil { |
480 t.Fatalf("Case %dB: Detected a cycle: %s
", i, cycleDescription) | 480 t.Fatalf("Case %dB: Detected a cycle: %s
", i, cycleDescription) |
481 } | 481 } |
482 } else { | 482 } else { |
483 if cycleDescription == nil { | 483 if cycleDescription == nil { |
484 t.Fatalf("Case %dB: Expected a cycle.",
i) | 484 t.Fatalf("Case %dB: Expected a cycle.",
i) |
485 } | 485 } |
486 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("first:%s", c.expectedFirstB)) { | 486 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("first:%s", c.expectedFirstB)) { |
487 » » » » » t.Fatalf("Case %dB: got=%s expectedFirst
=%q", i, cycleDescription.String(), c.expectedFirstB) | 487 » » » » » t.Fatalf("Case %dB: got=%s expectedFirst
B=%q", i, cycleDescription.String(), c.expectedFirstB) |
488 } | 488 } |
489 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("last:%s", c.expectedLastB)) { | 489 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("last:%s", c.expectedLastB)) { |
490 » » » » » t.Fatalf("Case %dB: got=%s expectedLast=
%q", i, cycleDescription.String(), c.expectedLastB) | 490 » » » » » t.Fatalf("Case %dB: got=%s expectedLastB
=%q", i, cycleDescription.String(), c.expectedLastB) |
491 } | 491 } |
492 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("{%s}", c.expectedPathB)) { | 492 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("{%s}", c.expectedPathB)) { |
493 » » » » » t.Fatalf("Case %dB: got=%s expectedPath=
%q", i, cycleDescription.String(), c.expectedPathB) | 493 » » » » » t.Fatalf("Case %dB: got=%s expectedPathB
=%q", i, cycleDescription.String(), c.expectedPathB) |
494 } | 494 } |
495 } | 495 } |
496 } | 496 } |
497 } | 497 } |
498 } | 498 } |
499 | 499 |
500 // TestWellFoundedIsWellFounded tests the function |checkWellFounded| on graphs | 500 // TestWellFoundedIsWellFounded tests the function |checkWellFounded| on graphs |
501 // that contain both circles and squares and are well-founded. | 501 // that contain both circles and squares and are well-founded. |
502 func TestWellFoundedIsWellFounded(t *testing.T) { | 502 func TestWellFoundedIsWellFounded(t *testing.T) { |
503 cases := []WellFoundedGraphTestCase{ | 503 cases := []WellFoundedGraphTestCase{ |
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1340 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("last:%s", c.expectedLastB)) { | 1340 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("last:%s", c.expectedLastB)) { |
1341 t.Fatalf("Case %dB: got=%s expectedLast=
%q", i, cycleDescription.String(), c.expectedLastB) | 1341 t.Fatalf("Case %dB: got=%s expectedLast=
%q", i, cycleDescription.String(), c.expectedLastB) |
1342 } | 1342 } |
1343 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("{%s}", c.expectedPathB)) { | 1343 if !strings.Contains(cycleDescription.String(),
fmt.Sprintf("{%s}", c.expectedPathB)) { |
1344 t.Fatalf("Case %dB: got=%s expectedPath=
%q", i, cycleDescription.String(), c.expectedPathB) | 1344 t.Fatalf("Case %dB: got=%s expectedPath=
%q", i, cycleDescription.String(), c.expectedPathB) |
1345 } | 1345 } |
1346 } | 1346 } |
1347 } | 1347 } |
1348 } | 1348 } |
1349 } | 1349 } |
OLD | NEW |