Files
weave-scope/render/dsl/expression_internal_test.go
2015-09-09 15:46:49 +02:00

246 lines
11 KiB
Go

package dsl
import (
"path/filepath"
"reflect"
"runtime"
"sort"
"testing"
"github.com/weaveworks/scope/probe/endpoint"
"github.com/weaveworks/scope/probe/host"
"github.com/weaveworks/scope/render"
"github.com/weaveworks/scope/report"
)
func TestSelectAll(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a"),
"c": render.NewRenderableNode("c"),
"b": render.NewRenderableNode("b"),
}
testStringSlice(t, []string{"a", "b", "c"}, selectAll(rns))
}
func TestSelectConnected(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNode().WithAdjacency(report.MakeIDList("m", "b", "c"))),
"b": render.NewRenderableNode("b").WithNode(report.MakeNode().WithAdjacency(report.MakeIDList("m", "c"))),
"c": render.NewRenderableNode("c").WithNode(report.MakeNode().WithAdjacency(report.MakeIDList("m"))),
"m": render.NewRenderableNode("m").WithNode(report.MakeNode().WithAdjacency(report.MakeIDList("n"))),
"n": render.NewRenderableNode("n"),
"x": render.NewRenderableNode("x"),
"y": render.NewRenderableNode("y"),
"z": render.NewRenderableNode("z"),
}
testStringSlice(t, []string{"a", "b", "c", "m", "n"}, selectConnected(rns))
}
func TestSelectNonlocal(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{host.LocalNetworks: "10.10.1.0/24"})),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{host.LocalNetworks: "10.10.2.0/24"})),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{host.LocalNetworks: "10.20.0.0/16"})),
// Test selecting nonlocal via endpoint.Addr metadata key
"x1": render.NewRenderableNode("x1").WithNode(report.MakeNodeWith(map[string]string{endpoint.Addr: "10.10.1.34"})), // local
"x2": render.NewRenderableNode("x2").WithNode(report.MakeNodeWith(map[string]string{endpoint.Addr: "10.20.99.1"})), // local
"x3": render.NewRenderableNode("x3").WithNode(report.MakeNodeWith(map[string]string{endpoint.Addr: "10.10.3.33"})), // nonlocal
"x4": render.NewRenderableNode("x4").WithNode(report.MakeNodeWith(map[string]string{endpoint.Addr: "192.168.1.1"})), // nonlocal
}
// Test selecting nonlocal via parsing the node ID
var (
local1 = report.MakeAddressNodeID("some-host", "10.10.2.2")
nonlocal1 = report.MakeAddressNodeID("some-host", "10.11.12.13")
local2 = report.MakeEndpointNodeID("some-host", "10.20.0.1", "4040")
nonlocal2 = report.MakeEndpointNodeID("some-host", "10.21.32.43", "8080")
)
rns[local1] = render.NewRenderableNode(local1).WithNode(report.MakeNode())
rns[nonlocal1] = render.NewRenderableNode(nonlocal1).WithNode(report.MakeNode())
rns[local2] = render.NewRenderableNode(local2).WithNode(report.MakeNode())
rns[nonlocal2] = render.NewRenderableNode(nonlocal2).WithNode(report.MakeNode())
testStringSlice(t, []string{"x3", "x4", nonlocal1, nonlocal2}, selectNonlocal(rns))
}
func TestSelectLike(t *testing.T) {
rns := render.RenderableNodes{
"abcfooxyz": render.NewRenderableNode("abcfooxyz"),
"abcfoxyz": render.NewRenderableNode("abcfoxyz"),
"fo": render.NewRenderableNode("fo"),
"foo": render.NewRenderableNode("foo"),
"fooo": render.NewRenderableNode("fooo"),
"x_foo_y": render.NewRenderableNode("x_foo_y"),
}
testStringSlice(t, []string{"abcfooxyz", "foo", "fooo", "x_foo_y"}, selectLike(`.*foo.*`)(rns))
}
func TestSelectWith(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo": "bar"})),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"foo": "bar"})),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"foo": "baz"})),
"x": render.NewRenderableNode("x").WithNode(report.MakeNodeWith(map[string]string{"qux": "qix"})),
"y": render.NewRenderableNode("y").WithNode(report.MakeNode()),
}
testStringSlice(t, []string{"a", "b", "c"}, selectWith("foo")(rns))
testStringSlice(t, []string{"a", "b"}, selectWith("foo=bar")(rns))
testStringSlice(t, []string{"x"}, selectWith("qux")(rns))
testStringSlice(t, []string{"x"}, selectWith("qux=qix")(rns))
testStringSlice(t, []string{}, selectWith("qux=XXX")(rns))
}
func TestSelectNot(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"})),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"foo": "2"})),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"foo": "3"})),
"x": render.NewRenderableNode("x").WithNode(report.MakeNodeWith(map[string]string{"bar": "1"})),
"y": render.NewRenderableNode("y").WithNode(report.MakeNodeWith(map[string]string{"bar": "2"})),
"z": render.NewRenderableNode("z").WithNode(report.MakeNodeWith(map[string]string{"bar": "3"})),
}
testStringSlice(t, []string{"x", "y", "z"}, selectNot(selectWith("foo"))(rns))
testStringSlice(t, []string{"a", "b", "c"}, selectNot(selectWith("bar"))(rns))
testStringSlice(t, []string{}, selectNot(selectAll)(rns))
}
func TestTransformHighlight(t *testing.T) {
rns := render.RenderableNodes{"a": render.NewRenderableNode("a")}
get := func(rns render.RenderableNodes) string { return rns["a"].Metadata[highlightKey] }
out := transformHighlight(rns, selectAll(rns))
if want, have := "true", get(out); want != have {
t.Errorf("want %q, have %q", want, have)
}
}
func TestTransformRemove(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"}).WithAdjacency(report.MakeIDList("b", "c"))),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"bar": "1"}).WithAdjacency(report.MakeIDList("c"))),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"baz": "1"})),
}
// Remove all should totally kill the RenderableNodes
if want, have := 0, len(transformRemove(rns, selectAll(rns))); want != have {
t.Errorf("remove all: want %d, have %d", want, have)
}
// Removing c should kill the adjacency links to it
out := transformRemove(rns, selectLike("c")(rns))
if want, have := 2, len(out); want != have {
t.Errorf("want %d, have %d", want, have)
}
if want, have := 1, len(out["a"].Node.Adjacency); want != have {
t.Errorf("want %d, have %d", want, have)
}
if want, have := 0, len(out["b"].Node.Adjacency); want != have {
t.Errorf("want %d, have %d", want, have)
}
}
func TestTransformShowOnly(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"}).WithAdjacency(report.MakeIDList("b", "c"))),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"bar": "1"}).WithAdjacency(report.MakeIDList("c"))),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"baz": "1"})),
}
// Show only b should eliminate a, c, and the link to c
out := transformShowOnly(rns, selectLike("b")(rns))
if want, have := 1, len(out); want != have {
t.Errorf("want %d, have %d (%#+v)", want, have, out)
}
if want, have := 0, len(out["b"].Node.Adjacency); want != have {
t.Errorf("want %d, have %d", want, have)
}
}
func TestTransformMerge(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"}).WithAdjacency(report.MakeIDList("b", "c"))),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"bar": "1"}).WithAdjacency(report.MakeIDList("c"))),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"baz": "1"})),
}
name := "supernode"
out := transformMerge(name)(rns, selectAll(rns))
if want, have := 1, len(out); want != have {
t.Errorf("want %d, have %d", want, have)
}
if want, have := 3, len(out[name].Node.Metadata); want != have {
t.Errorf("want %d, have %d", want, have)
}
if want, have := 1, len(out[name].Node.Adjacency); want != have {
t.Fatalf("want %d, have %d", want, have)
}
if want, have := name, out[name].Node.Adjacency[0]; want != have {
t.Errorf("want %q, have %q", want, have)
}
}
func TestTransformGroupBy(t *testing.T) {
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"}).WithAdjacency(report.MakeIDList("b")).WithCounters(map[string]int{"c": 1})),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"}).WithAdjacency(report.MakeIDList("c")).WithCounters(map[string]int{"c": 2})),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"foo": "1"}).WithAdjacency(report.MakeIDList("d")).WithCounters(map[string]int{"c": 4})),
"d": render.NewRenderableNode("d").WithNode(report.MakeNodeWith(map[string]string{"foo": "2"}).WithCounters(map[string]int{"c": 8})),
}
out := transformGroupBy("foo")(rns, selectAll(rns))
if want, have := 2, len(out); want != have {
t.Errorf("want %d, have %d", want, have)
}
if _, ok := out["foo-1"]; !ok {
t.Fatalf("missing merged node")
}
if _, ok := out["foo-2"]; !ok {
t.Fatalf("missing unmerged node")
}
if want, have := 2, len(out["foo-1"].Node.Adjacency); want != have { // self-edge, and link to the other
t.Errorf("want %d, have %d", want, have)
}
if want, have := 1+2+4, out["foo-1"].Node.Counters["c"]; want != have {
t.Errorf("want %d, have %d", want, have)
}
if want, have := 8, out["foo-2"].Node.Counters["c"]; want != have {
t.Errorf("want %d, have %d", want, have)
}
}
func TestTransformJoin(t *testing.T) {
const key, value = "😇", "😈"
rns := render.RenderableNodes{
"a": render.NewRenderableNode("a").WithNode(report.MakeNodeWith(map[string]string{"foo_node": "d", "1": "1"}).WithCounters(map[string]int{"c": 1})),
"b": render.NewRenderableNode("b").WithNode(report.MakeNodeWith(map[string]string{"foo_node": "d", "2": "2"}).WithCounters(map[string]int{"c": 2})),
"c": render.NewRenderableNode("c").WithNode(report.MakeNodeWith(map[string]string{"foo_node": "x", "4": "4"}).WithCounters(map[string]int{"c": 4})),
"d": render.NewRenderableNode("d").WithNode(report.MakeNodeWith(map[string]string{key: value}).WithCounters(map[string]int{"c": 8})),
}
out := transformJoin("foo_node")(rns, selectAll(rns))
if want, have := 3, len(out); want != have {
t.Errorf("want %d, have %d", want, have)
}
for _, id := range []string{"a", "b"} {
if want, have := value, out[id].Node.Metadata[key]; want != have {
t.Errorf("%s[%q]: want %q, have %q", id, key, want, have)
}
}
if want, have := 1+8, out["a"].Node.Counters["c"]; want != have {
t.Errorf("a: want %d, have %d", want, have)
}
if want, have := 2+8, out["b"].Node.Counters["c"]; want != have {
t.Errorf("b: want %d, have %d", want, have)
}
}
func testStringSlice(t *testing.T, want, have []string) {
sort.Strings(want)
sort.Strings(have)
if !reflect.DeepEqual(want, have) {
_, file, line, _ := runtime.Caller(1)
t.Errorf("%s:%d: want %v, have %v", filepath.Base(file), line, want, have)
}
}