walinator_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package metric
  2. import (
  3. "reflect"
  4. "testing"
  5. "time"
  6. "github.com/opencost/opencost/core/pkg/storage"
  7. "github.com/opencost/opencost/core/pkg/util/timeutil"
  8. "github.com/opencost/opencost/modules/collector-source/pkg/metric/aggregator"
  9. "github.com/opencost/opencost/modules/collector-source/pkg/util"
  10. )
  11. const TestActiveMinutesID = "TestActiveMinutes"
  12. const TestAverageID = "TestAverage"
  13. const TestMetric = "test_metric"
  14. func testMetricCollector() MetricStore {
  15. memStore := NewInMemoryMetricStore()
  16. memStore.Register(NewMetricCollector(
  17. TestActiveMinutesID,
  18. TestMetric,
  19. []string{
  20. "test",
  21. },
  22. aggregator.ActiveMinutes,
  23. nil,
  24. ))
  25. memStore.Register(NewMetricCollector(
  26. TestAverageID,
  27. TestMetric,
  28. []string{
  29. "test",
  30. },
  31. aggregator.AverageOverTime,
  32. nil,
  33. ))
  34. return memStore
  35. }
  36. func TestWalinator_Update(t *testing.T) {
  37. time2 := time.Now().UTC().Truncate(timeutil.Day)
  38. time1 := time2.Add(-timeutil.Day)
  39. store := storage.NewMemoryStorage()
  40. res1d, _ := util.NewResolution(util.ResolutionConfiguration{
  41. Interval: "1d",
  42. Retention: 3,
  43. })
  44. resolutions := []*util.Resolution{
  45. res1d,
  46. }
  47. repo := NewMetricRepository(
  48. resolutions,
  49. testMetricCollector,
  50. )
  51. wal, _ := NewWalinator(
  52. "test",
  53. store,
  54. resolutions,
  55. repo,
  56. )
  57. inputUpdateSet1 := UpdateSet{
  58. Updates: []Update{
  59. {
  60. Name: TestMetric,
  61. Labels: map[string]string{
  62. "test": "test",
  63. },
  64. Value: 1,
  65. AdditionalInfo: nil,
  66. },
  67. },
  68. }
  69. wal.Update(inputUpdateSet1.Updates, time1)
  70. // check that the repo has a collector
  71. if len(repo.resolutionStores["1d"].collectors) != 1 {
  72. t.Error("call to Update did not update repository correctly")
  73. }
  74. files, _ := store.List(wal.paths.Dir())
  75. // check storage
  76. if len(files) != 1 {
  77. t.Error("Update did not update storage")
  78. }
  79. }
  80. func TestWalinator_restore(t *testing.T) {
  81. time3 := time.Now().UTC().Truncate(timeutil.Day)
  82. time2 := time3.Add(-12 * time.Hour)
  83. time1 := time3.Add(-timeutil.Day)
  84. store := storage.NewMemoryStorage()
  85. res1d, _ := util.NewResolution(util.ResolutionConfiguration{
  86. Interval: "1d",
  87. Retention: 3,
  88. })
  89. resolutions := []*util.Resolution{
  90. res1d,
  91. }
  92. repo := NewMetricRepository(
  93. resolutions,
  94. testMetricCollector,
  95. )
  96. wal, _ := NewWalinator(
  97. "test",
  98. store,
  99. resolutions,
  100. repo,
  101. )
  102. inputUpdateSet1 := UpdateSet{
  103. Updates: []Update{
  104. {
  105. Name: TestMetric,
  106. Labels: map[string]string{
  107. "test": "test",
  108. },
  109. Value: 1,
  110. AdditionalInfo: nil,
  111. },
  112. },
  113. }
  114. inputUpdateSet2 := UpdateSet{
  115. Updates: []Update{
  116. {
  117. Name: TestMetric,
  118. Labels: map[string]string{
  119. "test": "test",
  120. },
  121. Value: 2,
  122. AdditionalInfo: nil,
  123. },
  124. },
  125. }
  126. inputUpdateSet3 := UpdateSet{
  127. Updates: []Update{
  128. {
  129. Name: TestMetric,
  130. Labels: map[string]string{
  131. "test": "test",
  132. },
  133. Value: 3,
  134. AdditionalInfo: nil,
  135. },
  136. },
  137. }
  138. wal.Update(inputUpdateSet1.Updates, time1)
  139. wal.Update(inputUpdateSet2.Updates, time2)
  140. wal.Update(inputUpdateSet3.Updates, time3)
  141. repo2 := NewMetricRepository(
  142. resolutions,
  143. testMetricCollector,
  144. )
  145. // replace the repo in the walinator
  146. wal.repo = repo2
  147. wal.restore()
  148. collector1, err := repo.GetCollector("1d", time3)
  149. if err != nil {
  150. t.Fatalf("failed to get collector from repo1: %s", err.Error())
  151. }
  152. activeMinutesRes1, err := collector1.Query(TestActiveMinutesID)
  153. if err != nil {
  154. t.Fatalf("failed to query %s from repo1: %s", TestActiveMinutesID, err.Error())
  155. }
  156. averageRes1, err := collector1.Query(TestAverageID)
  157. if err != nil {
  158. t.Fatalf("failed to query %s from repo1: %s", TestAverageID, err.Error())
  159. }
  160. collector2, err := repo2.GetCollector("1d", time3)
  161. if err != nil {
  162. t.Fatalf("failed to get collector from repo2: %s", err.Error())
  163. }
  164. activeMinutesRes2, err := collector2.Query(TestActiveMinutesID)
  165. if err != nil {
  166. t.Fatalf("failed to query %s from repo2: %s", TestActiveMinutesID, err.Error())
  167. }
  168. averageRes2, err := collector2.Query(TestAverageID)
  169. if err != nil {
  170. t.Fatalf("failed to query %s from repo2: %s", TestAverageID, err.Error())
  171. }
  172. if !reflect.DeepEqual(activeMinutesRes1, activeMinutesRes2) {
  173. t.Errorf("active minute query results did not match 1: %v, 2: %v", activeMinutesRes1, activeMinutesRes2)
  174. }
  175. if !reflect.DeepEqual(averageRes1, averageRes2) {
  176. t.Errorf("average query results did not match 1: %v, 2: %v", averageRes1, averageRes2)
  177. }
  178. }
  179. func TestWalinator_clean(t *testing.T) {
  180. time3 := time.Now().UTC().Truncate(timeutil.Day)
  181. time2 := time3.Add(-timeutil.Day)
  182. time1 := time2.Add(-timeutil.Day)
  183. store := storage.NewMemoryStorage()
  184. res1d, _ := util.NewResolution(util.ResolutionConfiguration{
  185. Interval: "1d",
  186. Retention: 2,
  187. })
  188. resolutions := []*util.Resolution{
  189. res1d,
  190. }
  191. repo := NewMetricRepository(
  192. resolutions,
  193. testMetricCollector,
  194. )
  195. wal, _ := NewWalinator(
  196. "test",
  197. store,
  198. resolutions,
  199. repo,
  200. )
  201. inputUpdateSet1 := UpdateSet{
  202. Updates: []Update{
  203. {
  204. Name: TestMetric,
  205. Labels: map[string]string{
  206. "test": "test",
  207. },
  208. Value: 1,
  209. AdditionalInfo: nil,
  210. },
  211. },
  212. }
  213. wal.Update(inputUpdateSet1.Updates, time1)
  214. wal.Update(inputUpdateSet1.Updates, time2)
  215. wal.Update(inputUpdateSet1.Updates, time3)
  216. files, err := wal.getFileInfos()
  217. if err != nil {
  218. t.Errorf("failed to retrieve file info: %s", err.Error())
  219. }
  220. if len(files) != 3 {
  221. t.Errorf("incorrect number of files after updates: wanted %d, got %d", 3, len(files))
  222. }
  223. wal.clean()
  224. files, err = wal.getFileInfos()
  225. if err != nil {
  226. t.Errorf("failed to retrieve file info: %s", err.Error())
  227. }
  228. if len(files) != 2 {
  229. t.Errorf("incorrect number of files after clean: wanted %d, got %d", 2, len(files))
  230. }
  231. }