github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/dag/dag_test.go (about) 1 package dag 2 3 import ( 4 "flag" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "os" 9 "reflect" 10 "strings" 11 "sync" 12 "testing" 13 14 "github.com/hashicorp/terraform/helper/logging" 15 ) 16 17 func TestMain(m *testing.M) { 18 flag.Parse() 19 if testing.Verbose() { 20 // if we're verbose, use the logging requested by TF_LOG 21 logging.SetOutput() 22 } else { 23 // otherwise silence all logs 24 log.SetOutput(ioutil.Discard) 25 } 26 27 os.Exit(m.Run()) 28 } 29 30 func TestAcyclicGraphRoot(t *testing.T) { 31 var g AcyclicGraph 32 g.Add(1) 33 g.Add(2) 34 g.Add(3) 35 g.Connect(BasicEdge(3, 2)) 36 g.Connect(BasicEdge(3, 1)) 37 38 if root, err := g.Root(); err != nil { 39 t.Fatalf("err: %s", err) 40 } else if root != 3 { 41 t.Fatalf("bad: %#v", root) 42 } 43 } 44 45 func TestAcyclicGraphRoot_cycle(t *testing.T) { 46 var g AcyclicGraph 47 g.Add(1) 48 g.Add(2) 49 g.Add(3) 50 g.Connect(BasicEdge(1, 2)) 51 g.Connect(BasicEdge(2, 3)) 52 g.Connect(BasicEdge(3, 1)) 53 54 if _, err := g.Root(); err == nil { 55 t.Fatal("should error") 56 } 57 } 58 59 func TestAcyclicGraphRoot_multiple(t *testing.T) { 60 var g AcyclicGraph 61 g.Add(1) 62 g.Add(2) 63 g.Add(3) 64 g.Connect(BasicEdge(3, 2)) 65 66 if _, err := g.Root(); err == nil { 67 t.Fatal("should error") 68 } 69 } 70 71 func TestAyclicGraphTransReduction(t *testing.T) { 72 var g AcyclicGraph 73 g.Add(1) 74 g.Add(2) 75 g.Add(3) 76 g.Connect(BasicEdge(1, 2)) 77 g.Connect(BasicEdge(1, 3)) 78 g.Connect(BasicEdge(2, 3)) 79 g.TransitiveReduction() 80 81 actual := strings.TrimSpace(g.String()) 82 expected := strings.TrimSpace(testGraphTransReductionStr) 83 if actual != expected { 84 t.Fatalf("bad: %s", actual) 85 } 86 } 87 88 func TestAyclicGraphTransReduction_more(t *testing.T) { 89 var g AcyclicGraph 90 g.Add(1) 91 g.Add(2) 92 g.Add(3) 93 g.Add(4) 94 g.Connect(BasicEdge(1, 2)) 95 g.Connect(BasicEdge(1, 3)) 96 g.Connect(BasicEdge(1, 4)) 97 g.Connect(BasicEdge(2, 3)) 98 g.Connect(BasicEdge(2, 4)) 99 g.Connect(BasicEdge(3, 4)) 100 g.TransitiveReduction() 101 102 actual := strings.TrimSpace(g.String()) 103 expected := strings.TrimSpace(testGraphTransReductionMoreStr) 104 if actual != expected { 105 t.Fatalf("bad: %s", actual) 106 } 107 } 108 109 func TestAcyclicGraphValidate(t *testing.T) { 110 var g AcyclicGraph 111 g.Add(1) 112 g.Add(2) 113 g.Add(3) 114 g.Connect(BasicEdge(3, 2)) 115 g.Connect(BasicEdge(3, 1)) 116 117 if err := g.Validate(); err != nil { 118 t.Fatalf("err: %s", err) 119 } 120 } 121 122 func TestAcyclicGraphValidate_cycle(t *testing.T) { 123 var g AcyclicGraph 124 g.Add(1) 125 g.Add(2) 126 g.Add(3) 127 g.Connect(BasicEdge(3, 2)) 128 g.Connect(BasicEdge(3, 1)) 129 g.Connect(BasicEdge(1, 2)) 130 g.Connect(BasicEdge(2, 1)) 131 132 if err := g.Validate(); err == nil { 133 t.Fatal("should error") 134 } 135 } 136 137 func TestAcyclicGraphValidate_cycleSelf(t *testing.T) { 138 var g AcyclicGraph 139 g.Add(1) 140 g.Add(2) 141 g.Connect(BasicEdge(1, 1)) 142 143 if err := g.Validate(); err == nil { 144 t.Fatal("should error") 145 } 146 } 147 148 func TestAcyclicGraphAncestors(t *testing.T) { 149 var g AcyclicGraph 150 g.Add(1) 151 g.Add(2) 152 g.Add(3) 153 g.Add(4) 154 g.Add(5) 155 g.Connect(BasicEdge(0, 1)) 156 g.Connect(BasicEdge(1, 2)) 157 g.Connect(BasicEdge(2, 3)) 158 g.Connect(BasicEdge(3, 4)) 159 g.Connect(BasicEdge(4, 5)) 160 161 actual, err := g.Ancestors(2) 162 if err != nil { 163 t.Fatalf("err: %#v", err) 164 } 165 166 expected := []Vertex{3, 4, 5} 167 168 if actual.Len() != len(expected) { 169 t.Fatalf("bad length! expected %#v to have len %d", actual, len(expected)) 170 } 171 172 for _, e := range expected { 173 if !actual.Include(e) { 174 t.Fatalf("expected: %#v to include: %#v", expected, actual) 175 } 176 } 177 } 178 179 func TestAcyclicGraphDescendents(t *testing.T) { 180 var g AcyclicGraph 181 g.Add(1) 182 g.Add(2) 183 g.Add(3) 184 g.Add(4) 185 g.Add(5) 186 g.Connect(BasicEdge(0, 1)) 187 g.Connect(BasicEdge(1, 2)) 188 g.Connect(BasicEdge(2, 3)) 189 g.Connect(BasicEdge(3, 4)) 190 g.Connect(BasicEdge(4, 5)) 191 192 actual, err := g.Descendents(2) 193 if err != nil { 194 t.Fatalf("err: %#v", err) 195 } 196 197 expected := []Vertex{0, 1} 198 199 if actual.Len() != len(expected) { 200 t.Fatalf("bad length! expected %#v to have len %d", actual, len(expected)) 201 } 202 203 for _, e := range expected { 204 if !actual.Include(e) { 205 t.Fatalf("expected: %#v to include: %#v", expected, actual) 206 } 207 } 208 } 209 210 func TestAcyclicGraphWalk(t *testing.T) { 211 var g AcyclicGraph 212 g.Add(1) 213 g.Add(2) 214 g.Add(3) 215 g.Connect(BasicEdge(3, 2)) 216 g.Connect(BasicEdge(3, 1)) 217 218 var visits []Vertex 219 var lock sync.Mutex 220 err := g.Walk(func(v Vertex) error { 221 lock.Lock() 222 defer lock.Unlock() 223 visits = append(visits, v) 224 return nil 225 }) 226 if err != nil { 227 t.Fatalf("err: %s", err) 228 } 229 230 expected := [][]Vertex{ 231 {1, 2, 3}, 232 {2, 1, 3}, 233 } 234 for _, e := range expected { 235 if reflect.DeepEqual(visits, e) { 236 return 237 } 238 } 239 240 t.Fatalf("bad: %#v", visits) 241 } 242 243 func TestAcyclicGraphWalk_error(t *testing.T) { 244 var g AcyclicGraph 245 g.Add(1) 246 g.Add(2) 247 g.Add(3) 248 g.Add(4) 249 g.Connect(BasicEdge(4, 3)) 250 g.Connect(BasicEdge(3, 2)) 251 g.Connect(BasicEdge(2, 1)) 252 253 var visits []Vertex 254 var lock sync.Mutex 255 err := g.Walk(func(v Vertex) error { 256 lock.Lock() 257 defer lock.Unlock() 258 259 if v == 2 { 260 return fmt.Errorf("error") 261 } 262 263 visits = append(visits, v) 264 return nil 265 }) 266 if err == nil { 267 t.Fatal("should error") 268 } 269 270 expected := [][]Vertex{ 271 {1}, 272 } 273 for _, e := range expected { 274 if reflect.DeepEqual(visits, e) { 275 return 276 } 277 } 278 279 t.Fatalf("bad: %#v", visits) 280 } 281 282 func TestAcyclicGraph_ReverseDepthFirstWalk_WithRemoval(t *testing.T) { 283 var g AcyclicGraph 284 g.Add(1) 285 g.Add(2) 286 g.Add(3) 287 g.Connect(BasicEdge(3, 2)) 288 g.Connect(BasicEdge(2, 1)) 289 290 var visits []Vertex 291 var lock sync.Mutex 292 err := g.ReverseDepthFirstWalk([]Vertex{1}, func(v Vertex, d int) error { 293 lock.Lock() 294 defer lock.Unlock() 295 visits = append(visits, v) 296 g.Remove(v) 297 return nil 298 }) 299 if err != nil { 300 t.Fatalf("err: %s", err) 301 } 302 303 expected := []Vertex{1, 2, 3} 304 if !reflect.DeepEqual(visits, expected) { 305 t.Fatalf("expected: %#v, got: %#v", expected, visits) 306 } 307 } 308 309 const testGraphTransReductionStr = ` 310 1 311 2 312 2 313 3 314 3 315 ` 316 317 const testGraphTransReductionMoreStr = ` 318 1 319 2 320 2 321 3 322 3 323 4 324 4 325 `