tsdb_test.go 4.7 KB

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