@@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
1414limitations under the License.
1515*/
1616
17- package metricsstore_test
17+ package metricsstore
1818
1919import (
2020 "fmt"
21+ "github.com/google/go-cmp/cmp"
22+ "github.com/prometheus/common/expfmt"
23+ "reflect"
2124 "strings"
2225 "testing"
2326
24- "github.com/prometheus/common/expfmt"
25-
2627 v1 "k8s.io/api/core/v1"
2728 "k8s.io/apimachinery/pkg/api/meta"
2829 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2930
3031 "k8s.io/kube-state-metrics/v2/pkg/metric"
31- metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store"
3232)
3333
3434func TestWriteAllWithSingleStore (t * testing.T ) {
@@ -62,7 +62,7 @@ func TestWriteAllWithSingleStore(t *testing.T) {
6262
6363 return []metric.FamilyInterface {& mf1 , & mf2 }
6464 }
65- store := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
65+ store := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
6666 svcs := []v1.Service {
6767 {
6868 ObjectMeta : metav1.ObjectMeta {
@@ -86,7 +86,7 @@ func TestWriteAllWithSingleStore(t *testing.T) {
8686 }
8787 }
8888
89- multiNsWriter := metricsstore . NewMetricsWriter (store )
89+ multiNsWriter := NewMetricsWriter (store )
9090 w := strings.Builder {}
9191 err := multiNsWriter .WriteAll (& w )
9292 if err != nil {
@@ -150,7 +150,7 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
150150
151151 return []metric.FamilyInterface {& mf1 , & mf2 }
152152 }
153- s1 := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
153+ s1 := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
154154 svcs1 := []v1.Service {
155155 {
156156 ObjectMeta : metav1.ObjectMeta {
@@ -190,15 +190,15 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
190190 },
191191 },
192192 }
193- s2 := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
193+ s2 := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
194194 for _ , s := range svcs2 {
195195 svc := s
196196 if err := s2 .Add (& svc ); err != nil {
197197 t .Fatal (err )
198198 }
199199 }
200200
201- multiNsWriter := metricsstore . NewMetricsWriter (s1 , s2 )
201+ multiNsWriter := NewMetricsWriter (s1 , s2 )
202202 w := strings.Builder {}
203203 err := multiNsWriter .WriteAll (& w )
204204 if err != nil {
@@ -250,9 +250,9 @@ func TestWriteAllWithEmptyStores(t *testing.T) {
250250
251251 return []metric.FamilyInterface {& mf1 , & mf2 }
252252 }
253- store := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
253+ store := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
254254
255- multiNsWriter := metricsstore . NewMetricsWriter (store )
255+ multiNsWriter := NewMetricsWriter (store )
256256 w := strings.Builder {}
257257 err := multiNsWriter .WriteAll (& w )
258258 if err != nil {
@@ -266,6 +266,103 @@ func TestWriteAllWithEmptyStores(t *testing.T) {
266266 }
267267}
268268
269+ // TODO: AFAIR empty headers are ignored by Prometheus? If not, we should remove them.
270+ func TestSanitizeHeaders (t * testing.T ) {
271+ boilerplateHeaders := []string {
272+ "" ,
273+ "" ,
274+ "# HELP foo foo_help\n # TYPE foo gauge" ,
275+ "# HELP foo foo_help\n # TYPE foo info" ,
276+ "# HELP foo foo_help\n # TYPE foo stateset" ,
277+ "# HELP foo foo_help\n # TYPE foo counter" ,
278+ }
279+ duplicatedBoilerplateHeaders := []string {
280+ "" ,
281+ "" ,
282+ "# HELP foo foo_help\n # TYPE foo gauge" ,
283+ "# HELP foo foo_help\n # TYPE foo gauge" ,
284+ "# HELP foo foo_help\n # TYPE foo info" ,
285+ "# HELP foo foo_help\n # TYPE foo info" ,
286+ "# HELP foo foo_help\n # TYPE foo stateset" ,
287+ "# HELP foo foo_help\n # TYPE foo stateset" ,
288+ "# HELP foo foo_help\n # TYPE foo counter" ,
289+ "# HELP foo foo_help\n # TYPE foo counter" ,
290+ }
291+ dedepedBoilerplateHeaders := []string {
292+ "" ,
293+ "" ,
294+ "# HELP foo foo_help\n # TYPE foo gauge" ,
295+ "" ,
296+ "# HELP foo foo_help\n # TYPE foo info" ,
297+ "" ,
298+ "# HELP foo foo_help\n # TYPE foo stateset" ,
299+ "" ,
300+ "# HELP foo foo_help\n # TYPE foo counter" ,
301+ "" ,
302+ }
303+ protoIngestibleHeaders := []string {
304+ "" ,
305+ "" ,
306+ "# HELP foo foo_help\n # TYPE foo gauge" ,
307+ "# HELP foo foo_help\n # TYPE foo gauge" ,
308+ "# HELP foo foo_help\n # TYPE foo gauge" ,
309+ "# HELP foo foo_help\n # TYPE foo counter" ,
310+ }
311+ dedepedProtoIngestibleHeaders := []string {
312+ "" ,
313+ "" ,
314+ "# HELP foo foo_help\n # TYPE foo gauge" ,
315+ "" ,
316+ "# HELP foo foo_help\n # TYPE foo gauge" ,
317+ "" ,
318+ "# HELP foo foo_help\n # TYPE foo gauge" ,
319+ "" ,
320+ "# HELP foo foo_help\n # TYPE foo counter" ,
321+ "" ,
322+ }
323+ testcases := []struct {
324+ name string
325+ contentType expfmt.Format
326+ headers []string
327+ expectedHeaders []string
328+ }{
329+ {
330+ name : "text-format unique headers" ,
331+ contentType : expfmt .FmtText ,
332+ headers : boilerplateHeaders ,
333+ expectedHeaders : boilerplateHeaders ,
334+ },
335+ {
336+ name : "text-format consecutive duplicate headers" ,
337+ contentType : expfmt .FmtText ,
338+ headers : duplicatedBoilerplateHeaders ,
339+ expectedHeaders : dedepedBoilerplateHeaders ,
340+ },
341+ {
342+ name : "proto-format unique headers" ,
343+ contentType : expfmt .ProtoFmt , // Prometheus ProtoFmt is the only proto-based format we check for.
344+ headers : boilerplateHeaders ,
345+ expectedHeaders : protoIngestibleHeaders ,
346+ },
347+ {
348+ name : "proto-format consecutive duplicate headers" ,
349+ contentType : expfmt .ProtoFmt , // Prometheus ProtoFmt is the only proto-based format we check for.
350+ headers : duplicatedBoilerplateHeaders ,
351+ expectedHeaders : dedepedProtoIngestibleHeaders ,
352+ },
353+ }
354+
355+ for _ , testcase := range testcases {
356+ writer := NewMetricsWriter (NewMetricsStore (testcase .headers , nil ))
357+ t .Run (testcase .name , func (t * testing.T ) {
358+ SanitizeHeaders (string (testcase .contentType ), MetricsWriterList {writer })
359+ if ! reflect .DeepEqual (testcase .expectedHeaders , writer .stores [0 ].headers ) {
360+ t .Fatalf ("(-want, +got):\n %s" , cmp .Diff (testcase .expectedHeaders , writer .stores [0 ].headers ))
361+ }
362+ })
363+ }
364+ }
365+
269366func BenchmarkSanitizeHeaders (b * testing.B ) {
270367 benchmarks := []struct {
271368 name string
@@ -303,10 +400,10 @@ func BenchmarkSanitizeHeaders(b *testing.B) {
303400 headers = append (headers , fmt .Sprintf ("# HELP foo_%d foo_help\n # TYPE foo_%d info" , j , j ))
304401 }
305402 }
306- writer := metricsstore . NewMetricsWriter (metricsstore . NewMetricsStore (headers , nil ))
403+ writer := NewMetricsWriter (NewMetricsStore (headers , nil ))
307404 b .Run (benchmark .name , func (b * testing.B ) {
308405 for i := 0 ; i < b .N ; i ++ {
309- metricsstore . SanitizeHeaders (string (benchmark .contentType ), metricsstore. MetricsWriterList {writer })
406+ SanitizeHeaders (string (benchmark .contentType ), MetricsWriterList {writer })
310407 }
311408 })
312409 }
0 commit comments