github.com/grafana/pyroscope@v1.18.0/pkg/frontend/readpath/queryfrontend/compat_test.go (about)

     1  package queryfrontend
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/prometheus/prometheus/model/labels"
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  func Test_matchersToLabelSelector(t *testing.T) {
    11  	tests := []struct {
    12  		name     string
    13  		matchers []*labels.Matcher
    14  		expected string
    15  	}{
    16  		{
    17  			name:     "empty matchers",
    18  			matchers: []*labels.Matcher{},
    19  			expected: "{}",
    20  		},
    21  		{
    22  			name: "single standard label name with equals",
    23  			matchers: []*labels.Matcher{
    24  				labels.MustNewMatcher(labels.MatchEqual, "service_name", "my-service"),
    25  			},
    26  			expected: `{service_name="my-service"}`,
    27  		},
    28  		{
    29  			name: "label name with dots",
    30  			matchers: []*labels.Matcher{
    31  				labels.MustNewMatcher(labels.MatchEqual, "service.name", "test"),
    32  			},
    33  			expected: `{"service.name"="test"}`,
    34  		},
    35  		{
    36  			name: "label name with hyphen",
    37  			matchers: []*labels.Matcher{
    38  				labels.MustNewMatcher(labels.MatchEqual, "service-name", "value"),
    39  			},
    40  			expected: `{"service-name"="value"}`,
    41  		},
    42  		{
    43  			name: "label name with special character (√)",
    44  			matchers: []*labels.Matcher{
    45  				labels.MustNewMatcher(labels.MatchEqual, "my√label", "value"),
    46  			},
    47  			expected: `{"my√label"="value"}`,
    48  		},
    49  		{
    50  			name: "label name with unicode (世界)",
    51  			matchers: []*labels.Matcher{
    52  				labels.MustNewMatcher(labels.MatchEqual, "世界", "value"),
    53  			},
    54  			expected: `{"世界"="value"}`,
    55  		},
    56  		{
    57  			name: "label name starting with number",
    58  			matchers: []*labels.Matcher{
    59  				labels.MustNewMatcher(labels.MatchEqual, "123label", "value"),
    60  			},
    61  			expected: `{"123label"="value"}`,
    62  		},
    63  		{
    64  			name: "not equal matcher",
    65  			matchers: []*labels.Matcher{
    66  				labels.MustNewMatcher(labels.MatchNotEqual, "service_name", "test"),
    67  			},
    68  			expected: `{service_name!="test"}`,
    69  		},
    70  		{
    71  			name: "regex match matcher",
    72  			matchers: []*labels.Matcher{
    73  				labels.MustNewMatcher(labels.MatchRegexp, "service_name", ".*test.*"),
    74  			},
    75  			expected: `{service_name=~".*test.*"}`,
    76  		},
    77  		{
    78  			name: "regex not match matcher",
    79  			matchers: []*labels.Matcher{
    80  				labels.MustNewMatcher(labels.MatchNotRegexp, "service_name", "test.*"),
    81  			},
    82  			expected: `{service_name!~"test.*"}`,
    83  		},
    84  		{
    85  			name: "multiple standard matchers",
    86  			matchers: []*labels.Matcher{
    87  				labels.MustNewMatcher(labels.MatchEqual, "service_name", "my-service"),
    88  				labels.MustNewMatcher(labels.MatchEqual, "environment", "production"),
    89  				labels.MustNewMatcher(labels.MatchEqual, "region", "us-west-2"),
    90  			},
    91  			expected: `{service_name="my-service",environment="production",region="us-west-2"}`,
    92  		},
    93  		{
    94  			name: "multiple matchers with special characters",
    95  			matchers: []*labels.Matcher{
    96  				labels.MustNewMatcher(labels.MatchEqual, "service.name", "my-service"),
    97  				labels.MustNewMatcher(labels.MatchEqual, "app-version", "v1.0"),
    98  				labels.MustNewMatcher(labels.MatchEqual, "my√label", "value"),
    99  			},
   100  			expected: `{"service.name"="my-service","app-version"="v1.0","my√label"="value"}`,
   101  		},
   102  		{
   103  			name: "mixed matcher types",
   104  			matchers: []*labels.Matcher{
   105  				labels.MustNewMatcher(labels.MatchEqual, "service_name", "test"),
   106  				labels.MustNewMatcher(labels.MatchNotEqual, "environment", "dev"),
   107  				labels.MustNewMatcher(labels.MatchRegexp, "region", "us-.*"),
   108  			},
   109  			expected: `{service_name="test",environment!="dev",region=~"us-.*"}`,
   110  		},
   111  		{
   112  			name: "value with quotes needs escaping",
   113  			matchers: []*labels.Matcher{
   114  				labels.MustNewMatcher(labels.MatchEqual, "label", `value"with"quotes`),
   115  			},
   116  			expected: `{label="value\"with\"quotes"}`,
   117  		},
   118  		{
   119  			name: "label name and value with special characters",
   120  			matchers: []*labels.Matcher{
   121  				labels.MustNewMatcher(labels.MatchEqual, "label-name.special", "value/with\\special"),
   122  			},
   123  			expected: `{"label-name.special"="value/with\\special"}`,
   124  		},
   125  		{
   126  			name: "standard alphanumeric labels don't get quoted",
   127  			matchers: []*labels.Matcher{
   128  				labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"),
   129  				labels.MustNewMatcher(labels.MatchEqual, "foo123", "bar456"),
   130  				labels.MustNewMatcher(labels.MatchEqual, "__internal__", "value"),
   131  			},
   132  			expected: `{foo="bar",foo123="bar456",__internal__="value"}`,
   133  		},
   134  	}
   135  
   136  	for _, tt := range tests {
   137  		t.Run(tt.name, func(t *testing.T) {
   138  			result := matchersToLabelSelector(tt.matchers)
   139  			require.Equal(t, tt.expected, result, "matchersToLabelSelector output mismatch")
   140  		})
   141  	}
   142  }
   143  
   144  func Test_buildLabelSelectorFromMatchers(t *testing.T) {
   145  	tests := []struct {
   146  		name     string
   147  		matchers []string
   148  		expected string
   149  		wantErr  bool
   150  	}{
   151  		{
   152  			name:     "single matcher",
   153  			matchers: []string{`{service_name="test"}`},
   154  			expected: `{service_name="test"}`,
   155  			wantErr:  false,
   156  		},
   157  		{
   158  			name:     "matcher with special characters in label name",
   159  			matchers: []string{`{"service.name"="test"}`},
   160  			expected: `{"service.name"="test"}`,
   161  			wantErr:  false,
   162  		},
   163  		{
   164  			name:     "multiple matchers",
   165  			matchers: []string{`{service_name="test"}`, `{environment="prod"}`},
   166  			expected: `{service_name="test",environment="prod"}`,
   167  			wantErr:  false,
   168  		},
   169  		{
   170  			name:     "invalid matcher syntax",
   171  			matchers: []string{`{unclosed`},
   172  			expected: "",
   173  			wantErr:  true,
   174  		},
   175  		{
   176  			name:     "empty matchers",
   177  			matchers: []string{},
   178  			expected: `{}`,
   179  			wantErr:  false,
   180  		},
   181  	}
   182  
   183  	for _, tt := range tests {
   184  		t.Run(tt.name, func(t *testing.T) {
   185  			result, err := buildLabelSelectorFromMatchers(tt.matchers)
   186  			if tt.wantErr {
   187  				require.Error(t, err)
   188  			} else {
   189  				require.NoError(t, err)
   190  				require.Equal(t, tt.expected, result)
   191  			}
   192  		})
   193  	}
   194  }