github.com/openshift/installer@v1.4.17/pkg/metrics/builder/builder_test.go (about)

     1  package builder
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"sort"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func getDescStruct(opts MetricOpts, labelKeyValues map[string]string) string {
    15  	lpStrings := make([]string, 0, len(labelKeyValues))
    16  	for key, value := range labelKeyValues {
    17  		lpStrings = append(lpStrings, fmt.Sprintf("%s=%q", key, value))
    18  	}
    19  	sort.Strings(lpStrings)
    20  	return fmt.Sprintf("Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: %v}",
    21  		opts.Name, opts.Desc, strings.Join(lpStrings, ","), "{}")
    22  }
    23  
    24  func getCollectorDescription(collector prometheus.Collector) string {
    25  	switch reflect.TypeOf(collector).Elem().Name() {
    26  	case "histogram":
    27  		return collector.(prometheus.Histogram).Desc().String()
    28  	case "counter":
    29  		return collector.(prometheus.Counter).Desc().String()
    30  	default:
    31  		return ""
    32  	}
    33  }
    34  
    35  // TestNewMetricBuilder tests the Metric Builder initializer.
    36  func TestMetricBuilder(t *testing.T) {
    37  	cases := []struct {
    38  		name                  string
    39  		expectedCollectorType string
    40  		opts                  MetricOpts
    41  		labelKeyValues        map[string]string
    42  		value                 float64
    43  		expectedErrorMessage  string
    44  	}{
    45  		{
    46  			name:                  "Test histogram creation",
    47  			expectedCollectorType: "histogram",
    48  			opts: MetricOpts{
    49  				Labels:     []string{"test1", "test2"},
    50  				Desc:       "test histogram metrics",
    51  				Name:       "test_histogram",
    52  				Buckets:    []float64{10, 20, 30},
    53  				MetricType: Histogram,
    54  			},
    55  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
    56  			value:                0,
    57  			expectedErrorMessage: "",
    58  		},
    59  		{
    60  			name:                  "Test invalid labels",
    61  			expectedCollectorType: "histogram",
    62  			opts: MetricOpts{
    63  				Labels:     nil,
    64  				Desc:       "test metric",
    65  				Name:       "test",
    66  				MetricType: "Histogram",
    67  			},
    68  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
    69  			value:                0,
    70  			expectedErrorMessage: `labels cannot be empty`,
    71  		},
    72  		{
    73  			name:                  "Test invalid name",
    74  			expectedCollectorType: "histogram",
    75  			opts: MetricOpts{
    76  				Labels:     []string{"test1", "test2"},
    77  				Desc:       "test metric",
    78  				Name:       "",
    79  				MetricType: "Histogram",
    80  			},
    81  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
    82  			value:                0,
    83  			expectedErrorMessage: `name cannot be empty`,
    84  		},
    85  		{
    86  			name:                  "Test invalid metric type",
    87  			expectedCollectorType: "histogram",
    88  			opts: MetricOpts{
    89  				Labels:     []string{"test1", "test2"},
    90  				Desc:       "test metric",
    91  				Name:       "test",
    92  				MetricType: "",
    93  			},
    94  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
    95  			value:                0,
    96  			expectedErrorMessage: `metricType cannot be empty`,
    97  		},
    98  	}
    99  	for _, tc := range cases {
   100  		t.Run(tc.name, func(t *testing.T) {
   101  			_, err := NewMetricBuilder(tc.opts, tc.value, tc.labelKeyValues)
   102  			if tc.expectedErrorMessage == "" {
   103  				assert.NoError(t, err, "expected successful builder creation")
   104  			} else {
   105  				assert.Error(t, err, "expected builder creation failure but builder was created")
   106  				assert.EqualError(t, err, tc.expectedErrorMessage)
   107  			}
   108  		})
   109  	}
   110  }
   111  
   112  // TestMetricBuilderCollector tests the PromCollector function.
   113  func TestMetricBuilderCollector(t *testing.T) {
   114  	cases := []struct {
   115  		name                  string
   116  		expectedCollectorType string
   117  		opts                  MetricOpts
   118  		labelKeyValues        map[string]string
   119  		value                 float64
   120  		expectedErrorMessage  string
   121  	}{
   122  		{
   123  			name:                  "Test histogram creation",
   124  			expectedCollectorType: "histogram",
   125  			opts: MetricOpts{
   126  				Labels:     []string{"test1", "test2"},
   127  				Desc:       "test histogram metrics",
   128  				Name:       "test_histogram",
   129  				Buckets:    []float64{10, 20, 30},
   130  				MetricType: Histogram,
   131  			},
   132  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
   133  			value:                0,
   134  			expectedErrorMessage: "",
   135  		},
   136  		{
   137  			name:                  "Test counter creation",
   138  			expectedCollectorType: "counter",
   139  			opts: MetricOpts{
   140  				Labels:     []string{"test1", "test2"},
   141  				Desc:       "test modification metric",
   142  				Name:       "test_modification",
   143  				MetricType: Counter,
   144  			},
   145  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
   146  			expectedErrorMessage: "",
   147  		},
   148  		{
   149  			name:                  "Test empty label values",
   150  			expectedCollectorType: "counter",
   151  			opts: MetricOpts{
   152  				Labels:     []string{"test1", "test2"},
   153  				Desc:       "test modification metric",
   154  				Name:       "test_modification",
   155  				MetricType: Counter,
   156  			},
   157  			labelKeyValues:       nil,
   158  			value:                0,
   159  			expectedErrorMessage: "",
   160  		},
   161  		{
   162  			name:                  "Test invalid metricType",
   163  			expectedCollectorType: "Linear",
   164  			opts: MetricOpts{
   165  				Labels:     []string{"test1", "test2"},
   166  				Desc:       "test metric",
   167  				Name:       "test",
   168  				MetricType: "Linear",
   169  			},
   170  			labelKeyValues:       map[string]string{"test1": "test1", "test2": "test2"},
   171  			value:                0,
   172  			expectedErrorMessage: `invalid metric builder type "Linear". cannot create collector`,
   173  		},
   174  	}
   175  	for _, tc := range cases {
   176  		t.Run(tc.name, func(t *testing.T) {
   177  			metricBuilder, err := NewMetricBuilder(tc.opts, tc.value, tc.labelKeyValues)
   178  			if !assert.NoError(t, err, "error constructing new metric builder") {
   179  				return
   180  			}
   181  			collector, err := metricBuilder.PromCollector()
   182  			if tc.expectedErrorMessage == "" {
   183  				assert.NoError(t, err, "expected successful collector creation")
   184  				assert.EqualValues(t, tc.expectedCollectorType, reflect.TypeOf(collector).Elem().Name())
   185  				expectedString := getDescStruct(tc.opts, tc.labelKeyValues)
   186  				assert.EqualValues(t, expectedString, getCollectorDescription(collector))
   187  			} else {
   188  				assert.Error(t, err, "expected collector creation failure but collector was created")
   189  				assert.EqualError(t, err, tc.expectedErrorMessage)
   190  			}
   191  		})
   192  	}
   193  }
   194  
   195  // TestNewMetricBuilder tests the Metric Builder initializer.
   196  func TestNewMetricBuilder(t *testing.T) {
   197  	opts := MetricOpts{
   198  		Labels:     []string{"test1", "test2", "test3"},
   199  		Desc:       "test metric",
   200  		Name:       "test",
   201  		Buckets:    []float64{10, 20, 30},
   202  		MetricType: Histogram,
   203  	}
   204  	labelKeyValues := map[string]string{"test1": "test1", "test2": "test2"}
   205  	metricBuilder, err := NewMetricBuilder(opts, 10, labelKeyValues)
   206  	if err != nil {
   207  		assert.Failf(t, err.Error(), "error creating metric builder")
   208  	} else {
   209  		assert.EqualValues(t, metricBuilder.value, 10)
   210  		assert.EqualValues(t, metricBuilder.labels, opts.Labels)
   211  		assert.EqualValues(t, metricBuilder.labelKeyValues, labelKeyValues)
   212  		assert.EqualValues(t, metricBuilder.desc, opts.Desc)
   213  		assert.EqualValues(t, metricBuilder.name, opts.Name)
   214  		assert.EqualValues(t, metricBuilder.buckets, opts.Buckets)
   215  		assert.EqualValues(t, metricBuilder.metricType, Histogram)
   216  	}
   217  	metricBuilder.SetValue(10)
   218  	assert.EqualValues(t, 10, metricBuilder.value)
   219  
   220  	err = metricBuilder.AddLabelValue("test", "metric labels")
   221  	assert.Error(t, err, "expected error adding label")
   222  	_, found := metricBuilder.labelKeyValues["test"]
   223  	assert.False(t, found)
   224  
   225  	err = metricBuilder.AddLabelValue("test3", "metric labels")
   226  	if err != nil {
   227  		assert.Failf(t, err.Error(), "error adding label value")
   228  	}
   229  	_, found = metricBuilder.labelKeyValues["test3"]
   230  	assert.True(t, found)
   231  }