costmodel_test.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package costmodel
  2. import (
  3. "testing"
  4. "github.com/opencost/opencost/core/pkg/util"
  5. )
  6. func Test_CostData_GetController_CronJob(t *testing.T) {
  7. cases := []struct {
  8. name string
  9. cd CostData
  10. expectedName string
  11. expectedKind string
  12. expectedHasController bool
  13. }{
  14. {
  15. name: "batch/v1beta1 CronJob Job name",
  16. cd: CostData{
  17. // batch/v1beta1 CronJobs create Jobs with a 10 character
  18. // timestamp appended to the end of the name.
  19. //
  20. // It looks like this:
  21. // CronJob: cronjob-1
  22. // Job: cronjob-1-1651057200
  23. // Pod: cronjob-1-1651057200-mf5c9
  24. Jobs: []string{"cronjob-1-1651057200"},
  25. },
  26. expectedName: "cronjob-1",
  27. expectedKind: "job",
  28. expectedHasController: true,
  29. },
  30. {
  31. name: "batch/v1 CronJob Job name",
  32. cd: CostData{
  33. // batch/v1CronJobs create Jobs with an 8 character timestamp
  34. // appended to the end of the name.
  35. //
  36. // It looks like this:
  37. // CronJob: cj-v1
  38. // Job: cj-v1-27517770
  39. // Pod: cj-v1-27517770-xkrgn
  40. Jobs: []string{"cj-v1-27517770"},
  41. },
  42. expectedName: "cj-v1",
  43. expectedKind: "job",
  44. expectedHasController: true,
  45. },
  46. }
  47. for _, c := range cases {
  48. t.Run(c.name, func(t *testing.T) {
  49. name, kind, hasController := c.cd.GetController()
  50. if name != c.expectedName {
  51. t.Errorf("Name mismatch. Expected: %s. Got: %s", c.expectedName, name)
  52. }
  53. if kind != c.expectedKind {
  54. t.Errorf("Kind mismatch. Expected: %s. Got: %s", c.expectedKind, kind)
  55. }
  56. if hasController != c.expectedHasController {
  57. t.Errorf("HasController mismatch. Expected: %t. Got: %t", c.expectedHasController, hasController)
  58. }
  59. })
  60. }
  61. }
  62. func Test_getContainerAllocation(t *testing.T) {
  63. cases := []struct {
  64. name string
  65. cd CostData
  66. expectedCPUAllocation []*util.Vector
  67. expectedRAMAllocation []*util.Vector
  68. }{
  69. {
  70. name: "Requests greater than usage",
  71. cd: CostData{
  72. CPUReq: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  73. CPUUsed: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  74. RAMReq: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  75. RAMUsed: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  76. },
  77. expectedCPUAllocation: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  78. expectedRAMAllocation: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  79. },
  80. {
  81. name: "Requests less than usage",
  82. cd: CostData{
  83. CPUReq: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  84. CPUUsed: []*util.Vector{{Value: 2.2, Timestamp: 1686929350}},
  85. RAMReq: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  86. RAMUsed: []*util.Vector{{Value: 75000000, Timestamp: 1686929350}},
  87. },
  88. expectedCPUAllocation: []*util.Vector{{Value: 2.2, Timestamp: 1686929350}},
  89. expectedRAMAllocation: []*util.Vector{{Value: 75000000, Timestamp: 1686929350}},
  90. },
  91. {
  92. // Expected behavior for getContainerAllocation is to always use the
  93. // highest Timestamp value. The significance of 10 seconds comes
  94. // from the current default in ApplyVectorOp() in
  95. // pkg/util/vector.go.
  96. name: "Mismatched timestamps less than 10 seconds apart",
  97. cd: CostData{
  98. CPUReq: []*util.Vector{{Value: 1.0, Timestamp: 1686929354}},
  99. CPUUsed: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  100. RAMReq: []*util.Vector{{Value: 10000000, Timestamp: 1686929354}},
  101. RAMUsed: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  102. },
  103. expectedCPUAllocation: []*util.Vector{{Value: 1.0, Timestamp: 1686929354}},
  104. expectedRAMAllocation: []*util.Vector{{Value: 10000000, Timestamp: 1686929354}},
  105. },
  106. {
  107. // Expected behavior for getContainerAllocation is to always use the
  108. // hightest Timestamp value. The significance of 10 seconds comes
  109. // from the current default in ApplyVectorOp() in
  110. // pkg/util/vector.go.
  111. name: "Mismatched timestamps greater than 10 seconds apart",
  112. cd: CostData{
  113. CPUReq: []*util.Vector{{Value: 1.0, Timestamp: 1686929399}},
  114. CPUUsed: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  115. RAMReq: []*util.Vector{{Value: 10000000, Timestamp: 1686929399}},
  116. RAMUsed: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  117. },
  118. expectedCPUAllocation: []*util.Vector{{Value: 1.0, Timestamp: 1686929399}},
  119. expectedRAMAllocation: []*util.Vector{{Value: 10000000, Timestamp: 1686929399}},
  120. },
  121. {
  122. name: "Requests has no values",
  123. cd: CostData{
  124. CPUReq: []*util.Vector{{Value: 0, Timestamp: 0}},
  125. CPUUsed: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  126. RAMReq: []*util.Vector{{Value: 0, Timestamp: 0}},
  127. RAMUsed: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  128. },
  129. expectedCPUAllocation: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  130. expectedRAMAllocation: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  131. },
  132. {
  133. name: "Usage has no values",
  134. cd: CostData{
  135. CPUReq: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  136. CPUUsed: []*util.Vector{{Value: 0, Timestamp: 0}},
  137. RAMReq: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  138. RAMUsed: []*util.Vector{{Value: 0, Timestamp: 0}},
  139. },
  140. expectedCPUAllocation: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  141. expectedRAMAllocation: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  142. },
  143. {
  144. // WRN Log should be thrown
  145. name: "Both have no values",
  146. cd: CostData{
  147. CPUReq: []*util.Vector{{Value: 0, Timestamp: 0}},
  148. CPUUsed: []*util.Vector{{Value: 0, Timestamp: 0}},
  149. RAMReq: []*util.Vector{{Value: 0, Timestamp: 0}},
  150. RAMUsed: []*util.Vector{{Value: 0, Timestamp: 0}},
  151. },
  152. expectedCPUAllocation: []*util.Vector{{Value: 0, Timestamp: 0}},
  153. expectedRAMAllocation: []*util.Vector{{Value: 0, Timestamp: 0}},
  154. },
  155. {
  156. name: "Requests is Nil",
  157. cd: CostData{
  158. CPUReq: []*util.Vector{nil},
  159. CPUUsed: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  160. RAMReq: []*util.Vector{nil},
  161. RAMUsed: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  162. },
  163. expectedCPUAllocation: []*util.Vector{{Value: .01, Timestamp: 1686929350}},
  164. expectedRAMAllocation: []*util.Vector{{Value: 5500000, Timestamp: 1686929350}},
  165. },
  166. {
  167. name: "Usage is nil",
  168. cd: CostData{
  169. CPUReq: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  170. CPUUsed: []*util.Vector{nil},
  171. RAMReq: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  172. RAMUsed: []*util.Vector{nil},
  173. },
  174. expectedCPUAllocation: []*util.Vector{{Value: 1.0, Timestamp: 1686929350}},
  175. expectedRAMAllocation: []*util.Vector{{Value: 10000000, Timestamp: 1686929350}},
  176. },
  177. }
  178. for _, c := range cases {
  179. t.Run(c.name, func(t *testing.T) {
  180. cpuAllocation := getContainerAllocation(c.cd.CPUReq[0], c.cd.CPUUsed[0], "CPU")
  181. ramAllocation := getContainerAllocation(c.cd.RAMReq[0], c.cd.RAMUsed[0], "RAM")
  182. if cpuAllocation[0].Value != c.expectedCPUAllocation[0].Value {
  183. t.Errorf("CPU Allocation mismatch. Expected Value: %f. Got: %f", cpuAllocation[0].Value, c.expectedCPUAllocation[0].Value)
  184. }
  185. if cpuAllocation[0].Timestamp != c.expectedCPUAllocation[0].Timestamp {
  186. t.Errorf("CPU Allocation mismatch. Expected Timestamp: %f. Got: %f", cpuAllocation[0].Timestamp, c.expectedCPUAllocation[0].Timestamp)
  187. }
  188. if ramAllocation[0].Value != c.expectedRAMAllocation[0].Value {
  189. t.Errorf("RAM Allocation mismatch. Expected Value: %f. Got: %f", ramAllocation[0].Value, c.expectedRAMAllocation[0].Value)
  190. }
  191. if ramAllocation[0].Timestamp != c.expectedRAMAllocation[0].Timestamp {
  192. t.Errorf("RAM Allocation mismatch. Expected Timestamp: %f. Got: %f", ramAllocation[0].Timestamp, c.expectedRAMAllocation[0].Timestamp)
  193. }
  194. })
  195. }
  196. }