Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / event / export / ocagent / ocagent_test.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package ocagent_test
6
7 import (
8         "bytes"
9         "context"
10         "encoding/json"
11         "fmt"
12         "io/ioutil"
13         "net/http"
14         "sync"
15         "testing"
16         "time"
17
18         "golang.org/x/tools/internal/event"
19         "golang.org/x/tools/internal/event/core"
20         "golang.org/x/tools/internal/event/export"
21         "golang.org/x/tools/internal/event/export/metric"
22         "golang.org/x/tools/internal/event/export/ocagent"
23         "golang.org/x/tools/internal/event/keys"
24         "golang.org/x/tools/internal/event/label"
25 )
26
27 const testNodeStr = `{
28         "node":{
29                 "identifier":{
30                         "host_name":"tester",
31                         "pid":1,
32                         "start_timestamp":"1970-01-01T00:00:00Z"
33                 },
34                 "library_info":{
35                         "language":4,
36                         "exporter_version":"0.0.1",
37                         "core_library_version":"x/tools"
38                 },
39                 "service_info":{
40                         "name":"ocagent-tests"
41                 }
42         },`
43
44 var (
45         keyDB     = keys.NewString("db", "the database name")
46         keyMethod = keys.NewString("method", "a metric grouping key")
47         keyRoute  = keys.NewString("route", "another metric grouping key")
48
49         key1DB = keys.NewString("1_db", "A test string key")
50
51         key2aAge      = keys.NewFloat64("2a_age", "A test float64 key")
52         key2bTTL      = keys.NewFloat32("2b_ttl", "A test float32 key")
53         key2cExpiryMS = keys.NewFloat64("2c_expiry_ms", "A test float64 key")
54
55         key3aRetry = keys.NewBoolean("3a_retry", "A test boolean key")
56         key3bStale = keys.NewBoolean("3b_stale", "Another test boolean key")
57
58         key4aMax      = keys.NewInt("4a_max", "A test int key")
59         key4bOpcode   = keys.NewInt8("4b_opcode", "A test int8 key")
60         key4cBase     = keys.NewInt16("4c_base", "A test int16 key")
61         key4eChecksum = keys.NewInt32("4e_checksum", "A test int32 key")
62         key4fMode     = keys.NewInt64("4f_mode", "A test int64 key")
63
64         key5aMin     = keys.NewUInt("5a_min", "A test uint key")
65         key5bMix     = keys.NewUInt8("5b_mix", "A test uint8 key")
66         key5cPort    = keys.NewUInt16("5c_port", "A test uint16 key")
67         key5dMinHops = keys.NewUInt32("5d_min_hops", "A test uint32 key")
68         key5eMaxHops = keys.NewUInt64("5e_max_hops", "A test uint64 key")
69
70         recursiveCalls = keys.NewInt64("recursive_calls", "Number of recursive calls")
71         bytesIn        = keys.NewInt64("bytes_in", "Number of bytes in")           //, unit.Bytes)
72         latencyMs      = keys.NewFloat64("latency", "The latency in milliseconds") //, unit.Milliseconds)
73
74         metricLatency = metric.HistogramFloat64{
75                 Name:        "latency_ms",
76                 Description: "The latency of calls in milliseconds",
77                 Keys:        []label.Key{keyMethod, keyRoute},
78                 Buckets:     []float64{0, 5, 10, 25, 50},
79         }
80
81         metricBytesIn = metric.HistogramInt64{
82                 Name:        "latency_ms",
83                 Description: "The latency of calls in milliseconds",
84                 Keys:        []label.Key{keyMethod, keyRoute},
85                 Buckets:     []int64{0, 10, 50, 100, 500, 1000, 2000},
86         }
87
88         metricRecursiveCalls = metric.Scalar{
89                 Name:        "latency_ms",
90                 Description: "The latency of calls in milliseconds",
91                 Keys:        []label.Key{keyMethod, keyRoute},
92         }
93 )
94
95 type testExporter struct {
96         ocagent *ocagent.Exporter
97         sent    fakeSender
98 }
99
100 func registerExporter() *testExporter {
101         exporter := &testExporter{}
102         cfg := ocagent.Config{
103                 Host:    "tester",
104                 Process: 1,
105                 Service: "ocagent-tests",
106                 Client:  &http.Client{Transport: &exporter.sent},
107         }
108         cfg.Start, _ = time.Parse(time.RFC3339Nano, "1970-01-01T00:00:00Z")
109         exporter.ocagent = ocagent.Connect(&cfg)
110
111         metrics := metric.Config{}
112         metricLatency.Record(&metrics, latencyMs)
113         metricBytesIn.Record(&metrics, bytesIn)
114         metricRecursiveCalls.SumInt64(&metrics, recursiveCalls)
115
116         e := exporter.ocagent.ProcessEvent
117         e = metrics.Exporter(e)
118         e = spanFixer(e)
119         e = export.Spans(e)
120         e = export.Labels(e)
121         e = timeFixer(e)
122         event.SetExporter(e)
123         return exporter
124 }
125
126 func timeFixer(output event.Exporter) event.Exporter {
127         start, _ := time.Parse(time.RFC3339Nano, "1970-01-01T00:00:30Z")
128         at, _ := time.Parse(time.RFC3339Nano, "1970-01-01T00:00:40Z")
129         end, _ := time.Parse(time.RFC3339Nano, "1970-01-01T00:00:50Z")
130         return func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
131                 switch {
132                 case event.IsStart(ev):
133                         ev = core.CloneEvent(ev, start)
134                 case event.IsEnd(ev):
135                         ev = core.CloneEvent(ev, end)
136                 default:
137                         ev = core.CloneEvent(ev, at)
138                 }
139                 return output(ctx, ev, lm)
140         }
141 }
142
143 func spanFixer(output event.Exporter) event.Exporter {
144         return func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
145                 if event.IsStart(ev) {
146                         span := export.GetSpan(ctx)
147                         span.ID = export.SpanContext{}
148                 }
149                 return output(ctx, ev, lm)
150         }
151 }
152
153 func (e *testExporter) Output(route string) []byte {
154         e.ocagent.Flush()
155         return e.sent.get(route)
156 }
157
158 func checkJSON(t *testing.T, got, want []byte) {
159         // compare the compact form, to allow for formatting differences
160         g := &bytes.Buffer{}
161         if err := json.Compact(g, got); err != nil {
162                 t.Fatal(err)
163         }
164         w := &bytes.Buffer{}
165         if err := json.Compact(w, want); err != nil {
166                 t.Fatal(err)
167         }
168         if g.String() != w.String() {
169                 t.Fatalf("Got:\n%s\nWant:\n%s", g, w)
170         }
171 }
172
173 type fakeSender struct {
174         mu   sync.Mutex
175         data map[string][]byte
176 }
177
178 func (s *fakeSender) get(route string) []byte {
179         s.mu.Lock()
180         defer s.mu.Unlock()
181         data, found := s.data[route]
182         if found {
183                 delete(s.data, route)
184         }
185         return data
186 }
187
188 func (s *fakeSender) RoundTrip(req *http.Request) (*http.Response, error) {
189         s.mu.Lock()
190         defer s.mu.Unlock()
191         if s.data == nil {
192                 s.data = make(map[string][]byte)
193         }
194         data, err := ioutil.ReadAll(req.Body)
195         if err != nil {
196                 return nil, err
197         }
198         path := req.URL.EscapedPath()
199         if _, found := s.data[path]; found {
200                 return nil, fmt.Errorf("duplicate delivery to %v", path)
201         }
202         s.data[path] = data
203         return &http.Response{
204                 Status:     "200 OK",
205                 StatusCode: 200,
206                 Proto:      "HTTP/1.0",
207                 ProtoMajor: 1,
208                 ProtoMinor: 0,
209         }, nil
210 }