@@ -39,6 +39,10 @@ import (
39
39
40
40
var enabledFunctions []* parser.Function
41
41
42
+ const (
43
+ prometheusLatestImage = "quay.io/prometheus/prometheus:v3.2.1"
44
+ )
45
+
42
46
func init () {
43
47
for _ , f := range parser .Functions {
44
48
// Ignore native histogram functions for now as our test cases are only float samples.
@@ -52,8 +56,116 @@ func init() {
52
56
}
53
57
}
54
58
59
+ func TestNativeHistogramFuzz (t * testing.T ) {
60
+ s , err := e2e .NewScenario (networkName )
61
+ require .NoError (t , err )
62
+ defer s .Close ()
63
+
64
+ // Start dependencies.
65
+ consul := e2edb .NewConsulWithName ("consul" )
66
+ require .NoError (t , s .StartAndWaitReady (consul ))
67
+
68
+ baseFlags := mergeFlags (AlertmanagerLocalFlags (), BlocksStorageFlags ())
69
+ flags := mergeFlags (
70
+ baseFlags ,
71
+ map [string ]string {
72
+ "-blocks-storage.tsdb.head-compaction-interval" : "4m" ,
73
+ "-blocks-storage.tsdb.block-ranges-period" : "2h" ,
74
+ "-blocks-storage.tsdb.ship-interval" : "1h" ,
75
+ "-blocks-storage.bucket-store.sync-interval" : "1s" ,
76
+ "-blocks-storage.tsdb.retention-period" : "24h" ,
77
+ "-blocks-storage.bucket-store.index-cache.backend" : tsdb .IndexCacheBackendInMemory ,
78
+ "-querier.query-store-for-labels-enabled" : "true" ,
79
+ // Ingester.
80
+ "-ring.store" : "consul" ,
81
+ "-consul.hostname" : consul .NetworkHTTPEndpoint (),
82
+ // Distributor.
83
+ "-distributor.replication-factor" : "1" ,
84
+ // alert manager
85
+ "-alertmanager.web.external-url" : "http://localhost/alertmanager" ,
86
+ },
87
+ )
88
+ // make alert manager config dir
89
+ require .NoError (t , writeFileToSharedDir (s , "alertmanager_configs" , []byte {}))
90
+
91
+ minio := e2edb .NewMinio (9000 , flags ["-blocks-storage.s3.bucket-name" ])
92
+ require .NoError (t , s .StartAndWaitReady (minio ))
93
+
94
+ cortex := e2ecortex .NewSingleBinary ("cortex" , flags , "" )
95
+ require .NoError (t , s .StartAndWaitReady (cortex ))
96
+
97
+ // Wait until Cortex replicas have updated the ring state.
98
+ require .NoError (t , cortex .WaitSumMetrics (e2e .Equals (float64 (512 )), "cortex_ring_tokens_total" ))
99
+
100
+ now := time .Now ()
101
+ start := now .Add (- time .Hour * 2 )
102
+ end := now .Add (- time .Hour )
103
+ numSeries := 10
104
+ numSamples := 60
105
+ lbls := make ([]labels.Labels , 0 , numSeries * 2 )
106
+ scrapeInterval := time .Minute
107
+ statusCodes := []string {"200" , "400" , "404" , "500" , "502" }
108
+ for i := 0 ; i < numSeries ; i ++ {
109
+ lbls = append (lbls , labels.Labels {
110
+ {Name : labels .MetricName , Value : "test_series_a" },
111
+ {Name : "job" , Value : "test" },
112
+ {Name : "series" , Value : strconv .Itoa (i % 3 )},
113
+ {Name : "status_code" , Value : statusCodes [i % 5 ]},
114
+ })
115
+
116
+ lbls = append (lbls , labels.Labels {
117
+ {Name : labels .MetricName , Value : "test_series_b" },
118
+ {Name : "job" , Value : "test" },
119
+ {Name : "series" , Value : strconv .Itoa ((i + 1 ) % 3 )},
120
+ {Name : "status_code" , Value : statusCodes [(i + 1 )% 5 ]},
121
+ })
122
+ }
123
+
124
+ ctx := context .Background ()
125
+ rnd := rand .New (rand .NewSource (time .Now ().Unix ()))
126
+
127
+ dir := filepath .Join (s .SharedDir (), "data" )
128
+ err = os .MkdirAll (dir , os .ModePerm )
129
+ require .NoError (t , err )
130
+ storage , err := e2ecortex .NewS3ClientForMinio (minio , flags ["-blocks-storage.s3.bucket-name" ])
131
+ require .NoError (t , err )
132
+ bkt := bucket .NewUserBucketClient ("user-1" , storage .GetBucket (), nil )
133
+ id , err := e2e .CreateNHBlock (ctx , rnd , dir , lbls , numSamples , start .UnixMilli (), end .UnixMilli (), scrapeInterval .Milliseconds (), 10 )
134
+ require .NoError (t , err )
135
+ err = block .Upload (ctx , log .Logger , bkt , filepath .Join (dir , id .String ()), metadata .NoneFunc )
136
+ require .NoError (t , err )
137
+
138
+ // Wait for querier and store to sync blocks.
139
+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (float64 (1 )), []string {"cortex_blocks_meta_synced" }, e2e .WaitMissingMetrics , e2e .WithLabelMatchers (labels .MustNewMatcher (labels .MatchEqual , "component" , "store-gateway" ))))
140
+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (float64 (1 )), []string {"cortex_blocks_meta_synced" }, e2e .WaitMissingMetrics , e2e .WithLabelMatchers (labels .MustNewMatcher (labels .MatchEqual , "component" , "querier" ))))
141
+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (float64 (1 )), []string {"cortex_bucket_store_blocks_loaded" }, e2e .WaitMissingMetrics ))
142
+
143
+ c1 , err := e2ecortex .NewClient ("" , cortex .HTTPEndpoint (), "" , "" , "user-1" )
144
+ require .NoError (t , err )
145
+
146
+ err = writeFileToSharedDir (s , "prometheus.yml" , []byte ("" ))
147
+ require .NoError (t , err )
148
+ prom := e2edb .NewPrometheus ("" , nil )
149
+ require .NoError (t , s .StartAndWaitReady (prom ))
150
+
151
+ c2 , err := e2ecortex .NewPromQueryClient (prom .HTTPEndpoint ())
152
+ require .NoError (t , err )
153
+
154
+ waitUntilReady (t , ctx , c1 , c2 , `{job="test"}` , start , end )
155
+
156
+ opts := []promqlsmith.Option {
157
+ promqlsmith .WithEnableOffset (true ),
158
+ promqlsmith .WithEnableAtModifier (true ),
159
+ promqlsmith .WithEnabledAggrs ([]parser.ItemType {
160
+ parser .SUM , parser .MIN , parser .MAX , parser .AVG , parser .GROUP , parser .COUNT , parser .COUNT_VALUES , parser .QUANTILE ,
161
+ }),
162
+ }
163
+ ps := promqlsmith .New (rnd , lbls , opts ... )
164
+
165
+ runQueryFuzzTestCases (t , ps , c1 , c2 , end , start , end , scrapeInterval , 1000 , false )
166
+ }
167
+
55
168
func TestExperimentalPromQLFuncsWithPrometheus (t * testing.T ) {
56
- prometheusLatestImage := "quay.io/prometheus/prometheus:v3.2.1"
57
169
s , err := e2e .NewScenario (networkName )
58
170
require .NoError (t , err )
59
171
defer s .Close ()
@@ -148,7 +260,7 @@ func TestExperimentalPromQLFuncsWithPrometheus(t *testing.T) {
148
260
149
261
err = writeFileToSharedDir (s , "prometheus.yml" , []byte ("" ))
150
262
require .NoError (t , err )
151
- prom := e2edb .NewPrometheus (prometheusLatestImage , map [string ]string {
263
+ prom := e2edb .NewPrometheus ("" , map [string ]string {
152
264
"--enable-feature" : "promql-experimental-functions" ,
153
265
})
154
266
require .NoError (t , s .StartAndWaitReady (prom ))
@@ -841,6 +953,10 @@ var comparer = cmp.Comparer(func(x, y model.Value) bool {
841
953
const fraction = 1.e-10 // 0.00000001%
842
954
return cmp .Equal (l , r , cmpopts .EquateNaNs (), cmpopts .EquateApprox (fraction , epsilon ))
843
955
}
956
+ compareHistograms := func (l , r * model.SampleHistogram ) bool {
957
+ return l .Equal (r )
958
+ }
959
+
844
960
// count_values returns a metrics with one label {"value": "1.012321"}
845
961
compareValueMetrics := func (l , r model.Metric ) (valueMetric bool , equals bool ) {
846
962
lLabels := model .LabelSet (l ).Clone ()
@@ -906,6 +1022,9 @@ var comparer = cmp.Comparer(func(x, y model.Value) bool {
906
1022
if ! compareFloats (float64 (vx [i ].Value ), float64 (vy [i ].Value )) {
907
1023
return false
908
1024
}
1025
+ if ! compareHistograms (vx [i ].Histogram , vy [i ].Histogram ) {
1026
+ return false
1027
+ }
909
1028
}
910
1029
return true
911
1030
}
@@ -942,6 +1061,21 @@ var comparer = cmp.Comparer(func(x, y model.Value) bool {
942
1061
return false
943
1062
}
944
1063
}
1064
+
1065
+ xhs := mxs .Histograms
1066
+ yhs := mys .Histograms
1067
+
1068
+ if len (xhs ) != len (yhs ) {
1069
+ return false
1070
+ }
1071
+ for j := 0 ; j < len (xhs ); j ++ {
1072
+ if xhs [j ].Timestamp != yhs [j ].Timestamp {
1073
+ return false
1074
+ }
1075
+ if ! compareHistograms (xhs [j ].Histogram , yhs [j ].Histogram ) {
1076
+ return false
1077
+ }
1078
+ }
945
1079
}
946
1080
return true
947
1081
}
@@ -1423,7 +1557,6 @@ func TestBackwardCompatibilityQueryFuzz(t *testing.T) {
1423
1557
1424
1558
// TestPrometheusCompatibilityQueryFuzz compares Cortex with latest Prometheus release.
1425
1559
func TestPrometheusCompatibilityQueryFuzz (t * testing.T ) {
1426
- prometheusLatestImage := "quay.io/prometheus/prometheus:v3.2.1"
1427
1560
s , err := e2e .NewScenario (networkName )
1428
1561
require .NoError (t , err )
1429
1562
defer s .Close ()
@@ -1516,7 +1649,7 @@ func TestPrometheusCompatibilityQueryFuzz(t *testing.T) {
1516
1649
1517
1650
err = writeFileToSharedDir (s , "prometheus.yml" , []byte ("" ))
1518
1651
require .NoError (t , err )
1519
- prom := e2edb .NewPrometheus (prometheusLatestImage , map [string ]string {})
1652
+ prom := e2edb .NewPrometheus ("" , map [string ]string {})
1520
1653
require .NoError (t , s .StartAndWaitReady (prom ))
1521
1654
1522
1655
c2 , err := e2ecortex .NewPromQueryClient (prom .HTTPEndpoint ())
0 commit comments