memoryrepository_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. package cloudcost
  2. import (
  3. "reflect"
  4. "testing"
  5. "time"
  6. "github.com/opencost/opencost/pkg/kubecost"
  7. "github.com/opencost/opencost/pkg/util/timeutil"
  8. )
  9. func TestMemoryRepository_Get(t *testing.T) {
  10. defaultStart := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
  11. defaultEnd := defaultStart.Add(timeutil.Day)
  12. defaultData := map[string]map[time.Time]*kubecost.CloudCostSet{
  13. "key-1": {
  14. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  15. },
  16. }
  17. tests := map[string]struct {
  18. data map[string]map[time.Time]*kubecost.CloudCostSet
  19. startTime time.Time
  20. key string
  21. want *kubecost.CloudCostSet
  22. wantErr bool
  23. }{
  24. "No Data": {
  25. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  26. startTime: defaultStart,
  27. key: "key-1",
  28. want: nil,
  29. wantErr: false,
  30. },
  31. "has data": {
  32. data: defaultData,
  33. startTime: defaultStart,
  34. key: "key-1",
  35. want: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  36. wantErr: false,
  37. },
  38. "wrong key": {
  39. data: defaultData,
  40. startTime: defaultStart,
  41. key: "key-2",
  42. want: nil,
  43. wantErr: false,
  44. },
  45. "wrong time": {
  46. data: defaultData,
  47. startTime: defaultEnd,
  48. key: "key-1",
  49. want: nil,
  50. wantErr: false,
  51. },
  52. }
  53. for name, tt := range tests {
  54. t.Run(name, func(t *testing.T) {
  55. m := &MemoryRepository{
  56. data: tt.data,
  57. }
  58. got, err := m.Get(tt.startTime, tt.key)
  59. if (err != nil) != tt.wantErr {
  60. t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
  61. return
  62. }
  63. if !reflect.DeepEqual(got, tt.want) {
  64. t.Errorf("Get() got = %v, want %v", got, tt.want)
  65. }
  66. })
  67. }
  68. }
  69. func TestMemoryRepository_Has(t *testing.T) {
  70. defaultStart := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
  71. defaultEnd := defaultStart.Add(timeutil.Day)
  72. defaultData := map[string]map[time.Time]*kubecost.CloudCostSet{
  73. "key-1": {
  74. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  75. },
  76. }
  77. tests := map[string]struct {
  78. data map[string]map[time.Time]*kubecost.CloudCostSet
  79. startTime time.Time
  80. key string
  81. want bool
  82. wantErr bool
  83. }{
  84. "No Data": {
  85. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  86. startTime: defaultStart,
  87. key: "key-1",
  88. want: false,
  89. wantErr: false,
  90. },
  91. "has data": {
  92. data: defaultData,
  93. startTime: defaultStart,
  94. key: "key-1",
  95. want: true,
  96. wantErr: false,
  97. },
  98. "wrong key": {
  99. data: defaultData,
  100. startTime: defaultStart,
  101. key: "key-2",
  102. want: false,
  103. wantErr: false,
  104. },
  105. "wrong time": {
  106. data: defaultData,
  107. startTime: defaultEnd,
  108. key: "key-1",
  109. want: false,
  110. wantErr: false,
  111. },
  112. }
  113. for name, tt := range tests {
  114. t.Run(name, func(t *testing.T) {
  115. m := &MemoryRepository{
  116. data: tt.data,
  117. }
  118. got, err := m.Has(tt.startTime, tt.key)
  119. if (err != nil) != tt.wantErr {
  120. t.Errorf("Has() error = %v, wantErr %v", err, tt.wantErr)
  121. return
  122. }
  123. if got != tt.want {
  124. t.Errorf("Has() got = %v, want %v", got, tt.want)
  125. }
  126. })
  127. }
  128. }
  129. func TestMemoryRepository_Keys(t *testing.T) {
  130. tests := map[string]struct {
  131. data map[string]map[time.Time]*kubecost.CloudCostSet
  132. want []string
  133. wantErr bool
  134. }{
  135. "empty": {
  136. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  137. want: []string{},
  138. wantErr: false,
  139. },
  140. "one-key": {
  141. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  142. "key-1": nil,
  143. },
  144. want: []string{"key-1"},
  145. wantErr: false,
  146. },
  147. "two-key": {
  148. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  149. "key-1": nil,
  150. "key-2": {
  151. time.Now(): nil,
  152. time.Now().Add(1): nil,
  153. },
  154. },
  155. want: []string{"key-1", "key-2"},
  156. wantErr: false,
  157. },
  158. }
  159. for name, tt := range tests {
  160. t.Run(name, func(t *testing.T) {
  161. m := &MemoryRepository{
  162. data: tt.data,
  163. }
  164. got, err := m.Keys()
  165. if (err != nil) != tt.wantErr {
  166. t.Errorf("Keys() error = %v, wantErr %v", err, tt.wantErr)
  167. return
  168. }
  169. if !reflect.DeepEqual(got, tt.want) {
  170. t.Errorf("Keys() got = %v, want %v", got, tt.want)
  171. }
  172. })
  173. }
  174. }
  175. func TestMemoryRepository_Put(t *testing.T) {
  176. defaultStart := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
  177. defaultEnd := defaultStart.Add(timeutil.Day)
  178. tests := map[string]struct {
  179. data map[string]map[time.Time]*kubecost.CloudCostSet
  180. input *kubecost.CloudCostSet
  181. want map[string]map[time.Time]*kubecost.CloudCostSet
  182. wantErr bool
  183. }{
  184. "nil set": {
  185. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  186. input: nil,
  187. want: map[string]map[time.Time]*kubecost.CloudCostSet{},
  188. wantErr: true,
  189. },
  190. "invalid window": {
  191. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  192. input: &kubecost.CloudCostSet{
  193. CloudCosts: nil,
  194. Window: kubecost.Window{},
  195. Integration: "key-1",
  196. },
  197. want: map[string]map[time.Time]*kubecost.CloudCostSet{},
  198. wantErr: true,
  199. },
  200. "invalid key": {
  201. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  202. input: &kubecost.CloudCostSet{
  203. CloudCosts: nil,
  204. Window: kubecost.NewClosedWindow(defaultStart, defaultEnd),
  205. Integration: "",
  206. },
  207. want: map[string]map[time.Time]*kubecost.CloudCostSet{},
  208. wantErr: true,
  209. },
  210. "valid input": {
  211. data: map[string]map[time.Time]*kubecost.CloudCostSet{},
  212. input: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  213. want: map[string]map[time.Time]*kubecost.CloudCostSet{
  214. "key-1": {
  215. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  216. },
  217. },
  218. wantErr: false,
  219. },
  220. "overwrite": {
  221. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  222. "key-1": {
  223. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "gcp", "key-1"),
  224. },
  225. },
  226. input: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  227. want: map[string]map[time.Time]*kubecost.CloudCostSet{
  228. "key-1": {
  229. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "aws", "key-1"),
  230. },
  231. },
  232. wantErr: false,
  233. },
  234. "invalid overwrite": {
  235. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  236. "key-1": {
  237. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "gcp", "key-1"),
  238. },
  239. },
  240. input: &kubecost.CloudCostSet{
  241. Window: kubecost.NewWindow(&defaultStart, nil),
  242. Integration: "key-1",
  243. },
  244. want: map[string]map[time.Time]*kubecost.CloudCostSet{
  245. "key-1": {
  246. defaultStart: DefaultMockCloudCostSet(defaultStart, defaultEnd, "gcp", "key-1"),
  247. },
  248. },
  249. wantErr: true,
  250. },
  251. }
  252. for name, tt := range tests {
  253. t.Run(name, func(t *testing.T) {
  254. m := &MemoryRepository{data: tt.data}
  255. if err := m.Put(tt.input); (err != nil) != tt.wantErr {
  256. t.Errorf("Put() error = %v, wantErr %v", err, tt.wantErr)
  257. }
  258. if !reflect.DeepEqual(m.data, tt.want) {
  259. t.Errorf("Put() got = %v, want %v", m.data, tt.want)
  260. }
  261. })
  262. }
  263. }
  264. func TestMemoryRepository_Expire(t *testing.T) {
  265. dayOne := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
  266. dayTwo := time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC)
  267. dayThree := time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC)
  268. tests := map[string]struct {
  269. data map[string]map[time.Time]*kubecost.CloudCostSet
  270. limit time.Time
  271. want map[string]map[time.Time]*kubecost.CloudCostSet
  272. wantErr bool
  273. }{
  274. "no expire": {
  275. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  276. "key-1": {
  277. dayTwo: nil,
  278. },
  279. },
  280. limit: dayOne,
  281. want: map[string]map[time.Time]*kubecost.CloudCostSet{
  282. "key-1": {
  283. dayTwo: nil,
  284. },
  285. },
  286. wantErr: false,
  287. },
  288. "limit match": {
  289. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  290. "key-1": {
  291. dayTwo: nil,
  292. },
  293. },
  294. limit: dayTwo,
  295. want: map[string]map[time.Time]*kubecost.CloudCostSet{
  296. "key-1": {
  297. dayTwo: nil,
  298. },
  299. },
  300. wantErr: false,
  301. },
  302. "single expire": {
  303. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  304. "key-1": {
  305. dayTwo: nil,
  306. },
  307. },
  308. limit: dayThree,
  309. want: map[string]map[time.Time]*kubecost.CloudCostSet{},
  310. wantErr: false,
  311. },
  312. "one key expire": {
  313. data: map[string]map[time.Time]*kubecost.CloudCostSet{
  314. "key-1": {
  315. dayOne: nil,
  316. dayTwo: nil,
  317. },
  318. "key-2": {
  319. dayOne: nil,
  320. },
  321. },
  322. limit: dayTwo,
  323. want: map[string]map[time.Time]*kubecost.CloudCostSet{
  324. "key-1": {
  325. dayTwo: nil,
  326. },
  327. },
  328. wantErr: false,
  329. },
  330. }
  331. for name, tt := range tests {
  332. t.Run(name, func(t *testing.T) {
  333. m := &MemoryRepository{
  334. data: tt.data,
  335. }
  336. if err := m.Expire(tt.limit); (err != nil) != tt.wantErr {
  337. t.Errorf("Expire() error = %v, wantErr %v", err, tt.wantErr)
  338. }
  339. if !reflect.DeepEqual(m.data, tt.want) {
  340. t.Errorf("Expire() got = %v, want %v", m.data, tt.want)
  341. }
  342. })
  343. }
  344. }