depgraph: add String method to Graph for testing/debugging

This commit is contained in:
Mitchell Hashimoto 2014-05-24 13:28:12 -07:00
parent 3728e1cfc0
commit f7a50503b7
2 changed files with 72 additions and 0 deletions

View File

@ -6,7 +6,9 @@
package depgraph
import (
"bytes"
"fmt"
"strings"
"github.com/hashicorp/terraform/digraph"
)
@ -104,6 +106,44 @@ func (g *Graph) CheckConstraints() error {
return nil
}
// String generates a little ASCII string of the graph, useful in
// debugging output.
func (g *Graph) String() string {
var buf bytes.Buffer
cb := func(n *Noun, depth int) {
buf.WriteString(fmt.Sprintf(
"%s%s\n",
strings.Repeat(" ", depth),
n.Name))
}
type listItem struct {
n *Noun
d int
}
nodes := []listItem{{g.Root, 0}}
for len(nodes) > 0 {
// Pop current node
n := len(nodes)
current := nodes[n-1]
nodes = nodes[:n-1]
// Visit
cb(current.n, current.d)
// Traverse
for _, dep := range current.n.Deps {
nodes = append(nodes, listItem{
n: dep.Target,
d: current.d + 1,
})
}
}
return buf.String()
}
// Validate is used to ensure that a few properties of the graph are not violated:
// 1) There must be a single "root", or source on which nothing depends.
// 2) All nouns in the graph must be reachable from the root

View File

@ -53,6 +53,38 @@ func NounMapToList(m map[string]*Noun) []*Noun {
return list
}
func TestGraph_String(t *testing.T) {
nodes := ParseNouns(`a -> b
a -> c
b -> d
b -> e
c -> d
c -> e`)
g := &Graph{
Name: "Test",
Nouns: NounMapToList(nodes),
Root: nodes["a"],
}
actual := g.String()
expected := `
a
c
e
d
b
e
d
`
actual = strings.TrimSpace(actual)
expected = strings.TrimSpace(expected)
if actual != expected {
t.Fatalf("bad:\n%s\n!=\n%s", actual, expected)
}
}
func TestGraph_Validate(t *testing.T) {
nodes := ParseNouns(`a -> b
a -> c