toposort_test.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package toposort
  2. import (
  3. "github.com/stretchr/testify/assert"
  4. "testing"
  5. )
  6. func index(s []string, v string) int {
  7. for i, s := range s {
  8. if s == v {
  9. return i
  10. }
  11. }
  12. return -1
  13. }
  14. type Edge struct {
  15. From string
  16. To string
  17. }
  18. func TestToposortDuplicatedNode(t *testing.T) {
  19. graph := NewGraph()
  20. graph.AddNode("a")
  21. if graph.AddNode("a") {
  22. t.Error("not raising duplicated node error")
  23. }
  24. }
  25. func TestToposortRemoveNotExistEdge(t *testing.T) {
  26. graph := NewGraph()
  27. if graph.RemoveEdge("a", "b") {
  28. t.Error("not raising not exist edge error")
  29. }
  30. }
  31. func TestToposortWikipedia(t *testing.T) {
  32. graph := NewGraph()
  33. graph.AddNodes("2", "3", "5", "7", "8", "9", "10", "11")
  34. edges := []Edge{
  35. {"7", "8"},
  36. {"7", "11"},
  37. {"5", "11"},
  38. {"3", "8"},
  39. {"3", "10"},
  40. {"11", "2"},
  41. {"11", "9"},
  42. {"11", "10"},
  43. {"8", "9"},
  44. }
  45. for _, e := range edges {
  46. graph.AddEdge(e.From, e.To)
  47. }
  48. result, ok := graph.Toposort()
  49. if !ok {
  50. t.Error("closed path detected in no closed pathed graph")
  51. }
  52. for _, e := range edges {
  53. if i, j := index(result, e.From), index(result, e.To); i > j {
  54. t.Errorf("dependency failed: not satisfy %v(%v) > %v(%v)", e.From, i, e.To, j)
  55. }
  56. }
  57. }
  58. func TestToposortCycle(t *testing.T) {
  59. graph := NewGraph()
  60. graph.AddNodes("1", "2", "3")
  61. graph.AddEdge("1", "2")
  62. graph.AddEdge("2", "3")
  63. graph.AddEdge("3", "1")
  64. _, ok := graph.Toposort()
  65. if ok {
  66. t.Error("closed path not detected in closed pathed graph")
  67. }
  68. }
  69. func TestToposortCopy(t *testing.T) {
  70. graph := NewGraph()
  71. graph.AddNodes("1", "2", "3")
  72. graph.AddEdge("1", "2")
  73. graph.AddEdge("2", "3")
  74. graph.AddEdge("3", "1")
  75. gc := graph.Copy()
  76. assert.Equal(t, graph.inputs, gc.inputs)
  77. assert.Equal(t, graph.outputs, gc.outputs)
  78. delete(graph.outputs, "1")
  79. assert.NotEqual(t, graph.outputs, gc.outputs)
  80. }
  81. func TestToposortReindexNode(t *testing.T) {
  82. graph := NewGraph()
  83. graph.AddNodes("1", "2", "3")
  84. graph.AddEdge("1", "2")
  85. graph.AddEdge("2", "3")
  86. graph.AddEdge("3", "1")
  87. graph.AddEdge("1", "3")
  88. graph.RemoveEdge("1", "2")
  89. assert.Len(t, graph.outputs["1"], 1)
  90. assert.Equal(t, graph.outputs["1"]["3"], 2)
  91. assert.Equal(t, graph.inputs["2"], 0)
  92. graph.ReindexNode("1")
  93. assert.Equal(t, graph.outputs["1"]["3"], 1)
  94. }
  95. func TestToposortBreadthSort(t *testing.T) {
  96. graph := NewGraph()
  97. graph.AddNodes("0", "1", "2", "3", "4")
  98. graph.AddEdge("0", "1")
  99. graph.AddEdge("1", "2")
  100. graph.AddEdge("2", "3")
  101. graph.AddEdge("1", "3")
  102. graph.AddEdge("3", "4")
  103. graph.AddEdge("4", "1")
  104. order := graph.BreadthSort()
  105. var expected [5]string
  106. if order[2] == "2" {
  107. expected = [...]string{"0", "1", "2", "3", "4"}
  108. } else {
  109. expected = [...]string{"0", "1", "3", "2", "4"}
  110. }
  111. assert.Equal(t, expected[:], order)
  112. }
  113. func TestToposortFindCycle(t *testing.T) {
  114. graph := NewGraph()
  115. graph.AddNodes("1", "2", "3", "4", "5")
  116. graph.AddEdge("1", "2")
  117. graph.AddEdge("2", "3")
  118. graph.AddEdge("2", "4")
  119. graph.AddEdge("3", "1")
  120. graph.AddEdge("5", "1")
  121. cycle := graph.FindCycle("2")
  122. expected := [...]string{"2", "3", "1"}
  123. assert.Equal(t, expected[:], cycle)
  124. cycle = graph.FindCycle("5")
  125. assert.Len(t, cycle, 0)
  126. }
  127. func TestToposortFindParents(t *testing.T) {
  128. graph := NewGraph()
  129. graph.AddNodes("1", "2", "3", "4", "5")
  130. graph.AddEdge("1", "2")
  131. graph.AddEdge("2", "3")
  132. graph.AddEdge("2", "4")
  133. graph.AddEdge("3", "1")
  134. graph.AddEdge("5", "1")
  135. parents := graph.FindParents("2")
  136. expected := [...]string{"1"}
  137. assert.Equal(t, expected[:], parents)
  138. parents = graph.FindParents("1")
  139. assert.Len(t, parents, 2)
  140. checks := [2]bool{}
  141. for _, p := range parents {
  142. if p == "3" {
  143. checks[0] = true
  144. } else if p == "5" {
  145. checks[1] = true
  146. }
  147. }
  148. assert.Equal(t, [2]bool{true, true}, checks)
  149. }
  150. func TestToposortFindChildren(t *testing.T) {
  151. graph := NewGraph()
  152. graph.AddNodes("1", "2", "3", "4", "5")
  153. graph.AddEdge("1", "2")
  154. graph.AddEdge("2", "3")
  155. graph.AddEdge("2", "4")
  156. graph.AddEdge("3", "1")
  157. graph.AddEdge("5", "1")
  158. children := graph.FindChildren("1")
  159. expected := [...]string{"2"}
  160. assert.Equal(t, expected[:], children)
  161. children = graph.FindChildren("2")
  162. assert.Len(t, children, 2)
  163. checks := [2]bool{}
  164. for _, p := range children {
  165. if p == "3" {
  166. checks[0] = true
  167. } else if p == "4" {
  168. checks[1] = true
  169. }
  170. }
  171. assert.Equal(t, [2]bool{true, true}, checks)
  172. }
  173. func TestToposortSerialize(t *testing.T) {
  174. graph := NewGraph()
  175. graph.AddNodes("1", "2", "3", "4", "5")
  176. graph.AddEdge("1", "2")
  177. graph.AddEdge("2", "3")
  178. graph.AddEdge("2", "4")
  179. graph.AddEdge("3", "1")
  180. graph.AddEdge("5", "1")
  181. order := [...]string{"5", "4", "3", "2", "1"}
  182. gv := graph.Serialize(order[:])
  183. assert.Equal(t, `digraph Hercules {
  184. "4 1" -> "3 2"
  185. "3 2" -> "2 3"
  186. "3 2" -> "1 4"
  187. "2 3" -> "4 1"
  188. "0 5" -> "4 1"
  189. }`, gv)
  190. }