From 2f6d8bf0ad77a8a81251456588966c51ed5044d1 Mon Sep 17 00:00:00 2001 From: Ian Cottrell Date: Wed, 27 Nov 2019 11:24:29 -0500 Subject: [PATCH] internal/lsp: change tests to use the main exporter Now the tests are at a high enough level, we can switch them to using the full exporter by bulding a fake http client to bind it to. This lets us use the true public interface and also excercise more of the functionality in the tests. With this we are now ready to replace the entire implementation safely. Change-Id: Ifdbf6230de3ec7c7c5381c840b135cb7a0bc1e55 Reviewed-on: https://go-review.googlesource.com/c/tools/+/209161 Run-TryBot: Ian Cottrell TryBot-Result: Gobot Gobot Reviewed-by: Emmanuel Odeke --- .../telemetry/export/ocagent/metrics_test.go | 10 +-- internal/telemetry/export/ocagent/ocagent.go | 14 ---- .../telemetry/export/ocagent/ocagent_test.go | 72 +++++++++++++++---- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/internal/telemetry/export/ocagent/metrics_test.go b/internal/telemetry/export/ocagent/metrics_test.go index 38ffa7813d..c7a0a982ef 100644 --- a/internal/telemetry/export/ocagent/metrics_test.go +++ b/internal/telemetry/export/ocagent/metrics_test.go @@ -1,11 +1,11 @@ package ocagent_test import ( + "context" "testing" "time" "golang.org/x/tools/internal/telemetry" - "golang.org/x/tools/internal/telemetry/export/ocagent" "golang.org/x/tools/internal/telemetry/metric" ) @@ -312,12 +312,12 @@ func TestEncodeMetric(t *testing.T) { }, } + ctx := context.TODO() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := ocagent.EncodeMetric(cfg, tt.data) - if err != nil { - t.Fatal(err) - } + exporter.Metric(ctx, tt.data) + exporter.Flush() + got := sent.get("/v1/metrics") checkJSON(t, got, []byte(tt.want)) }) } diff --git a/internal/telemetry/export/ocagent/ocagent.go b/internal/telemetry/export/ocagent/ocagent.go index 14511d8451..986d6d5a13 100644 --- a/internal/telemetry/export/ocagent/ocagent.go +++ b/internal/telemetry/export/ocagent/ocagent.go @@ -149,20 +149,6 @@ func (cfg *Config) buildNode() *wire.Node { } } -func EncodeSpan(cfg Config, span *telemetry.Span) ([]byte, error) { - return json.Marshal(&wire.ExportTraceServiceRequest{ - Node: cfg.buildNode(), - Spans: []*wire.Span{convertSpan(span)}, - }) -} - -func EncodeMetric(cfg Config, m telemetry.MetricData) ([]byte, error) { - return json.Marshal(&wire.ExportMetricsServiceRequest{ - Node: cfg.buildNode(), - Metrics: []*wire.Metric{convertMetric(m, cfg.Start)}, - }) -} - func (e *exporter) send(endpoint string, message interface{}) { blob, err := json.Marshal(message) if err != nil { diff --git a/internal/telemetry/export/ocagent/ocagent_test.go b/internal/telemetry/export/ocagent/ocagent_test.go index 97d2c2a01c..8f7d7df363 100644 --- a/internal/telemetry/export/ocagent/ocagent_test.go +++ b/internal/telemetry/export/ocagent/ocagent_test.go @@ -9,27 +9,36 @@ import ( "context" "encoding/json" "errors" + "fmt" + "io/ioutil" + "net/http" + "sync" "testing" "time" "golang.org/x/tools/internal/telemetry" + "golang.org/x/tools/internal/telemetry/export" "golang.org/x/tools/internal/telemetry/export/ocagent" "golang.org/x/tools/internal/telemetry/tag" ) var ( - cfg = ocagent.Config{ - Host: "tester", - Process: 1, - Service: "ocagent-tests", - } - start time.Time - at time.Time - end time.Time + exporter export.Exporter + sent fakeSender + start time.Time + at time.Time + end time.Time ) func init() { + cfg := ocagent.Config{ + Host: "tester", + Process: 1, + Service: "ocagent-tests", + Client: &http.Client{Transport: &sent}, + } cfg.Start, _ = time.Parse(time.RFC3339Nano, "1970-01-01T00:00:00Z") + exporter = ocagent.Connect(&cfg) } const testNodeStr = `{ @@ -267,10 +276,10 @@ func TestEvents(t *testing.T) { Finish: end, Events: []telemetry.Event{tt.event(ctx)}, } - got, err := ocagent.EncodeSpan(cfg, span) - if err != nil { - t.Fatal(err) - } + exporter.StartSpan(ctx, span) + exporter.FinishSpan(ctx, span) + exporter.Flush() + got := sent.get("/v1/trace") checkJSON(t, got, []byte(tt.want)) }) } @@ -291,3 +300,42 @@ func checkJSON(t *testing.T, got, want []byte) { t.Fatalf("Got:\n%s\nWant:\n%s", g, w) } } + +type fakeSender struct { + mu sync.Mutex + data map[string][]byte +} + +func (s *fakeSender) get(route string) []byte { + s.mu.Lock() + defer s.mu.Unlock() + data, found := s.data[route] + if found { + delete(s.data, route) + } + return data +} + +func (s *fakeSender) RoundTrip(req *http.Request) (*http.Response, error) { + s.mu.Lock() + defer s.mu.Unlock() + if s.data == nil { + s.data = make(map[string][]byte) + } + data, err := ioutil.ReadAll(req.Body) + if err != nil { + return nil, err + } + path := req.URL.EscapedPath() + if _, found := s.data[path]; found { + return nil, fmt.Errorf("duplicate delivery to %v", path) + } + s.data[path] = data + return &http.Response{ + Status: "200 OK", + StatusCode: 200, + Proto: "HTTP/1.0", + ProtoMajor: 1, + ProtoMinor: 0, + }, nil +}