Merge pull request #12121 from hashicorp/jbardin/dag-tests
Fix some intermittent dag test failures
This commit is contained in:
commit
be5230c673
282
dag/walk_test.go
282
dag/walk_test.go
|
@ -92,180 +92,186 @@ func TestWalker_error(t *testing.T) {
|
|||
}
|
||||
|
||||
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 AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
|
||||
var order []interface{}
|
||||
w := &Walker{Callback: walkCbRecord(&order)}
|
||||
w.Update(&g)
|
||||
// Record function
|
||||
var order []interface{}
|
||||
recordF := walkCbRecord(&order)
|
||||
done2 := make(chan int)
|
||||
|
||||
// Wait a bit
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Update the graph
|
||||
g.Add(3)
|
||||
w.Update(&g)
|
||||
|
||||
// Update the graph again but with the same vertex
|
||||
g.Add(3)
|
||||
w.Update(&g)
|
||||
|
||||
// Wait
|
||||
if err := w.Wait(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
// Build a callback that notifies us when 2 has been walked
|
||||
var w *Walker
|
||||
cb := func(v Vertex) error {
|
||||
if v == 2 {
|
||||
defer close(done2)
|
||||
}
|
||||
return recordF(v)
|
||||
}
|
||||
|
||||
// Check
|
||||
expected := []interface{}{1, 2, 3}
|
||||
if !reflect.DeepEqual(order, expected) {
|
||||
t.Fatalf("bad: %#v", order)
|
||||
}
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
|
||||
// if 2 has been visited, the walk is complete so far
|
||||
<-done2
|
||||
|
||||
// Update the graph
|
||||
g.Add(3)
|
||||
w.Update(&g)
|
||||
|
||||
// Update the graph again but with the same vertex
|
||||
g.Add(3)
|
||||
w.Update(&g)
|
||||
|
||||
// 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 AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
|
||||
// Record function
|
||||
var order []interface{}
|
||||
recordF := walkCbRecord(&order)
|
||||
// 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.Remove(2)
|
||||
w.Update(&g)
|
||||
}
|
||||
|
||||
return recordF(v)
|
||||
var w *Walker
|
||||
cb := func(v Vertex) error {
|
||||
if v == 1 {
|
||||
g.Remove(2)
|
||||
w.Update(&g)
|
||||
}
|
||||
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
return recordF(v)
|
||||
}
|
||||
|
||||
// Wait
|
||||
if err := w.Wait(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
|
||||
// Check
|
||||
expected := []interface{}{1}
|
||||
if !reflect.DeepEqual(order, expected) {
|
||||
t.Fatalf("bad: %#v", order)
|
||||
}
|
||||
// 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 AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
|
||||
// Record function
|
||||
var order []interface{}
|
||||
recordF := walkCbRecord(&order)
|
||||
// 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)
|
||||
}
|
||||
var w *Walker
|
||||
cb := func(v Vertex) error {
|
||||
// record where we are first, otherwise the Updated vertex may get
|
||||
// walked before the first visit.
|
||||
err := recordF(v)
|
||||
|
||||
return recordF(v)
|
||||
if v == 1 {
|
||||
g.Add(3)
|
||||
g.Connect(BasicEdge(3, 2))
|
||||
w.Update(&g)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
|
||||
// Wait
|
||||
if err := w.Wait(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
// Check
|
||||
expected := []interface{}{1, 3, 2}
|
||||
if !reflect.DeepEqual(order, expected) {
|
||||
t.Fatalf("bad: %#v", order)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWalker_removeEdge(t *testing.T) {
|
||||
// Run it a bunch of times since it is timing dependent
|
||||
for i := 0; i < 50; i++ {
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Add(3)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
g.Connect(BasicEdge(3, 2))
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Add(3)
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
g.Connect(BasicEdge(1, 3))
|
||||
g.Connect(BasicEdge(3, 2))
|
||||
|
||||
// Record function
|
||||
var order []interface{}
|
||||
recordF := walkCbRecord(&order)
|
||||
// Record function
|
||||
var order []interface{}
|
||||
recordF := walkCbRecord(&order)
|
||||
|
||||
// The way this works is that our original graph forces
|
||||
// the order of 1 => 3 => 2. During the execution of 1, we
|
||||
// remove the edge forcing 3 before 2. Then, during the execution
|
||||
// of 3, we wait on a channel that is only closed by 2, implicitly
|
||||
// forcing 2 before 3 via the callback (and not the graph). If
|
||||
// 2 cannot execute before 3 (edge removal is non-functional), then
|
||||
// this test will timeout.
|
||||
var w *Walker
|
||||
gateCh := make(chan struct{})
|
||||
cb := func(v Vertex) error {
|
||||
if v == 1 {
|
||||
g.RemoveEdge(BasicEdge(3, 2))
|
||||
w.Update(&g)
|
||||
// The way this works is that our original graph forces
|
||||
// the order of 1 => 3 => 2. During the execution of 1, we
|
||||
// remove the edge forcing 3 before 2. Then, during the execution
|
||||
// of 3, we wait on a channel that is only closed by 2, implicitly
|
||||
// forcing 2 before 3 via the callback (and not the graph). If
|
||||
// 2 cannot execute before 3 (edge removal is non-functional), then
|
||||
// this test will timeout.
|
||||
var w *Walker
|
||||
gateCh := make(chan struct{})
|
||||
cb := func(v Vertex) error {
|
||||
switch v {
|
||||
case 1:
|
||||
g.RemoveEdge(BasicEdge(3, 2))
|
||||
w.Update(&g)
|
||||
|
||||
case 2:
|
||||
// this visit isn't completed until we've recorded it
|
||||
// Once the visit is official, we can then close the gate to
|
||||
// let 3 continue.
|
||||
defer close(gateCh)
|
||||
|
||||
case 3:
|
||||
select {
|
||||
case <-gateCh:
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
return fmt.Errorf("timeout 3 waiting for 2")
|
||||
}
|
||||
|
||||
if v == 2 {
|
||||
close(gateCh)
|
||||
}
|
||||
|
||||
if v == 3 {
|
||||
select {
|
||||
case <-gateCh:
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
return fmt.Errorf("timeout 3 waiting for 2")
|
||||
}
|
||||
}
|
||||
|
||||
return recordF(v)
|
||||
}
|
||||
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
return recordF(v)
|
||||
}
|
||||
|
||||
// Wait
|
||||
if err := w.Wait(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
// Add the initial vertices
|
||||
w = &Walker{Callback: cb}
|
||||
w.Update(&g)
|
||||
|
||||
// Check
|
||||
expected := []interface{}{1, 2, 3}
|
||||
if !reflect.DeepEqual(order, expected) {
|
||||
t.Fatalf("bad: %#v", order)
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue