interval_test.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. package util
  2. import (
  3. "reflect"
  4. "testing"
  5. "time"
  6. "github.com/opencost/opencost/core/pkg/util/timeutil"
  7. )
  8. func TestNewInterval(t *testing.T) {
  9. tests := map[string]struct {
  10. def string
  11. want Interval
  12. wantErr bool
  13. }{
  14. "invalid": {
  15. def: "invalid",
  16. want: nil,
  17. wantErr: true,
  18. },
  19. "invalid2": {
  20. def: "1M",
  21. want: nil,
  22. wantErr: true,
  23. },
  24. "invalid3": {
  25. def: "d20",
  26. want: nil,
  27. wantErr: true,
  28. },
  29. "one minute": {
  30. def: "1m",
  31. want: &durationInterval{
  32. duration: time.Minute,
  33. },
  34. wantErr: false,
  35. },
  36. "ten minute": {
  37. def: "10m",
  38. want: &durationInterval{
  39. duration: time.Minute * 10,
  40. },
  41. wantErr: false,
  42. },
  43. "one hour": {
  44. def: "1h",
  45. want: &durationInterval{
  46. duration: time.Hour,
  47. },
  48. },
  49. "six hours": {
  50. def: "6h",
  51. want: &durationInterval{
  52. duration: time.Hour * 6,
  53. },
  54. },
  55. "one day": {
  56. def: "1d",
  57. want: &durationInterval{
  58. duration: timeutil.Day,
  59. },
  60. },
  61. "seven days": {
  62. def: "7d",
  63. want: &durationInterval{
  64. duration: timeutil.Day * 7,
  65. },
  66. },
  67. "one week": {
  68. def: "1w",
  69. want: &weekInterval{
  70. count: 1,
  71. },
  72. },
  73. "two weeks": {
  74. def: "2w",
  75. want: &weekInterval{
  76. count: 2,
  77. },
  78. },
  79. }
  80. for name, tt := range tests {
  81. t.Run(name, func(t *testing.T) {
  82. got, err := NewInterval(tt.def)
  83. if (err != nil) != tt.wantErr {
  84. t.Errorf("NewInterval() error = %v, wantErr %v", err, tt.wantErr)
  85. return
  86. }
  87. if !reflect.DeepEqual(got, tt.want) {
  88. t.Errorf("NewInterval() got = %v, want %v", got, tt.want)
  89. }
  90. })
  91. }
  92. }
  93. func Test_durationInterval_Add(t *testing.T) {
  94. type args struct {
  95. t time.Time
  96. i int
  97. }
  98. tests := map[string]struct {
  99. duration time.Duration
  100. args args
  101. want time.Time
  102. }{
  103. "day interval add 1": {
  104. duration: timeutil.Day,
  105. args: args{
  106. t: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  107. i: 1,
  108. },
  109. want: time.Date(2025, time.April, 3, 0, 0, 0, 0, time.UTC),
  110. },
  111. "day interval sub 1": {
  112. duration: timeutil.Day,
  113. args: args{
  114. t: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  115. i: -1,
  116. },
  117. want: time.Date(2025, time.April, 1, 0, 0, 0, 0, time.UTC),
  118. },
  119. }
  120. for name, tt := range tests {
  121. t.Run(name, func(t *testing.T) {
  122. d := &durationInterval{
  123. duration: tt.duration,
  124. }
  125. if got := d.Add(tt.args.t, tt.args.i); !reflect.DeepEqual(got, tt.want) {
  126. t.Errorf("Add() = %v, want %v", got, tt.want)
  127. }
  128. })
  129. }
  130. }
  131. func Test_durationInterval_Truncate(t *testing.T) {
  132. tests := map[string]struct {
  133. duration time.Duration
  134. input time.Time
  135. want time.Time
  136. }{
  137. "one day truncate": {
  138. duration: timeutil.Day,
  139. input: time.Date(2025, time.April, 7, 3, 0, 0, 0, time.UTC),
  140. want: time.Date(2025, time.April, 7, 0, 0, 0, 0, time.UTC),
  141. },
  142. "two day truncate": {
  143. duration: 2 * timeutil.Day,
  144. input: time.Date(2025, time.April, 7, 3, 0, 0, 0, time.UTC),
  145. want: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  146. },
  147. "two day truncate 2": {
  148. duration: 2 * timeutil.Day,
  149. input: time.Date(2025, time.April, 6, 3, 0, 0, 0, time.UTC),
  150. want: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  151. },
  152. "seven day truncate": {
  153. duration: 7 * timeutil.Day,
  154. input: time.Date(2025, time.April, 7, 3, 0, 0, 0, time.UTC),
  155. want: time.Date(2025, time.April, 7, 0, 0, 0, 0, time.UTC),
  156. },
  157. "seven day truncate 2": {
  158. duration: 7 * timeutil.Day,
  159. input: time.Date(2025, time.March, 7, 3, 0, 0, 0, time.UTC),
  160. want: time.Date(2025, time.March, 3, 0, 0, 0, 0, time.UTC),
  161. },
  162. "seven day truncate 3": {
  163. duration: 7 * timeutil.Day,
  164. input: time.Date(2025, time.March, 3, 0, 0, 0, 0, time.UTC),
  165. want: time.Date(2025, time.March, 3, 0, 0, 0, 0, time.UTC),
  166. },
  167. }
  168. for name, tt := range tests {
  169. t.Run(name, func(t *testing.T) {
  170. d := &durationInterval{
  171. duration: tt.duration,
  172. }
  173. if got := d.Truncate(tt.input); !reflect.DeepEqual(got, tt.want) {
  174. t.Errorf("Truncate() = %v, want %v", got, tt.want)
  175. }
  176. })
  177. }
  178. }
  179. func Test_weekInterval_Add(t *testing.T) {
  180. tests := map[string]struct {
  181. count int
  182. t time.Time
  183. num int
  184. want time.Time
  185. }{
  186. "one week add one": {
  187. count: 1,
  188. t: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  189. num: 1,
  190. want: time.Date(2025, time.April, 9, 0, 0, 0, 0, time.UTC),
  191. },
  192. "one week subtract one": {
  193. count: 1,
  194. t: time.Date(2025, time.April, 9, 0, 0, 0, 0, time.UTC),
  195. num: -1,
  196. want: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  197. },
  198. "two week add one": {
  199. count: 1,
  200. t: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  201. num: 2,
  202. want: time.Date(2025, time.April, 16, 0, 0, 0, 0, time.UTC),
  203. },
  204. "one week add two": {
  205. count: 2,
  206. t: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  207. num: 1,
  208. want: time.Date(2025, time.April, 16, 0, 0, 0, 0, time.UTC),
  209. },
  210. "two week add two": {
  211. count: 2,
  212. t: time.Date(2025, time.April, 2, 0, 0, 0, 0, time.UTC),
  213. num: 2,
  214. want: time.Date(2025, time.April, 30, 0, 0, 0, 0, time.UTC),
  215. },
  216. }
  217. for name, tt := range tests {
  218. t.Run(name, func(t *testing.T) {
  219. w := &weekInterval{
  220. count: tt.count,
  221. }
  222. if got := w.Add(tt.t, tt.num); !reflect.DeepEqual(got, tt.want) {
  223. t.Errorf("Add() = %v, want %v", got, tt.want)
  224. }
  225. })
  226. }
  227. }
  228. func Test_weekInterval_Truncate(t *testing.T) {
  229. tests := map[string]struct {
  230. count int
  231. input time.Time
  232. want time.Time
  233. }{
  234. "one week no change": {
  235. count: 1,
  236. input: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  237. want: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  238. },
  239. "one week": {
  240. count: 1,
  241. input: time.Date(2025, time.April, 7, 3, 0, 0, 0, time.UTC),
  242. want: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  243. },
  244. "one week 2": {
  245. count: 1,
  246. input: time.Date(2025, time.March, 7, 3, 0, 0, 0, time.UTC),
  247. want: time.Date(2025, time.March, 2, 0, 0, 0, 0, time.UTC),
  248. },
  249. "one week 3": {
  250. count: 1,
  251. input: time.Date(2025, time.March, 3, 0, 0, 0, 0, time.UTC),
  252. want: time.Date(2025, time.March, 2, 0, 0, 0, 0, time.UTC),
  253. },
  254. "two week no change": {
  255. count: 2,
  256. input: time.Date(2025, time.March, 30, 0, 0, 0, 0, time.UTC),
  257. want: time.Date(2025, time.March, 30, 0, 0, 0, 0, time.UTC),
  258. },
  259. "two week": {
  260. count: 2,
  261. input: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  262. want: time.Date(2025, time.March, 30, 0, 0, 0, 0, time.UTC),
  263. },
  264. "two week 2": {
  265. count: 2,
  266. input: time.Date(2025, time.April, 13, 0, 0, 0, 0, time.UTC),
  267. want: time.Date(2025, time.April, 13, 0, 0, 0, 0, time.UTC),
  268. },
  269. "three week": {
  270. count: 3,
  271. input: time.Date(2025, time.April, 7, 0, 0, 0, 0, time.UTC),
  272. want: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  273. },
  274. "three week 2": {
  275. count: 3,
  276. input: time.Date(2025, time.April, 14, 0, 0, 0, 0, time.UTC),
  277. want: time.Date(2025, time.April, 6, 0, 0, 0, 0, time.UTC),
  278. },
  279. "one week first week": {
  280. count: 1,
  281. input: time.Date(1, time.January, 6, 0, 0, 0, 0, time.UTC),
  282. want: time.Time{}.Add(-1 * timeutil.Day),
  283. },
  284. "one week second week": {
  285. count: 1,
  286. input: time.Date(1, time.January, 9, 0, 0, 0, 0, time.UTC),
  287. want: time.Date(1, time.January, 7, 0, 0, 0, 0, time.UTC),
  288. },
  289. "two week second week": {
  290. count: 2,
  291. input: time.Date(1, time.January, 9, 0, 0, 0, 0, time.UTC),
  292. want: time.Time{}.Add(-1 * timeutil.Day),
  293. },
  294. }
  295. for name, tt := range tests {
  296. t.Run(name, func(t *testing.T) {
  297. w := &weekInterval{
  298. count: tt.count,
  299. }
  300. got := w.Truncate(tt.input)
  301. if got.Weekday() != time.Sunday {
  302. t.Errorf("result was not a sunday: %s", got.Weekday().String())
  303. }
  304. if !reflect.DeepEqual(got, tt.want) {
  305. t.Errorf("Truncate() = %v, want %v", got, tt.want)
  306. }
  307. })
  308. }
  309. }