3
0
Files
corteza/pkg/envoy/graph_test.go
2020-11-27 11:19:15 +01:00

202 lines
4.2 KiB
Go

package envoy
import (
"context"
"testing"
"github.com/stretchr/testify/require"
)
type (
TestNode struct {
rr NodeRelationships
ii NodeIdentifiers
}
)
func (n *TestNode) Identifiers() NodeIdentifiers {
return n.ii
}
func (n *TestNode) Matches(resource string, identifiers ...string) bool {
if resource != n.Resource() {
return false
}
return n.Identifiers().HasAny(identifiers...)
}
func (n *TestNode) Resource() string {
return "envoy:test:"
}
func (n *TestNode) Relations() NodeRelationships {
return n.rr
}
func TestEnvoyGraph_Rel(t *testing.T) {
req := require.New(t)
t.Run("simple node, no rels", func(t *testing.T) {
g := NewGraph()
rr := NodeRelationships{}
ii := NodeIdentifiers{"p1"}
n := &TestNode{rr: rr, ii: ii}
g.Add(n)
cc := g.Children(n)
req.Empty(cc)
pp := g.Parents(n)
req.Empty(pp)
})
t.Run("node with child and parent nodes", func(t *testing.T) {
g := NewGraph()
// The child node
rr1 := NodeRelationships{}
ii1 := NodeIdentifiers{"c1"}
n1 := &TestNode{rr: rr1, ii: ii1}
g.Add(n1)
// The middle node
rr2 := NodeRelationships{"envoy:test:": NodeIdentifiers{"c1"}}
ii2 := NodeIdentifiers{"n"}
n := &TestNode{rr: rr2, ii: ii2}
g.Add(n)
// The parent node
rr3 := NodeRelationships{"envoy:test:": NodeIdentifiers{"n"}}
ii3 := NodeIdentifiers{"p1"}
n3 := &TestNode{rr: rr3, ii: ii3}
g.Add(n3)
cc := g.Children(n)
req.Len(cc, 1)
req.Equal(n1, cc[0])
pp := g.Parents(n)
req.Len(pp, 1)
req.Equal(n3, pp[0])
})
t.Run("(inverted) node with child and parent nodes", func(t *testing.T) {
g := NewGraph()
g.Invert()
// The child node
rr1 := NodeRelationships{}
ii1 := NodeIdentifiers{"c1"}
n1 := &TestNode{rr: rr1, ii: ii1}
g.Add(n1)
// The middle node
rr2 := NodeRelationships{"envoy:test:": NodeIdentifiers{"c1"}}
ii2 := NodeIdentifiers{"n"}
n := &TestNode{rr: rr2, ii: ii2}
g.Add(n)
// The parent node
rr3 := NodeRelationships{"envoy:test:": NodeIdentifiers{"n"}}
ii3 := NodeIdentifiers{"p1"}
n3 := &TestNode{rr: rr3, ii: ii3}
g.Add(n3)
cc := g.Children(n)
req.Len(cc, 1)
req.Equal(n3, cc[0])
pp := g.Parents(n)
req.Len(pp, 1)
req.Equal(n1, pp[0])
})
}
func TestEnvoyGraph_DepResolution(t *testing.T) {
req := require.New(t)
ctx := context.Background()
t.Run("simple acyclic linear graph; (n1) => (n2) => (n3)", func(t *testing.T) {
g := NewGraph()
rr1 := NodeRelationships{"envoy:test:": NodeIdentifiers{"n2"}}
ii1 := NodeIdentifiers{"n1"}
n1 := &TestNode{rr: rr1, ii: ii1}
g.Add(n1)
rr2 := NodeRelationships{"envoy:test:": NodeIdentifiers{"n3"}}
ii2 := NodeIdentifiers{"n2"}
n2 := &TestNode{rr: rr2, ii: ii2}
g.Add(n2)
rr3 := NodeRelationships{}
ii3 := NodeIdentifiers{"n3"}
n3 := &TestNode{rr: rr3, ii: ii3}
g.Add(n3)
// 1. n1 since it has no parent nodes
n, pp, cc, err := g.Next(ctx)
req.Equal(n1, n)
req.NoError(err)
req.NotEmpty(cc)
req.Empty(pp)
// 2. n2 since its parents are resolved
n, pp, cc, err = g.Next(ctx)
req.Equal(n2, n)
req.NoError(err)
req.NotEmpty(cc)
req.NotEmpty(pp)
// 2. n3 since its parents are resolved
n, pp, cc, err = g.Next(ctx)
req.Equal(n3, n)
req.NoError(err)
req.Empty(cc)
req.NotEmpty(pp)
})
}
func TestEnvoyGraph_GarbageCollector(t *testing.T) {
req := require.New(t)
ctx := context.Background()
t.Run("simple acyclic linear graph; (n1) => (n2) => (n3)", func(t *testing.T) {
g := NewGraph()
rr1 := NodeRelationships{"envoy:test:": NodeIdentifiers{"n2"}}
ii1 := NodeIdentifiers{"n1"}
n1 := &TestNode{rr: rr1, ii: ii1}
g.Add(n1)
rr2 := NodeRelationships{"envoy:test:": NodeIdentifiers{"n3"}}
ii2 := NodeIdentifiers{"n2"}
n2 := &TestNode{rr: rr2, ii: ii2}
g.Add(n2)
rr3 := NodeRelationships{}
ii3 := NodeIdentifiers{"n3"}
n3 := &TestNode{rr: rr3, ii: ii3}
g.Add(n3)
// n1 marked as processed; no garbage
g.Next(ctx)
req.Len(g.nodes, 3)
req.Len(g.processed, 1)
req.Equal(g.processed[0], n1)
// n2 marked as processed; garbage in nodes, processed
g.Next(ctx)
req.Len(g.nodes, 2)
req.Len(g.processed, 1)
req.Equal(g.processed[0], n2)
// all nodes processed; resetting graph
g.Next(ctx)
req.Len(g.nodes, 0)
req.Len(g.processed, 0)
})
}