knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/observability/metrics/metricstest/assert_test.go (about)

     1  /*
     2  Copyright 2025 The Knative 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 metricstest
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"go.opentelemetry.io/otel/attribute"
    24  	"go.opentelemetry.io/otel/sdk/instrumentation"
    25  	"go.opentelemetry.io/otel/sdk/metric/metricdata"
    26  )
    27  
    28  func TestAssertMetricsPresent(t *testing.T) {
    29  	ft := &fakeT{}
    30  
    31  	m := &metrics{
    32  		ScopeMetrics: []metricdata.ScopeMetrics{{
    33  			Scope: instrumentation.Scope{
    34  				Name: "first",
    35  			},
    36  			Metrics: []metricdata.Metrics{{
    37  				Name: "a",
    38  			}},
    39  		}},
    40  	}
    41  
    42  	AssertMetrics(ft, m, MetricsPresent("first", "a"))
    43  
    44  	if ft.Failed() {
    45  		t.Error("unexpected failure")
    46  	}
    47  
    48  	ft = &fakeT{}
    49  
    50  	AssertMetrics(ft, m, MetricsPresent("second", "a"))
    51  
    52  	if !ft.Failed() {
    53  		t.Error("should have failed")
    54  	}
    55  
    56  	AssertMetrics(ft, m, MetricsPresent("first", "b"))
    57  
    58  	if !ft.Failed() {
    59  		t.Error("should have failed")
    60  	}
    61  }
    62  
    63  func TestHasAttributes(t *testing.T) {
    64  	m := &metrics{
    65  		ScopeMetrics: []metricdata.ScopeMetrics{{
    66  			Scope: instrumentation.Scope{Name: "first-scope"},
    67  			Metrics: []metricdata.Metrics{{
    68  				Name: "a-metric",
    69  				Data: metricdata.Sum[int64]{
    70  					DataPoints: []metricdata.DataPoint[int64]{{
    71  						Attributes: attribute.NewSet(
    72  							attribute.String("k", "v"),
    73  						),
    74  					}},
    75  				},
    76  			}},
    77  		}, {
    78  			Scope: instrumentation.Scope{Name: "second-scope"},
    79  			Metrics: []metricdata.Metrics{{
    80  				Name: "b-metric",
    81  				Data: metricdata.Sum[int64]{
    82  					DataPoints: []metricdata.DataPoint[int64]{{
    83  						Attributes: attribute.NewSet(
    84  							attribute.String("k", "v"),
    85  						),
    86  					}},
    87  				},
    88  			}, {
    89  				Name: "c-metric",
    90  				Data: metricdata.Histogram[int64]{
    91  					DataPoints: []metricdata.HistogramDataPoint[int64]{{
    92  						Attributes: attribute.NewSet(
    93  							attribute.String("k", "v"),
    94  						),
    95  					}},
    96  				},
    97  			}, {
    98  				Name: "d-metric",
    99  				Data: metricdata.Histogram[float64]{
   100  					DataPoints: []metricdata.HistogramDataPoint[float64]{{
   101  						Attributes: attribute.NewSet(
   102  							attribute.String("k", "v"),
   103  						),
   104  					}},
   105  				},
   106  			}},
   107  		}},
   108  	}
   109  
   110  	t.Run("no attributes", func(t *testing.T) {
   111  		ft := &fakeT{}
   112  
   113  		AssertMetrics(ft, m, HasAttributes("first", "a"))
   114  
   115  		// no metric prefix
   116  		AssertMetrics(ft, m, HasAttributes("first", ""))
   117  
   118  		// no scope prefix
   119  		AssertMetrics(ft, m, HasAttributes("", "a",
   120  			attribute.String("k", "v"),
   121  		))
   122  
   123  		// no scope and metric prefix
   124  		AssertMetrics(ft, m, HasAttributes("", ""))
   125  
   126  		if ft.Failed() {
   127  			t.Error("unexpected failure")
   128  		}
   129  	})
   130  
   131  	t.Run("has attributes", func(t *testing.T) {
   132  		ft := &fakeT{}
   133  
   134  		AssertMetrics(ft, m, HasAttributes("first", "a",
   135  			attribute.String("k", "v"),
   136  		))
   137  
   138  		// no metric prefix
   139  		AssertMetrics(ft, m, HasAttributes("first", "",
   140  			attribute.String("k", "v"),
   141  		))
   142  
   143  		// no scope prefix
   144  		AssertMetrics(ft, m, HasAttributes("", "a",
   145  			attribute.String("k", "v"),
   146  		))
   147  
   148  		// no scope and metric prefix
   149  		AssertMetrics(ft, m, HasAttributes("", "",
   150  			attribute.String("k", "v"),
   151  		))
   152  
   153  		if ft.Failed() {
   154  			t.Error("unexpected failure")
   155  		}
   156  	})
   157  
   158  	t.Run("no match", func(t *testing.T) {
   159  		ft := &fakeT{}
   160  
   161  		AssertMetrics(ft, m,
   162  			HasAttributes("", "", attribute.String("k", "a")))
   163  
   164  		if !ft.Failed() {
   165  			t.Error("expected failure")
   166  		}
   167  	})
   168  
   169  	t.Run("no metrics", func(t *testing.T) {
   170  		ft := &fakeT{}
   171  		m := &metrics{}
   172  
   173  		AssertMetrics(ft, m,
   174  			HasAttributes("first", "a", attribute.String("k", "a")))
   175  
   176  		if !ft.Failed() {
   177  			t.Error("expected failure")
   178  		}
   179  	})
   180  }
   181  
   182  type metrics metricdata.ResourceMetrics
   183  
   184  func (f *metrics) Collect(ctx context.Context, rm *metricdata.ResourceMetrics) error {
   185  	*rm = (metricdata.ResourceMetrics)(*f)
   186  	return nil
   187  }
   188  
   189  type fakeT struct {
   190  	failed bool
   191  }
   192  
   193  func (t *fakeT) Failed() bool {
   194  	return t.failed
   195  }
   196  func (t *fakeT) Error(args ...any)                 { t.failed = true }
   197  func (t *fakeT) Errorf(format string, args ...any) { t.failed = true }
   198  func (t *fakeT) Fatal(args ...any)                 { t.failed = true }
   199  func (t *fakeT) Fatalf(format string, args ...any) { t.failed = true }
   200  func (t *fakeT) Helper()                           {}