opentofu/digraph/util_test.go
2014-05-24 12:47:04 -07:00

234 lines
3.5 KiB
Go

package digraph
import (
"reflect"
"testing"
)
func TestDepthFirstWalk(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
d -> f
e -> a ; cycle`)
root := nodes["a"]
expected := []string{
"a",
"b",
"e",
"c",
"d",
"f",
}
index := 0
DepthFirstWalk(root, func(n Node) bool {
name := n.(*BasicNode).Name
if expected[index] != name {
t.Fatalf("expected: %v, got %v", expected[index], name)
}
index++
return true
})
}
func TestInDegree(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
c -> e
d -> f`)
var nlist []Node
for _, n := range nodes {
nlist = append(nlist, n)
}
expected := map[string]int{
"a": 0,
"b": 1,
"c": 1,
"d": 1,
"e": 2,
"f": 1,
}
indegree := InDegree(nlist)
for n, d := range indegree {
name := n.(*BasicNode).Name
exp := expected[name]
if exp != d {
t.Fatalf("Expected %d for %s, got %d",
exp, name, d)
}
}
}
func TestOutDegree(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
c -> e
d -> f`)
var nlist []Node
for _, n := range nodes {
nlist = append(nlist, n)
}
expected := map[string]int{
"a": 3,
"b": 1,
"c": 1,
"d": 1,
"e": 0,
"f": 0,
}
outDegree := OutDegree(nlist)
for n, d := range outDegree {
name := n.(*BasicNode).Name
exp := expected[name]
if exp != d {
t.Fatalf("Expected %d for %s, got %d",
exp, name, d)
}
}
}
func TestSinks(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
c -> e
d -> f`)
var nlist []Node
for _, n := range nodes {
nlist = append(nlist, n)
}
sinks := Sinks(nlist)
var haveE, haveF bool
for _, n := range sinks {
name := n.(*BasicNode).Name
switch name {
case "e":
haveE = true
case "f":
haveF = true
}
}
if !haveE || !haveF {
t.Fatalf("missing sink")
}
}
func TestSources(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
c -> e
d -> f
x -> y`)
var nlist []Node
for _, n := range nodes {
nlist = append(nlist, n)
}
sources := Sources(nlist)
if len(sources) != 2 {
t.Fatalf("bad: %v", sources)
}
var haveA, haveX bool
for _, n := range sources {
name := n.(*BasicNode).Name
switch name {
case "a":
haveA = true
case "x":
haveX = true
}
}
if !haveA || !haveX {
t.Fatalf("missing source %v %v", haveA, haveX)
}
}
func TestUnreachable(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
c -> e
d -> f
f -> a
x -> y
y -> z`)
var nlist []Node
for _, n := range nodes {
nlist = append(nlist, n)
}
unreached := Unreachable(nodes["a"], nlist)
if len(unreached) != 3 {
t.Fatalf("bad: %v", unreached)
}
var haveX, haveY, haveZ bool
for _, n := range unreached {
name := n.(*BasicNode).Name
switch name {
case "x":
haveX = true
case "y":
haveY = true
case "z":
haveZ = true
}
}
if !haveX || !haveY || !haveZ {
t.Fatalf("missing %v %v %v", haveX, haveY, haveZ)
}
}
func TestUnreachable2(t *testing.T) {
nodes := ParseBasic(`a -> b
a -> c
a -> d
b -> e
c -> e
d -> f
f -> a
x -> y
y -> z`)
var nlist []Node
for _, n := range nodes {
nlist = append(nlist, n)
}
unreached := Unreachable(nodes["x"], nlist)
if len(unreached) != 6 {
t.Fatalf("bad: %v", unreached)
}
expected := map[string]struct{}{
"a": struct{}{},
"b": struct{}{},
"c": struct{}{},
"d": struct{}{},
"e": struct{}{},
"f": struct{}{},
}
out := map[string]struct{}{}
for _, n := range unreached {
name := n.(*BasicNode).Name
out[name] = struct{}{}
}
if !reflect.DeepEqual(out, expected) {
t.Fatalf("bad: %v %v", out, expected)
}
}