|
6 | 6 | "encoding/json" |
7 | 7 | "errors" |
8 | 8 | "fmt" |
| 9 | + "github.com/stretchr/testify/require" |
9 | 10 | "io" |
10 | 11 | "log" |
11 | 12 | "math" |
@@ -596,6 +597,83 @@ func TestHandler_Query_CloseNotify(t *testing.T) { |
596 | 597 | } |
597 | 598 | } |
598 | 599 |
|
| 600 | +// Ensure the handler returns results with RFC3339 timestamp format when requested. |
| 601 | +func TestHandler_Query_RFC3339(t *testing.T) { |
| 602 | + testTime1 := time.Date(2021, 1, 1, 12, 0, 0, 0, time.UTC) |
| 603 | + testTime2 := time.Date(2021, 1, 2, 12, 0, 0, 0, time.UTC) |
| 604 | + testTimeNano := time.Date(2021, 1, 1, 12, 0, 0, 123456789, time.UTC) |
| 605 | + |
| 606 | + tests := []struct { |
| 607 | + name string |
| 608 | + series []*models.Row |
| 609 | + expectedResult string |
| 610 | + }{ |
| 611 | + { |
| 612 | + name: "single series", |
| 613 | + series: []*models.Row{{ |
| 614 | + Name: "series0", |
| 615 | + Columns: []string{"time", "value"}, |
| 616 | + Values: [][]interface{}{ |
| 617 | + {testTime1, 42}, |
| 618 | + }, |
| 619 | + }}, |
| 620 | + expectedResult: fmt.Sprintf(`{"results":[{"statement_id":1,"series":[{"name":"series0","columns":["time","value"],"values":[["%s",42]]}]}]}`, testTime1.Format(time.RFC3339Nano)), |
| 621 | + }, |
| 622 | + { |
| 623 | + name: "multiple series", |
| 624 | + series: []*models.Row{ |
| 625 | + { |
| 626 | + Name: "series0", |
| 627 | + Columns: []string{"time", "value"}, |
| 628 | + Values: [][]interface{}{ |
| 629 | + {testTime1, 42}, |
| 630 | + {testTime2, 43}, |
| 631 | + }, |
| 632 | + }, |
| 633 | + { |
| 634 | + Name: "series1", |
| 635 | + Columns: []string{"time", "value"}, |
| 636 | + Values: [][]interface{}{ |
| 637 | + {testTime1, 100}, |
| 638 | + }, |
| 639 | + }, |
| 640 | + }, |
| 641 | + expectedResult: fmt.Sprintf(`{"results":[{"statement_id":1,"series":[{"name":"series0","columns":["time","value"],"values":[["%s",42],["%s",43]]},{"name":"series1","columns":["time","value"],"values":[["%s",100]]}]}]}`, testTime1.Format(time.RFC3339Nano), testTime2.Format(time.RFC3339Nano), testTime1.Format(time.RFC3339Nano)), |
| 642 | + }, |
| 643 | + { |
| 644 | + name: "nanosecond precision", |
| 645 | + series: []*models.Row{{ |
| 646 | + Name: "series0", |
| 647 | + Columns: []string{"time", "value"}, |
| 648 | + Values: [][]interface{}{ |
| 649 | + {testTimeNano, 42}, |
| 650 | + }, |
| 651 | + }}, |
| 652 | + expectedResult: fmt.Sprintf(`{"results":[{"statement_id":1,"series":[{"name":"series0","columns":["time","value"],"values":[["%s",42]]}]}]}`, testTimeNano.Format(time.RFC3339Nano)), |
| 653 | + }, |
| 654 | + } |
| 655 | + |
| 656 | + for _, tt := range tests { |
| 657 | + t.Run(tt.name, func(t *testing.T) { |
| 658 | + h := NewHandler(false) |
| 659 | + h.StatementExecutor.ExecuteStatementFn = func(stmt influxql.Statement, ctx *query.ExecutionContext) error { |
| 660 | + ctx.Results <- &query.Result{ |
| 661 | + StatementID: 1, |
| 662 | + Series: tt.series, |
| 663 | + } |
| 664 | + return nil |
| 665 | + } |
| 666 | + |
| 667 | + w := httptest.NewRecorder() |
| 668 | + h.ServeHTTP(w, MustNewJSONRequest("GET", "/query?db=foo&q=SELECT+*+FROM+bar&time_format=rfc3339", nil)) |
| 669 | + require.Equal(t, http.StatusOK, w.Code, "response status") |
| 670 | + |
| 671 | + body := strings.TrimSpace(w.Body.String()) |
| 672 | + require.Equal(t, tt.expectedResult, body, "response body") |
| 673 | + }) |
| 674 | + } |
| 675 | +} |
| 676 | + |
599 | 677 | // Ensure the handler returns an appropriate 401 status when authentication |
600 | 678 | // fails on ping endpoints. |
601 | 679 | func TestHandler_Ping_ErrAuthorize(t *testing.T) { |
|
0 commit comments