github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/jujud/agent/unit/manifolds_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package unit_test
     5  
     6  import (
     7  	gc "gopkg.in/check.v1"
     8  
     9  	"github.com/juju/juju/agent"
    10  	"github.com/juju/juju/cmd/jujud/agent/unit"
    11  	"github.com/juju/juju/testing"
    12  )
    13  
    14  type ManifoldsSuite struct {
    15  	testing.BaseSuite
    16  }
    17  
    18  var _ = gc.Suite(&ManifoldsSuite{})
    19  
    20  func (s *ManifoldsSuite) TestStartFuncs(c *gc.C) {
    21  	manifolds := unit.Manifolds(unit.ManifoldsConfig{
    22  		Agent: fakeAgent{},
    23  	})
    24  
    25  	for name, manifold := range manifolds {
    26  		c.Logf("checking %q manifold", name)
    27  		c.Check(manifold.Start, gc.NotNil)
    28  	}
    29  }
    30  
    31  // TODO(cmars) 2015/08/10: rework this into builtin Engine cycle checker.
    32  func (s *ManifoldsSuite) TestAcyclic(c *gc.C) {
    33  	manifolds := unit.Manifolds(unit.ManifoldsConfig{
    34  		Agent: fakeAgent{},
    35  	})
    36  	count := len(manifolds)
    37  
    38  	// Set of vars for depth-first topological sort of manifolds. (Note that,
    39  	// because we've already got outgoing links stored conveniently, we're
    40  	// actually checking the transpose of the dependency graph. Cycles will
    41  	// still be cycles in either direction, though.)
    42  	done := make(map[string]bool)
    43  	doing := make(map[string]bool)
    44  	sorted := make([]string, 0, count)
    45  
    46  	// Stupid _-suffix malarkey allows recursion. Seems cleaner to keep these
    47  	// considerations inside this func than to embody the algorithm in a type.
    48  	visit := func(node string) {}
    49  	visit_ := func(node string) {
    50  		if doing[node] {
    51  			c.Fatalf("cycle detected at %q (considering: %v)", node, doing)
    52  		}
    53  		if !done[node] {
    54  			doing[node] = true
    55  			for _, input := range manifolds[node].Inputs {
    56  				visit(input)
    57  			}
    58  			done[node] = true
    59  			doing[node] = false
    60  			sorted = append(sorted, node)
    61  		}
    62  	}
    63  	visit = visit_
    64  
    65  	// Actually sort them, or fail if we find a cycle.
    66  	for node := range manifolds {
    67  		visit(node)
    68  	}
    69  	c.Logf("got: %v", sorted)
    70  	c.Check(sorted, gc.HasLen, count) // Final sanity check.
    71  }
    72  
    73  type fakeAgent struct {
    74  	agent.Agent
    75  }