asset_unmarshal_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. package kubecost
  2. import (
  3. "github.com/opencost/opencost/pkg/util/json"
  4. "testing"
  5. "time"
  6. )
  7. var s = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)
  8. var e = start1.Add(day)
  9. var unmarshalWindow = NewWindow(&s, &e)
  10. func TestAny_Unmarshal(t *testing.T) {
  11. any1 := NewAsset(*unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  12. any1.SetProperties(&AssetProperties{
  13. Name: "any1",
  14. Cluster: "cluster1",
  15. ProviderID: "any1",
  16. })
  17. any1.Cost = 9.0
  18. any1.SetAdjustment(1.0)
  19. bytes, _ := json.Marshal(any1)
  20. var testany Any
  21. any2 := &testany
  22. err := json.Unmarshal(bytes, any2)
  23. // Check if unmarshal was successful
  24. if err != nil {
  25. t.Fatalf("Any Unmarshal: unexpected error: %s", err)
  26. }
  27. // Check if all fields in initial Any equal those in Any from unmarshal
  28. if !any1.properties.Equal(any2.properties) {
  29. t.Fatalf("Any Unmarshal: properties mutated in unmarshal")
  30. }
  31. if !any1.labels.Equal(any2.labels) {
  32. t.Fatalf("Any Unmarshal: labels mutated in unmarshal")
  33. }
  34. if !any1.window.Equal(any2.window) {
  35. t.Fatalf("Any Unmarshal: window mutated in unmarshal")
  36. }
  37. if !any1.start.Equal(any2.start) {
  38. t.Fatalf("Any Unmarshal: start mutated in unmarshal")
  39. }
  40. if !any1.end.Equal(any2.end) {
  41. t.Fatalf("Any Unmarshal: end mutated in unmarshal")
  42. }
  43. if any1.adjustment != any2.adjustment {
  44. t.Fatalf("Any Unmarshal: adjustment mutated in unmarshal")
  45. }
  46. if any1.Cost != any2.Cost {
  47. t.Fatalf("Any Unmarshal: cost mutated in unmarshal")
  48. }
  49. // As a final check, make sure the above checks out
  50. if !any1.Equal(any2) {
  51. t.Fatalf("Any Unmarshal: Any mutated in unmarshal")
  52. }
  53. }
  54. func TestCloud_Unmarshal(t *testing.T) {
  55. cloud1 := NewCloud("Compute", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  56. cloud1.SetLabels(map[string]string{
  57. "namespace": "namespace1",
  58. "env": "env1",
  59. "product": "product1",
  60. })
  61. cloud1.Cost = 10.00
  62. cloud1.Credit = -1.0
  63. bytes, _ := json.Marshal(cloud1)
  64. var testcloud Cloud
  65. cloud2 := &testcloud
  66. err := json.Unmarshal(bytes, cloud2)
  67. // Check if unmarshal was successful
  68. if err != nil {
  69. t.Fatalf("Cloud Unmarshal: unexpected error: %s", err)
  70. }
  71. // Check if all fields in initial Cloud equal those in Cloud from unmarshal
  72. if !cloud1.properties.Equal(cloud2.properties) {
  73. t.Fatalf("Cloud Unmarshal: properties mutated in unmarshal")
  74. }
  75. if !cloud1.labels.Equal(cloud2.labels) {
  76. t.Fatalf("Cloud Unmarshal: labels mutated in unmarshal")
  77. }
  78. if !cloud1.window.Equal(cloud2.window) {
  79. t.Fatalf("Cloud Unmarshal: window mutated in unmarshal")
  80. }
  81. if !cloud1.start.Equal(cloud2.start) {
  82. t.Fatalf("Cloud Unmarshal: start mutated in unmarshal")
  83. }
  84. if !cloud1.end.Equal(cloud2.end) {
  85. t.Fatalf("Cloud Unmarshal: end mutated in unmarshal")
  86. }
  87. if cloud1.adjustment != cloud2.adjustment {
  88. t.Fatalf("Cloud Unmarshal: adjustment mutated in unmarshal")
  89. }
  90. if cloud1.Cost != cloud2.Cost {
  91. t.Fatalf("Cloud Unmarshal: cost mutated in unmarshal")
  92. }
  93. if cloud1.Credit != cloud2.Credit {
  94. t.Fatalf("Cloud Unmarshal: credit mutated in unmarshal")
  95. }
  96. // As a final check, make sure the above checks out
  97. if !cloud1.Equal(cloud2) {
  98. t.Fatalf("Cloud Unmarshal: Cloud mutated in unmarshal")
  99. }
  100. }
  101. func TestClusterManagement_Unmarshal(t *testing.T) {
  102. cm1 := NewClusterManagement(GCPProvider, "cluster1", unmarshalWindow)
  103. cm1.Cost = 9.0
  104. bytes, _ := json.Marshal(cm1)
  105. var testcm ClusterManagement
  106. cm2 := &testcm
  107. err := json.Unmarshal(bytes, cm2)
  108. // Check if unmarshal was successful
  109. if err != nil {
  110. t.Fatalf("ClusterManagement Unmarshal: unexpected error: %s", err)
  111. }
  112. // Check if all fields in initial ClusterManagement equal those in ClusterManagement from unmarshal
  113. if !cm1.properties.Equal(cm2.properties) {
  114. t.Fatalf("ClusterManagement Unmarshal: properties mutated in unmarshal")
  115. }
  116. if !cm1.labels.Equal(cm2.labels) {
  117. t.Fatalf("ClusterManagement Unmarshal: labels mutated in unmarshal")
  118. }
  119. if !cm1.window.Equal(cm2.window) {
  120. t.Fatalf("ClusterManagement Unmarshal: window mutated in unmarshal")
  121. }
  122. if cm1.Cost != cm2.Cost {
  123. t.Fatalf("ClusterManagement Unmarshal: cost mutated in unmarshal")
  124. }
  125. // As a final check, make sure the above checks out
  126. if !cm1.Equal(cm2) {
  127. t.Fatalf("ClusterManagement Unmarshal: ClusterManagement mutated in unmarshal")
  128. }
  129. }
  130. func TestDisk_Unmarshal(t *testing.T) {
  131. hours := unmarshalWindow.Duration().Hours()
  132. disk1 := NewDisk("disk1", "cluster1", "disk1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  133. disk1.ByteHours = 60.0 * gb * hours
  134. disk1.Cost = 4.0
  135. disk1.Local = 1.0
  136. disk1.SetAdjustment(1.0)
  137. disk1.Breakdown = &Breakdown{
  138. Idle: 0.1,
  139. System: 0.2,
  140. User: 0.3,
  141. Other: 0.4,
  142. }
  143. bytes, _ := json.Marshal(disk1)
  144. var testdisk Disk
  145. disk2 := &testdisk
  146. err := json.Unmarshal(bytes, disk2)
  147. // Check if unmarshal was successful
  148. if err != nil {
  149. t.Fatalf("Disk Unmarshal: unexpected error: %s", err)
  150. }
  151. // Check if all fields in initial Disk equal those in Disk from unmarshal
  152. if !disk1.properties.Equal(disk2.properties) {
  153. t.Fatalf("Disk Unmarshal: properties mutated in unmarshal")
  154. }
  155. if !disk1.labels.Equal(disk2.labels) {
  156. t.Fatalf("Disk Unmarshal: labels mutated in unmarshal")
  157. }
  158. if !disk1.window.Equal(disk2.window) {
  159. t.Fatalf("Disk Unmarshal: window mutated in unmarshal")
  160. }
  161. if !disk1.Breakdown.Equal(disk2.Breakdown) {
  162. t.Fatalf("Disk Unmarshal: Breakdown mutated in unmarshal")
  163. }
  164. if !disk1.start.Equal(disk2.start) {
  165. t.Fatalf("Disk Unmarshal: start mutated in unmarshal")
  166. }
  167. if !disk1.end.Equal(disk2.end) {
  168. t.Fatalf("Disk Unmarshal: end mutated in unmarshal")
  169. }
  170. if disk1.adjustment != disk2.adjustment {
  171. t.Fatalf("Disk Unmarshal: adjustment mutated in unmarshal")
  172. }
  173. if disk1.ByteHours != disk2.ByteHours {
  174. t.Fatalf("Disk Unmarshal: ByteHours mutated in unmarshal")
  175. }
  176. if disk1.Cost != disk2.Cost {
  177. t.Fatalf("Disk Unmarshal: cost mutated in unmarshal")
  178. }
  179. // Local from Disk is not marhsaled, and cannot be calculated from marshaled values.
  180. // Currently, it is just ignored and not set in the resulting unmarshal to Disk. Thus,
  181. // it is also ignored in this test; be aware that this means a resulting Disk from an
  182. // unmarshal is therefore NOT equal to the originally marshaled Disk.
  183. }
  184. func TestNetwork_Unmarshal(t *testing.T) {
  185. network1 := NewNetwork("network1", "cluster1", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  186. network1.Cost = 4.0
  187. network1.SetAdjustment(1.0)
  188. bytes, _ := json.Marshal(network1)
  189. var testnw Network
  190. network2 := &testnw
  191. err := json.Unmarshal(bytes, network2)
  192. // Check if unmarshal was successful
  193. if err != nil {
  194. t.Fatalf("Network Unmarshal: unexpected error: %s", err)
  195. }
  196. // Check if all fields in initial Network equal those in Network from unmarshal
  197. if !network1.properties.Equal(network2.properties) {
  198. t.Fatalf("Network Unmarshal: properties mutated in unmarshal")
  199. }
  200. if !network1.labels.Equal(network2.labels) {
  201. t.Fatalf("Network Unmarshal: labels mutated in unmarshal")
  202. }
  203. if !network1.window.Equal(network2.window) {
  204. t.Fatalf("Network Unmarshal: window mutated in unmarshal")
  205. }
  206. if !network1.start.Equal(network2.start) {
  207. t.Fatalf("Network Unmarshal: start mutated in unmarshal")
  208. }
  209. if !network1.end.Equal(network2.end) {
  210. t.Fatalf("Network Unmarshal: end mutated in unmarshal")
  211. }
  212. if network1.adjustment != network2.adjustment {
  213. t.Fatalf("Network Unmarshal: adjustment mutated in unmarshal")
  214. }
  215. if network1.Cost != network2.Cost {
  216. t.Fatalf("Network Unmarshal: cost mutated in unmarshal")
  217. }
  218. // As a final check, make sure the above checks out
  219. if !network1.Equal(network2) {
  220. t.Fatalf("Network Unmarshal: Network mutated in unmarshal")
  221. }
  222. }
  223. func TestNode_Unmarshal(t *testing.T) {
  224. hours := unmarshalWindow.Duration().Hours()
  225. node1 := NewNode("node1", "cluster1", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  226. node1.CPUCoreHours = 1.0 * hours
  227. node1.RAMByteHours = 2.0 * gb * hours
  228. node1.GPUHours = 0.0 * hours
  229. node1.GPUCost = 0.0
  230. node1.CPUCost = 8.0
  231. node1.RAMCost = 4.0
  232. node1.Discount = 0.3
  233. node1.CPUBreakdown = &Breakdown{
  234. Idle: 0.6,
  235. System: 0.2,
  236. User: 0.2,
  237. Other: 0.0,
  238. }
  239. node1.RAMBreakdown = &Breakdown{
  240. Idle: 0.6,
  241. System: 0.2,
  242. User: 0.2,
  243. Other: 0.0,
  244. }
  245. node1.SetAdjustment(1.6)
  246. bytes, _ := json.Marshal(node1)
  247. var testnode Node
  248. node2 := &testnode
  249. err := json.Unmarshal(bytes, node2)
  250. // Check if unmarshal was successful
  251. if err != nil {
  252. t.Fatalf("Node Unmarshal: unexpected error: %s", err)
  253. }
  254. // Check if all fields in initial Node equal those in Node from unmarshal
  255. if !node1.properties.Equal(node2.properties) {
  256. t.Fatalf("Node Unmarshal: properties mutated in unmarshal")
  257. }
  258. if !node1.labels.Equal(node2.labels) {
  259. t.Fatalf("Node Unmarshal: labels mutated in unmarshal")
  260. }
  261. if !node1.window.Equal(node2.window) {
  262. t.Fatalf("Node Unmarshal: window mutated in unmarshal")
  263. }
  264. if !node1.CPUBreakdown.Equal(node2.CPUBreakdown) {
  265. t.Fatalf("Node Unmarshal: CPUBreakdown mutated in unmarshal")
  266. }
  267. if !node1.RAMBreakdown.Equal(node2.RAMBreakdown) {
  268. t.Fatalf("Node Unmarshal: RAMBreakdown mutated in unmarshal")
  269. }
  270. if !node1.start.Equal(node2.start) {
  271. t.Fatalf("Node Unmarshal: start mutated in unmarshal")
  272. }
  273. if !node1.end.Equal(node2.end) {
  274. t.Fatalf("Node Unmarshal: end mutated in unmarshal")
  275. }
  276. if node1.adjustment != node2.adjustment {
  277. t.Fatalf("Node Unmarshal: adjustment mutated in unmarshal")
  278. }
  279. if node1.NodeType != node2.NodeType {
  280. t.Fatalf("Node Unmarshal: NodeType mutated in unmarshal")
  281. }
  282. if node1.CPUCoreHours != node2.CPUCoreHours {
  283. t.Fatalf("Node Unmarshal: CPUCoreHours mutated in unmarshal")
  284. }
  285. if node1.RAMByteHours != node2.RAMByteHours {
  286. t.Fatalf("Node Unmarshal: RAMByteHours mutated in unmarshal")
  287. }
  288. if node1.GPUHours != node2.GPUHours {
  289. t.Fatalf("Node Unmarshal: GPUHours mutated in unmarshal")
  290. }
  291. if node1.CPUCost != node2.CPUCost {
  292. t.Fatalf("Node Unmarshal: CPUCost mutated in unmarshal")
  293. }
  294. if node1.GPUCost != node2.GPUCost {
  295. t.Fatalf("Node Unmarshal: GPUCost mutated in unmarshal")
  296. }
  297. if node1.GPUCount != node2.GPUCount {
  298. t.Fatalf("Node Unmarshal: GPUCount mutated in unmarshal")
  299. }
  300. if node1.RAMCost != node2.RAMCost {
  301. t.Fatalf("Node Unmarshal: RAMCost mutated in unmarshal")
  302. }
  303. if node1.Discount != node2.Discount {
  304. t.Fatalf("Node Unmarshal: Discount mutated in unmarshal")
  305. }
  306. if node1.Preemptible != node2.Preemptible {
  307. t.Fatalf("Node Unmarshal: Preemptible mutated in unmarshal")
  308. }
  309. // As a final check, make sure the above checks out
  310. if !node1.Equal(node2) {
  311. t.Fatalf("Node Unmarshal: Node mutated in unmarshal")
  312. }
  313. }
  314. func TestLoadBalancer_Unmarshal(t *testing.T) {
  315. lb1 := NewLoadBalancer("loadbalancer1", "cluster1", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  316. lb1.Cost = 12.0
  317. lb1.SetAdjustment(4.0)
  318. bytes, _ := json.Marshal(lb1)
  319. var testlb LoadBalancer
  320. lb2 := &testlb
  321. err := json.Unmarshal(bytes, lb2)
  322. // Check if unmarshal was successful
  323. if err != nil {
  324. t.Fatalf("LoadBalancer Unmarshal: unexpected error: %s", err)
  325. }
  326. // Check if all fields in initial LoadBalancer equal those in LoadBalancer from unmarshal
  327. if !lb1.properties.Equal(lb2.properties) {
  328. t.Fatalf("LoadBalancer Unmarshal: properties mutated in unmarshal")
  329. }
  330. if !lb1.labels.Equal(lb2.labels) {
  331. t.Fatalf("LoadBalancer Unmarshal: labels mutated in unmarshal")
  332. }
  333. if !lb1.window.Equal(lb2.window) {
  334. t.Fatalf("LoadBalancer Unmarshal: window mutated in unmarshal")
  335. }
  336. if !lb1.start.Equal(lb2.start) {
  337. t.Fatalf("LoadBalancer Unmarshal: start mutated in unmarshal")
  338. }
  339. if !lb1.end.Equal(lb2.end) {
  340. t.Fatalf("LoadBalancer Unmarshal: end mutated in unmarshal")
  341. }
  342. if lb1.adjustment != lb2.adjustment {
  343. t.Fatalf("LoadBalancer Unmarshal: adjustment mutated in unmarshal")
  344. }
  345. if lb1.Cost != lb2.Cost {
  346. t.Fatalf("LoadBalancer Unmarshal: cost mutated in unmarshal")
  347. }
  348. // As a final check, make sure the above checks out
  349. if !lb1.Equal(lb2) {
  350. t.Fatalf("LoadBalancer Unmarshal: LoadBalancer mutated in unmarshal")
  351. }
  352. }
  353. func TestSharedAsset_Unmarshal(t *testing.T) {
  354. sa1 := NewSharedAsset("sharedasset1", unmarshalWindow)
  355. sa1.Cost = 7.0
  356. bytes, _ := json.Marshal(sa1)
  357. var testsa SharedAsset
  358. sa2 := &testsa
  359. err := json.Unmarshal(bytes, sa2)
  360. // Check if unmarshal was successful
  361. if err != nil {
  362. t.Fatalf("SharedAsset Unmarshal: unexpected error: %s", err)
  363. }
  364. // Check if all fields in initial SharedAsset equal those in SharedAsset from unmarshal
  365. if !sa1.properties.Equal(sa2.properties) {
  366. t.Fatalf("SharedAsset Unmarshal: properties mutated in unmarshal")
  367. }
  368. if !sa1.labels.Equal(sa2.labels) {
  369. t.Fatalf("SharedAsset Unmarshal: labels mutated in unmarshal")
  370. }
  371. if !sa1.window.Equal(sa2.window) {
  372. t.Fatalf("SharedAsset Unmarshal: window mutated in unmarshal")
  373. }
  374. if sa1.Cost != sa2.Cost {
  375. t.Fatalf("SharedAsset Unmarshal: cost mutated in unmarshal")
  376. }
  377. // As a final check, make sure the above checks out
  378. if !sa1.Equal(sa2) {
  379. t.Fatalf("SharedAsset Unmarshal: SharedAsset mutated in unmarshal")
  380. }
  381. }
  382. func TestAssetset_Unmarshal(t *testing.T) {
  383. var s time.Time
  384. var e time.Time
  385. unmarshalWindow := NewWindow(&s, &e)
  386. any := NewAsset(*unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  387. cloud := NewCloud("Compute", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  388. cm := NewClusterManagement(GCPProvider, "cluster1", unmarshalWindow)
  389. disk := NewDisk("disk1", "cluster1", "disk1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  390. network := NewNetwork("network1", "cluster1", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  391. node := NewNode("node1", "cluster1", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  392. lb := NewLoadBalancer("loadbalancer1", "cluster1", "provider1", *unmarshalWindow.start, *unmarshalWindow.end, unmarshalWindow)
  393. sa := NewSharedAsset("sharedasset1", unmarshalWindow)
  394. assetList := []Asset{any, cloud, cm, disk, network, node, lb, sa}
  395. assetset := NewAssetSet(s, e, assetList...)
  396. bytes, _ := json.Marshal(assetset)
  397. var assetSetResponse AssetSetResponse
  398. assetUnmarshalResponse := &assetSetResponse
  399. err := json.Unmarshal(bytes, assetUnmarshalResponse)
  400. // Check if unmarshal was successful
  401. if err != nil {
  402. t.Fatalf("AssetSet Unmarshal: unexpected error: %s", err)
  403. }
  404. // For each asset in unmarshaled AssetSetResponse, check if it is equal to the corresponding AssetSet asset
  405. for key, asset := range assetset.assets {
  406. if unmarshaledAsset, exists := assetUnmarshalResponse.Assets[key]; exists {
  407. // As Disk is not marshaled with all fields, the resultant Disk will be unequal. Test all fields we have instead.
  408. if unmarshaledAsset.Type().String() == "Disk" {
  409. udiskEq := func(d1 Asset, d2 Asset) bool {
  410. asset, _ := asset.(*Disk)
  411. unmarshaledAsset, _ := unmarshaledAsset.(*Disk)
  412. if !asset.Labels().Equal(unmarshaledAsset.Labels()) {
  413. return false
  414. }
  415. if !asset.Properties().Equal(unmarshaledAsset.Properties()) {
  416. return false
  417. }
  418. if !asset.Start().Equal(unmarshaledAsset.Start()) {
  419. return false
  420. }
  421. if !asset.End().Equal(unmarshaledAsset.End()) {
  422. return false
  423. }
  424. if !asset.window.Equal(unmarshaledAsset.window) {
  425. return false
  426. }
  427. if asset.adjustment != unmarshaledAsset.adjustment {
  428. return false
  429. }
  430. if asset.Cost != unmarshaledAsset.Cost {
  431. return false
  432. }
  433. if asset.ByteHours != unmarshaledAsset.ByteHours {
  434. return false
  435. }
  436. if !asset.Breakdown.Equal(unmarshaledAsset.Breakdown) {
  437. return false
  438. }
  439. return true
  440. }
  441. if res := udiskEq(asset, unmarshaledAsset); !res {
  442. t.Fatalf("AssetSet Unmarshal: asset at key '%s' from unmarshaled AssetSetResponse does not match corresponding asset from AssetSet", key)
  443. }
  444. } else {
  445. if !asset.Equal(unmarshaledAsset) {
  446. t.Fatalf("AssetSet Unmarshal: asset at key '%s' from unmarshaled AssetSetResponse does not match corresponding asset from AssetSet", key)
  447. }
  448. }
  449. } else {
  450. t.Fatalf("AssetSet Unmarshal: key '%s' from marshaled AssetSet does not exist in AssetSetResponse", key)
  451. }
  452. }
  453. }