diff --git a/api/prometheus/v1/api_test.go b/api/prometheus/v1/api_test.go index 82c234bbd..4afbc2a79 100644 --- a/api/prometheus/v1/api_test.go +++ b/api/prometheus/v1/api_test.go @@ -17,6 +17,7 @@ import ( "context" "errors" "fmt" + "io" "io/ioutil" "math" "net/http" @@ -64,7 +65,7 @@ func (c *apiTestClient) URL(ep string, args map[string]string) *url.URL { return u } -func (c *apiTestClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, Warnings, error) { +func (c *apiTestClient) Do(_ context.Context, req *http.Request) (*http.Response, []byte, Warnings, error) { test := c.curTest @@ -75,6 +76,25 @@ func (c *apiTestClient) Do(ctx context.Context, req *http.Request) (*http.Respon c.Errorf("unexpected request method: want %s, got %s", test.reqMethod, req.Method) } + var vals url.Values + switch test.reqMethod { + case http.MethodGet: + if req.URL.RawQuery != "" { + vals = req.URL.Query() + } + case http.MethodPost: + if req.Body != nil { + reqBody, _ := io.ReadAll(req.Body) + vals, _ = url.ParseQuery(string(reqBody)) + } else if req.URL.RawQuery != "" { + vals = req.URL.Query() + } + } + + if !reflect.DeepEqual(vals, test.reqParam) { + c.Fatalf("unexpected request body: want %s, got %s", vals, test.reqParam) + } + b, err := json.Marshal(test.inRes) if err != nil { c.Fatal(err) @@ -158,15 +178,15 @@ func TestAPIs(t *testing.T) { } } - doLabelNames := func(matches []string) func() (interface{}, Warnings, error) { + doLabelNames := func(matches []string, startTime time.Time, endTime time.Time) func() (interface{}, Warnings, error) { return func() (interface{}, Warnings, error) { - return promAPI.LabelNames(context.Background(), matches, time.Now().Add(-100*time.Hour), time.Now()) + return promAPI.LabelNames(context.Background(), matches, startTime, endTime) } } - doLabelValues := func(matches []string, label string) func() (interface{}, Warnings, error) { + doLabelValues := func(matches []string, label string, startTime time.Time, endTime time.Time) func() (interface{}, Warnings, error) { return func() (interface{}, Warnings, error) { - return promAPI.LabelValues(context.Background(), label, matches, time.Now().Add(-100*time.Hour), time.Now()) + return promAPI.LabelValues(context.Background(), label, matches, startTime, endTime) } } @@ -259,7 +279,7 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query", reqParam: url.Values{ "query": []string{"2"}, - "time": []string{testTime.Format(time.RFC3339Nano)}, + "time": []string{formatTime(testTime)}, "timeout": []string{(5 * time.Second).String()}, }, res: &model.Scalar{ @@ -275,7 +295,7 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query", reqParam: url.Values{ "query": []string{"2"}, - "time": []string{testTime.Format(time.RFC3339Nano)}, + "time": []string{formatTime(testTime)}, }, err: fmt.Errorf("some error"), }, @@ -293,7 +313,7 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query", reqParam: url.Values{ "query": []string{"2"}, - "time": []string{testTime.Format(time.RFC3339Nano)}, + "time": []string{formatTime(testTime)}, }, err: errors.New("server_error: server error: 500"), }, @@ -311,7 +331,7 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query", reqParam: url.Values{ "query": []string{"2"}, - "time": []string{testTime.Format(time.RFC3339Nano)}, + "time": []string{formatTime(testTime)}, }, err: errors.New("client_error: client error: 404"), }, @@ -331,7 +351,7 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query", reqParam: url.Values{ "query": []string{"2"}, - "time": []string{testTime.Format(time.RFC3339Nano)}, + "time": []string{formatTime(testTime)}, }, res: &model.Scalar{ Value: 2, @@ -355,7 +375,7 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query", reqParam: url.Values{ "query": []string{"2"}, - "time": []string{testTime.Format(time.RFC3339Nano)}, + "time": []string{formatTime(testTime)}, }, err: errors.New("client_error: client error: 404"), warnings: []string{"warning"}, @@ -365,7 +385,7 @@ func TestAPIs(t *testing.T) { do: doQueryRange("2", Range{ Start: testTime.Add(-time.Minute), End: testTime, - Step: time.Minute, + Step: 1 * time.Minute, }, WithTimeout(5*time.Second)), inErr: fmt.Errorf("some error"), @@ -373,96 +393,136 @@ func TestAPIs(t *testing.T) { reqPath: "/api/v1/query_range", reqParam: url.Values{ "query": []string{"2"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, - "step": []string{time.Minute.String()}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, + "step": []string{"60"}, "timeout": []string{(5 * time.Second).String()}, }, err: fmt.Errorf("some error"), }, { - do: doLabelNames(nil), + do: doLabelNames(nil, testTime.Add(-100*time.Hour), testTime), inRes: []string{"val1", "val2"}, reqMethod: "GET", reqPath: "/api/v1/labels", - res: []string{"val1", "val2"}, + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + res: []string{"val1", "val2"}, }, { - do: doLabelNames(nil), + do: doLabelNames(nil, testTime.Add(-100*time.Hour), testTime), inRes: []string{"val1", "val2"}, inWarnings: []string{"a"}, reqMethod: "GET", reqPath: "/api/v1/labels", - res: []string{"val1", "val2"}, - warnings: []string{"a"}, + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + res: []string{"val1", "val2"}, + warnings: []string{"a"}, }, { - do: doLabelNames(nil), + do: doLabelNames(nil, testTime.Add(-100*time.Hour), testTime), inErr: fmt.Errorf("some error"), reqMethod: "GET", reqPath: "/api/v1/labels", - err: fmt.Errorf("some error"), + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + err: fmt.Errorf("some error"), }, { - do: doLabelNames(nil), + do: doLabelNames(nil, testTime.Add(-100*time.Hour), testTime), inErr: fmt.Errorf("some error"), inWarnings: []string{"a"}, reqMethod: "GET", reqPath: "/api/v1/labels", - err: fmt.Errorf("some error"), - warnings: []string{"a"}, + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + err: fmt.Errorf("some error"), + warnings: []string{"a"}, }, { - do: doLabelNames([]string{"up"}), + do: doLabelNames([]string{"up"}, testTime.Add(-100*time.Hour), testTime), inRes: []string{"val1", "val2"}, reqMethod: "GET", reqPath: "/api/v1/labels", - reqParam: url.Values{"match[]": {"up"}}, - res: []string{"val1", "val2"}, + reqParam: url.Values{ + "match[]": {"up"}, + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + res: []string{"val1", "val2"}, }, { - do: doLabelValues(nil, "mylabel"), + do: doLabelValues(nil, "mylabel", testTime.Add(-100*time.Hour), testTime), inRes: []string{"val1", "val2"}, reqMethod: "GET", reqPath: "/api/v1/label/mylabel/values", - res: model.LabelValues{"val1", "val2"}, + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + res: model.LabelValues{"val1", "val2"}, }, { - do: doLabelValues(nil, "mylabel"), + do: doLabelValues(nil, "mylabel", testTime.Add(-100*time.Hour), testTime), inRes: []string{"val1", "val2"}, inWarnings: []string{"a"}, reqMethod: "GET", reqPath: "/api/v1/label/mylabel/values", - res: model.LabelValues{"val1", "val2"}, - warnings: []string{"a"}, + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + res: model.LabelValues{"val1", "val2"}, + warnings: []string{"a"}, }, { - do: doLabelValues(nil, "mylabel"), + do: doLabelValues(nil, "mylabel", testTime.Add(-100*time.Hour), testTime), inErr: fmt.Errorf("some error"), reqMethod: "GET", reqPath: "/api/v1/label/mylabel/values", - err: fmt.Errorf("some error"), + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + err: fmt.Errorf("some error"), }, { - do: doLabelValues(nil, "mylabel"), + do: doLabelValues(nil, "mylabel", testTime.Add(-100*time.Hour), testTime), inErr: fmt.Errorf("some error"), inWarnings: []string{"a"}, reqMethod: "GET", reqPath: "/api/v1/label/mylabel/values", - err: fmt.Errorf("some error"), - warnings: []string{"a"}, + reqParam: url.Values{ + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + err: fmt.Errorf("some error"), + warnings: []string{"a"}, }, { - do: doLabelValues([]string{"up"}, "mylabel"), + do: doLabelValues([]string{"up"}, "mylabel", testTime.Add(-100*time.Hour), testTime), inRes: []string{"val1", "val2"}, reqMethod: "GET", reqPath: "/api/v1/label/mylabel/values", - reqParam: url.Values{"match[]": {"up"}}, - res: model.LabelValues{"val1", "val2"}, + reqParam: url.Values{ + "match[]": {"up"}, + "start": []string{formatTime(testTime.Add(-100 * time.Hour))}, + "end": []string{formatTime(testTime)}, + }, + res: model.LabelValues{"val1", "val2"}, }, { @@ -476,9 +536,9 @@ func TestAPIs(t *testing.T) { reqMethod: "GET", reqPath: "/api/v1/series", reqParam: url.Values{ - "match": []string{"up"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, + "match[]": []string{"up"}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, }, res: []model.LabelSet{ { @@ -501,9 +561,9 @@ func TestAPIs(t *testing.T) { reqMethod: "GET", reqPath: "/api/v1/series", reqParam: url.Values{ - "match": []string{"up"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, + "match[]": []string{"up"}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, }, res: []model.LabelSet{ { @@ -521,9 +581,9 @@ func TestAPIs(t *testing.T) { reqMethod: "GET", reqPath: "/api/v1/series", reqParam: url.Values{ - "match": []string{"up"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, + "match[]": []string{"up"}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, }, err: fmt.Errorf("some error"), }, @@ -535,9 +595,9 @@ func TestAPIs(t *testing.T) { reqMethod: "GET", reqPath: "/api/v1/series", reqParam: url.Values{ - "match": []string{"up"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, + "match[]": []string{"up"}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, }, err: fmt.Errorf("some error"), warnings: []string{"a"}, @@ -563,7 +623,10 @@ func TestAPIs(t *testing.T) { inErr: fmt.Errorf("some error"), reqMethod: "POST", reqPath: "/api/v1/admin/tsdb/snapshot", - err: fmt.Errorf("some error"), + reqParam: url.Values{ + "skip_head": []string{"true"}, + }, + err: fmt.Errorf("some error"), }, { @@ -591,9 +654,9 @@ func TestAPIs(t *testing.T) { reqMethod: "POST", reqPath: "/api/v1/admin/tsdb/delete_series", reqParam: url.Values{ - "match": []string{"up"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, + "match[]": []string{"up"}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, }, }, @@ -603,9 +666,9 @@ func TestAPIs(t *testing.T) { reqMethod: "POST", reqPath: "/api/v1/admin/tsdb/delete_series", reqParam: url.Values{ - "match": []string{"up"}, - "start": []string{testTime.Add(-time.Minute).Format(time.RFC3339Nano)}, - "end": []string{testTime.Format(time.RFC3339Nano)}, + "match[]": []string{"up"}, + "start": []string{formatTime(testTime.Add(-time.Minute))}, + "end": []string{formatTime(testTime)}, }, err: fmt.Errorf("some error"), }, @@ -1245,14 +1308,24 @@ func TestAPIs(t *testing.T) { do: doQueryExemplars("tns_request_duration_seconds_bucket", testTime.Add(-1*time.Minute), testTime), reqMethod: "GET", reqPath: "/api/v1/query_exemplars", - inErr: fmt.Errorf("some error"), - err: fmt.Errorf("some error"), + reqParam: url.Values{ + "query": []string{"tns_request_duration_seconds_bucket"}, + "start": []string{formatTime(testTime.Add(-1 * time.Minute))}, + "end": []string{formatTime(testTime)}, + }, + inErr: fmt.Errorf("some error"), + err: fmt.Errorf("some error"), }, { do: doQueryExemplars("tns_request_duration_seconds_bucket", testTime.Add(-1*time.Minute), testTime), reqMethod: "GET", reqPath: "/api/v1/query_exemplars", + reqParam: url.Values{ + "query": []string{"tns_request_duration_seconds_bucket"}, + "start": []string{formatTime(testTime.Add(-1 * time.Minute))}, + "end": []string{formatTime(testTime)}, + }, inRes: []interface{}{ map[string]interface{}{ "seriesLabels": map[string]interface{}{