diff --git a/config/http_config_test.go b/config/http_config_test.go index 4639ae47..698ea38f 100644 --- a/config/http_config_test.go +++ b/config/http_config_test.go @@ -320,10 +320,6 @@ func TestBearerAuthRoundTripper(t *testing.T) { } func TestBearerAuthFileRoundTripper(t *testing.T) { - const ( - newBearerToken = "goodbyeandthankyouforthefish" - ) - fakeRoundTripper := NewRoundTripCheckRequest(func(req *http.Request) { bearer := req.Header.Get("Authorization") if bearer != ExpectedBearer { diff --git a/expfmt/decode_test.go b/expfmt/decode_test.go index 82c1130c..47c480ef 100644 --- a/expfmt/decode_test.go +++ b/expfmt/decode_test.go @@ -258,6 +258,65 @@ func TestProtoDecoder(t *testing.T) { }, }, }, + { + in: "\u007f\n\x1drequest_duration_microseconds\x12\x15The response latency.\x18\x04\"E:C\b\x85\x15\x11\xcd\xcc\xccL\x8f\xcb:A\x1a\v\b{\x11\x00\x00\x00\x00\x00\x00Y@\x1a\f\b\x9c\x03\x11\x00\x00\x00\x00\x00\x00^@\x1a\f\b\xd0\x04\x11\x00\x00\x00\x00\x00\x00b@\x1a\f\b\xf4\v\x11\x9a\x99\x99\x99\x99\x99e@", + expected: model.Vector{ + &model.Sample{ + Metric: model.Metric{ + model.MetricNameLabel: "request_duration_microseconds_count", + }, + Value: 2693, + Timestamp:testTime, + }, + &model.Sample{ + Metric: model.Metric{ + "le": "+Inf", + model.MetricNameLabel: "request_duration_microseconds_bucket", + }, + Value: 2693, + Timestamp:testTime, + }, + &model.Sample{ + Metric: model.Metric{ + model.MetricNameLabel: "request_duration_microseconds_sum", + }, + Value: 1756047.3, + Timestamp:testTime, + }, + &model.Sample{ + Metric: model.Metric{ + "le": "172.8", + model.MetricNameLabel: "request_duration_microseconds_bucket", + }, + Value: 1524, + Timestamp:testTime, + }, + &model.Sample{ + Metric: model.Metric{ + "le": "144", + model.MetricNameLabel: "request_duration_microseconds_bucket", + }, + Value: 592, + Timestamp:testTime, + }, + &model.Sample{ + Metric: model.Metric{ + "le": "120", + model.MetricNameLabel: "request_duration_microseconds_bucket", + }, + Value: 412, + Timestamp:testTime, + }, + &model.Sample{ + Metric: model.Metric{ + "le": "100", + model.MetricNameLabel: "request_duration_microseconds_bucket", + }, + Value: 123, + Timestamp:testTime, + }, + }, + }, { // The metric type is unset in this protobuf, which needs to be handled // correctly by the decoder. diff --git a/expfmt/encode_test.go b/expfmt/encode_test.go new file mode 100644 index 00000000..16255e0e --- /dev/null +++ b/expfmt/encode_test.go @@ -0,0 +1,122 @@ +package expfmt + +import ( + "bytes" + "github.com/golang/protobuf/proto" + dto "github.com/prometheus/client_model/go" + "net/http" + "testing" +) + +func TestNegotiate(t *testing.T) { + acceptValuePrefix := "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily" + tests := []struct { + name string + acceptHeaderValue string + expectedFmt string + }{ + { + name: "delimited format", + acceptHeaderValue: acceptValuePrefix + ";encoding=delimited", + expectedFmt: string(FmtProtoDelim), + }, + { + name: "text format", + acceptHeaderValue: acceptValuePrefix + ";encoding=text", + expectedFmt: string(FmtProtoText), + }, + { + name: "compact text format", + acceptHeaderValue: acceptValuePrefix + ";encoding=compact-text", + expectedFmt: string(FmtProtoCompact), + }, + { + name: "plain text format", + acceptHeaderValue: "text/plain;version=0.0.4", + expectedFmt: string(FmtText), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + h := http.Header{} + h.Add(hdrAccept, test.acceptHeaderValue) + actualFmt := string(Negotiate(h)) + if actualFmt != test.expectedFmt { + t.Errorf("expected Negotiate to return format %s, but got %s instead", test.expectedFmt, actualFmt) + } + }) + } +} + +func TestEncode(t *testing.T) { + var buff bytes.Buffer + delimEncoder := NewEncoder(&buff, FmtProtoDelim) + metric := &dto.MetricFamily{ + Name: proto.String("foo_metric"), + Type: dto.MetricType_UNTYPED.Enum(), + Metric: []*dto.Metric{ + { + Untyped: &dto.Untyped{ + Value: proto.Float64(1.234), + }, + }, + }, + } + + err := delimEncoder.Encode(metric) + if err != nil { + t.Errorf("unexpected error during encode: %s", err.Error()) + } + + out := buff.Bytes() + if len(out) == 0 { + t.Errorf("expected the output bytes buffer to be non-empty") + } + + buff.Reset() + + compactEncoder := NewEncoder(&buff, FmtProtoCompact) + err = compactEncoder.Encode(metric) + if err != nil { + t.Errorf("unexpected error during encode: %s", err.Error()) + } + + out = buff.Bytes() + if len(out) == 0 { + t.Errorf("expected the output bytes buffer to be non-empty") + } + + buff.Reset() + + protoTextEncoder := NewEncoder(&buff, FmtProtoText) + err = protoTextEncoder.Encode(metric) + if err != nil { + t.Errorf("unexpected error during encode: %s", err.Error()) + } + + out = buff.Bytes() + if len(out) == 0 { + t.Errorf("expected the output bytes buffer to be non-empty") + } + + buff.Reset() + + textEncoder := NewEncoder(&buff, FmtText) + err = textEncoder.Encode(metric) + if err != nil { + t.Errorf("unexpected error during encode: %s", err.Error()) + } + + out = buff.Bytes() + if len(out) == 0 { + t.Errorf("expected the output bytes buffer to be non-empty") + } + + expected := "# TYPE foo_metric untyped\n" + + "foo_metric 1.234\n" + + if string(out) != expected { + t.Errorf("expected TextEncoder to return %s, but got %s instead", expected, string(out)) + } +} diff --git a/model/metric_test.go b/model/metric_test.go index 06f9de52..d708b575 100644 --- a/model/metric_test.go +++ b/model/metric_test.go @@ -119,6 +119,10 @@ func TestMetricNameIsValid(t *testing.T) { mn: "colon:in:the:middle", valid: true, }, + { + mn: "", + valid: false, + }, } for _, s := range scenarios {