1// Copyright 2018 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package expfmt 15 16import ( 17 "bytes" 18 "github.com/golang/protobuf/proto" 19 dto "github.com/prometheus/client_model/go" 20 "net/http" 21 "testing" 22) 23 24func TestNegotiate(t *testing.T) { 25 acceptValuePrefix := "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily" 26 tests := []struct { 27 name string 28 acceptHeaderValue string 29 expectedFmt string 30 }{ 31 { 32 name: "delimited format", 33 acceptHeaderValue: acceptValuePrefix + ";encoding=delimited", 34 expectedFmt: string(FmtProtoDelim), 35 }, 36 { 37 name: "text format", 38 acceptHeaderValue: acceptValuePrefix + ";encoding=text", 39 expectedFmt: string(FmtProtoText), 40 }, 41 { 42 name: "compact text format", 43 acceptHeaderValue: acceptValuePrefix + ";encoding=compact-text", 44 expectedFmt: string(FmtProtoCompact), 45 }, 46 { 47 name: "plain text format", 48 acceptHeaderValue: "text/plain;version=0.0.4", 49 expectedFmt: string(FmtText), 50 }, 51 } 52 53 for _, test := range tests { 54 t.Run(test.name, func(t *testing.T) { 55 h := http.Header{} 56 h.Add(hdrAccept, test.acceptHeaderValue) 57 actualFmt := string(Negotiate(h)) 58 if actualFmt != test.expectedFmt { 59 t.Errorf("expected Negotiate to return format %s, but got %s instead", test.expectedFmt, actualFmt) 60 } 61 }) 62 } 63} 64 65func TestEncode(t *testing.T) { 66 var buff bytes.Buffer 67 delimEncoder := NewEncoder(&buff, FmtProtoDelim) 68 metric := &dto.MetricFamily{ 69 Name: proto.String("foo_metric"), 70 Type: dto.MetricType_UNTYPED.Enum(), 71 Metric: []*dto.Metric{ 72 { 73 Untyped: &dto.Untyped{ 74 Value: proto.Float64(1.234), 75 }, 76 }, 77 }, 78 } 79 80 err := delimEncoder.Encode(metric) 81 if err != nil { 82 t.Errorf("unexpected error during encode: %s", err.Error()) 83 } 84 85 out := buff.Bytes() 86 if len(out) == 0 { 87 t.Errorf("expected the output bytes buffer to be non-empty") 88 } 89 90 buff.Reset() 91 92 compactEncoder := NewEncoder(&buff, FmtProtoCompact) 93 err = compactEncoder.Encode(metric) 94 if err != nil { 95 t.Errorf("unexpected error during encode: %s", err.Error()) 96 } 97 98 out = buff.Bytes() 99 if len(out) == 0 { 100 t.Errorf("expected the output bytes buffer to be non-empty") 101 } 102 103 buff.Reset() 104 105 protoTextEncoder := NewEncoder(&buff, FmtProtoText) 106 err = protoTextEncoder.Encode(metric) 107 if err != nil { 108 t.Errorf("unexpected error during encode: %s", err.Error()) 109 } 110 111 out = buff.Bytes() 112 if len(out) == 0 { 113 t.Errorf("expected the output bytes buffer to be non-empty") 114 } 115 116 buff.Reset() 117 118 textEncoder := NewEncoder(&buff, FmtText) 119 err = textEncoder.Encode(metric) 120 if err != nil { 121 t.Errorf("unexpected error during encode: %s", err.Error()) 122 } 123 124 out = buff.Bytes() 125 if len(out) == 0 { 126 t.Errorf("expected the output bytes buffer to be non-empty") 127 } 128 129 expected := "# TYPE foo_metric untyped\n" + 130 "foo_metric 1.234\n" 131 132 if string(out) != expected { 133 t.Errorf("expected TextEncoder to return %s, but got %s instead", expected, string(out)) 134 } 135} 136