timeutil_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. package timeutil
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. )
  7. func Test_DurationString(t *testing.T) {
  8. testCases := map[string]struct {
  9. duration time.Duration
  10. expectedDuration string
  11. }{
  12. "1a": {
  13. duration: 0,
  14. expectedDuration: "",
  15. },
  16. "1b": {
  17. duration: 24 * time.Hour,
  18. expectedDuration: "1d",
  19. },
  20. "1c": {
  21. duration: 24*time.Hour + 5*time.Minute,
  22. expectedDuration: "1445m",
  23. },
  24. "1d": {
  25. duration: 25 * time.Hour,
  26. expectedDuration: "25h",
  27. },
  28. "1e": {
  29. duration: 25 * time.Hour,
  30. expectedDuration: "25h",
  31. },
  32. "1f": {
  33. duration: 72 * time.Hour,
  34. expectedDuration: "3d",
  35. },
  36. "1g": {
  37. duration: 25 * time.Hour,
  38. expectedDuration: "25h",
  39. },
  40. "1h": {
  41. duration: 24*time.Hour + time.Second,
  42. expectedDuration: "86401s",
  43. },
  44. // Expect empty strings if durations are negative
  45. "1i": {
  46. duration: -25 * time.Hour,
  47. expectedDuration: "",
  48. },
  49. }
  50. for name, test := range testCases {
  51. t.Run(name, func(t *testing.T) {
  52. dur := DurationString(test.duration)
  53. if dur != test.expectedDuration {
  54. t.Fatalf("DurationOffsetStrings: exp (%s); act (%s)", test.expectedDuration, dur)
  55. }
  56. })
  57. }
  58. }
  59. func Test_DurationToPromOffsetString(t *testing.T) {
  60. testCases := map[string]struct {
  61. duration time.Duration
  62. expectedDuration string
  63. }{
  64. "1a": {
  65. duration: 0,
  66. expectedDuration: "",
  67. },
  68. "1b": {
  69. duration: 24 * time.Hour,
  70. expectedDuration: "offset 1d",
  71. },
  72. "1c": {
  73. duration: 24*time.Hour + 5*time.Minute,
  74. expectedDuration: "offset 1445m",
  75. },
  76. "1d": {
  77. duration: 25 * time.Hour,
  78. expectedDuration: "offset 25h",
  79. },
  80. "1e": {
  81. duration: 25 * time.Hour,
  82. expectedDuration: "offset 25h",
  83. },
  84. "1f": {
  85. duration: 72 * time.Hour,
  86. expectedDuration: "offset 3d",
  87. },
  88. "1g": {
  89. duration: 25 * time.Hour,
  90. expectedDuration: "offset 25h",
  91. },
  92. "1h": {
  93. duration: 24*time.Hour + time.Second,
  94. expectedDuration: "offset 86401s",
  95. },
  96. // Expect empty strings if durations are negative
  97. "1i": {
  98. duration: -25 * time.Hour,
  99. expectedDuration: "",
  100. },
  101. }
  102. for name, test := range testCases {
  103. t.Run(name, func(t *testing.T) {
  104. dur := DurationToPromOffsetString(test.duration)
  105. if dur != test.expectedDuration {
  106. t.Fatalf("DurationOffsetStrings: exp (%s); act (%s)", test.expectedDuration, dur)
  107. }
  108. })
  109. }
  110. }
  111. func Test_FormatStoreResolution(t *testing.T) {
  112. testCases := map[string]struct {
  113. duration time.Duration
  114. expectedDuration string
  115. }{
  116. "1a": {
  117. duration: 0,
  118. expectedDuration: "0s",
  119. },
  120. "1b": {
  121. duration: 24 * time.Hour,
  122. expectedDuration: "1d",
  123. },
  124. "1c": {
  125. duration: 24*time.Hour + 5*time.Minute,
  126. expectedDuration: "1d",
  127. },
  128. "1d": {
  129. duration: 25 * time.Hour,
  130. expectedDuration: "1d",
  131. },
  132. "1e": {
  133. duration: 25 * time.Hour,
  134. expectedDuration: "1d",
  135. },
  136. "1f": {
  137. duration: 72 * time.Hour,
  138. expectedDuration: "3d",
  139. },
  140. "1g": {
  141. duration: 25 * time.Hour,
  142. expectedDuration: "1d",
  143. },
  144. "1h": {
  145. duration: 24*time.Hour + time.Second,
  146. expectedDuration: "1d",
  147. },
  148. // Expect empty strings if durations are negative
  149. "1i": {
  150. duration: -25 * time.Hour,
  151. expectedDuration: "-25h0m0s",
  152. },
  153. }
  154. for name, test := range testCases {
  155. t.Run(name, func(t *testing.T) {
  156. dur := FormatStoreResolution(test.duration)
  157. if dur != test.expectedDuration {
  158. t.Fatalf("DurationOffsetStrings: exp (%s); act (%s)", test.expectedDuration, dur)
  159. }
  160. })
  161. }
  162. }
  163. func Test_DurationOffsetStrings(t *testing.T) {
  164. testCases := map[string]struct {
  165. duration time.Duration
  166. offset time.Duration
  167. expectedDuration string
  168. expectedOffset string
  169. }{
  170. "1a": {
  171. duration: 0,
  172. offset: 0,
  173. expectedDuration: "",
  174. expectedOffset: "",
  175. },
  176. "1b": {
  177. duration: 24 * time.Hour,
  178. offset: 0,
  179. expectedDuration: "1d",
  180. expectedOffset: "",
  181. },
  182. "1c": {
  183. duration: 24*time.Hour + 5*time.Minute,
  184. offset: 0,
  185. expectedDuration: "1445m",
  186. expectedOffset: "",
  187. },
  188. "1d": {
  189. duration: 25 * time.Hour,
  190. offset: 5 * time.Minute,
  191. expectedDuration: "25h",
  192. expectedOffset: "5m",
  193. },
  194. "1e": {
  195. duration: 25 * time.Hour,
  196. offset: 60 * time.Minute,
  197. expectedDuration: "25h",
  198. expectedOffset: "1h",
  199. },
  200. "1f": {
  201. duration: 72 * time.Hour,
  202. offset: 1440 * time.Minute,
  203. expectedDuration: "3d",
  204. expectedOffset: "1d",
  205. },
  206. "1g": {
  207. duration: 25 * time.Hour,
  208. offset: 1 * time.Second,
  209. expectedDuration: "25h",
  210. expectedOffset: "1s",
  211. },
  212. "1h": {
  213. duration: 24*time.Hour + time.Second,
  214. offset: 1 * time.Second,
  215. expectedDuration: "86401s",
  216. expectedOffset: "1s",
  217. },
  218. // Expect empty strings if durations are negative
  219. "1i": {
  220. duration: -25 * time.Hour,
  221. offset: -1 * time.Second,
  222. expectedDuration: "",
  223. expectedOffset: "",
  224. },
  225. }
  226. for name, test := range testCases {
  227. t.Run(name, func(t *testing.T) {
  228. dur, off := DurationOffsetStrings(test.duration, test.offset)
  229. if dur != test.expectedDuration || off != test.expectedOffset {
  230. t.Fatalf("DurationOffsetStrings: exp (%s %s); act (%s, %s)", test.expectedDuration, test.expectedOffset, dur, off)
  231. }
  232. })
  233. }
  234. }
  235. func Test_ParseDuration(t *testing.T) {
  236. testCases := map[string]struct {
  237. input string
  238. expected time.Duration
  239. }{
  240. "expected": {
  241. input: "3h",
  242. expected: time.Hour * 3,
  243. },
  244. "white space": {
  245. input: " 4s ",
  246. expected: time.Second * 4,
  247. },
  248. "prom prefix": {
  249. input: "offset 3m",
  250. expected: time.Minute * 3,
  251. },
  252. "prom prefix white space": {
  253. input: " offset 3d ",
  254. expected: 24.0 * time.Hour * 3,
  255. },
  256. "ms duration": {
  257. input: "100ms",
  258. expected: 100 * time.Millisecond,
  259. },
  260. "complex duration": {
  261. input: "2d3h14m2s",
  262. expected: (24 * time.Hour * 2) + (3 * time.Hour) + (14 * time.Minute) + (2 * time.Second),
  263. },
  264. "negative duration": {
  265. input: "-2d",
  266. expected: -48 * time.Hour,
  267. },
  268. "zero": {
  269. input: "0h",
  270. expected: time.Duration(0),
  271. },
  272. "empty": {
  273. input: "",
  274. expected: time.Duration(0),
  275. },
  276. "bad string": {
  277. input: "oqwd3dk5hk",
  278. expected: time.Duration(0),
  279. },
  280. "digit": {
  281. input: "3",
  282. expected: time.Duration(0),
  283. },
  284. "unit": {
  285. input: "h",
  286. expected: time.Duration(0),
  287. },
  288. }
  289. for name, test := range testCases {
  290. t.Run(name, func(t *testing.T) {
  291. dur, _ := ParseDuration(test.input)
  292. if dur != test.expected {
  293. t.Errorf("Expected duration %v did not match result %v", test.expected, dur)
  294. }
  295. })
  296. }
  297. }
  298. func Test_CleanDurationString(t *testing.T) {
  299. testCases := map[string]struct {
  300. input string
  301. expected string
  302. }{
  303. "white space": {
  304. input: " 1d ",
  305. expected: "1d",
  306. },
  307. "no change": {
  308. input: "1d",
  309. expected: "1d",
  310. },
  311. "prefix": {
  312. input: "offset 1d",
  313. expected: "1d",
  314. },
  315. "prefix white space": {
  316. input: " offset 1d ",
  317. expected: "1d",
  318. },
  319. "empty": {
  320. input: "",
  321. expected: "",
  322. },
  323. "random": {
  324. input: "oqwd3dk5hk",
  325. expected: "oqwd3dk5hk",
  326. },
  327. }
  328. for name, test := range testCases {
  329. t.Run(name, func(t *testing.T) {
  330. res := CleanDurationString(test.input)
  331. if res != test.expected {
  332. t.Errorf("Expected output %s did not match result %s", test.expected, res)
  333. }
  334. })
  335. }
  336. }
  337. func Test_FormatDurationStringDaysToHours(t *testing.T) {
  338. testCases := map[string]struct {
  339. input string
  340. expected string
  341. }{
  342. "1 day": {
  343. input: "1d",
  344. expected: "24h",
  345. },
  346. "2 days": {
  347. input: "1d",
  348. expected: "24h",
  349. },
  350. "500 days": {
  351. input: "500d",
  352. expected: "12000h",
  353. },
  354. "1h": {
  355. input: "1h",
  356. expected: "1h",
  357. },
  358. "empty": {
  359. input: "",
  360. expected: "",
  361. },
  362. "no unit": {
  363. input: "1",
  364. expected: "1",
  365. },
  366. "random": {
  367. input: "oqwd3dk5hk",
  368. expected: "oqwd3dk5hk",
  369. },
  370. }
  371. for name, test := range testCases {
  372. t.Run(name, func(t *testing.T) {
  373. res, _ := FormatDurationStringDaysToHours(test.input)
  374. if res != test.expected {
  375. t.Errorf("Expected output %s did not match result %s", test.expected, res)
  376. }
  377. })
  378. }
  379. }
  380. func TestRoundToStartOfWeek(t *testing.T) {
  381. sunday := time.Date(2023, 03, 26, 12, 12, 12, 12, time.UTC)
  382. roundedFromSunday := RoundToStartOfWeek(sunday)
  383. if roundedFromSunday.Day() != 26 || roundedFromSunday.Weekday() == time.Sunday {
  384. fmt.Errorf("expected date to be rounded to the same sunday, got: %d, %s", roundedFromSunday.Day(), roundedFromSunday.Weekday().String())
  385. }
  386. tuesday := time.Date(2023, 03, 28, 12, 12, 12, 12, time.UTC)
  387. roundedFromTuesday := RoundToStartOfWeek(tuesday)
  388. if roundedFromTuesday.Day() != 26 || roundedFromTuesday.Weekday() == time.Sunday {
  389. fmt.Errorf("expected date to be rounded to the same sunday, got: %d, %s", roundedFromTuesday.Day(), roundedFromTuesday.Weekday().String())
  390. }
  391. }
  392. func TestRoundToStartOfFollowingWeek(t *testing.T) {
  393. sunday := time.Date(2023, 03, 26, 12, 12, 12, 12, time.UTC)
  394. roundedFromSunday := RoundToStartOfFollowingWeek(sunday)
  395. if roundedFromSunday.Month() != 4 || roundedFromSunday.Day() != 2 || roundedFromSunday.Weekday() == time.Sunday {
  396. fmt.Errorf("expected date to be rounded to the same sunday, got: %d, %s", roundedFromSunday.Day(), roundedFromSunday.Weekday().String())
  397. }
  398. tuesday := time.Date(2023, 03, 28, 12, 12, 12, 12, time.UTC)
  399. roundedFromTuesday := RoundToStartOfFollowingWeek(tuesday)
  400. if roundedFromTuesday.Month() != 4 || roundedFromTuesday.Day() != 2 || roundedFromTuesday.Weekday() == time.Sunday {
  401. fmt.Errorf("expected date to be rounded to the same sunday, got: %d, %s", roundedFromTuesday.Day(), roundedFromTuesday.Weekday().String())
  402. }
  403. }