terraform/dag/walk_test.go

168 lines
3.1 KiB
Go
Raw Normal View History

2017-02-02 20:41:46 +01:00
package dag
import (
"reflect"
"sync"
"testing"
"time"
2017-02-02 20:41:46 +01:00
)
func TestWalker_basic(t *testing.T) {
var g Graph
g.Add(1)
g.Add(2)
g.Connect(BasicEdge(1, 2))
// Run it a bunch of times since it is timing dependent
for i := 0; i < 50; i++ {
var order []interface{}
w := &walker{Callback: walkCbRecord(&order)}
w.Update(g.vertices, g.edges)
// Wait
if err := w.Wait(); err != nil {
t.Fatalf("err: %s", err)
}
// Check
expected := []interface{}{1, 2}
if !reflect.DeepEqual(order, expected) {
t.Fatalf("bad: %#v", order)
}
}
}
func TestWalker_newVertex(t *testing.T) {
// Run it a bunch of times since it is timing dependent
for i := 0; i < 50; i++ {
var g Graph
g.Add(1)
g.Add(2)
g.Connect(BasicEdge(1, 2))
var order []interface{}
w := &walker{Callback: walkCbRecord(&order)}
w.Update(g.vertices, g.edges)
// Wait a bit
time.Sleep(10 * time.Millisecond)
// Update the graph
g.Add(3)
w.Update(g.vertices, g.edges)
// Update the graph again but with the same vertex
g.Add(3)
w.Update(g.vertices, g.edges)
// Wait
if err := w.Wait(); err != nil {
t.Fatalf("err: %s", err)
}
// Check
expected := []interface{}{1, 2, 3}
if !reflect.DeepEqual(order, expected) {
t.Fatalf("bad: %#v", order)
}
}
}
func TestWalker_removeVertex(t *testing.T) {
// Run it a bunch of times since it is timing dependent
for i := 0; i < 50; i++ {
var g Graph
g.Add(1)
g.Add(2)
g.Connect(BasicEdge(1, 2))
// Record function
var order []interface{}
recordF := walkCbRecord(&order)
// Build a callback that delays until we close a channel
gateCh := make(chan struct{})
cb := func(v Vertex) error {
if v == 1 {
<-gateCh
}
return recordF(v)
}
// Add the initial vertices
w := &walker{Callback: cb}
w.Update(g.vertices, g.edges)
// Remove a vertex
g.Remove(2)
w.Update(g.vertices, g.edges)
// Open gate
close(gateCh)
// Wait
if err := w.Wait(); err != nil {
t.Fatalf("err: %s", err)
}
// Check
expected := []interface{}{1}
if !reflect.DeepEqual(order, expected) {
t.Fatalf("bad: %#v", order)
}
}
}
func TestWalker_newEdge(t *testing.T) {
// Run it a bunch of times since it is timing dependent
for i := 0; i < 50; i++ {
var g Graph
g.Add(1)
g.Add(2)
g.Connect(BasicEdge(1, 2))
// Record function
var order []interface{}
recordF := walkCbRecord(&order)
// Build a callback that delays until we close a channel
var w *walker
cb := func(v Vertex) error {
if v == 1 {
g.Add(3)
g.Connect(BasicEdge(3, 2))
w.Update(g.vertices, g.edges)
}
return recordF(v)
}
// Add the initial vertices
w = &walker{Callback: cb}
w.Update(g.vertices, g.edges)
// Wait
if err := w.Wait(); err != nil {
t.Fatalf("err: %s", err)
}
// Check
expected := []interface{}{1, 3, 2}
if !reflect.DeepEqual(order, expected) {
t.Fatalf("bad: %#v", order)
}
}
}
2017-02-02 20:41:46 +01:00
// walkCbRecord is a test helper callback that just records the order called.
func walkCbRecord(order *[]interface{}) WalkFunc {
var l sync.Mutex
return func(v Vertex) error {
l.Lock()
defer l.Unlock()
*order = append(*order, v)
return nil
}
}