|
@@ -1,6 +1,9 @@
|
|
|
package toposort
|
|
|
|
|
|
-import "testing"
|
|
|
+import (
|
|
|
+ "testing"
|
|
|
+ "github.com/stretchr/testify/assert"
|
|
|
+)
|
|
|
|
|
|
func index(s []string, v string) int {
|
|
|
for i, s := range s {
|
|
@@ -16,7 +19,7 @@ type Edge struct {
|
|
|
To string
|
|
|
}
|
|
|
|
|
|
-func TestDuplicatedNode(t *testing.T) {
|
|
|
+func TestToposortDuplicatedNode(t *testing.T) {
|
|
|
graph := NewGraph()
|
|
|
graph.AddNode("a")
|
|
|
if graph.AddNode("a") {
|
|
@@ -25,14 +28,14 @@ func TestDuplicatedNode(t *testing.T) {
|
|
|
|
|
|
}
|
|
|
|
|
|
-func TestRemoveNotExistEdge(t *testing.T) {
|
|
|
+func TestToposortRemoveNotExistEdge(t *testing.T) {
|
|
|
graph := NewGraph()
|
|
|
if graph.RemoveEdge("a", "b") {
|
|
|
t.Error("not raising not exist edge error")
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func TestWikipedia(t *testing.T) {
|
|
|
+func TestToposortWikipedia(t *testing.T) {
|
|
|
graph := NewGraph()
|
|
|
graph.AddNodes("2", "3", "5", "7", "8", "9", "10", "11")
|
|
|
|
|
@@ -68,7 +71,7 @@ func TestWikipedia(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func TestCycle(t *testing.T) {
|
|
|
+func TestToposortCycle(t *testing.T) {
|
|
|
graph := NewGraph()
|
|
|
graph.AddNodes("1", "2", "3")
|
|
|
|
|
@@ -81,3 +84,145 @@ func TestCycle(t *testing.T) {
|
|
|
t.Error("closed path not detected in closed pathed graph")
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+func TestToposortCopy(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("1", "2", "3")
|
|
|
+
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("3", "1")
|
|
|
+
|
|
|
+ gc := graph.Copy()
|
|
|
+ assert.Equal(t, graph.inputs, gc.inputs)
|
|
|
+ assert.Equal(t, graph.outputs, gc.outputs)
|
|
|
+ delete(graph.outputs, "1")
|
|
|
+ assert.NotEqual(t, graph.outputs, gc.outputs)
|
|
|
+}
|
|
|
+
|
|
|
+func TestToposortReindexNode(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("1", "2", "3")
|
|
|
+
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("3", "1")
|
|
|
+ graph.AddEdge("1", "3")
|
|
|
+ graph.RemoveEdge("1", "2")
|
|
|
+ assert.Len(t, graph.outputs["1"], 1)
|
|
|
+ assert.Equal(t, graph.outputs["1"]["3"], 2)
|
|
|
+ assert.Equal(t, graph.inputs["2"], 0)
|
|
|
+ graph.ReindexNode("1")
|
|
|
+ assert.Equal(t, graph.outputs["1"]["3"], 1)
|
|
|
+}
|
|
|
+
|
|
|
+func TestToposortBreadthSort(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("0", "1", "2", "3", "4")
|
|
|
+
|
|
|
+ graph.AddEdge("0", "1")
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("1", "3")
|
|
|
+ graph.AddEdge("3", "4")
|
|
|
+ graph.AddEdge("4", "1")
|
|
|
+ order := graph.BreadthSort()
|
|
|
+ var expected [5]string
|
|
|
+ if order[2] == "2" {
|
|
|
+ expected = [...]string{"0", "1", "2", "3", "4"}
|
|
|
+ } else {
|
|
|
+ expected = [...]string{"0", "1", "3", "2", "4"}
|
|
|
+ }
|
|
|
+ assert.Equal(t, expected[:], order)
|
|
|
+}
|
|
|
+
|
|
|
+func TestToposortFindCycle(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("1", "2", "3", "4", "5")
|
|
|
+
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("2", "4")
|
|
|
+ graph.AddEdge("3", "1")
|
|
|
+ graph.AddEdge("5", "1")
|
|
|
+
|
|
|
+ cycle := graph.FindCycle("2")
|
|
|
+ expected := [...]string{"2", "3", "1"}
|
|
|
+ assert.Equal(t, expected[:], cycle)
|
|
|
+ cycle = graph.FindCycle("5")
|
|
|
+ assert.Len(t, cycle, 0)
|
|
|
+}
|
|
|
+
|
|
|
+func TestToposortFindParents(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("1", "2", "3", "4", "5")
|
|
|
+
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("2", "4")
|
|
|
+ graph.AddEdge("3", "1")
|
|
|
+ graph.AddEdge("5", "1")
|
|
|
+
|
|
|
+ parents := graph.FindParents("2")
|
|
|
+ expected := [...]string{"1"}
|
|
|
+ assert.Equal(t, expected[:], parents)
|
|
|
+ parents = graph.FindParents("1")
|
|
|
+ assert.Len(t, parents, 2)
|
|
|
+ checks := [2]bool{}
|
|
|
+ for _, p := range parents {
|
|
|
+ if p == "3" {
|
|
|
+ checks[0] = true
|
|
|
+ } else if p == "5" {
|
|
|
+ checks[1] = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ assert.Equal(t, [2]bool{true, true}, checks)
|
|
|
+}
|
|
|
+
|
|
|
+func TestToposortFindChildren(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("1", "2", "3", "4", "5")
|
|
|
+
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("2", "4")
|
|
|
+ graph.AddEdge("3", "1")
|
|
|
+ graph.AddEdge("5", "1")
|
|
|
+
|
|
|
+ children := graph.FindChildren("1")
|
|
|
+ expected := [...]string{"2"}
|
|
|
+ assert.Equal(t, expected[:], children)
|
|
|
+ children = graph.FindChildren("2")
|
|
|
+ assert.Len(t, children, 2)
|
|
|
+ checks := [2]bool{}
|
|
|
+ for _, p := range children {
|
|
|
+ if p == "3" {
|
|
|
+ checks[0] = true
|
|
|
+ } else if p == "4" {
|
|
|
+ checks[1] = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ assert.Equal(t, [2]bool{true, true}, checks)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func TestToposortSerialize(t *testing.T) {
|
|
|
+ graph := NewGraph()
|
|
|
+ graph.AddNodes("1", "2", "3", "4", "5")
|
|
|
+
|
|
|
+ graph.AddEdge("1", "2")
|
|
|
+ graph.AddEdge("2", "3")
|
|
|
+ graph.AddEdge("2", "4")
|
|
|
+ graph.AddEdge("3", "1")
|
|
|
+ graph.AddEdge("5", "1")
|
|
|
+
|
|
|
+ order := [...]string{"5", "4", "3", "2", "1"}
|
|
|
+ gv := graph.Serialize(order[:])
|
|
|
+ assert.Equal(t, `digraph Hercules {
|
|
|
+ "4 1" -> "3 2"
|
|
|
+ "3 2" -> "2 3"
|
|
|
+ "3 2" -> "1 4"
|
|
|
+ "2 3" -> "4 1"
|
|
|
+ "0 5" -> "4 1"
|
|
|
+}`, gv)
|
|
|
+}
|