tsdb_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package tsdb
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/grafana/grafana/pkg/models"
  7. . "github.com/smartystreets/goconvey/convey"
  8. )
  9. func TestMetricQuery(t *testing.T) {
  10. Convey("When batches groups for query", t, func() {
  11. Convey("Given 3 queries for 2 data sources", func() {
  12. request := &Request{
  13. Queries: QuerySlice{
  14. {RefId: "A", DataSource: &models.DataSource{Id: 1}},
  15. {RefId: "B", DataSource: &models.DataSource{Id: 1}},
  16. {RefId: "C", DataSource: &models.DataSource{Id: 2}},
  17. },
  18. }
  19. batches, err := getBatches(request)
  20. So(err, ShouldBeNil)
  21. Convey("Should group into two batches", func() {
  22. So(len(batches), ShouldEqual, 2)
  23. })
  24. })
  25. Convey("Given query 2 depends on query 1", func() {
  26. request := &Request{
  27. Queries: QuerySlice{
  28. {RefId: "A", DataSource: &models.DataSource{Id: 1}},
  29. {RefId: "B", DataSource: &models.DataSource{Id: 2}},
  30. {RefId: "C", DataSource: &models.DataSource{Id: 3}, Depends: []string{"A", "B"}},
  31. },
  32. }
  33. batches, err := getBatches(request)
  34. So(err, ShouldBeNil)
  35. Convey("Should return three batch groups", func() {
  36. So(len(batches), ShouldEqual, 3)
  37. })
  38. Convey("Group 3 should have group 1 and 2 as dependencies", func() {
  39. So(batches[2].Depends["A"], ShouldEqual, true)
  40. So(batches[2].Depends["B"], ShouldEqual, true)
  41. })
  42. })
  43. })
  44. Convey("When executing request with one query", t, func() {
  45. req := &Request{
  46. Queries: QuerySlice{
  47. {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}},
  48. },
  49. }
  50. fakeExecutor := registerFakeExecutor()
  51. fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}})
  52. res, err := HandleRequest(context.TODO(), req)
  53. So(err, ShouldBeNil)
  54. Convey("Should return query results", func() {
  55. So(res.Results["A"].Series, ShouldNotBeEmpty)
  56. So(res.Results["A"].Series[0].Name, ShouldEqual, "argh")
  57. })
  58. })
  59. Convey("When executing one request with two queries from same data source", t, func() {
  60. req := &Request{
  61. Queries: QuerySlice{
  62. {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}},
  63. {RefId: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}},
  64. },
  65. }
  66. fakeExecutor := registerFakeExecutor()
  67. fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}})
  68. fakeExecutor.Return("B", TimeSeriesSlice{&TimeSeries{Name: "barg"}})
  69. res, err := HandleRequest(context.TODO(), req)
  70. So(err, ShouldBeNil)
  71. Convey("Should return query results", func() {
  72. So(len(res.Results), ShouldEqual, 2)
  73. So(res.Results["B"].Series[0].Name, ShouldEqual, "barg")
  74. })
  75. Convey("Should have been batched in one request", func() {
  76. So(len(res.BatchTimings), ShouldEqual, 1)
  77. })
  78. })
  79. Convey("When executing one request with three queries from different datasources", t, func() {
  80. req := &Request{
  81. Queries: QuerySlice{
  82. {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}},
  83. {RefId: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}},
  84. {RefId: "C", DataSource: &models.DataSource{Id: 2, Type: "test"}},
  85. },
  86. }
  87. res, err := HandleRequest(context.TODO(), req)
  88. So(err, ShouldBeNil)
  89. Convey("Should have been batched in two requests", func() {
  90. So(len(res.BatchTimings), ShouldEqual, 2)
  91. })
  92. })
  93. Convey("When query uses data source of unknown type", t, func() {
  94. req := &Request{
  95. Queries: QuerySlice{
  96. {RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "asdasdas"}},
  97. },
  98. }
  99. _, err := HandleRequest(context.TODO(), req)
  100. So(err, ShouldNotBeNil)
  101. })
  102. Convey("When executing request that depend on other query", t, func() {
  103. req := &Request{
  104. Queries: QuerySlice{
  105. {
  106. RefId: "A", DataSource: &models.DataSource{Id: 1, Type: "test"},
  107. },
  108. {
  109. RefId: "B", DataSource: &models.DataSource{Id: 2, Type: "test"}, Depends: []string{"A"},
  110. },
  111. },
  112. }
  113. fakeExecutor := registerFakeExecutor()
  114. fakeExecutor.HandleQuery("A", func(c *QueryContext) *QueryResult {
  115. time.Sleep(10 * time.Millisecond)
  116. return &QueryResult{
  117. Series: TimeSeriesSlice{
  118. &TimeSeries{Name: "Ares"},
  119. }}
  120. })
  121. fakeExecutor.HandleQuery("B", func(c *QueryContext) *QueryResult {
  122. return &QueryResult{
  123. Series: TimeSeriesSlice{
  124. &TimeSeries{Name: "Bres+" + c.Results["A"].Series[0].Name},
  125. }}
  126. })
  127. res, err := HandleRequest(context.TODO(), req)
  128. So(err, ShouldBeNil)
  129. Convey("Should have been batched in two requests", func() {
  130. So(len(res.BatchTimings), ShouldEqual, 2)
  131. })
  132. Convey("Query B should have access to Query A results", func() {
  133. So(res.Results["B"].Series[0].Name, ShouldEqual, "Bres+Ares")
  134. })
  135. })
  136. }
  137. func registerFakeExecutor() *FakeExecutor {
  138. executor, _ := NewFakeExecutor(nil)
  139. RegisterExecutor("test", func(dsInfo *models.DataSource) (Executor, error) {
  140. return executor, nil
  141. })
  142. return executor
  143. }