Nav apraksta

graph_test.go 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package graph
  2. import (
  3. "fmt"
  4. "testing"
  5. )
  6. func edgeDebugString(edge *Edge) string {
  7. debug := ""
  8. debug += fmt.Sprintf("\t\tSrc: %p\n", edge.Src)
  9. debug += fmt.Sprintf("\t\tDest: %p\n", edge.Dest)
  10. debug += fmt.Sprintf("\t\tResidual: %t\n", edge.Residual)
  11. debug += fmt.Sprintf("\t\tInline: %t\n", edge.Inline)
  12. return debug
  13. }
  14. func edgeMapsDebugString(in, out EdgeMap) string {
  15. debug := ""
  16. debug += "In Edges:\n"
  17. for parent, edge := range in {
  18. debug += fmt.Sprintf("\tParent: %p\n", parent)
  19. debug += edgeDebugString(edge)
  20. }
  21. debug += "Out Edges:\n"
  22. for child, edge := range out {
  23. debug += fmt.Sprintf("\tChild: %p\n", child)
  24. debug += edgeDebugString(edge)
  25. }
  26. return debug
  27. }
  28. func graphDebugString(graph *Graph) string {
  29. debug := ""
  30. for i, node := range graph.Nodes {
  31. debug += fmt.Sprintf("Node %d: %p\n", i, node)
  32. }
  33. for i, node := range graph.Nodes {
  34. debug += "\n"
  35. debug += fmt.Sprintf("=== Node %d: %p ===\n", i, node)
  36. debug += edgeMapsDebugString(node.In, node.Out)
  37. }
  38. return debug
  39. }
  40. func expectedNodesDebugString(Expected []ExpectedNode) string {
  41. debug := ""
  42. for i, node := range Expected {
  43. debug += fmt.Sprintf("Node %d: %p\n", i, node.Node)
  44. }
  45. for i, node := range Expected {
  46. debug += "\n"
  47. debug += fmt.Sprintf("=== Node %d: %p ===\n", i, node.Node)
  48. debug += edgeMapsDebugString(node.In, node.Out)
  49. }
  50. return debug
  51. }
  52. // Checks if two edges are equal
  53. func edgesEqual(this, that *Edge) bool {
  54. return this.Src == that.Src && this.Dest == that.Dest &&
  55. this.Residual == that.Residual && this.Inline == that.Inline
  56. }
  57. // Checks if all the edges in this equal all the edges in that.
  58. func edgeMapsEqual(this, that EdgeMap) bool {
  59. if len(this) != len(that) {
  60. return false
  61. }
  62. for node, thisEdge := range this {
  63. if !edgesEqual(thisEdge, that[node]) {
  64. return false
  65. }
  66. }
  67. return true
  68. }
  69. // Check if node is equal to Expected
  70. func nodesEqual(node *Node, Expected ExpectedNode) bool {
  71. return node == Expected.Node && edgeMapsEqual(node.In, Expected.In) &&
  72. edgeMapsEqual(node.Out, Expected.Out)
  73. }
  74. // Check if the graph equals the one templated by Expected.
  75. func graphsEqual(graph *Graph, Expected []ExpectedNode) bool {
  76. if len(graph.Nodes) != len(Expected) {
  77. return false
  78. }
  79. ExpectedSet := make(map[*Node]ExpectedNode)
  80. for i := range Expected {
  81. ExpectedSet[Expected[i].Node] = Expected[i]
  82. }
  83. for _, node := range graph.Nodes {
  84. ExpectedNode, found := ExpectedSet[node]
  85. if !found || !nodesEqual(node, ExpectedNode) {
  86. return false
  87. }
  88. }
  89. return true
  90. }
  91. type ExpectedNode struct {
  92. Node *Node
  93. In, Out EdgeMap
  94. }
  95. type TrimTreeTestCase struct {
  96. Initial *Graph
  97. Expected []ExpectedNode
  98. Keep NodeSet
  99. }
  100. // Makes the edge from parent to child residual
  101. func makeExpectedEdgeResidual(parent, child ExpectedNode) {
  102. parent.Out[child.Node].Residual = true
  103. child.In[parent.Node].Residual = true
  104. }
  105. func makeEdgeInline(edgeMap EdgeMap, node *Node) {
  106. edgeMap[node].Inline = true
  107. }
  108. // Creates a directed edges from the parent to each of the children
  109. func createEdges(parent *Node, children ...*Node) {
  110. for _, child := range children {
  111. edge := &Edge{
  112. Src: parent,
  113. Dest: child,
  114. }
  115. parent.Out[child] = edge
  116. child.In[parent] = edge
  117. }
  118. }
  119. // Creates a node without any edges
  120. func createEmptyNode() *Node {
  121. return &Node{
  122. In: make(EdgeMap),
  123. Out: make(EdgeMap),
  124. }
  125. }
  126. // Creates an array of ExpectedNodes from nodes.
  127. func createExpectedNodes(nodes ...*Node) ([]ExpectedNode, NodeSet) {
  128. Expected := make([]ExpectedNode, len(nodes))
  129. Keep := NodeSet{
  130. Ptr: make(map[*Node]bool, len(nodes)),
  131. }
  132. for i, node := range nodes {
  133. Expected[i] = ExpectedNode{
  134. Node: node,
  135. In: make(EdgeMap),
  136. Out: make(EdgeMap),
  137. }
  138. Keep.Ptr[node] = true
  139. }
  140. return Expected, Keep
  141. }
  142. // Creates a directed edges from the parent to each of the children
  143. func createExpectedEdges(parent ExpectedNode, children ...ExpectedNode) {
  144. for _, child := range children {
  145. edge := &Edge{
  146. Src: parent.Node,
  147. Dest: child.Node,
  148. }
  149. parent.Out[child.Node] = edge
  150. child.In[parent.Node] = edge
  151. }
  152. }
  153. // The first test case looks like:
  154. // 0
  155. // |
  156. // 1
  157. // / \
  158. // 2 3
  159. //
  160. // After Keeping 0, 2, 3. We should see:
  161. // 0
  162. // / \
  163. // 2 3
  164. func createTestCase1() TrimTreeTestCase {
  165. // Create Initial graph
  166. graph := &Graph{make(Nodes, 4)}
  167. nodes := graph.Nodes
  168. for i := range nodes {
  169. nodes[i] = createEmptyNode()
  170. }
  171. createEdges(nodes[0], nodes[1])
  172. createEdges(nodes[1], nodes[2], nodes[3])
  173. makeEdgeInline(nodes[0].Out, nodes[1])
  174. makeEdgeInline(nodes[1].Out, nodes[2])
  175. // Create Expected graph
  176. Expected, Keep := createExpectedNodes(nodes[0], nodes[2], nodes[3])
  177. createExpectedEdges(Expected[0], Expected[1], Expected[2])
  178. makeEdgeInline(Expected[0].Out, Expected[1].Node)
  179. makeExpectedEdgeResidual(Expected[0], Expected[1])
  180. makeExpectedEdgeResidual(Expected[0], Expected[2])
  181. return TrimTreeTestCase{
  182. Initial: graph,
  183. Expected: Expected,
  184. Keep: Keep,
  185. }
  186. }
  187. // This test case looks like:
  188. // 3
  189. // |
  190. // 1
  191. // |
  192. // 2
  193. // |
  194. // 0
  195. // |
  196. // 4
  197. //
  198. // After Keeping 3 and 4. We should see:
  199. // 3
  200. // |
  201. // 4
  202. func createTestCase2() TrimTreeTestCase {
  203. // Create Initial graph
  204. graph := &Graph{make(Nodes, 5)}
  205. nodes := graph.Nodes
  206. for i := range nodes {
  207. nodes[i] = createEmptyNode()
  208. }
  209. createEdges(nodes[3], nodes[1])
  210. createEdges(nodes[1], nodes[2])
  211. createEdges(nodes[2], nodes[0])
  212. createEdges(nodes[0], nodes[4])
  213. // Create Expected graph
  214. Expected, Keep := createExpectedNodes(nodes[3], nodes[4])
  215. createExpectedEdges(Expected[0], Expected[1])
  216. makeExpectedEdgeResidual(Expected[0], Expected[1])
  217. return TrimTreeTestCase{
  218. Initial: graph,
  219. Expected: Expected,
  220. Keep: Keep,
  221. }
  222. }
  223. // If we trim an empty graph it should still be empty afterwards
  224. func createTestCase3() TrimTreeTestCase {
  225. graph := &Graph{make(Nodes, 0)}
  226. Expected, Keep := createExpectedNodes()
  227. return TrimTreeTestCase{
  228. Initial: graph,
  229. Expected: Expected,
  230. Keep: Keep,
  231. }
  232. }
  233. // This test case looks like:
  234. // 0
  235. //
  236. // After Keeping 0. We should see:
  237. // 0
  238. func createTestCase4() TrimTreeTestCase {
  239. graph := &Graph{make(Nodes, 1)}
  240. nodes := graph.Nodes
  241. for i := range nodes {
  242. nodes[i] = createEmptyNode()
  243. }
  244. Expected, Keep := createExpectedNodes(nodes[0])
  245. return TrimTreeTestCase{
  246. Initial: graph,
  247. Expected: Expected,
  248. Keep: Keep,
  249. }
  250. }
  251. func createTrimTreeTestCases() []TrimTreeTestCase {
  252. caseGenerators := []func() TrimTreeTestCase{
  253. createTestCase1,
  254. createTestCase2,
  255. createTestCase3,
  256. createTestCase4,
  257. }
  258. cases := make([]TrimTreeTestCase, len(caseGenerators))
  259. for i, gen := range caseGenerators {
  260. cases[i] = gen()
  261. }
  262. return cases
  263. }
  264. func TestTrimTree(t *testing.T) {
  265. tests := createTrimTreeTestCases()
  266. for _, test := range tests {
  267. graph := test.Initial
  268. graph.TrimTree(test.Keep)
  269. if !graphsEqual(graph, test.Expected) {
  270. t.Fatalf("Graphs do not match.\nExpected: %s\nFound: %s\n",
  271. expectedNodesDebugString(test.Expected),
  272. graphDebugString(graph))
  273. }
  274. }
  275. }