// Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ocagent_test import ( "bytes" "context" "encoding/json" "errors" "testing" "golang.org/x/tools/internal/telemetry" "golang.org/x/tools/internal/telemetry/export/ocagent" "golang.org/x/tools/internal/telemetry/tag" ) func TestConvert_annotation(t *testing.T) { tests := []struct { name string event func(ctx context.Context) telemetry.Event want string }{ { name: "no tags", event: func(ctx context.Context) telemetry.Event { return telemetry.Event{} }, want: "null", }, { name: "description no error", event: func(ctx context.Context) telemetry.Event { return telemetry.Event{ Message: "cache miss", Tags: telemetry.TagList{ tag.Of("db", "godb"), }, } }, want: `{ "description": { "value": "cache miss" }, "attributes": { "attributeMap": { "db": { "stringValue": { "value": "godb" } } } } }`, }, { name: "description and error", event: func(ctx context.Context) telemetry.Event { return telemetry.Event{ Message: "cache miss", Error: errors.New("no network connectivity"), Tags: telemetry.TagList{ tag.Of("db", "godb"), }, } }, want: `{ "description": { "value": "cache miss" }, "attributes": { "attributeMap": { "Error": { "stringValue": { "value": "no network connectivity" } }, "db": { "stringValue": { "value": "godb" } } } } }`, }, { name: "no description, but error", event: func(ctx context.Context) telemetry.Event { return telemetry.Event{ Error: errors.New("no network connectivity"), Tags: telemetry.TagList{ tag.Of("db", "godb"), }, } }, want: `{ "description": { "value": "no network connectivity" }, "attributes": { "attributeMap": { "db": { "stringValue": { "value": "godb" } } } } }`, }, { name: "enumerate all attribute types", event: func(ctx context.Context) telemetry.Event { return telemetry.Event{ Message: "cache miss", Tags: telemetry.TagList{ tag.Of("db", "godb"), tag.Of("age", 0.456), // Constant converted into "float64" tag.Of("ttl", float32(5000)), tag.Of("expiry_ms", float64(1e3)), tag.Of("retry", false), tag.Of("stale", true), tag.Of("max", 0x7fff), // Constant converted into "int" tag.Of("opcode", int8(0x7e)), tag.Of("base", int16(1<<9)), tag.Of("checksum", int32(0x11f7e294)), tag.Of("mode", int64(0644)), tag.Of("min", uint(1)), tag.Of("mix", uint8(44)), tag.Of("port", uint16(55678)), tag.Of("min_hops", uint32(1<<9)), tag.Of("max_hops", uint64(0xffffff)), }, } }, want: `{ "description": { "value": "cache miss" }, "attributes": { "attributeMap": { "age": { "doubleValue": 0.456 }, "base": { "intValue": 512 }, "checksum": { "intValue": 301458068 }, "db": { "stringValue": { "value": "godb" } }, "expiry_ms": { "doubleValue": 1000 }, "max": { "intValue": 32767 }, "max_hops": { "intValue": 16777215 }, "min": { "intValue": 1 }, "min_hops": { "intValue": 512 }, "mix": { "intValue": 44 }, "mode": { "intValue": 420 }, "opcode": { "intValue": 126 }, "port": { "intValue": 55678 }, "retry": {}, "stale": { "boolValue": true }, "ttl": { "doubleValue": 5000 } } } }`, }, } ctx := context.TODO() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := ocagent.EncodeAnnotation(tt.event(ctx)) if err != nil { t.Fatal(err) } checkJSON(t, got, []byte(tt.want)) }) } } func checkJSON(t *testing.T, got, want []byte) { // compare the compact form, to allow for formatting differences g := &bytes.Buffer{} if err := json.Compact(g, got); err != nil { t.Fatal(err) } w := &bytes.Buffer{} if err := json.Compact(w, want); err != nil { t.Fatal(err) } if g.String() != w.String() { t.Fatalf("Got:\n%s\nWant:\n%s", got, want) } }