func TestMerger(t *testing.T) { // Use 3 reports to check the pair-wise merging in SmartMerger report1 := report.MakeReport() report1.Endpoint.AddNode(report.MakeNode("foo")) report2 := report.MakeReport() report2.Endpoint.AddNode(report.MakeNode("bar")) report3 := report.MakeReport() report3.Endpoint.AddNode(report.MakeNode("baz")) reports := []report.Report{ report1, report2, report3, } want := report.MakeReport() want.Endpoint. AddNode(report.MakeNode("foo")). AddNode(report.MakeNode("bar")). AddNode(report.MakeNode("baz")) for _, merger := range []app.Merger{app.MakeDumbMerger(), app.NewSmartMerger()} { // Test the empty list case if have := merger.Merge([]report.Report{}); !reflect.DeepEqual(have, report.MakeReport()) { t.Errorf("Bad merge: %s", test.Diff(have, want)) } if have := merger.Merge(reports); !reflect.DeepEqual(have, want) { t.Errorf("Bad merge: %s", test.Diff(have, want)) } // Repeat the above test to ensure caching works if have := merger.Merge(reports); !reflect.DeepEqual(have, want) { t.Errorf("Bad merge: %s", test.Diff(have, want)) } } }
func TestMerge(t *testing.T) { var ( hostID = "xyz" src = newMockSource([]byte{}, nil) on = time.Millisecond off = time.Millisecond rpt = report.MakeReport() p = sniff.Packet{ SrcIP: "1.0.0.0", SrcPort: "1000", DstIP: "2.0.0.0", DstPort: "2000", Network: 512, Transport: 256, } _, ipnet, _ = net.ParseCIDR(p.SrcIP + "/24") // ;) localNets = report.Networks([]*net.IPNet{ipnet}) ) sniff.New(hostID, localNets, src, on, off).Merge(p, &rpt) var ( srcEndpointNodeID = report.MakeEndpointNodeID(hostID, p.SrcIP, p.SrcPort) dstEndpointNodeID = report.MakeEndpointNodeID(hostID, p.DstIP, p.DstPort) ) if want, have := (report.Topology{ Nodes: report.Nodes{ srcEndpointNodeID: report.MakeNode(srcEndpointNodeID).WithEdge(dstEndpointNodeID, report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(256), }), dstEndpointNodeID: report.MakeNode(dstEndpointNodeID), }, }), rpt.Endpoint; !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } var ( srcAddressNodeID = report.MakeAddressNodeID(hostID, p.SrcIP) dstAddressNodeID = report.MakeAddressNodeID(hostID, p.DstIP) ) if want, have := (report.Topology{ Nodes: report.Nodes{ srcAddressNodeID: report.MakeNode(srcAddressNodeID).WithEdge(dstAddressNodeID, report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(512), }), dstAddressNodeID: report.MakeNode(dstAddressNodeID), }, }), rpt.Address; !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestMetricCopy(t *testing.T) { want := report.MakeMetric() have := want.Copy() if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } want = report.MakeMetric().Add(time.Now(), 1) have = want.Copy() if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } }
func TestCountersDeepEquals(t *testing.T) { want := EmptyCounters. Add("foo", 3) have := EmptyCounters. Add("foo", 3) if !reflect.DeepEqual(want, have) { t.Errorf(test.Diff(want, have)) } notequal := EmptyCounters. Add("foo", 4) if reflect.DeepEqual(want, notequal) { t.Errorf(test.Diff(want, have)) } }
func TestLatestMapDeepEquals(t *testing.T) { now := time.Now() want := EmptyLatestMap. Set("foo", now, "Bar") have := EmptyLatestMap. Set("foo", now, "Bar") if !reflect.DeepEqual(want, have) { t.Errorf(test.Diff(want, have)) } notequal := EmptyLatestMap. Set("foo", now, "Baz") if reflect.DeepEqual(want, notequal) { t.Errorf(test.Diff(want, have)) } }
func TestPipes(t *testing.T) { oldNewPipe := controls.NewPipe defer func() { controls.NewPipe = oldNewPipe }() controls.NewPipe = func(_ controls.PipeClient, _ string) (string, xfer.Pipe, error) { return "pipeid", mockPipe{}, nil } mdc := newMockClient() setupStubs(mdc, func() { registry, _ := docker.NewRegistry(10*time.Second, nil, false, "") defer registry.Stop() test.Poll(t, 100*time.Millisecond, true, func() interface{} { _, ok := registry.GetContainer("ping") return ok }) for _, tc := range []string{ docker.AttachContainer, docker.ExecContainer, } { result := controls.HandleControlRequest(xfer.Request{ Control: tc, NodeID: report.MakeContainerNodeID("ping"), }) want := xfer.Response{ Pipe: "pipeid", RawTTY: true, } if !reflect.DeepEqual(result, want) { t.Errorf("diff %s: %s", tc, test.Diff(want, result)) } } }) }
func TestMetadataRowCopy(t *testing.T) { var ( row = report.MetadataRow{ ID: "id", Value: "value", Priority: 1, Datatype: "datatype", } cp = row.Copy() ) // copy should be identical if !reflect.DeepEqual(row, cp) { t.Error(test.Diff(row, cp)) } // changing the copy should not change the original cp.ID = "" cp.Value = "" cp.Priority = 2 cp.Datatype = "" if row.ID != "id" || row.Value != "value" || row.Priority != 1 || row.Datatype != "datatype" { t.Errorf("Expected changing the copy not to modify the original") } }
func TestLatestMapDeleteNil(t *testing.T) { want := LatestMap{} have := LatestMap{}.Delete("foo") if !reflect.DeepEqual(want, have) { t.Errorf(test.Diff(want, have)) } }
func TestLatestMapEncodingNil(t *testing.T) { want := LatestMap{} { gobs, err := want.GobEncode() if err != nil { t.Fatal(err) } have := EmptyLatestMap have.GobDecode(gobs) if have.Map == nil { t.Error("Decoded LatestMap.psMap should not be nil") } } { for _, h := range []codec.Handle{ codec.Handle(&codec.MsgpackHandle{}), codec.Handle(&codec.JsonHandle{}), } { buf := &bytes.Buffer{} encoder := codec.NewEncoder(buf, h) want.CodecEncodeSelf(encoder) decoder := codec.NewDecoder(buf, h) have := EmptyLatestMap have.CodecDecodeSelf(decoder) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } } }
func TestReportPostHandler(t *testing.T) { test := func(contentType string, encoder func(interface{}) ([]byte, error)) { router := mux.NewRouter() c := app.NewCollector(1 * time.Minute) app.RegisterReportPostHandler(c, router) ts := httptest.NewServer(router) defer ts.Close() b, err := encoder(fixture.Report) if err != nil { t.Fatalf("Content-Type %s: %s", contentType, err) } req, err := http.NewRequest("POST", ts.URL+"/api/report", bytes.NewReader(b)) if err != nil { t.Fatalf("Error posting report: %v", err) } req.Header.Set("Content-Type", contentType) resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatalf("Error posting report %v", err) } _, err = ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { t.Fatalf("Error posting report: %v", err) } if resp.StatusCode != http.StatusOK { t.Fatalf("Error posting report: %d", resp.StatusCode) } ctx := context.Background() report, err := c.Report(ctx) if err != nil { t.Error(err) } if want, have := fixture.Report.Endpoint.Nodes, report.Endpoint.Nodes; len(have) == 0 || len(want) != len(have) { t.Fatalf("Content-Type %s: %v", contentType, test.Diff(have, want)) } } test("", func(v interface{}) ([]byte, error) { buf := &bytes.Buffer{} err := gob.NewEncoder(buf).Encode(v) return buf.Bytes(), err }) test("application/json", func(v interface{}) ([]byte, error) { buf := &bytes.Buffer{} err := codec.NewEncoder(buf, &codec.JsonHandle{}).Encode(v) return buf.Bytes(), err }) test("application/msgpack", func(v interface{}) ([]byte, error) { buf := &bytes.Buffer{} err := codec.NewEncoder(buf, &codec.MsgpackHandle{}).Encode(v) return buf.Bytes(), err }) }
func TestEdgeMetadatasEncodingNil(t *testing.T) { want := EdgeMetadatas{} { gobs, err := want.GobEncode() if err != nil { t.Fatal(err) } have := EmptyEdgeMetadatas have.GobDecode(gobs) if have.psMap == nil { t.Error("needed to get back a non-nil psMap for EdgeMetadata") } } { for _, h := range []codec.Handle{ codec.Handle(&codec.MsgpackHandle{}), codec.Handle(&codec.JsonHandle{}), } { buf := &bytes.Buffer{} encoder := codec.NewEncoder(buf, h) want.CodecEncodeSelf(encoder) decoder := codec.NewDecoder(buf, h) have := EmptyEdgeMetadatas have.CodecDecodeSelf(decoder) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } } }
func TestHostRenderer(t *testing.T) { have := Prune(render.HostRenderer.Render(fixture.Report, render.FilterNoop)) want := Prune(expected.RenderedHosts) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestContainerRenderer(t *testing.T) { have := Prune(render.ContainerWithImageNameRenderer.Render(fixture.Report, render.FilterNoop)) want := Prune(expected.RenderedContainers) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestDNSAdd(t *testing.T) { mtx := sync.Mutex{} published := map[string]entry{} s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mtx.Lock() defer mtx.Unlock() parts := strings.SplitN(r.URL.Path, "/", 4) containerID, ip := parts[2], net.ParseIP(parts[3]) fqdn := r.FormValue("fqdn") published[fqdn] = entry{containerID, ip} w.WriteHeader(http.StatusNoContent) })) defer s.Close() client := weave.NewClient(s.URL) err := client.AddDNSEntry(mockHostname, mockContainerID, mockIP) if err != nil { t.Fatal(err) } want := map[string]entry{ mockHostname: {mockContainerID, mockIP}, } if !reflect.DeepEqual(published, want) { t.Fatal(test.Diff(published, want)) } }
func TestMetricRowSummary(t *testing.T) { var ( now = time.Now() metric = report.MakeMetric().Add(now, 1.234) row = report.MetricRow{ ID: "id", Format: "format", Group: "group", Value: 1.234, Priority: 1, Metric: &metric, } summary = row.Summary() ) // summary should not have any samples if summary.Metric.Len() != 0 { t.Errorf("Expected summary to have no samples, but had %d", summary.Metric.Len()) } // original metric should still have its samples if metric.Len() != 1 { t.Errorf("Expected original metric to still have it's samples, but had %d", metric.Len()) } // summary should have all the same fields (minus the metric) summary.Metric = nil row.Metric = nil if !reflect.DeepEqual(summary, row) { t.Errorf("Expected summary to have same fields as original: %s", test.Diff(summary, row)) } }
func TestContainerHostnameFilterRenderer(t *testing.T) { // add a system container into the topology and ensure // it is filtered out correctly. input := fixture.Report.Copy() clientContainer2ID := "f6g7h8i9j1" clientContainer2NodeID := report.MakeContainerNodeID(clientContainer2ID) input.Container.AddNode(report.MakeNodeWith(clientContainer2NodeID, map[string]string{ docker.LabelPrefix + "works.weave.role": "system", docker.ContainerHostname: fixture.ClientContainerHostname, report.HostNodeID: fixture.ClientHostNodeID, }). WithParents(report.EmptySets. Add("host", report.MakeStringSet(fixture.ClientHostNodeID)), ).WithTopology(report.Container)) have := Prune(render.ContainerHostnameRenderer.Render(input, render.FilterApplication)) want := Prune(expected.RenderedContainerHostnames) // Test works by virtue of the RenderedContainerHostname only having a container // counter == 1 if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestPodServiceRenderer(t *testing.T) { have := Prune(render.PodServiceRenderer.Render(fixture.Report, nil)) want := Prune(expected.RenderedPodServices) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestReportLocalNetworks(t *testing.T) { r := report.MakeReport().Merge(report.Report{ Host: report.Topology{ Nodes: report.Nodes{ "nonets": report.MakeNode("nonets"), "foo": report.MakeNode("foo").WithSets(report.EmptySets. Add(host.LocalNetworks, report.MakeStringSet( "10.0.0.1/8", "192.168.1.1/24", "10.0.0.1/8", "badnet/33")), ), }, }, Overlay: report.Topology{ Nodes: report.Nodes{ "router": report.MakeNode("router").WithSets(report.EmptySets. Add(host.LocalNetworks, report.MakeStringSet("10.32.0.1/12")), ), }, }, }) want := report.Networks([]*net.IPNet{ mustParseCIDR("10.0.0.1/8"), mustParseCIDR("192.168.1.1/24"), mustParseCIDR("10.32.0.1/12"), }) have := render.LocalNetworks(r) if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestEdgeMetadataFlatten(t *testing.T) { // Test two EdgeMetadatas flatten to the correct values { have := (EdgeMetadata{ EgressPacketCount: newu64(1), }).Flatten(EdgeMetadata{ EgressPacketCount: newu64(4), EgressByteCount: newu64(8), }) want := EdgeMetadata{ EgressPacketCount: newu64(1 + 4), EgressByteCount: newu64(8), } if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } // Test an EdgeMetadatas flatten to the correct value (should // just sum) { have := EmptyEdgeMetadatas. Add("foo", EdgeMetadata{ EgressPacketCount: newu64(1), }). Add("bar", EdgeMetadata{ EgressPacketCount: newu64(3), }).Flatten() want := EdgeMetadata{ EgressPacketCount: newu64(1 + 3), } if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } { // Should not panic on nil have := EdgeMetadatas{}.Flatten() want := EdgeMetadata{} if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } }
func TestMemoise(t *testing.T) { calls := 0 r := renderFunc(func(rpt report.Report) report.Nodes { calls++ return report.Nodes{rpt.ID: report.MakeNode(rpt.ID)} }) m := render.Memoise(r) rpt1 := report.MakeReport() result1 := m.Render(rpt1, nil) // it should have rendered it. if _, ok := result1[rpt1.ID]; !ok { t.Errorf("Expected rendered report to contain a node, but got: %v", result1) } if calls != 1 { t.Errorf("Expected renderer to have been called the first time") } result2 := m.Render(rpt1, nil) if !reflect.DeepEqual(result1, result2) { t.Errorf("Expected memoised result to be returned: %s", test.Diff(result1, result2)) } if calls != 1 { t.Errorf("Expected renderer to not have been called the second time") } rpt2 := report.MakeReport() result3 := m.Render(rpt2, nil) if reflect.DeepEqual(result1, result3) { t.Errorf("Expected different result for different report, but were the same") } if calls != 2 { t.Errorf("Expected renderer to have been called again for a different report") } render.ResetCache() result4 := m.Render(rpt1, nil) if !reflect.DeepEqual(result1, result4) { t.Errorf("Expected original result to be returned: %s", test.Diff(result1, result4)) } if calls != 3 { t.Errorf("Expected renderer to have been called again after cache reset") } }
func checkLoadedPlugins(t *testing.T, forEach iterator, expected []xfer.PluginSpec) { var plugins []xfer.PluginSpec forEach(func(p *Plugin) { plugins = append(plugins, p.PluginSpec) }) sort.Sort(xfer.PluginSpecsByID(plugins)) if !reflect.DeepEqual(plugins, expected) { t.Fatalf(test.Diff(expected, plugins)) } }
func TestLatestMapDelete(t *testing.T) { now := time.Now() want := EmptyLatestMap have := EmptyLatestMap. Set("foo", now, "Baz"). Delete("foo") if !reflect.DeepEqual(want, have) { t.Errorf(test.Diff(want, have)) } }
func TestNodeTables(t *testing.T) { inputs := []struct { name string rpt report.Report node report.Node want []report.Table }{ { name: "container", rpt: report.Report{ Container: report.MakeTopology(). WithTableTemplates(docker.ContainerTableTemplates), }, node: report.MakeNodeWith(fixture.ClientContainerNodeID, map[string]string{ docker.ContainerID: fixture.ClientContainerID, docker.LabelPrefix + "label1": "label1value", docker.ContainerState: docker.StateRunning, }).WithTopology(report.Container).WithSets(report.EmptySets. Add(docker.ContainerIPs, report.MakeStringSet("10.10.10.0/24", "10.10.10.1/24")), ), want: []report.Table{ { ID: docker.EnvPrefix, Label: "Environment Variables", Rows: []report.MetadataRow{}, }, { ID: docker.LabelPrefix, Label: "Docker Labels", Rows: []report.MetadataRow{ { ID: "label_label1", Label: "label1", Value: "label1value", }, }, }, }, }, { name: "unknown topology", rpt: report.MakeReport(), node: report.MakeNodeWith(fixture.ClientContainerNodeID, map[string]string{ docker.ContainerID: fixture.ClientContainerID, }).WithTopology("foobar"), want: nil, }, } for _, input := range inputs { have := detailed.NodeTables(input.rpt, input.node) if !reflect.DeepEqual(input.want, have) { t.Errorf("%s: %s", input.name, test.Diff(input.want, have)) } } }
func TestControlsNotFound(t *testing.T) { want := xfer.Response{ Error: "Control \"baz\" not recognised", } have := controls.HandleControlRequest(xfer.Request{ Control: "baz", }) if !reflect.DeepEqual(want, have) { t.Fatal(test.Diff(want, have)) } }
func TestEdgeMetadataReversed(t *testing.T) { have := EdgeMetadata{ EgressPacketCount: newu64(1), }.Reversed() want := EdgeMetadata{ IngressPacketCount: newu64(1), } if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestMetricsCopy(t *testing.T) { t1 := time.Now() want := report.Metrics{ "metric1": report.MakeMetric().Add(t1, 0.1), } delete(want.Copy(), "metric1") // Modify a copy have := want.Copy() // Check the original wasn't affected if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } }
func TestCollector(t *testing.T) { ctx := context.Background() window := 10 * time.Second c := app.NewCollector(window) r1 := report.MakeReport() r1.Endpoint.AddNode(report.MakeNode("foo")) r2 := report.MakeReport() r2.Endpoint.AddNode(report.MakeNode("foo")) have, err := c.Report(ctx) if err != nil { t.Error(err) } if want := report.MakeReport(); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } c.Add(ctx, r1) have, err = c.Report(ctx) if err != nil { t.Error(err) } if want := r1; !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } c.Add(ctx, r2) merged := report.MakeReport() merged = merged.Merge(r1) merged = merged.Merge(r2) have, err = c.Report(ctx) if err != nil { t.Error(err) } if want := merged; !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestCollectorExpire(t *testing.T) { now := time.Now() mtime.NowForce(now) defer mtime.NowReset() ctx := context.Background() window := 10 * time.Second c := app.NewCollector(window) // 1st check the collector is empty have, err := c.Report(ctx) if err != nil { t.Error(err) } if want := report.MakeReport(); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } // Now check an added report is returned r1 := report.MakeReport() r1.Endpoint.AddNode(report.MakeNode("foo")) c.Add(ctx, r1) have, err = c.Report(ctx) if err != nil { t.Error(err) } if want := r1; !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } // Finally move time forward to expire the report mtime.NowForce(now.Add(window)) have, err = c.Report(ctx) if err != nil { t.Error(err) } if want := report.MakeReport(); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestCache(t *testing.T) { processes := []process.Process{ {PID: 1, PPID: 0, Name: "init", Cmdline: "init"}, {PID: 2, PPID: 1, Name: "bash", Cmdline: "bash"}, {PID: 3, PPID: 1, Name: "apache", Threads: 2, Cmdline: "apache"}, {PID: 4, PPID: 2, Name: "ping", Cmdline: "ping foo.bar.local"}, } walker := &mockWalker{ processes: processes, } cachingWalker := process.NewCachingWalker(walker) err := cachingWalker.Tick() if err != nil { t.Fatal(err) } want, err := all(walker) have, err := all(cachingWalker) if err != nil || !reflect.DeepEqual(want, have) { t.Errorf("%v (%v)", test.Diff(want, have), err) } walker.processes = []process.Process{} have, err = all(cachingWalker) if err != nil || !reflect.DeepEqual(want, have) { t.Errorf("%v (%v)", test.Diff(want, have), err) } err = cachingWalker.Tick() if err != nil { t.Fatal(err) } have, err = all(cachingWalker) want = map[process.Process]struct{}{} if err != nil || !reflect.DeepEqual(want, have) { t.Errorf("%v (%v)", test.Diff(want, have), err) } }
func TestEdgeMetadatasEncoding(t *testing.T) { want := EmptyEdgeMetadatas. Add("foo", EdgeMetadata{ EgressPacketCount: newu64(1), }). Add("bar", EdgeMetadata{ EgressPacketCount: newu64(3), }) { gobs, err := want.GobEncode() if err != nil { t.Fatal(err) } have := EmptyEdgeMetadatas have.GobDecode(gobs) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } { for _, h := range []codec.Handle{ codec.Handle(&codec.MsgpackHandle{}), codec.Handle(&codec.JsonHandle{}), } { buf := &bytes.Buffer{} encoder := codec.NewEncoder(buf, h) want.CodecEncodeSelf(encoder) decoder := codec.NewDecoder(buf, h) have := EmptyEdgeMetadatas have.CodecDecodeSelf(decoder) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } } }