github.com/GoogleCloudPlatform/testgrid@v0.0.174/util/metrics/prometheus/prometheus_test.go (about)

     1  /*
     2  Copyright 2021 The TestGrid Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package prometheus
    18  
    19  import (
    20  	"strings"
    21  	"sync"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  )
    27  
    28  func TestInt64Set(t *testing.T) {
    29  	cases := []struct {
    30  		name   string
    31  		fields []string
    32  		sets   []map[int64][]string
    33  		want   map[string]float64
    34  	}{
    35  		{
    36  			name: "zero",
    37  			want: map[string]float64{},
    38  		},
    39  		{
    40  			name:   "basic",
    41  			fields: []string{"component"},
    42  			sets: []map[int64][]string{
    43  				{64: {"updater"}},
    44  			},
    45  			want: map[string]float64{
    46  				"updater": float64(64),
    47  			},
    48  		},
    49  		{
    50  			name:   "fields",
    51  			fields: []string{"component", "source"},
    52  			sets: []map[int64][]string{
    53  				{64: {"updater", "prow"}},
    54  			},
    55  			want: map[string]float64{
    56  				"updater|prow": float64(64),
    57  			},
    58  		},
    59  		{
    60  			name:   "serial values",
    61  			fields: []string{"component"},
    62  			sets: []map[int64][]string{
    63  				{64: {"updater"}},
    64  				{32: {"updater"}},
    65  			},
    66  			want: map[string]float64{
    67  				"updater": float64(32),
    68  			},
    69  		},
    70  		{
    71  			name:   "complex",
    72  			fields: []string{"component", "source"},
    73  			sets: []map[int64][]string{
    74  				{
    75  					64: {"updater", "prow"},
    76  					66: {"updater", "google"},
    77  					32: {"summarizer", "google"},
    78  				},
    79  				{
    80  					64: {"updater", "prow"},
    81  					22: {"summarizer", "google"},
    82  				},
    83  			},
    84  			want: map[string]float64{
    85  				"updater|prow":      float64(64),
    86  				"updater|google":    float64(66),
    87  				"summarizer|google": float64(22),
    88  			},
    89  		},
    90  	}
    91  
    92  	for _, tc := range cases {
    93  		t.Run(tc.name, func(t *testing.T) {
    94  			mName := strings.Replace(tc.name, " ", "_", -1) + "_int"
    95  			m := NewInt64(mName, "fake desc", tc.fields...)
    96  			var wg sync.WaitGroup
    97  			for _, set := range tc.sets {
    98  				for n, fields := range set {
    99  					wg.Add(1)
   100  					go func(n int64, fields []string) {
   101  						m.Set(n, fields...)
   102  						m.(Valuer).Values() // Set and Values must be able to run concurrently
   103  						wg.Done()
   104  					}(n, fields)
   105  				}
   106  				wg.Wait()
   107  			}
   108  			got := m.(Valuer).Values()
   109  			if diff := cmp.Diff(tc.want, got); diff != "" {
   110  				t.Errorf("Set() got unexpected diff (-want +got):\n%s", diff)
   111  			}
   112  		})
   113  	}
   114  }
   115  
   116  func TestCounterAdd(t *testing.T) {
   117  	cases := []struct {
   118  		name   string
   119  		fields []string
   120  		adds   []map[int64][]string
   121  		want   map[string]float64
   122  	}{
   123  		{
   124  			name: "zero",
   125  			want: map[string]float64{},
   126  		},
   127  		{
   128  			name:   "basic",
   129  			fields: []string{"component"},
   130  			adds: []map[int64][]string{
   131  				{
   132  					12: {"updater"},
   133  				},
   134  			},
   135  			want: map[string]float64{
   136  				"updater": float64(12),
   137  			},
   138  		},
   139  		{
   140  			name:   "fields",
   141  			fields: []string{"component", "source"},
   142  			adds: []map[int64][]string{
   143  				{64: {"updater", "prow"}},
   144  			},
   145  			want: map[string]float64{
   146  				"updater|prow": float64(64),
   147  			},
   148  		},
   149  		{
   150  			name:   "concurrent values",
   151  			fields: []string{"component"},
   152  			adds: []map[int64][]string{
   153  				{
   154  					32: {"updater"},
   155  					64: {"updater"},
   156  				},
   157  				{32: {"updater"}},
   158  			},
   159  			want: map[string]float64{
   160  				"updater": float64(32 + 32 + 64),
   161  			},
   162  		},
   163  		{
   164  			name:   "fields and values",
   165  			fields: []string{"component", "source"},
   166  			adds: []map[int64][]string{
   167  				{64: {"updater", "prow"}},
   168  				{32: {"updater", "prow"}},
   169  			},
   170  			want: map[string]float64{
   171  				"updater|prow": float64(64 + 32),
   172  			},
   173  		},
   174  		{
   175  			name:   "complex",
   176  			fields: []string{"component", "source"},
   177  			adds: []map[int64][]string{
   178  				{
   179  					64: {"updater", "prow"},
   180  					66: {"updater", "google"},
   181  					32: {"summarizer", "google"},
   182  					22: {"summarizer", "google"},
   183  				},
   184  			},
   185  			want: map[string]float64{
   186  				"updater|prow":      float64(64),
   187  				"updater|google":    float64(66),
   188  				"summarizer|google": float64(32 + 22),
   189  			},
   190  		},
   191  	}
   192  
   193  	for _, tc := range cases {
   194  		t.Run(tc.name, func(t *testing.T) {
   195  			mName := strings.Replace(tc.name, " ", "_", -1) + "_counter"
   196  			m := NewCounter(mName, "fake desc", tc.fields...)
   197  			var wg sync.WaitGroup
   198  			for _, add := range tc.adds {
   199  				for n, values := range add {
   200  					wg.Add(1)
   201  					go func(n int64, values []string) {
   202  						m.Add(n, values...)
   203  						m.(Valuer).Values() // Add and Values must be able to run concurrently
   204  						wg.Done()
   205  					}(n, values)
   206  				}
   207  				wg.Wait()
   208  			}
   209  			got := m.(Valuer).Values()
   210  			if diff := cmp.Diff(tc.want, got); diff != "" {
   211  				t.Errorf("Add() got unexpected diff (-want +got):\n%s", diff)
   212  			}
   213  		})
   214  	}
   215  }
   216  
   217  func TestDurationSet(t *testing.T) {
   218  	cases := []struct {
   219  		name   string
   220  		fields []string
   221  		sets   []map[time.Duration][]string
   222  		want   map[string]float64
   223  	}{
   224  		{
   225  			name: "zero",
   226  			want: map[string]float64{},
   227  		},
   228  		{
   229  			name:   "basic",
   230  			fields: []string{"component"},
   231  			sets: []map[time.Duration][]string{
   232  				{(1100 * time.Millisecond): {"updater"}},
   233  			},
   234  			want: map[string]float64{
   235  				"updater": float64(1.1),
   236  			},
   237  		},
   238  		{
   239  			name:   "fields",
   240  			fields: []string{"component", "source"},
   241  			sets: []map[time.Duration][]string{
   242  				{time.Second: {"updater", "prow"}},
   243  			},
   244  			want: map[string]float64{
   245  				"updater|prow": float64(1),
   246  			},
   247  		},
   248  		{
   249  			name:   "serial values",
   250  			fields: []string{"component"},
   251  			sets: []map[time.Duration][]string{
   252  				{time.Second: {"updater"}},
   253  				{time.Minute: {"updater"}},
   254  			},
   255  			want: map[string]float64{
   256  				"updater": float64(60),
   257  			},
   258  		},
   259  		{
   260  			name:   "complex",
   261  			fields: []string{"component", "source"},
   262  			sets: []map[time.Duration][]string{
   263  				{
   264  					time.Second:      {"updater", "prow"},
   265  					time.Minute:      {"updater", "google"},
   266  					time.Millisecond: {"summarizer", "google"},
   267  				},
   268  				{
   269  					time.Second:       {"updater", "prow"},
   270  					(2 * time.Second): {"summarizer", "google"},
   271  				},
   272  			},
   273  			want: map[string]float64{
   274  				"updater|prow":      float64(1),
   275  				"updater|google":    float64(60),
   276  				"summarizer|google": float64(2),
   277  			},
   278  		},
   279  	}
   280  
   281  	for _, tc := range cases {
   282  		t.Run(tc.name, func(t *testing.T) {
   283  			mName := strings.Replace(tc.name, " ", "_", -1) + "_duration"
   284  			m := NewDuration(mName, "fake desc", tc.fields...)
   285  			var wg sync.WaitGroup
   286  			for _, set := range tc.sets {
   287  				for n, fields := range set {
   288  					wg.Add(1)
   289  					go func(n time.Duration, fields []string) {
   290  						m.Set(n, fields...)
   291  						m.(Valuer).Values() // Set and Values must be able to run concurrently
   292  						wg.Done()
   293  					}(n, fields)
   294  				}
   295  				wg.Wait()
   296  			}
   297  			got := m.(Valuer).Values()
   298  			if diff := cmp.Diff(tc.want, got); diff != "" {
   299  				t.Errorf("Set() got unexpected diff (-want +got):\n%s", diff)
   300  			}
   301  		})
   302  	}
   303  }