depgraph: add String method to Graph for testing/debugging
This commit is contained in:
parent
3728e1cfc0
commit
f7a50503b7
|
@ -6,7 +6,9 @@
|
||||||
package depgraph
|
package depgraph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/digraph"
|
"github.com/hashicorp/terraform/digraph"
|
||||||
)
|
)
|
||||||
|
@ -104,6 +106,44 @@ func (g *Graph) CheckConstraints() error {
|
||||||
return nil
|
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:
|
// 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.
|
// 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
|
// 2) All nouns in the graph must be reachable from the root
|
||||||
|
|
|
@ -53,6 +53,38 @@ func NounMapToList(m map[string]*Noun) []*Noun {
|
||||||
return list
|
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) {
|
func TestGraph_Validate(t *testing.T) {
|
||||||
nodes := ParseNouns(`a -> b
|
nodes := ParseNouns(`a -> b
|
||||||
a -> c
|
a -> c
|
||||||
|
|
Loading…
Reference in New Issue