| 
									
										
										
										
											2017-10-24 04:39:40 +08:00
										 |  |  | // Copyright 2017 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | package remote | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/pkg/labels" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/prompb" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/storage" | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/util/testutil" | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestValidateLabelsAndMetricName(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		input       labels.Labels | 
					
						
							|  |  |  | 		expectedErr string | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 		description string | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name", | 
					
						
							|  |  |  | 				"labelName", "labelValue", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			expectedErr: "", | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			description: "regular labels", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name", | 
					
						
							|  |  |  | 				"_labelName", "labelValue", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			expectedErr: "", | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			description: "label name with _", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name", | 
					
						
							|  |  |  | 				"@labelName", "labelValue", | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			expectedErr: "invalid label name: @labelName", | 
					
						
							|  |  |  | 			description: "label name with @", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name", | 
					
						
							|  |  |  | 				"123labelName", "labelValue", | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			expectedErr: "invalid label name: 123labelName", | 
					
						
							|  |  |  | 			description: "label name starts with numbers", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name", | 
					
						
							|  |  |  | 				"", "labelValue", | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			expectedErr: "invalid label name: ", | 
					
						
							|  |  |  | 			description: "label name is empty string", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name", | 
					
						
							|  |  |  | 				"labelName", string([]byte{0xff}), | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			expectedErr: "invalid label value: " + string([]byte{0xff}), | 
					
						
							|  |  |  | 			description: "label value is an invalid UTF-8 value", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "@invalid_name", | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 			expectedErr: "invalid metric name: @invalid_name", | 
					
						
							|  |  |  | 			description: "metric name starts with @", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"__name__", "name1", | 
					
						
							|  |  |  | 				"__name__", "name2", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			expectedErr: "duplicate label with name: __name__", | 
					
						
							|  |  |  | 			description: "duplicate label names", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"label1", "name", | 
					
						
							|  |  |  | 				"label2", "name", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			expectedErr: "", | 
					
						
							|  |  |  | 			description: "duplicate label values", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			input: labels.FromStrings( | 
					
						
							|  |  |  | 				"", "name", | 
					
						
							|  |  |  | 				"label2", "name", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			expectedErr: "invalid label name: ", | 
					
						
							|  |  |  | 			description: "don't report as duplicate label name", | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, test := range tests { | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 		t.Run(test.description, func(t *testing.T) { | 
					
						
							|  |  |  | 			err := validateLabelsAndMetricName(test.input) | 
					
						
							| 
									
										
										
										
											2019-10-08 01:35:53 +08:00
										 |  |  | 			if test.expectedErr != "" { | 
					
						
							|  |  |  | 				testutil.NotOk(t, err) | 
					
						
							|  |  |  | 				testutil.Equals(t, test.expectedErr, err.Error()) | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2019-10-08 01:35:53 +08:00
										 |  |  | 				testutil.Ok(t, err) | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestConcreteSeriesSet(t *testing.T) { | 
					
						
							|  |  |  | 	series1 := &concreteSeries{ | 
					
						
							|  |  |  | 		labels:  labels.FromStrings("foo", "bar"), | 
					
						
							| 
									
										
										
										
											2019-01-17 06:28:08 +08:00
										 |  |  | 		samples: []prompb.Sample{{Value: 1, Timestamp: 2}}, | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	series2 := &concreteSeries{ | 
					
						
							|  |  |  | 		labels:  labels.FromStrings("foo", "baz"), | 
					
						
							| 
									
										
										
										
											2019-01-17 06:28:08 +08:00
										 |  |  | 		samples: []prompb.Sample{{Value: 3, Timestamp: 4}}, | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	c := &concreteSeriesSet{ | 
					
						
							|  |  |  | 		series: []storage.Series{series1, series2}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-08 01:35:53 +08:00
										 |  |  | 	testutil.Assert(t, c.Next(), "Expected Next() to be true.") | 
					
						
							|  |  |  | 	testutil.Equals(t, series1, c.At(), "Unexpected series returned.") | 
					
						
							|  |  |  | 	testutil.Assert(t, c.Next(), "Expected Next() to be true.") | 
					
						
							|  |  |  | 	testutil.Equals(t, series2, c.At(), "Unexpected series returned.") | 
					
						
							|  |  |  | 	testutil.Assert(t, !c.Next(), "Expected Next() to be false.") | 
					
						
							| 
									
										
										
										
											2017-10-24 04:28:17 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-12 07:47:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestConcreteSeriesClonesLabels(t *testing.T) { | 
					
						
							|  |  |  | 	lbls := labels.Labels{ | 
					
						
							|  |  |  | 		labels.Label{Name: "a", Value: "b"}, | 
					
						
							|  |  |  | 		labels.Label{Name: "c", Value: "d"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cs := concreteSeries{ | 
					
						
							|  |  |  | 		labels: labels.New(lbls...), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gotLabels := cs.Labels() | 
					
						
							| 
									
										
										
										
											2019-08-09 09:36:42 +08:00
										 |  |  | 	testutil.Equals(t, lbls, gotLabels) | 
					
						
							| 
									
										
										
										
											2017-11-12 07:47:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	gotLabels[0].Value = "foo" | 
					
						
							|  |  |  | 	gotLabels[1].Value = "bar" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gotLabels = cs.Labels() | 
					
						
							| 
									
										
										
										
											2019-08-09 09:36:42 +08:00
										 |  |  | 	testutil.Equals(t, lbls, gotLabels) | 
					
						
							| 
									
										
										
										
											2017-11-12 07:47:47 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-07 23:13:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestFromQueryResultWithDuplicates(t *testing.T) { | 
					
						
							|  |  |  | 	ts1 := prompb.TimeSeries{ | 
					
						
							|  |  |  | 		Labels: []prompb.Label{ | 
					
						
							|  |  |  | 			prompb.Label{Name: "foo", Value: "bar"}, | 
					
						
							|  |  |  | 			prompb.Label{Name: "foo", Value: "def"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Samples: []prompb.Sample{ | 
					
						
							|  |  |  | 			prompb.Sample{Value: 0.0, Timestamp: 0}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res := prompb.QueryResult{ | 
					
						
							|  |  |  | 		Timeseries: []*prompb.TimeSeries{ | 
					
						
							|  |  |  | 			&ts1, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	series := FromQueryResult(&res) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	errSeries, isErrSeriesSet := series.(errSeriesSet) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	testutil.Assert(t, isErrSeriesSet, "Expected resulting series to be an errSeriesSet") | 
					
						
							|  |  |  | 	errMessage := errSeries.Err().Error() | 
					
						
							|  |  |  | 	testutil.Assert(t, errMessage == "duplicate label with name: foo", fmt.Sprintf("Expected error to be from duplicate label, but got: %s", errMessage)) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-20 04:16:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestNegotiateResponseType(t *testing.T) { | 
					
						
							|  |  |  | 	r, err := NegotiateResponseType([]prompb.ReadRequest_ResponseType{ | 
					
						
							|  |  |  | 		prompb.ReadRequest_STREAMED_XOR_CHUNKS, | 
					
						
							|  |  |  | 		prompb.ReadRequest_SAMPLES, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	testutil.Ok(t, err) | 
					
						
							|  |  |  | 	testutil.Equals(t, prompb.ReadRequest_STREAMED_XOR_CHUNKS, r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r2, err := NegotiateResponseType([]prompb.ReadRequest_ResponseType{ | 
					
						
							|  |  |  | 		prompb.ReadRequest_SAMPLES, | 
					
						
							|  |  |  | 		prompb.ReadRequest_STREAMED_XOR_CHUNKS, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	testutil.Ok(t, err) | 
					
						
							|  |  |  | 	testutil.Equals(t, prompb.ReadRequest_SAMPLES, r2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r3, err := NegotiateResponseType([]prompb.ReadRequest_ResponseType{}) | 
					
						
							|  |  |  | 	testutil.Ok(t, err) | 
					
						
							|  |  |  | 	testutil.Equals(t, prompb.ReadRequest_SAMPLES, r3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = NegotiateResponseType([]prompb.ReadRequest_ResponseType{20}) | 
					
						
							|  |  |  | 	testutil.NotOk(t, err, "expected error due to not supported requested response types") | 
					
						
							|  |  |  | 	testutil.Equals(t, "server does not support any of the requested response types: [20]; supported: map[SAMPLES:{} STREAMED_XOR_CHUNKS:{}]", err.Error()) | 
					
						
							|  |  |  | } |