| 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 |