cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.18.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/promapi/query_test.go

237lines · modecode

1package promapi_test
2
3import (
4 "context"
5 "fmt"
6 "net/http"
7 "net/http/httptest"
8 "sync"
9 "testing"
10 "time"
11
12 "github.com/prometheus/common/model"
13 "github.com/stretchr/testify/assert"
14
15 "github.com/cloudflare/pint/internal/promapi"
16)
17
18func TestQuery(t *testing.T) {
19 done := sync.Map{}
20 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21 err := r.ParseForm()
22 if err != nil {
23 t.Fatal(err)
24 }
25 query := r.Form.Get("query")
26
27 switch query {
28 case "empty":
29 w.WriteHeader(200)
30 w.Header().Set("Content-Type", "application/json")
31 _, _ = w.Write([]byte(`{
32 "status":"success",
33 "data":{
34 "resultType":"vector",
35 "result":[]
36 }
37 }`))
38 case "single_result":
39 w.WriteHeader(200)
40 w.Header().Set("Content-Type", "application/json")
41 _, _ = w.Write([]byte(`{
42 "status":"success",
43 "data":{
44 "resultType":"vector",
45 "result":[{"metric":{},"value":[1614859502.068,"1"]}]
46 }
47 }`))
48 case "three_results":
49 w.WriteHeader(200)
50 w.Header().Set("Content-Type", "application/json")
51 _, _ = w.Write([]byte(`{
52 "status":"success",
53 "data":{
54 "resultType":"vector",
55 "result":[
56 {"metric":{"instance": "1"},"value":[1614859502.068,"1"]},
57 {"metric":{"instance": "2"},"value":[1614859502.168,"2"]},
58 {"metric":{"instance": "3"},"value":[1614859503.000,"3"]}
59 ]
60 }
61 }`))
62 case "once":
63 if _, wasDone := done.Load(r.URL.Path); wasDone {
64 w.WriteHeader(500)
65 _, _ = w.Write([]byte("query already requested\n"))
66 return
67 }
68 w.WriteHeader(200)
69 w.Header().Set("Content-Type", "application/json")
70 _, _ = w.Write([]byte(`{
71 "status":"success",
72 "data":{
73 "resultType":"vector",
74 "result":[{"metric":{},"value":[1614859502.068,"1"]}]
75 }
76 }`))
77 done.Store(r.URL.Path, true)
78 case "matrix":
79 w.WriteHeader(200)
80 w.Header().Set("Content-Type", "application/json")
81 _, _ = w.Write([]byte(`{
82 "status":"success",
83 "data":{
84 "resultType":"matrix",
85 "result":[]
86 }
87 }`))
88 case "timeout":
89 w.WriteHeader(200)
90 w.Header().Set("Content-Type", "application/json")
91 time.Sleep(time.Second)
92 _, _ = w.Write([]byte(`{
93 "status":"success",
94 "data":{
95 "resultType":"vector",
96 "result":[]
97 }
98 }`))
99 default:
100 w.WriteHeader(400)
101 w.Header().Set("Content-Type", "application/json")
102 _, _ = w.Write([]byte(`{
103 "status":"error",
104 "errorType":"bad_data",
105 "error":"unhandled query"
106 }`))
107 }
108 }))
109 defer srv.Close()
110
111 type testCaseT struct {
112 query string
113 timeout time.Duration
114 result promapi.QueryResult
115 err string
116 runs int
117 }
118
119 testCases := []testCaseT{
120 {
121 query: "empty",
122 timeout: time.Second,
123 result: promapi.QueryResult{
124 URI: srv.URL,
125 Series: model.Vector{},
126 },
127 runs: 5,
128 },
129 {
130 query: "single_result",
131 timeout: time.Second,
132 result: promapi.QueryResult{
133 URI: srv.URL,
134 Series: model.Vector{
135 &model.Sample{
136 Metric: model.Metric{},
137 Value: model.SampleValue(1),
138 Timestamp: model.Time(1614859502068),
139 },
140 },
141 },
142 runs: 5,
143 },
144 {
145 query: "three_results",
146 timeout: time.Second,
147 result: promapi.QueryResult{
148 URI: srv.URL,
149 Series: model.Vector{
150 &model.Sample{
151 Metric: model.Metric{"instance": "1"},
152 Value: model.SampleValue(1),
153 Timestamp: model.Time(1614859502068),
154 },
155 &model.Sample{
156 Metric: model.Metric{"instance": "2"},
157 Value: model.SampleValue(2),
158 Timestamp: model.Time(1614859502168),
159 },
160 &model.Sample{
161 Metric: model.Metric{"instance": "3"},
162 Value: model.SampleValue(3),
163 Timestamp: model.Time(1614859503000),
164 },
165 },
166 },
167 runs: 5,
168 },
169 {
170 query: "error",
171 timeout: time.Second,
172 err: "bad_data: unhandled query",
173 runs: 5,
174 },
175 {
176 query: "matrix",
177 timeout: time.Second,
178 err: "unknown result type: matrix",
179 runs: 5,
180 },
181 {
182 query: "timeout",
183 timeout: time.Millisecond * 20,
184 err: fmt.Sprintf(`Post "%s/api/v1/query": context deadline exceeded`, srv.URL),
185 runs: 5,
186 },
187 {
188 query: "once",
189 timeout: time.Second,
190 result: promapi.QueryResult{
191 URI: srv.URL,
192 Series: model.Vector{
193 &model.Sample{
194 Metric: model.Metric{},
195 Value: model.SampleValue(1),
196 Timestamp: model.Time(1614859502068),
197 },
198 },
199 },
200 runs: 5,
201 },
202 // repeat once to ensure it errors
203 {
204 query: "once",
205 timeout: time.Second,
206 err: "server_error: server error: 500",
207 runs: 5,
208 },
209 }
210
211 for _, tc := range testCases {
212 t.Run(tc.query, func(t *testing.T) {
213 assert := assert.New(t)
214
215 prom := promapi.NewPrometheus("test", srv.URL, tc.timeout)
216
217 wg := sync.WaitGroup{}
218 wg.Add(tc.runs)
219 for i := 1; i <= tc.runs; i++ {
220 go func() {
221 qr, err := prom.Query(context.Background(), tc.query)
222 if tc.err != "" {
223 assert.EqualError(err, tc.err, tc)
224 } else {
225 assert.NoError(err)
226 }
227 if qr != nil {
228 assert.Equal(tc.result.URI, qr.URI)
229 assert.Equal(tc.result.Series, qr.Series)
230 }
231 wg.Done()
232 }()
233 }
234 wg.Wait()
235 })
236 }
237}
238