summaryallocation_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package kubecost
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/opencost/opencost/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. }