blob: a47374bf19fb68358c53a110bf8593b9296d6710 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dependency
import (
"testing"
"time"
)
var nextId = 0
type Dep struct {
deps []*Dep
stopped bool
id int
}
func NewDep(deps ...*Dep) *Dep {
d := &Dep{deps: deps, id: nextId}
nextId++
return d
}
func (d *Dep) Use(t *testing.T, by *Dep) {
if d.stopped {
t.Errorf("Object %d using %d after stop.", by.id, d.id)
}
}
func (d *Dep) Stop(t *testing.T) {
d.Use(t, d)
d.stopped = true
for _, dd := range d.deps {
dd.Use(t, d)
}
}
func TestGraph(t *testing.T) {
a := NewDep()
b, c := NewDep(a), NewDep(a)
d := NewDep(c)
g := NewGraph()
if err := g.Depend(a); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if err := g.Depend(b, a); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if err := g.Depend(c, a); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if err := g.Depend(d, c); err != nil {
t.Errorf("Unexpected error: %v", err)
}
alldone := make(chan struct{})
go func() {
g.CloseAndWaitForAll()
close(alldone)
}()
// Close d, which is a leaf.
finish := g.CloseAndWait(d)
d.Stop(t)
finish()
// Set a to close and wait which should wait for b and c.
done := make(chan struct{})
go func() {
finish := g.CloseAndWait(a)
a.Stop(t)
finish()
close(done)
}()
// done and alldone shouldn't be finished yet.
select {
case <-time.After(time.Second):
case <-done:
t.Errorf("done is finished before it's time")
case <-alldone:
t.Errorf("alldone is finished before it's time")
}
// Now close b and c.
finish = g.CloseAndWait(b)
b.Stop(t)
finish()
finish = g.CloseAndWait(c)
c.Stop(t)
finish()
<-done
<-alldone
}