2
0

summaryallocation_test.go 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. package opencost
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/opencost/opencost/core/pkg/util"
  6. )
  7. func TestSummaryAllocation_Add(t *testing.T) {
  8. window, _ := ParseWindowUTC("yesterday")
  9. var sa1, sa2, osa1, osa2, nilsa *SummaryAllocation
  10. var err error
  11. sa1Start := *window.Start()
  12. sa1End := *window.End()
  13. sa1 = &SummaryAllocation{
  14. Name: "cluster1/namespace1/pod1/container1",
  15. Properties: &AllocationProperties{
  16. Cluster: "cluster1",
  17. Namespace: "namespace1",
  18. Pod: "pod1",
  19. Container: "container1",
  20. },
  21. Start: sa1Start,
  22. End: sa1End,
  23. CPUCoreRequestAverage: 0.5,
  24. CPUCoreUsageAverage: 0.1,
  25. CPUCost: 0.2,
  26. GPUCost: 1.0,
  27. NetworkCost: 0.1,
  28. LoadBalancerCost: 0.6,
  29. PVCost: 0.005,
  30. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  31. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  32. RAMCost: 0.05,
  33. SharedCost: 1.0,
  34. ExternalCost: 1.0,
  35. }
  36. osa1 = sa1.Clone()
  37. // sa2 is just as expensive, with twice as much usage and request, and half
  38. // the time compared to sa1
  39. sa2Start := *window.Start()
  40. sa2Start = sa2Start.Add(6 * time.Hour)
  41. sa2End := *window.End()
  42. sa2End = sa2End.Add(-6 * time.Hour)
  43. sa2 = &SummaryAllocation{
  44. Name: "cluster1/namespace1/pod2/container2",
  45. Properties: &AllocationProperties{
  46. Cluster: "cluster1",
  47. Namespace: "namespace1",
  48. Pod: "pod2",
  49. Container: "container2",
  50. },
  51. Start: sa2Start,
  52. End: sa2End,
  53. CPUCoreRequestAverage: sa1.CPUCoreRequestAverage * 2.0,
  54. CPUCoreUsageAverage: sa1.CPUCoreUsageAverage * 2.0,
  55. CPUCost: sa1.CPUCost,
  56. GPUCost: sa1.GPUCost,
  57. NetworkCost: sa1.NetworkCost,
  58. LoadBalancerCost: sa1.LoadBalancerCost,
  59. PVCost: sa1.PVCost,
  60. RAMBytesRequestAverage: sa1.RAMBytesRequestAverage * 2.0,
  61. RAMBytesUsageAverage: sa1.RAMBytesUsageAverage * 2.0,
  62. RAMCost: sa1.RAMCost,
  63. SharedCost: sa1.SharedCost,
  64. ExternalCost: sa1.ExternalCost,
  65. }
  66. osa2 = sa2.Clone()
  67. // add nil to nil, expect and error
  68. t.Run("nil.Add(nil)", func(t *testing.T) {
  69. err = nilsa.Add(nilsa)
  70. if err == nil {
  71. t.Fatalf("expected error: cannot add nil SummaryAllocations")
  72. }
  73. })
  74. // reset
  75. sa1 = osa1.Clone()
  76. sa2 = osa2.Clone()
  77. // add sa1 to nil, expect and error
  78. t.Run("nil.Add(sa1)", func(t *testing.T) {
  79. err = nilsa.Add(sa1)
  80. if err == nil {
  81. t.Fatalf("expected error: cannot add nil SummaryAllocations")
  82. }
  83. })
  84. // reset
  85. sa1 = osa1.Clone()
  86. sa2 = osa2.Clone()
  87. // add nil to sa1, expect and error
  88. t.Run("sa1.Add(nil)", func(t *testing.T) {
  89. err = sa1.Add(nilsa)
  90. if err == nil {
  91. t.Fatalf("expected error: cannot add nil SummaryAllocations")
  92. }
  93. })
  94. // reset
  95. sa1 = osa1.Clone()
  96. sa2 = osa2.Clone()
  97. // add sa1 to sa2 and expect same averages, but double costs
  98. t.Run("sa2.Add(sa1)", func(t *testing.T) {
  99. err = sa2.Add(sa1)
  100. if err != nil {
  101. t.Fatalf("unexpected error: %s", err)
  102. }
  103. if sa2.Properties != nil {
  104. t.Fatalf("expected properties to be nil; actual: %s", sa1.Properties)
  105. }
  106. if !util.IsApproximately(sa2.CPUCoreRequestAverage, (0.5*osa2.CPUCoreRequestAverage)+osa1.CPUCoreRequestAverage) {
  107. t.Fatalf("incorrect CPUCoreRequestAverage: expected %.5f; actual %.5f", (0.5*osa2.CPUCoreRequestAverage)+osa1.CPUCoreRequestAverage, sa2.CPUCoreRequestAverage)
  108. }
  109. if !util.IsApproximately(sa2.CPUCoreUsageAverage, (0.5*osa2.CPUCoreUsageAverage)+osa1.CPUCoreUsageAverage) {
  110. t.Fatalf("incorrect CPUCoreUsageAverage: expected %.5f; actual %.5f", (0.5*osa2.CPUCoreUsageAverage)+osa1.CPUCoreRequestAverage, sa2.CPUCoreUsageAverage)
  111. }
  112. if !util.IsApproximately(sa2.RAMBytesRequestAverage, (0.5*osa2.RAMBytesRequestAverage)+osa1.RAMBytesRequestAverage) {
  113. t.Fatalf("incorrect RAMBytesRequestAverage: expected %.5f; actual %.5f", (0.5*osa2.RAMBytesRequestAverage)+osa1.RAMBytesRequestAverage, sa2.RAMBytesRequestAverage)
  114. }
  115. if !util.IsApproximately(sa2.RAMBytesUsageAverage, (0.5*osa2.RAMBytesUsageAverage)+osa1.RAMBytesUsageAverage) {
  116. t.Fatalf("incorrect RAMBytesUsageAverage: expected %.5f; actual %.5f", (0.5*osa2.RAMBytesUsageAverage)+osa1.RAMBytesRequestAverage, sa2.RAMBytesUsageAverage)
  117. }
  118. if !util.IsApproximately(sa2.CPUCost, osa2.CPUCost+osa1.CPUCost) {
  119. t.Fatalf("incorrect CPUCost: expected %.5f; actual %.5f", osa2.CPUCost+osa1.CPUCost, sa2.CPUCost)
  120. }
  121. if !util.IsApproximately(sa2.GPUCost, osa2.GPUCost+osa1.GPUCost) {
  122. t.Fatalf("incorrect GPUCost: expected %.5f; actual %.5f", osa2.GPUCost+osa1.GPUCost, sa2.GPUCost)
  123. }
  124. if !util.IsApproximately(sa2.NetworkCost, osa2.NetworkCost+osa1.NetworkCost) {
  125. t.Fatalf("incorrect NetworkCost: expected %.5f; actual %.5f", osa2.NetworkCost+osa1.NetworkCost, sa2.NetworkCost)
  126. }
  127. if !util.IsApproximately(sa2.LoadBalancerCost, osa2.LoadBalancerCost+osa1.LoadBalancerCost) {
  128. t.Fatalf("incorrect LoadBalancerCost: expected %.5f; actual %.5f", osa2.LoadBalancerCost+osa1.LoadBalancerCost, sa2.LoadBalancerCost)
  129. }
  130. if !util.IsApproximately(sa2.PVCost, osa2.PVCost+osa1.PVCost) {
  131. t.Fatalf("incorrect PVCost: expected %.5f; actual %.5f", osa2.PVCost+osa1.PVCost, sa2.PVCost)
  132. }
  133. if !util.IsApproximately(sa2.RAMCost, osa2.RAMCost+osa1.RAMCost) {
  134. t.Fatalf("incorrect RAMCost: expected %.5f; actual %.5f", osa2.RAMCost+osa1.RAMCost, sa2.RAMCost)
  135. }
  136. if !util.IsApproximately(sa2.SharedCost, osa2.SharedCost+osa1.SharedCost) {
  137. t.Fatalf("incorrect SharedCost: expected %.5f; actual %.5f", osa2.SharedCost+osa1.SharedCost, sa2.SharedCost)
  138. }
  139. if !util.IsApproximately(sa2.ExternalCost, osa2.ExternalCost+osa1.ExternalCost) {
  140. t.Fatalf("incorrect ExternalCost: expected %.5f; actual %.5f", osa2.ExternalCost+osa1.ExternalCost, sa2.ExternalCost)
  141. }
  142. })
  143. // reset
  144. sa1 = osa1.Clone()
  145. sa2 = osa2.Clone()
  146. // add sa2 to sa1 and expect same averages, but double costs
  147. t.Run("sa1.Add(sa2)", func(t *testing.T) {
  148. err = sa1.Add(sa2)
  149. if err != nil {
  150. t.Fatalf("unexpected error: %s", err)
  151. }
  152. if sa1.Properties != nil {
  153. t.Fatalf("expected properties to be nil; actual: %s", sa1.Properties)
  154. }
  155. if !util.IsApproximately(sa1.CPUCoreRequestAverage, (0.5*osa2.CPUCoreRequestAverage)+osa1.CPUCoreRequestAverage) {
  156. t.Fatalf("incorrect CPUCoreRequestAverage: expected %.5f; actual %.5f", (0.5*osa2.CPUCoreRequestAverage)+osa1.CPUCoreRequestAverage, sa2.CPUCoreRequestAverage)
  157. }
  158. if !util.IsApproximately(sa1.CPUCoreUsageAverage, (0.5*osa2.CPUCoreUsageAverage)+osa1.CPUCoreUsageAverage) {
  159. t.Fatalf("incorrect CPUCoreUsageAverage: expected %.5f; actual %.5f", (0.5*osa2.CPUCoreUsageAverage)+osa1.CPUCoreRequestAverage, sa2.CPUCoreUsageAverage)
  160. }
  161. if !util.IsApproximately(sa1.RAMBytesRequestAverage, (0.5*osa2.RAMBytesRequestAverage)+osa1.RAMBytesRequestAverage) {
  162. t.Fatalf("incorrect RAMBytesRequestAverage: expected %.5f; actual %.5f", (0.5*osa2.RAMBytesRequestAverage)+osa1.RAMBytesRequestAverage, sa2.RAMBytesRequestAverage)
  163. }
  164. if !util.IsApproximately(sa1.RAMBytesUsageAverage, (0.5*osa2.RAMBytesUsageAverage)+osa1.RAMBytesUsageAverage) {
  165. t.Fatalf("incorrect RAMBytesUsageAverage: expected %.5f; actual %.5f", (0.5*osa2.RAMBytesUsageAverage)+osa1.RAMBytesRequestAverage, sa2.RAMBytesUsageAverage)
  166. }
  167. if !util.IsApproximately(sa1.CPUCost, osa2.CPUCost+osa1.CPUCost) {
  168. t.Fatalf("incorrect CPUCost: expected %.5f; actual %.5f", osa2.CPUCost+osa1.CPUCost, sa2.CPUCost)
  169. }
  170. if !util.IsApproximately(sa1.GPUCost, osa2.GPUCost+osa1.GPUCost) {
  171. t.Fatalf("incorrect GPUCost: expected %.5f; actual %.5f", osa2.GPUCost+osa1.GPUCost, sa2.GPUCost)
  172. }
  173. if !util.IsApproximately(sa1.NetworkCost, osa2.NetworkCost+osa1.NetworkCost) {
  174. t.Fatalf("incorrect NetworkCost: expected %.5f; actual %.5f", osa2.NetworkCost+osa1.NetworkCost, sa2.NetworkCost)
  175. }
  176. if !util.IsApproximately(sa1.LoadBalancerCost, osa2.LoadBalancerCost+osa1.LoadBalancerCost) {
  177. t.Fatalf("incorrect LoadBalancerCost: expected %.5f; actual %.5f", osa2.LoadBalancerCost+osa1.LoadBalancerCost, sa2.LoadBalancerCost)
  178. }
  179. if !util.IsApproximately(sa1.PVCost, osa2.PVCost+osa1.PVCost) {
  180. t.Fatalf("incorrect PVCost: expected %.5f; actual %.5f", osa2.PVCost+osa1.PVCost, sa2.PVCost)
  181. }
  182. if !util.IsApproximately(sa1.RAMCost, osa2.RAMCost+osa1.RAMCost) {
  183. t.Fatalf("incorrect RAMCost: expected %.5f; actual %.5f", osa2.RAMCost+osa1.RAMCost, sa2.RAMCost)
  184. }
  185. if !util.IsApproximately(sa1.SharedCost, osa2.SharedCost+osa1.SharedCost) {
  186. t.Fatalf("incorrect SharedCost: expected %.5f; actual %.5f", osa2.SharedCost+osa1.SharedCost, sa2.SharedCost)
  187. }
  188. if !util.IsApproximately(sa1.ExternalCost, osa2.ExternalCost+osa1.ExternalCost) {
  189. t.Fatalf("incorrect ExternalCost: expected %.5f; actual %.5f", osa2.ExternalCost+osa1.ExternalCost, sa2.ExternalCost)
  190. }
  191. })
  192. }
  193. func TestSummaryAllocationSet_RAMEfficiency(t *testing.T) {
  194. // Generating 6 sample summary allocations for testing
  195. var sa1, sa2, sa3, sa4, sa5, sa6, idlesa *SummaryAllocation
  196. // Generating accumulated summary allocation sets for testing
  197. var sas1, sas2, sas3, sas4, sas5, sas6 *SummaryAllocationSet
  198. window, _ := ParseWindowUTC("7d")
  199. saStart := *window.Start()
  200. saEnd := *window.End()
  201. sa1 = &SummaryAllocation{
  202. Name: "cluster1/namespace1/pod1/container1",
  203. Properties: &AllocationProperties{
  204. Cluster: "cluster1",
  205. Namespace: "namespace1",
  206. Pod: "pod1",
  207. Container: "container1",
  208. },
  209. Start: saStart,
  210. End: saEnd,
  211. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  212. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  213. RAMCost: 0.05,
  214. }
  215. sa2 = &SummaryAllocation{
  216. Name: "cluster1/namespace1/pod1/container2",
  217. Properties: &AllocationProperties{
  218. Cluster: "cluster1",
  219. Namespace: "namespace1",
  220. Pod: "pod1",
  221. Container: "container2",
  222. },
  223. Start: saStart,
  224. End: saEnd,
  225. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  226. RAMBytesUsageAverage: 15.0 * 1024.0 * 1024.0,
  227. RAMCost: 0.10,
  228. }
  229. sa3 = &SummaryAllocation{
  230. Name: "cluster1/namespace1/pod1/container3",
  231. Properties: &AllocationProperties{
  232. Cluster: "cluster1",
  233. Namespace: "namespace1",
  234. Pod: "pod1",
  235. Container: "container3",
  236. },
  237. Start: saStart,
  238. End: saEnd,
  239. RAMBytesRequestAverage: 0.0,
  240. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  241. RAMCost: 0.0,
  242. }
  243. sa4 = &SummaryAllocation{
  244. Name: "cluster1/namespace1/pod1/container4",
  245. Properties: &AllocationProperties{
  246. Cluster: "cluster1",
  247. Namespace: "namespace1",
  248. Pod: "pod1",
  249. Container: "container4",
  250. },
  251. Start: saStart,
  252. End: saEnd,
  253. RAMBytesRequestAverage: 0.0,
  254. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  255. RAMCost: 0.0,
  256. }
  257. sa5 = &SummaryAllocation{
  258. Name: "cluster1/namespace1/pod1/container4",
  259. Properties: &AllocationProperties{
  260. Cluster: "cluster1",
  261. Namespace: "namespace1",
  262. Pod: "pod1",
  263. Container: "container5",
  264. },
  265. Start: saStart,
  266. End: saEnd,
  267. RAMBytesRequestAverage: 0.0,
  268. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  269. RAMCost: 0.10,
  270. }
  271. sa6 = &SummaryAllocation{
  272. Name: "cluster1/namespace1/pod1/container4",
  273. Properties: &AllocationProperties{
  274. Cluster: "cluster1",
  275. Namespace: "namespace1",
  276. Pod: "pod1",
  277. Container: "container6",
  278. },
  279. Start: saStart,
  280. End: saEnd,
  281. RAMBytesRequestAverage: 0.0,
  282. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  283. RAMCost: 0.10,
  284. }
  285. idlesa = &SummaryAllocation{
  286. Name: IdleSuffix,
  287. Properties: &AllocationProperties{
  288. Cluster: "cluster1",
  289. Namespace: "namespace1",
  290. Pod: "pod1",
  291. Container: "container7",
  292. },
  293. Start: saStart,
  294. End: saEnd,
  295. CPUCost: 1.0,
  296. RAMCost: 1.0,
  297. }
  298. testcase1Map := map[string]*SummaryAllocation{
  299. "cluster1/namespace1/pod1/container1": sa1,
  300. "cluster1/namespace1/pod1/container2": sa2,
  301. }
  302. testcase2Map := map[string]*SummaryAllocation{
  303. "cluster1/namespace1/pod1/container3": sa3,
  304. "cluster1/namespace1/pod1/container4": sa4,
  305. }
  306. testcase3Map := map[string]*SummaryAllocation{
  307. "cluster1/namespace1/pod1/container5": sa5,
  308. "cluster1/namespace1/pod1/container6": sa6,
  309. }
  310. testcase4Map := map[string]*SummaryAllocation{}
  311. testcase5Map := map[string]*SummaryAllocation{
  312. "cluster1/namespace1/pod1/container1": sa1,
  313. "cluster1/namespace1/pod1/container2": sa2,
  314. "cluster1/namespace1/pod1/container3": sa3,
  315. "cluster1/namespace1/pod1/container4": sa4,
  316. "cluster1/namespace1/pod1/container5": sa5,
  317. "cluster1/namespace1/pod1/container6": sa6,
  318. }
  319. testcase6Map := map[string]*SummaryAllocation{
  320. "cluster1/namespace1/pod1/container1": sa1,
  321. "cluster1/namespace1/pod1/container2": sa2,
  322. "cluster1/__idle__": idlesa,
  323. }
  324. sas1 = &SummaryAllocationSet{
  325. SummaryAllocations: testcase1Map,
  326. Window: window,
  327. }
  328. sas2 = &SummaryAllocationSet{
  329. SummaryAllocations: testcase2Map,
  330. Window: window,
  331. }
  332. sas3 = &SummaryAllocationSet{
  333. SummaryAllocations: testcase3Map,
  334. Window: window,
  335. }
  336. sas4 = &SummaryAllocationSet{
  337. SummaryAllocations: testcase4Map,
  338. Window: window,
  339. }
  340. sas5 = &SummaryAllocationSet{
  341. SummaryAllocations: testcase5Map,
  342. Window: window,
  343. }
  344. sas6 = &SummaryAllocationSet{
  345. SummaryAllocations: testcase6Map,
  346. Window: window,
  347. }
  348. cases := []struct {
  349. name string
  350. testsas *SummaryAllocationSet
  351. expectedEfficiency float64
  352. }{
  353. {
  354. name: "Check RAMEfficiency when totalRAMBytesRequest over allocation summary set is greater than 0",
  355. testsas: sas1,
  356. expectedEfficiency: 0.25,
  357. },
  358. {
  359. name: "Check RAMEfficiency when totalRAMBytesRequest is 0 and totalRAMCost or totalRAMBytesUsage equal to 0",
  360. testsas: sas2,
  361. expectedEfficiency: 0.0,
  362. },
  363. {
  364. name: "Check RAMEfficiency when totalRAMBytesRequest is 0 and totalRAMCost or totalRAMBytesUsage is not 0",
  365. testsas: sas3,
  366. expectedEfficiency: 1.0,
  367. },
  368. {
  369. name: "Check RAMEfficiency when allocation summary set is empty",
  370. testsas: sas4,
  371. expectedEfficiency: 0.0,
  372. },
  373. {
  374. name: "Check RAMEfficiency over combination of all allocation summaries",
  375. testsas: sas5,
  376. expectedEfficiency: 0.65,
  377. },
  378. {
  379. name: "Check RAMEfficiency in presence of an idle allocation",
  380. testsas: sas6,
  381. expectedEfficiency: 0.25,
  382. },
  383. }
  384. for _, c := range cases {
  385. t.Run(c.name, func(t *testing.T) {
  386. returnEfficiency := c.testsas.RAMEfficiency()
  387. if !util.IsApproximately(c.expectedEfficiency, returnEfficiency) {
  388. t.Errorf("Case %s failed: Expected RAM Efficiency %.2f but got RAM Efficiency of as %.2f", c.name, c.expectedEfficiency, returnEfficiency)
  389. t.Fail()
  390. }
  391. })
  392. }
  393. }
  394. func TestSummaryAllocationSet_CPUEfficiency(t *testing.T) {
  395. // Generating 6 sample summary allocations for testing
  396. var sa1, sa2, sa3, sa4, sa5, sa6, idlesa *SummaryAllocation
  397. // Generating accumulated summary allocation sets for testing
  398. var sas1, sas2, sas3, sas4, sas5, sas6 *SummaryAllocationSet
  399. window, _ := ParseWindowUTC("7d")
  400. saStart := *window.Start()
  401. saEnd := *window.End()
  402. sa1 = &SummaryAllocation{
  403. Name: "cluster1/namespace1/pod1/container1",
  404. Properties: &AllocationProperties{
  405. Cluster: "cluster1",
  406. Namespace: "namespace1",
  407. Pod: "pod1",
  408. Container: "container1",
  409. },
  410. Start: saStart,
  411. End: saEnd,
  412. CPUCoreRequestAverage: 0.5,
  413. CPUCoreUsageAverage: 0.1,
  414. CPUCost: 0.2,
  415. }
  416. sa2 = &SummaryAllocation{
  417. Name: "cluster1/namespace1/pod1/container2",
  418. Properties: &AllocationProperties{
  419. Cluster: "cluster1",
  420. Namespace: "namespace1",
  421. Pod: "pod1",
  422. Container: "container2",
  423. },
  424. Start: saStart,
  425. End: saEnd,
  426. CPUCoreRequestAverage: 0.5,
  427. CPUCoreUsageAverage: 0.2,
  428. CPUCost: 0.2,
  429. }
  430. sa3 = &SummaryAllocation{
  431. Name: "cluster1/namespace1/pod1/container3",
  432. Properties: &AllocationProperties{
  433. Cluster: "cluster1",
  434. Namespace: "namespace1",
  435. Pod: "pod1",
  436. Container: "container3",
  437. },
  438. Start: saStart,
  439. End: saEnd,
  440. CPUCoreRequestAverage: 0.0,
  441. CPUCoreUsageAverage: 0.0,
  442. CPUCost: 1.0,
  443. }
  444. sa4 = &SummaryAllocation{
  445. Name: "cluster1/namespace1/pod1/container4",
  446. Properties: &AllocationProperties{
  447. Cluster: "cluster1",
  448. Namespace: "namespace1",
  449. Pod: "pod1",
  450. Container: "container4",
  451. },
  452. Start: saStart,
  453. End: saEnd,
  454. CPUCoreRequestAverage: 0.0,
  455. CPUCoreUsageAverage: 0.0,
  456. CPUCost: 2.0,
  457. }
  458. sa5 = &SummaryAllocation{
  459. Name: "cluster1/namespace1/pod1/container4",
  460. Properties: &AllocationProperties{
  461. Cluster: "cluster1",
  462. Namespace: "namespace1",
  463. Pod: "pod1",
  464. Container: "container5",
  465. },
  466. Start: saStart,
  467. End: saEnd,
  468. CPUCoreRequestAverage: 0.0,
  469. CPUCoreUsageAverage: 0.1,
  470. CPUCost: 0.2,
  471. }
  472. sa6 = &SummaryAllocation{
  473. Name: "cluster1/namespace1/pod1/container4",
  474. Properties: &AllocationProperties{
  475. Cluster: "cluster1",
  476. Namespace: "namespace1",
  477. Pod: "pod1",
  478. Container: "container6",
  479. },
  480. Start: saStart,
  481. End: saEnd,
  482. CPUCoreRequestAverage: 0.0,
  483. CPUCoreUsageAverage: 0.1,
  484. CPUCost: 0.2,
  485. }
  486. idlesa = &SummaryAllocation{
  487. Name: IdleSuffix,
  488. Properties: &AllocationProperties{
  489. Cluster: "cluster1",
  490. Namespace: "namespace1",
  491. Pod: "pod1",
  492. Container: "container7",
  493. },
  494. Start: saStart,
  495. End: saEnd,
  496. CPUCost: 1.0,
  497. RAMCost: 1.0,
  498. }
  499. testcase1Map := map[string]*SummaryAllocation{
  500. "cluster1/namespace1/pod1/container1": sa1,
  501. "cluster1/namespace1/pod1/container2": sa2,
  502. }
  503. testcase2Map := map[string]*SummaryAllocation{
  504. "cluster1/namespace1/pod1/container3": sa3,
  505. "cluster1/namespace1/pod1/container4": sa4,
  506. }
  507. testcase3Map := map[string]*SummaryAllocation{
  508. "cluster1/namespace1/pod1/container5": sa5,
  509. "cluster1/namespace1/pod1/container6": sa6,
  510. }
  511. testcase4Map := map[string]*SummaryAllocation{}
  512. testcase5Map := map[string]*SummaryAllocation{
  513. "cluster1/namespace1/pod1/container1": sa1,
  514. "cluster1/namespace1/pod1/container2": sa2,
  515. "cluster1/namespace1/pod1/container3": sa3,
  516. "cluster1/namespace1/pod1/container4": sa4,
  517. "cluster1/namespace1/pod1/container5": sa5,
  518. "cluster1/namespace1/pod1/container6": sa6,
  519. }
  520. testcase6Map := map[string]*SummaryAllocation{
  521. "cluster1/namespace1/pod1/container1": sa1,
  522. "cluster1/namespace1/pod1/container2": sa2,
  523. "cluster1/__idle__": idlesa,
  524. }
  525. sas1 = &SummaryAllocationSet{
  526. SummaryAllocations: testcase1Map,
  527. Window: window,
  528. }
  529. sas2 = &SummaryAllocationSet{
  530. SummaryAllocations: testcase2Map,
  531. Window: window,
  532. }
  533. sas3 = &SummaryAllocationSet{
  534. SummaryAllocations: testcase3Map,
  535. Window: window,
  536. }
  537. sas4 = &SummaryAllocationSet{
  538. SummaryAllocations: testcase4Map,
  539. Window: window,
  540. }
  541. sas5 = &SummaryAllocationSet{
  542. SummaryAllocations: testcase5Map,
  543. Window: window,
  544. }
  545. sas6 = &SummaryAllocationSet{
  546. SummaryAllocations: testcase6Map,
  547. Window: window,
  548. }
  549. cases := []struct {
  550. name string
  551. testsas *SummaryAllocationSet
  552. expectedEfficiency float64
  553. }{
  554. {
  555. name: "Check CPUEfficiency when totalCPUCoreRequest is greater than 0 over allocation summary set",
  556. testsas: sas1,
  557. expectedEfficiency: 0.30,
  558. },
  559. {
  560. name: "Check CPUEfficiency when totalCPUCoreRequest is 0 and totalCPUCost or totalCPUCoreUsage equal to 0",
  561. testsas: sas2,
  562. expectedEfficiency: 0.0,
  563. },
  564. {
  565. name: "Check CPUEfficiency when totalCPUCoreRequest is 0 and totalCPUCost or totalCPUCoreUsage is not 0",
  566. testsas: sas3,
  567. expectedEfficiency: 1.0,
  568. },
  569. {
  570. name: "Check CPUEfficiency when allocation summary set is empty",
  571. testsas: sas4,
  572. expectedEfficiency: 0.0,
  573. },
  574. {
  575. name: "Check CPUEfficiency over combination of all allocation summaries",
  576. testsas: sas5,
  577. expectedEfficiency: 0.50,
  578. },
  579. {
  580. name: "Check CPUEfficiency in presence of an idle allocation",
  581. testsas: sas6,
  582. expectedEfficiency: 0.30,
  583. },
  584. }
  585. for _, c := range cases {
  586. t.Run(c.name, func(t *testing.T) {
  587. returnEfficiency := c.testsas.CPUEfficiency()
  588. if !util.IsApproximately(c.expectedEfficiency, returnEfficiency) {
  589. t.Errorf("Case %s failed: Expected CPU Efficiency %.2f but got CPU Efficiency of as %.2f", c.name, c.expectedEfficiency, returnEfficiency)
  590. t.Fail()
  591. }
  592. })
  593. }
  594. }
  595. func TestSummaryAllocationSet_TotalEfficiency(t *testing.T) {
  596. // Generating 6 sample summary allocations for testing
  597. var sa1, sa2, sa3, sa4, sa5, sa6, idlesa *SummaryAllocation
  598. // Generating accumulated summary allocation sets for testing
  599. var sas1, sas2, sas3, sas4 *SummaryAllocationSet
  600. window, _ := ParseWindowUTC("7d")
  601. saStart := *window.Start()
  602. saEnd := *window.End()
  603. sa1 = &SummaryAllocation{
  604. Name: "cluster1/namespace1/pod1/container1",
  605. Properties: &AllocationProperties{
  606. Cluster: "cluster1",
  607. Namespace: "namespace1",
  608. Pod: "pod1",
  609. Container: "container1",
  610. },
  611. Start: saStart,
  612. End: saEnd,
  613. CPUCoreRequestAverage: 0.5,
  614. CPUCoreUsageAverage: 0.1,
  615. CPUCost: 0.0,
  616. RAMBytesRequestAverage: 0.0,
  617. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  618. RAMCost: 0.0,
  619. }
  620. sa2 = &SummaryAllocation{
  621. Name: "cluster1/namespace1/pod1/container2",
  622. Properties: &AllocationProperties{
  623. Cluster: "cluster1",
  624. Namespace: "namespace1",
  625. Pod: "pod1",
  626. Container: "container2",
  627. },
  628. Start: saStart,
  629. End: saEnd,
  630. CPUCoreRequestAverage: 0.5,
  631. CPUCoreUsageAverage: 0.2,
  632. CPUCost: 0.0,
  633. RAMBytesRequestAverage: 0.0,
  634. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  635. RAMCost: 0.0,
  636. }
  637. sa3 = &SummaryAllocation{
  638. Name: "cluster1/namespace1/pod1/container3",
  639. Properties: &AllocationProperties{
  640. Cluster: "cluster1",
  641. Namespace: "namespace1",
  642. Pod: "pod1",
  643. Container: "container3",
  644. },
  645. Start: saStart,
  646. End: saEnd,
  647. CPUCoreRequestAverage: 0.5,
  648. CPUCoreUsageAverage: 0.2,
  649. CPUCost: 1.0,
  650. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  651. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  652. RAMCost: 1.0,
  653. }
  654. sa4 = &SummaryAllocation{
  655. Name: "cluster1/namespace1/pod1/container4",
  656. Properties: &AllocationProperties{
  657. Cluster: "cluster1",
  658. Namespace: "namespace1",
  659. Pod: "pod1",
  660. Container: "container4",
  661. },
  662. Start: saStart,
  663. End: saEnd,
  664. CPUCoreRequestAverage: 0.5,
  665. CPUCoreUsageAverage: 0.1,
  666. CPUCost: 1.0,
  667. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  668. RAMBytesUsageAverage: 20.0 * 1024.0 * 1024.0,
  669. RAMCost: 1.0,
  670. }
  671. sa5 = &SummaryAllocation{
  672. Name: "cluster1/namespace1/pod1/container4",
  673. Properties: &AllocationProperties{
  674. Cluster: "cluster1",
  675. Namespace: "namespace1",
  676. Pod: "pod1",
  677. Container: "container5",
  678. },
  679. Start: saStart,
  680. End: saEnd,
  681. CPUCoreRequestAverage: 0.5,
  682. CPUCoreUsageAverage: 0.1,
  683. CPUCost: 1.0,
  684. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  685. RAMBytesUsageAverage: 10.0 * 1024.0 * 1024.0,
  686. RAMCost: 1.0,
  687. }
  688. sa6 = &SummaryAllocation{
  689. Name: "cluster1/namespace1/pod1/container4",
  690. Properties: &AllocationProperties{
  691. Cluster: "cluster1",
  692. Namespace: "namespace1",
  693. Pod: "pod1",
  694. Container: "container6",
  695. },
  696. Start: saStart,
  697. End: saEnd,
  698. CPUCoreRequestAverage: 0.5,
  699. CPUCoreUsageAverage: 0.2,
  700. CPUCost: 1.0,
  701. RAMBytesRequestAverage: 50.0 * 1024.0 * 1024.0,
  702. RAMBytesUsageAverage: 20.0 * 1024.0 * 1024.0,
  703. RAMCost: 1.0,
  704. }
  705. idlesa = &SummaryAllocation{
  706. Name: IdleSuffix,
  707. Properties: &AllocationProperties{
  708. Cluster: "cluster1",
  709. Namespace: "namespace1",
  710. Pod: "pod1",
  711. Container: "container7",
  712. },
  713. Start: saStart,
  714. End: saEnd,
  715. CPUCost: 1.0,
  716. RAMCost: 1.0,
  717. }
  718. testcase1Map := map[string]*SummaryAllocation{
  719. "cluster1/namespace1/pod1/container1": sa1,
  720. "cluster1/namespace1/pod1/container2": sa2,
  721. }
  722. testcase2Map := map[string]*SummaryAllocation{}
  723. testcase3Map := map[string]*SummaryAllocation{
  724. "cluster1/namespace1/pod1/container3": sa3,
  725. "cluster1/namespace1/pod1/container4": sa4,
  726. "cluster1/namespace1/pod1/container5": sa5,
  727. "cluster1/namespace1/pod1/container6": sa6,
  728. }
  729. testcase4Map := map[string]*SummaryAllocation{
  730. "cluster1/namespace1/pod1/container5": sa5,
  731. "cluster1/namespace1/pod1/container6": sa6,
  732. "cluster1/__idle__": idlesa,
  733. }
  734. sas1 = &SummaryAllocationSet{
  735. SummaryAllocations: testcase1Map,
  736. Window: window,
  737. }
  738. sas2 = &SummaryAllocationSet{
  739. SummaryAllocations: testcase2Map,
  740. Window: window,
  741. }
  742. sas3 = &SummaryAllocationSet{
  743. SummaryAllocations: testcase3Map,
  744. Window: window,
  745. }
  746. sas4 = &SummaryAllocationSet{
  747. SummaryAllocations: testcase4Map,
  748. Window: window,
  749. }
  750. cases := []struct {
  751. name string
  752. testsas *SummaryAllocationSet
  753. expectedEfficiency float64
  754. }{
  755. {
  756. name: "When TotalEfficiency when sum of TotalRAMCost and TotalCPUCost is 0",
  757. testsas: sas1,
  758. expectedEfficiency: 0.0,
  759. },
  760. {
  761. name: "Check TotalEfficiency when allocation summary set is empty",
  762. testsas: sas2,
  763. expectedEfficiency: 0.0,
  764. },
  765. {
  766. name: "Check TotalEfficiency over all 4 allocation summaries",
  767. testsas: sas3,
  768. expectedEfficiency: 0.30,
  769. },
  770. {
  771. name: "Check TotalEfficiency with idle cost",
  772. testsas: sas4,
  773. expectedEfficiency: 0.30,
  774. },
  775. }
  776. for _, c := range cases {
  777. t.Run(c.name, func(t *testing.T) {
  778. returnEfficiency := c.testsas.TotalEfficiency()
  779. if !util.IsApproximately(c.expectedEfficiency, returnEfficiency) {
  780. t.Errorf("Case %s failed: Expected Total Efficiency %.2f but got Total Efficiency of as %.2f", c.name, c.expectedEfficiency, returnEfficiency)
  781. t.Fail()
  782. }
  783. })
  784. }
  785. }
  786. func TestSummaryAllocationSetRange_AccumulateBy_None(t *testing.T) {
  787. ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
  788. ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
  789. ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
  790. yesterday := time.Now().UTC().Truncate(day).Add(-day)
  791. today := time.Now().UTC().Truncate(day)
  792. ago4dSAS := NewMockUnitSummaryAllocationSet(ago4d, day)
  793. ago4dSAS.Insert(NewMockUnitSummaryAllocation("4", ago4d, day, nil))
  794. ago3dSAS := NewMockUnitSummaryAllocationSet(ago3d, day)
  795. ago3dSAS.Insert(NewMockUnitSummaryAllocation("a", ago3d, day, nil))
  796. ago2dSAS := NewMockUnitSummaryAllocationSet(ago2d, day)
  797. ago2dSAS.Insert(NewMockUnitSummaryAllocation("", ago2d, day, nil))
  798. yesterdaySAS := NewMockUnitSummaryAllocationSet(yesterday, day)
  799. yesterdaySAS.Insert(NewMockUnitSummaryAllocation("", yesterday, day, nil))
  800. todaySAS := NewMockUnitSummaryAllocationSet(today, day)
  801. todaySAS.Insert(NewMockUnitSummaryAllocation("", today, day, nil))
  802. asr := NewSummaryAllocationSetRange(ago4dSAS, ago3dSAS, ago2dSAS, yesterdaySAS, todaySAS)
  803. asr, err := asr.Accumulate(AccumulateOptionNone)
  804. if err != nil {
  805. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  806. }
  807. if len(asr.SummaryAllocationSets) != 5 {
  808. t.Fatalf("expected 5 allocation sets, got:%d", len(asr.SummaryAllocationSets))
  809. }
  810. }
  811. func TestSummaryAllocationSetRange_AccumulateBy_All(t *testing.T) {
  812. ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
  813. ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
  814. ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
  815. yesterday := time.Now().UTC().Truncate(day).Add(-day)
  816. today := time.Now().UTC().Truncate(day)
  817. ago4dSAS := NewMockUnitSummaryAllocationSet(ago4d, day)
  818. ago4dSAS.Insert(NewMockUnitSummaryAllocation("4", ago4d, day, nil))
  819. ago3dSAS := NewMockUnitSummaryAllocationSet(ago3d, day)
  820. ago3dSAS.Insert(NewMockUnitSummaryAllocation("a", ago3d, day, nil))
  821. ago2dSAS := NewMockUnitSummaryAllocationSet(ago2d, day)
  822. ago2dSAS.Insert(NewMockUnitSummaryAllocation("", ago2d, day, nil))
  823. yesterdaySAS := NewMockUnitSummaryAllocationSet(yesterday, day)
  824. yesterdaySAS.Insert(NewMockUnitSummaryAllocation("", yesterday, day, nil))
  825. todaySAS := NewMockUnitSummaryAllocationSet(today, day)
  826. todaySAS.Insert(NewMockUnitSummaryAllocation("", today, day, nil))
  827. asr := NewSummaryAllocationSetRange(ago4dSAS, ago3dSAS, ago2dSAS, yesterdaySAS, todaySAS)
  828. asr, err := asr.Accumulate(AccumulateOptionAll)
  829. if err != nil {
  830. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  831. }
  832. if len(asr.SummaryAllocationSets) != 1 {
  833. t.Fatalf("expected 1 allocation set, got:%d", len(asr.SummaryAllocationSets))
  834. }
  835. allocMap := asr.SummaryAllocationSets[0].SummaryAllocations
  836. alloc := allocMap["cluster1/namespace1/pod1/container1"]
  837. if alloc.Minutes() != 4320.0 {
  838. t.Errorf("accumulating AllocationSetRange: expected %f minutes; actual %f", 4320.0, alloc.Minutes())
  839. }
  840. }
  841. func TestSummaryAllocationSetRange_AccumulateBy_Hour(t *testing.T) {
  842. ago4h := time.Now().UTC().Truncate(time.Hour).Add(-4 * time.Hour)
  843. ago3h := time.Now().UTC().Truncate(time.Hour).Add(-3 * time.Hour)
  844. ago2h := time.Now().UTC().Truncate(time.Hour).Add(-2 * time.Hour)
  845. ago1h := time.Now().UTC().Truncate(time.Hour).Add(-time.Hour)
  846. currentHour := time.Now().UTC().Truncate(time.Hour)
  847. ago4hAS := NewMockUnitSummaryAllocationSet(ago4h, time.Hour)
  848. ago4hAS.Insert(NewMockUnitSummaryAllocation("4", ago4h, time.Hour, nil))
  849. ago3hAS := NewMockUnitSummaryAllocationSet(ago3h, time.Hour)
  850. ago3hAS.Insert(NewMockUnitSummaryAllocation("a", ago3h, time.Hour, nil))
  851. ago2hAS := NewMockUnitSummaryAllocationSet(ago2h, time.Hour)
  852. ago2hAS.Insert(NewMockUnitSummaryAllocation("", ago2h, time.Hour, nil))
  853. ago1hAS := NewMockUnitSummaryAllocationSet(ago1h, time.Hour)
  854. ago1hAS.Insert(NewMockUnitSummaryAllocation("", ago1h, time.Hour, nil))
  855. currentHourAS := NewMockUnitSummaryAllocationSet(currentHour, time.Hour)
  856. currentHourAS.Insert(NewMockUnitSummaryAllocation("", currentHour, time.Hour, nil))
  857. asr := NewSummaryAllocationSetRange(ago4hAS, ago3hAS, ago2hAS, ago1hAS, currentHourAS)
  858. asr, err := asr.Accumulate(AccumulateOptionHour)
  859. if err != nil {
  860. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  861. }
  862. if len(asr.SummaryAllocationSets) != 5 {
  863. t.Fatalf("expected 5 allocation sets, got:%d", len(asr.SummaryAllocationSets))
  864. }
  865. allocMap := asr.SummaryAllocationSets[0].SummaryAllocations
  866. alloc := allocMap["4"]
  867. if alloc.Minutes() != 60.0 {
  868. t.Errorf("accumulating AllocationSetRange: expected %f minutes; actual %f", 60.0, alloc.Minutes())
  869. }
  870. }
  871. func TestSummaryAllocationSetRange_AccumulateBy_Day_From_Day(t *testing.T) {
  872. ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
  873. ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
  874. ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
  875. yesterday := time.Now().UTC().Truncate(day).Add(-day)
  876. today := time.Now().UTC().Truncate(day)
  877. ago4dSAS := NewMockUnitSummaryAllocationSet(ago4d, day)
  878. ago4dSAS.Insert(NewMockUnitSummaryAllocation("4", ago4d, day, nil))
  879. ago3dSAS := NewMockUnitSummaryAllocationSet(ago3d, day)
  880. ago3dSAS.Insert(NewMockUnitSummaryAllocation("a", ago3d, day, nil))
  881. ago2dSAS := NewMockUnitSummaryAllocationSet(ago2d, day)
  882. ago2dSAS.Insert(NewMockUnitSummaryAllocation("", ago2d, day, nil))
  883. yesterdaySAS := NewMockUnitSummaryAllocationSet(yesterday, day)
  884. yesterdaySAS.Insert(NewMockUnitSummaryAllocation("", yesterday, day, nil))
  885. todaySAS := NewMockUnitSummaryAllocationSet(today, day)
  886. todaySAS.Insert(NewMockUnitSummaryAllocation("", today, day, nil))
  887. asr := NewSummaryAllocationSetRange(ago4dSAS, ago3dSAS, ago2dSAS, yesterdaySAS, todaySAS)
  888. asr, err := asr.Accumulate(AccumulateOptionNone)
  889. if err != nil {
  890. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  891. }
  892. if len(asr.SummaryAllocationSets) != 5 {
  893. t.Fatalf("expected 5 allocation sets, got:%d", len(asr.SummaryAllocationSets))
  894. }
  895. allocMap := asr.SummaryAllocationSets[0].SummaryAllocations
  896. alloc := allocMap["4"]
  897. if alloc.Minutes() != 1440.0 {
  898. t.Errorf("accumulating AllocationSetRange: expected %f minutes; actual %f", 1440.0, alloc.Minutes())
  899. }
  900. }
  901. func TestSummaryAllocationSetRange_AccumulateBy_Day_From_Hours(t *testing.T) {
  902. ago4h := time.Now().UTC().Truncate(time.Hour).Add(-4 * time.Hour)
  903. ago3h := time.Now().UTC().Truncate(time.Hour).Add(-3 * time.Hour)
  904. ago2h := time.Now().UTC().Truncate(time.Hour).Add(-2 * time.Hour)
  905. ago1h := time.Now().UTC().Truncate(time.Hour).Add(-time.Hour)
  906. currentHour := time.Now().UTC().Truncate(time.Hour)
  907. ago4hAS := NewMockUnitSummaryAllocationSet(ago4h, time.Hour)
  908. ago4hAS.Insert(NewMockUnitSummaryAllocation("", ago4h, time.Hour, nil))
  909. ago3hAS := NewMockUnitSummaryAllocationSet(ago3h, time.Hour)
  910. ago3hAS.Insert(NewMockUnitSummaryAllocation("", ago3h, time.Hour, nil))
  911. ago2hAS := NewMockUnitSummaryAllocationSet(ago2h, time.Hour)
  912. ago2hAS.Insert(NewMockUnitSummaryAllocation("", ago2h, time.Hour, nil))
  913. ago1hAS := NewMockUnitSummaryAllocationSet(ago1h, time.Hour)
  914. ago1hAS.Insert(NewMockUnitSummaryAllocation("", ago1h, time.Hour, nil))
  915. currentHourAS := NewMockUnitSummaryAllocationSet(currentHour, time.Hour)
  916. currentHourAS.Insert(NewMockUnitSummaryAllocation("", currentHour, time.Hour, nil))
  917. asr := NewSummaryAllocationSetRange(ago4hAS, ago3hAS, ago2hAS, ago1hAS, currentHourAS)
  918. asr, err := asr.Accumulate(AccumulateOptionDay)
  919. if err != nil {
  920. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  921. }
  922. if len(asr.SummaryAllocationSets) != 1 && len(asr.SummaryAllocationSets) != 2 {
  923. t.Fatalf("expected 1 allocation set, got:%d", len(asr.SummaryAllocationSets))
  924. }
  925. allocMap := asr.SummaryAllocationSets[0].SummaryAllocations
  926. alloc := allocMap["cluster1/namespace1/pod1/container1"]
  927. if alloc.Minutes() > 300.0 {
  928. t.Errorf("accumulating AllocationSetRange: expected %f or less minutes; actual %f", 300.0, alloc.Minutes())
  929. }
  930. }
  931. func TestSummaryAllocationSetRange_AccumulateBy_Week(t *testing.T) {
  932. ago9d := time.Now().UTC().Truncate(day).Add(-9 * day)
  933. ago8d := time.Now().UTC().Truncate(day).Add(-8 * day)
  934. ago7d := time.Now().UTC().Truncate(day).Add(-7 * day)
  935. ago6d := time.Now().UTC().Truncate(day).Add(-6 * day)
  936. ago5d := time.Now().UTC().Truncate(day).Add(-5 * day)
  937. ago4d := time.Now().UTC().Truncate(day).Add(-4 * day)
  938. ago3d := time.Now().UTC().Truncate(day).Add(-3 * day)
  939. ago2d := time.Now().UTC().Truncate(day).Add(-2 * day)
  940. yesterday := time.Now().UTC().Truncate(day).Add(-day)
  941. today := time.Now().UTC().Truncate(day)
  942. ago9dAS := NewMockUnitSummaryAllocationSet(ago9d, day)
  943. ago9dAS.Insert(NewMockUnitSummaryAllocation("4", ago9d, day, nil))
  944. ago8dAS := NewMockUnitSummaryAllocationSet(ago8d, day)
  945. ago8dAS.Insert(NewMockUnitSummaryAllocation("4", ago8d, day, nil))
  946. ago7dAS := NewMockUnitSummaryAllocationSet(ago7d, day)
  947. ago7dAS.Insert(NewMockUnitSummaryAllocation("4", ago7d, day, nil))
  948. ago6dAS := NewMockUnitSummaryAllocationSet(ago6d, day)
  949. ago6dAS.Insert(NewMockUnitSummaryAllocation("4", ago6d, day, nil))
  950. ago5dAS := NewMockUnitSummaryAllocationSet(ago5d, day)
  951. ago5dAS.Insert(NewMockUnitSummaryAllocation("4", ago5d, day, nil))
  952. ago4dAS := NewMockUnitSummaryAllocationSet(ago4d, day)
  953. ago4dAS.Insert(NewMockUnitSummaryAllocation("4", ago4d, day, nil))
  954. ago3dAS := NewMockUnitSummaryAllocationSet(ago3d, day)
  955. ago3dAS.Insert(NewMockUnitSummaryAllocation("4", ago3d, day, nil))
  956. ago2dAS := NewMockUnitSummaryAllocationSet(ago2d, day)
  957. ago2dAS.Insert(NewMockUnitSummaryAllocation("4", ago2d, day, nil))
  958. yesterdayAS := NewMockUnitSummaryAllocationSet(yesterday, day)
  959. yesterdayAS.Insert(NewMockUnitSummaryAllocation("", yesterday, day, nil))
  960. todayAS := NewMockUnitSummaryAllocationSet(today, day)
  961. todayAS.Insert(NewMockUnitSummaryAllocation("4", today, day, nil))
  962. asr := NewSummaryAllocationSetRange(ago9dAS, ago8dAS, ago7dAS, ago6dAS, ago5dAS, ago4dAS, ago3dAS, ago2dAS, yesterdayAS, todayAS)
  963. asr, err := asr.Accumulate(AccumulateOptionWeek)
  964. if err != nil {
  965. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  966. }
  967. if len(asr.SummaryAllocationSets) != 2 && len(asr.SummaryAllocationSets) != 3 {
  968. t.Fatalf("expected 2 allocation sets, got:%d", len(asr.SummaryAllocationSets))
  969. }
  970. for _, as := range asr.SummaryAllocationSets {
  971. if as.Window.Duration() < time.Hour*24 || as.Window.Duration() > time.Hour*24*7 {
  972. t.Fatalf("expected window duration to be between 1 and 7 days, got:%s", as.Window.Duration().String())
  973. }
  974. }
  975. }
  976. func TestSummaryAllocationSetRange_AccumulateBy_Month(t *testing.T) {
  977. prevMonth1stDay := time.Date(2020, 01, 29, 0, 0, 0, 0, time.UTC)
  978. prevMonth2ndDay := time.Date(2020, 01, 30, 0, 0, 0, 0, time.UTC)
  979. prevMonth3ndDay := time.Date(2020, 01, 31, 0, 0, 0, 0, time.UTC)
  980. nextMonth1stDay := time.Date(2020, 02, 01, 0, 0, 0, 0, time.UTC)
  981. prev1AS := NewMockUnitSummaryAllocationSet(prevMonth1stDay, day)
  982. prev1AS.Insert(NewMockUnitSummaryAllocation("", prevMonth1stDay, day, nil))
  983. prev2AS := NewMockUnitSummaryAllocationSet(prevMonth2ndDay, day)
  984. prev2AS.Insert(NewMockUnitSummaryAllocation("", prevMonth2ndDay, day, nil))
  985. prev3AS := NewMockUnitSummaryAllocationSet(prevMonth3ndDay, day)
  986. prev3AS.Insert(NewMockUnitSummaryAllocation("", prevMonth3ndDay, day, nil))
  987. nextAS := NewMockUnitSummaryAllocationSet(nextMonth1stDay, day)
  988. nextAS.Insert(NewMockUnitSummaryAllocation("", nextMonth1stDay, day, nil))
  989. asr := NewSummaryAllocationSetRange(prev1AS, prev2AS, prev3AS, nextAS)
  990. asr, err := asr.Accumulate(AccumulateOptionMonth)
  991. if err != nil {
  992. t.Fatalf("unexpected error calling accumulateBy: %s", err)
  993. }
  994. if len(asr.SummaryAllocationSets) != 2 {
  995. t.Fatalf("expected 2 allocation sets, got:%d", len(asr.SummaryAllocationSets))
  996. }
  997. for _, as := range asr.SummaryAllocationSets {
  998. if as.Window.Duration() < time.Hour*24 || as.Window.Duration() > time.Hour*24*31 {
  999. t.Fatalf("expected window duration to be between 1 and 7 days, got:%s", as.Window.Duration().String())
  1000. }
  1001. }
  1002. }