opencost_codecs_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. package opencost
  2. import (
  3. "bytes"
  4. "io"
  5. "testing"
  6. "time"
  7. )
  8. type UnmarshalFunc func(BingenUnmarshalable, []byte) error
  9. func RunAllocation_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  10. // TODO niko
  11. }
  12. func RunAllocationSet_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  13. end := time.Now().UTC().Truncate(day)
  14. start := end.Add(-day * 10)
  15. for start.Before(end) {
  16. set0 := GenerateMockAllocationSetClusterIdle(start)
  17. bytes, err := set0.MarshalBinary()
  18. if err != nil {
  19. t.Fatalf("Failed to AllocationSet.MarshalBinary: %s", err)
  20. return
  21. }
  22. set1 := new(AllocationSet)
  23. err = unmarshal(set1, bytes)
  24. if err != nil {
  25. t.Fatalf("Failed to AllocationSet.UnmarshalBinary: %s", err)
  26. return
  27. }
  28. for key, alloc := range set1.Allocations {
  29. other, ok := set0.Allocations[key]
  30. if !ok {
  31. t.Fatalf("Failed to match Allocation for key: %s", key)
  32. return
  33. }
  34. if !alloc.Equal(other) {
  35. t.Fatalf("allocations for key: %s did not match", key)
  36. }
  37. }
  38. start = start.Add(day)
  39. }
  40. }
  41. func BenchmarkAllocationSetRange_BinaryEncoding(b *testing.B) {
  42. endYesterday := time.Now().UTC().Truncate(day)
  43. startYesterday := endYesterday.Add(-day)
  44. startD2 := startYesterday
  45. startD1 := startD2.Add(-day)
  46. startD0 := startD1.Add(-day)
  47. var asr0, asr1 *AllocationSetRange
  48. var bs []byte
  49. var err error
  50. asr0 = NewAllocationSetRange(
  51. GenerateMockAllocationSetClusterIdle(startD0),
  52. GenerateMockAllocationSetClusterIdle(startD1),
  53. GenerateMockAllocationSetClusterIdle(startD2),
  54. )
  55. for it := 0; it < b.N; it++ {
  56. bs, err = asr0.MarshalBinary()
  57. if err != nil {
  58. b.Fatalf("AllocationSetRange.Binary: unexpected error: %s", err)
  59. return
  60. }
  61. asr1 = &AllocationSetRange{}
  62. err = asr1.UnmarshalBinary(bs)
  63. if err != nil {
  64. b.Fatalf("AllocationSetRange.Binary: unexpected error: %s", err)
  65. return
  66. }
  67. if asr0.Length() != asr1.Length() {
  68. b.Fatalf("AllocationSetRange.Binary: expected %d; found %d", asr0.Length(), asr1.Length())
  69. }
  70. if !asr0.Window().Equal(asr1.Window()) {
  71. b.Fatalf("AllocationSetRange.Binary: expected %s; found %s", asr0.Window(), asr1.Window())
  72. }
  73. for i, as0 := range asr0.Allocations {
  74. as1, err := asr1.Get(i)
  75. if err != nil {
  76. b.Fatalf("AllocationSetRange.Binary: unexpected error: %s", err)
  77. }
  78. if as0.Length() != as1.Length() {
  79. b.Fatalf("AllocationSetRange.Binary: expected %d; found %d", as0.Length(), as1.Length())
  80. }
  81. if !as0.Window.Equal(as1.Window) {
  82. b.Fatalf("AllocationSetRange.Binary: expected %s; found %s", as0.Window, as1.Window)
  83. }
  84. for k, a0 := range as0.Allocations {
  85. a1 := as1.Get(k)
  86. if a1 == nil {
  87. b.Fatalf("AllocationSetRange.Binary: missing Allocation: %s", a0)
  88. }
  89. if !a0.Equal(a1) {
  90. b.Fatalf("AllocationSetRange.Binary: unequal Allocations \"%s\": expected %s; found %s", k, a0, a1)
  91. }
  92. }
  93. }
  94. }
  95. }
  96. func RunAllocationSetRange_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  97. endYesterday := time.Now().UTC().Truncate(day)
  98. startYesterday := endYesterday.Add(-day)
  99. startD2 := startYesterday
  100. startD1 := startD2.Add(-day)
  101. startD0 := startD1.Add(-day)
  102. var asr0, asr1 *AllocationSetRange
  103. var err error
  104. asr0 = NewAllocationSetRange(
  105. GenerateMockAllocationSetClusterIdle(startD0),
  106. GenerateMockAllocationSetClusterIdle(startD1),
  107. GenerateMockAllocationSetClusterIdle(startD2),
  108. )
  109. asrSets0 := [][]byte{}
  110. for _, as := range asr0.Allocations {
  111. bytes, err := as.MarshalBinary()
  112. if err != nil {
  113. t.Fatalf("Failed to marshal allocation set into []byte: %s", err)
  114. return
  115. }
  116. asrSets0 = append(asrSets0, bytes)
  117. }
  118. asrSets1 := []*AllocationSet{}
  119. for _, bytes := range asrSets0 {
  120. allocSet := new(AllocationSet)
  121. err = unmarshal(allocSet, bytes)
  122. if err != nil {
  123. t.Fatalf("AllocationSet.Binary: unexpected error: %s", err)
  124. return
  125. }
  126. asrSets1 = append(asrSets1, allocSet)
  127. }
  128. asr1 = NewAllocationSetRange(asrSets1...)
  129. if asr0.Length() != asr1.Length() {
  130. t.Fatalf("AllocationSetRange.Binary: expected %d; found %d", asr0.Length(), asr1.Length())
  131. }
  132. if !asr0.Window().Equal(asr1.Window()) {
  133. t.Fatalf("AllocationSetRange.Binary: expected %s; found %s", asr0.Window(), asr1.Window())
  134. }
  135. for i, as0 := range asr0.Allocations {
  136. as1, err := asr1.Get(i)
  137. if err != nil {
  138. t.Fatalf("AllocationSetRange.Binary: unexpected error: %s", err)
  139. }
  140. if as0.Length() != as1.Length() {
  141. t.Fatalf("AllocationSetRange.Binary: expected %d; found %d", as0.Length(), as1.Length())
  142. }
  143. if !as0.Window.Equal(as1.Window) {
  144. t.Fatalf("AllocationSetRange.Binary: expected %s; found %s", as0.Window, as1.Window)
  145. }
  146. for k, a0 := range as0.Allocations {
  147. a1 := as1.Get(k)
  148. if a1 == nil {
  149. t.Fatalf("AllocationSetRange.Binary: missing Allocation: %s", a0)
  150. }
  151. // TODO Sean: fix JSON marshaling of PVs
  152. a1.PVs = a0.PVs
  153. if !a0.Equal(a1) {
  154. t.Fatalf("AllocationSetRange.Binary: unequal Allocations \"%s\": expected \"%s\"; found \"%s\"", k, a0, a1)
  155. }
  156. }
  157. }
  158. }
  159. func RunAny_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  160. start := time.Date(2020, time.September, 16, 0, 0, 0, 0, time.UTC)
  161. end := start.Add(24 * time.Hour)
  162. window := NewWindow(&start, &end)
  163. var a0, a1 *Any
  164. var bs []byte
  165. var err error
  166. a0 = NewAsset(*window.start, *window.end, window)
  167. a0.SetProperties(&AssetProperties{
  168. Name: "any1",
  169. Cluster: "cluster1",
  170. ProviderID: "世界",
  171. })
  172. a0.Cost = 123.45
  173. a0.SetAdjustment(1.23)
  174. bs, err = a0.MarshalBinary()
  175. if err != nil {
  176. t.Fatalf("Any.Binary: unexpected error: %s", err)
  177. }
  178. a1 = &Any{}
  179. err = unmarshal(a1, bs)
  180. if err != nil {
  181. t.Fatalf("Any.Binary: unexpected error: %s", err)
  182. }
  183. if a1.Properties.Name != a0.Properties.Name {
  184. t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties.Name, a1.Properties.Name)
  185. }
  186. if a1.Properties.Cluster != a0.Properties.Cluster {
  187. t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties.Cluster, a1.Properties.Cluster)
  188. }
  189. if a1.Properties.ProviderID != a0.Properties.ProviderID {
  190. t.Fatalf("Any.Binary: expected %s, found %s", a0.Properties.ProviderID, a1.Properties.ProviderID)
  191. }
  192. if a1.Adjustment != a0.Adjustment {
  193. t.Fatalf("Any.Binary: expected %f, found %f", a0.Adjustment, a1.Adjustment)
  194. }
  195. if a1.TotalCost() != a0.TotalCost() {
  196. t.Fatalf("Any.Binary: expected %f, found %f", a0.TotalCost(), a1.TotalCost())
  197. }
  198. if !a1.Window.Equal(a0.Window) {
  199. t.Fatalf("Any.Binary: expected %s, found %s", a0.Window, a1.Window)
  200. }
  201. }
  202. func RunAsset_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  203. // TODO niko
  204. }
  205. func RunAssetSet_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  206. // TODO niko
  207. }
  208. func RunAssetSetRange_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  209. endYesterday := time.Now().UTC().Truncate(day)
  210. startYesterday := endYesterday.Add(-day)
  211. startD2 := startYesterday
  212. startD1 := startD2.Add(-day)
  213. startD0 := startD1.Add(-day)
  214. var asr0, asr1 *AssetSetRange
  215. var bs []byte
  216. var err error
  217. asr0 = NewAssetSetRange(
  218. GenerateMockAssetSet(startD0, day),
  219. GenerateMockAssetSet(startD1, day),
  220. GenerateMockAssetSet(startD2, day),
  221. )
  222. bs, err = asr0.MarshalBinary()
  223. if err != nil {
  224. t.Fatalf("AssetSetRange.Binary: unexpected error: %s", err)
  225. return
  226. }
  227. asr1 = &AssetSetRange{}
  228. err = unmarshal(asr1, bs)
  229. if err != nil {
  230. t.Fatalf("AssetSetRange.Binary: unexpected error: %s", err)
  231. return
  232. }
  233. if asr0.Length() != asr1.Length() {
  234. t.Fatalf("AssetSetRange.Binary: expected %d; found %d", asr0.Length(), asr1.Length())
  235. }
  236. if !asr0.Window().Equal(asr1.Window()) {
  237. t.Fatalf("AssetSetRange.Binary: expected %s; found %s", asr0.Window(), asr1.Window())
  238. }
  239. for i, as0 := range asr0.Assets {
  240. as1, err := asr1.Get(i)
  241. if err != nil {
  242. t.Fatalf("AssetSetRange.Binary: unexpected error: %s", err)
  243. }
  244. if as0.Length() != as1.Length() {
  245. t.Fatalf("AssetSetRange.Binary: expected %d; found %d", as0.Length(), as1.Length())
  246. }
  247. if !as0.Window.Equal(as1.Window) {
  248. t.Fatalf("AssetSetRange.Binary: expected %s; found %s", as0.Window, as1.Window)
  249. }
  250. for k, a0 := range as0.Assets {
  251. a1, ok := as1.Get(k)
  252. if !ok {
  253. t.Fatalf("AssetSetRange.Binary: missing Asset: %s", a0)
  254. }
  255. if !a0.Equal(a1) {
  256. t.Fatalf("AssetSetRange.Binary: unequal Assets \"%s\": expected %s; found %s", k, a0, a1)
  257. }
  258. }
  259. }
  260. }
  261. func RunBreakdown_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  262. var b0, b1 *Breakdown
  263. var bs []byte
  264. var err error
  265. b0 = &Breakdown{
  266. Idle: 0.75,
  267. Other: 0.1,
  268. System: 0.0,
  269. User: 0.15,
  270. }
  271. bs, err = b0.MarshalBinary()
  272. if err != nil {
  273. t.Fatalf("Breakdown.Binary: unexpected error: %s", err)
  274. }
  275. b1 = &Breakdown{}
  276. err = unmarshal(b1, bs)
  277. if err != nil {
  278. t.Fatalf("Breakdown.Binary: unexpected error: %s", err)
  279. }
  280. if b1.Idle != b0.Idle {
  281. t.Fatalf("Breakdown.Binary: expected %f, found %f", b0.Idle, b1.Idle)
  282. }
  283. if b1.Other != b0.Other {
  284. t.Fatalf("Breakdown.Binary: expected %f, found %f", b0.Other, b1.Other)
  285. }
  286. if b1.System != b0.System {
  287. t.Fatalf("Breakdown.Binary: expected %f, found %f", b0.System, b1.System)
  288. }
  289. if b1.User != b0.User {
  290. t.Fatalf("Breakdown.Binary: expected %f, found %f", b0.User, b1.User)
  291. }
  292. }
  293. func RunCloudAny_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  294. ws := time.Date(2020, time.September, 16, 0, 0, 0, 0, time.UTC)
  295. we := ws.Add(24 * time.Hour)
  296. window := NewWindow(&ws, &we)
  297. var a0, a1 *Cloud
  298. var bs []byte
  299. var err error
  300. a0 = NewCloud(ComputeCategory, "providerid1", *window.start, *window.end, window)
  301. a0.Cost = 6.09
  302. a0.SetAdjustment(-1.23)
  303. bs, err = a0.MarshalBinary()
  304. if err != nil {
  305. t.Fatalf("CloudAny.Binary: unexpected error: %s", err)
  306. }
  307. a1 = &Cloud{}
  308. err = unmarshal(a1, bs)
  309. if err != nil {
  310. t.Fatalf("CloudAny.Binary: unexpected error: %s", err)
  311. }
  312. if !a0.Equal(a1) {
  313. t.Fatalf("CloudAny.Binary: expected %v, found %v", a0, a1)
  314. }
  315. }
  316. func RunClusterManagement_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  317. ws := time.Date(2020, time.September, 16, 0, 0, 0, 0, time.UTC)
  318. we := ws.Add(24 * time.Hour)
  319. window := NewWindow(&ws, &we)
  320. var a0, a1 *ClusterManagement
  321. var bs []byte
  322. var err error
  323. a0 = NewClusterManagement(AWSProvider, "cluster1", window)
  324. a0.Cost = 4.003
  325. a0.SetAdjustment(-3.23)
  326. bs, err = a0.MarshalBinary()
  327. if err != nil {
  328. t.Fatalf("ClusterManagement.Binary: unexpected error: %s", err)
  329. }
  330. a1 = &ClusterManagement{}
  331. err = a1.UnmarshalBinary(bs)
  332. if err != nil {
  333. t.Fatalf("ClusterManagement.Binary: unexpected error: %s", err)
  334. }
  335. if !a0.Equal(a1) {
  336. t.Fatalf("ClusterManagement.Binary: expected %v, found %v", a0, a1)
  337. }
  338. }
  339. func RunDisk_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  340. ws := time.Date(2020, time.September, 16, 0, 0, 0, 0, time.UTC)
  341. we := ws.Add(24 * time.Hour)
  342. window := NewWindow(&ws, &we)
  343. hours := window.Duration().Hours()
  344. start := time.Date(2020, time.September, 16, 3, 0, 0, 0, time.UTC)
  345. end := time.Date(2020, time.September, 16, 15, 12, 0, 0, time.UTC)
  346. var a0, a1 *Disk
  347. var bs []byte
  348. var err error
  349. a0 = NewDisk("any1", "cluster1", "世界", start, end, window)
  350. a0.ByteHours = 100 * 1024 * 1024 * 1024 * hours
  351. a0.Cost = 4.003
  352. a0.Local = 0.4
  353. a0.Breakdown = &Breakdown{
  354. Idle: 0.9,
  355. Other: 0.05,
  356. System: 0.05,
  357. User: 0.0,
  358. }
  359. a0.SetAdjustment(-3.23)
  360. bs, err = a0.MarshalBinary()
  361. if err != nil {
  362. t.Fatalf("Disk.Binary: unexpected error: %s", err)
  363. }
  364. a1 = &Disk{}
  365. err = unmarshal(a1, bs)
  366. if err != nil {
  367. t.Fatalf("Disk.Binary: unexpected error: %s", err)
  368. }
  369. if !a0.Equal(a1) {
  370. t.Fatalf("Disk.Binary: expected %v, found %v", a0, a1)
  371. }
  372. }
  373. func RunNode_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  374. ws := time.Date(2020, time.September, 16, 0, 0, 0, 0, time.UTC)
  375. we := ws.Add(24 * time.Hour)
  376. window := NewWindow(&ws, &we)
  377. hours := window.Duration().Hours()
  378. start := time.Date(2020, time.September, 16, 3, 0, 0, 0, time.UTC)
  379. end := time.Date(2020, time.September, 16, 15, 12, 0, 0, time.UTC)
  380. var a0, a1 *Node
  381. var bs []byte
  382. var err error
  383. a0 = NewNode("any1", "cluster1", "世界", start, end, window)
  384. a0.NodeType = "n2-standard"
  385. a0.Preemptible = 1.0
  386. a0.CPUCoreHours = 2.0 * hours
  387. a0.RAMByteHours = 12.0 * gb * hours
  388. a0.CPUCost = 1.50
  389. a0.GPUCost = 30.44
  390. a0.RAMCost = 15.0
  391. a0.Discount = 0.9
  392. a0.CPUBreakdown = &Breakdown{
  393. Idle: 0.9,
  394. Other: 0.05,
  395. System: 0.05,
  396. User: 0.0,
  397. }
  398. a0.RAMBreakdown = &Breakdown{
  399. Idle: 0.4,
  400. Other: 0.05,
  401. System: 0.05,
  402. User: 0.5,
  403. }
  404. a0.SetAdjustment(1.23)
  405. bs, err = a0.MarshalBinary()
  406. if err != nil {
  407. t.Fatalf("Node.Binary: unexpected error: %s", err)
  408. }
  409. a1 = &Node{}
  410. err = unmarshal(a1, bs)
  411. if err != nil {
  412. t.Fatalf("Node.Binary: unexpected error: %s", err)
  413. }
  414. if !a0.Equal(a1) {
  415. t.Fatalf("Node.Binary: expected %v, found %v", a0, a1)
  416. }
  417. }
  418. func RunProperties_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  419. var p0, p1 *AllocationProperties
  420. var bs []byte
  421. var err error
  422. // empty properties
  423. p0 = &AllocationProperties{}
  424. bs, err = p0.MarshalBinary()
  425. if err != nil {
  426. t.Fatalf("AllocationProperties.Binary: unexpected error: %s", err)
  427. }
  428. p1 = &AllocationProperties{}
  429. err = unmarshal(p1, bs)
  430. if err != nil {
  431. t.Fatalf("AllocationProperties.Binary: unexpected error: %s", err)
  432. }
  433. if !p0.Equal(p1) {
  434. t.Fatalf("AllocationProperties.Binary: expected %s; found %s", p0, p1)
  435. }
  436. // complete properties
  437. p0 = &AllocationProperties{}
  438. p0.Cluster = "cluster1"
  439. p0.Container = "container-abc-1"
  440. p0.Controller = "daemonset-abc"
  441. p0.ControllerKind = "daemonset"
  442. p0.Namespace = "namespace1"
  443. p0.NamespaceLabels = map[string]string{
  444. "app": "cost-analyzer-namespace",
  445. "kubernetes.io/name": "cost-analyzer",
  446. }
  447. p0.NamespaceAnnotations = map[string]string{
  448. "com.kubernetes.io/managed-by": "helm",
  449. "kubernetes.io/last-applied-configuration": "cost-analyzer",
  450. }
  451. p0.Node = "node1"
  452. p0.Pod = "daemonset-abc-123"
  453. p0.Labels = map[string]string{
  454. "app": "cost-analyzer",
  455. "tier": "frontend",
  456. }
  457. p0.Services = []string{"kubecost-frontend"}
  458. bs, err = p0.MarshalBinary()
  459. if err != nil {
  460. t.Fatalf("AllocationProperties.Binary: unexpected error: %s", err)
  461. }
  462. p1 = &AllocationProperties{}
  463. err = unmarshal(p1, bs)
  464. if err != nil {
  465. t.Fatalf("AllocationProperties.Binary: unexpected error: %s", err)
  466. }
  467. if !p0.Equal(p1) {
  468. t.Fatalf("AllocationProperties.Binary: expected %s; found %s", p0, p1)
  469. }
  470. // incomplete properties
  471. p0 = &AllocationProperties{}
  472. p0.Cluster = ("cluster1")
  473. p0.Controller = "daemonset-abc"
  474. p0.ControllerKind = "daemonset"
  475. p0.Namespace = "namespace1"
  476. p0.NamespaceAnnotations = map[string]string{
  477. "com.kubernetes.io/managed-by": "helm",
  478. "kubernetes.io/last-applied-configuration": "cost-analyzer",
  479. }
  480. p0.Services = []string{}
  481. bs, err = p0.MarshalBinary()
  482. if err != nil {
  483. t.Fatalf("AllocationProperties.Binary: unexpected error: %s", err)
  484. }
  485. p1 = &AllocationProperties{}
  486. err = unmarshal(p1, bs)
  487. if err != nil {
  488. t.Fatalf("AllocationProperties.Binary: unexpected error: %s", err)
  489. }
  490. if !p0.Equal(p1) {
  491. t.Fatalf("AllocationProperties.Binary: expected %s; found %s", p0, p1)
  492. }
  493. }
  494. func RunShared_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  495. ws := time.Date(2020, time.September, 16, 0, 0, 0, 0, time.UTC)
  496. we := ws.Add(24 * time.Hour)
  497. window := NewWindow(&ws, &we)
  498. var a0, a1 *SharedAsset
  499. var bs []byte
  500. var err error
  501. a0 = NewSharedAsset("any1", window)
  502. a0.Cost = 4.04
  503. a0.SetAdjustment(1.23)
  504. bs, err = a0.MarshalBinary()
  505. if err != nil {
  506. t.Fatalf("SharedAsset.Binary: unexpected error: %s", err)
  507. }
  508. a1 = &SharedAsset{}
  509. err = unmarshal(a1, bs)
  510. if err != nil {
  511. t.Fatalf("SharedAsset.Binary: unexpected error: %s", err)
  512. }
  513. if !a0.Equal(a1) {
  514. t.Fatalf("SharedAsset.Binary: expected %v, found %v", a0, a1)
  515. }
  516. }
  517. func RunWindow_BinaryEncodingTest(t *testing.T, unmarshal UnmarshalFunc) {
  518. var w0, w1 Window
  519. var bs []byte
  520. var err error
  521. // Window (nil, nil)
  522. w0 = NewWindow(nil, nil)
  523. bs, err = w0.MarshalBinary()
  524. if err != nil {
  525. t.Fatalf("Window.Binary: unexpected error: %s", err)
  526. }
  527. err = unmarshal(&w1, bs)
  528. if err != nil {
  529. t.Fatalf("Window.Binary: unexpected error: %s", err)
  530. }
  531. if w1.Start() != w0.Start() {
  532. t.Fatalf("Window.Binary: expected %v; found %v", w0.Start(), w1.Start())
  533. }
  534. if w1.End() != w0.End() {
  535. t.Fatalf("Window.Binary: expected %v; found %v", w0.End(), w1.End())
  536. }
  537. // Window (time, nil)
  538. ts := time.Now()
  539. w0 = NewWindow(&ts, nil)
  540. bs, err = w0.MarshalBinary()
  541. if err != nil {
  542. t.Fatalf("Window.Binary: unexpected error: %s", err)
  543. }
  544. err = unmarshal(&w1, bs)
  545. if err != nil {
  546. t.Fatalf("Window.Binary: unexpected error: %s", err)
  547. }
  548. if !w1.Start().Equal(*w0.Start()) {
  549. t.Fatalf("Window.Binary: expected %v; found %v", w0.Start(), w1.Start())
  550. }
  551. if w1.End() != w0.End() {
  552. t.Fatalf("Window.Binary: expected %v; found %v", w0.End(), w1.End())
  553. }
  554. // Window (nil, time)
  555. te := time.Now()
  556. w0 = NewWindow(nil, &te)
  557. bs, err = w0.MarshalBinary()
  558. if err != nil {
  559. t.Fatalf("Window.Binary: unexpected error: %s", err)
  560. }
  561. err = unmarshal(&w1, bs)
  562. if err != nil {
  563. t.Fatalf("Window.Binary: unexpected error: %s", err)
  564. }
  565. if w1.Start() != w0.Start() {
  566. t.Fatalf("Window.Binary: expected %v; found %v", w0.Start(), w1.Start())
  567. }
  568. if !w1.End().Equal(*w0.End()) {
  569. t.Fatalf("Window.Binary: expected %v; found %v", w0.End(), w1.End())
  570. }
  571. // Window (time, time)
  572. ts, te = time.Now(), time.Now()
  573. w0 = NewWindow(&ts, &te)
  574. bs, err = w0.MarshalBinary()
  575. if err != nil {
  576. t.Fatalf("Window.Binary: unexpected error: %s", err)
  577. }
  578. err = unmarshal(&w1, bs)
  579. if err != nil {
  580. t.Fatalf("Window.Binary: unexpected error: %s", err)
  581. }
  582. if !w1.Start().Equal(*w0.Start()) {
  583. t.Fatalf("Window.Binary: expected %v; found %v", w0.Start(), w1.Start())
  584. }
  585. if !w1.End().Equal(*w0.End()) {
  586. t.Fatalf("Window.Binary: expected %v; found %v", w0.End(), w1.End())
  587. }
  588. }
  589. type BingenUnmarshalable interface {
  590. UnmarshalBinary([]byte) error
  591. UnmarshalBinaryFromReader(io.Reader) error
  592. }
  593. func UnmarshalBingenBytes(value BingenUnmarshalable, b []byte) error {
  594. return value.UnmarshalBinary(b)
  595. }
  596. func UnmarshalBingenReader(value BingenUnmarshalable, b []byte) error {
  597. // convert bytes to reader in order to leverage io.Reader string table
  598. reader := bytes.NewReader(b)
  599. return value.UnmarshalBinaryFromReader(reader)
  600. }
  601. func RunAllOpencostBingenCodecTests(t *testing.T, unmarshal UnmarshalFunc) {
  602. tests := []struct {
  603. name string
  604. f func(*testing.T, UnmarshalFunc)
  605. }{
  606. {
  607. name: "RunAllocation_BinaryEncodingTest",
  608. f: RunAllocation_BinaryEncodingTest,
  609. },
  610. {
  611. name: "RunAllocationSet_BinaryEncodingTest",
  612. f: RunAllocationSet_BinaryEncodingTest,
  613. },
  614. {
  615. name: "RunAllocationSetRange_BinaryEncodingTest",
  616. f: RunAllocationSetRange_BinaryEncodingTest,
  617. },
  618. {
  619. name: "RunAny_BinaryEncodingTest",
  620. f: RunAny_BinaryEncodingTest,
  621. },
  622. {
  623. name: "RunAsset_BinaryEncodingTest",
  624. f: RunAsset_BinaryEncodingTest,
  625. },
  626. {
  627. name: "RunAssetSet_BinaryEncodingTest",
  628. f: RunAssetSet_BinaryEncodingTest,
  629. },
  630. {
  631. name: "RunAssetSetRange_BinaryEncodingTest",
  632. f: RunAssetSetRange_BinaryEncodingTest,
  633. },
  634. {
  635. name: "RunBreakdown_BinaryEncodingTest",
  636. f: RunBreakdown_BinaryEncodingTest,
  637. },
  638. {
  639. name: "RunCloudAny_BinaryEncodingTest",
  640. f: RunCloudAny_BinaryEncodingTest,
  641. },
  642. {
  643. name: "RunClusterManagement_BinaryEncodingTest",
  644. f: RunClusterManagement_BinaryEncodingTest,
  645. },
  646. {
  647. name: "RunDisk_BinaryEncodingTest",
  648. f: RunDisk_BinaryEncodingTest,
  649. },
  650. {
  651. name: "RunNode_BinaryEncodingTest",
  652. f: RunNode_BinaryEncodingTest,
  653. },
  654. {
  655. name: "RunProperties_BinaryEncodingTest",
  656. f: RunProperties_BinaryEncodingTest,
  657. },
  658. {
  659. name: "RunShared_BinaryEncodingTest",
  660. f: RunShared_BinaryEncodingTest,
  661. },
  662. {
  663. name: "RunWindow_BinaryEncodingTest",
  664. f: RunWindow_BinaryEncodingTest,
  665. },
  666. }
  667. for _, test := range tests {
  668. t.Run(test.name, func(tt *testing.T) {
  669. test.f(tt, unmarshal)
  670. })
  671. }
  672. }
  673. func TestOpencostBingenDefaultsWithBytes(t *testing.T) {
  674. config := DefaultBingenConfiguration()
  675. ConfigureBingen(config)
  676. RunAllOpencostBingenCodecTests(t, UnmarshalBingenBytes)
  677. }
  678. func TestOpencostBingenFileStringTableEnabledWithBytes(t *testing.T) {
  679. // This test _should_ still run the slice based string table because raw []byte
  680. // data always uses the string slice table
  681. config := DefaultBingenConfiguration()
  682. config.FileBackedStringTableEnabled = true
  683. config.FileBackedStringTableDir = t.TempDir()
  684. ConfigureBingen(config)
  685. // reset configuration to default on completion
  686. defer ConfigureBingen(DefaultBingenConfiguration())
  687. RunAllOpencostBingenCodecTests(t, UnmarshalBingenBytes)
  688. }
  689. func TestOpencostBingenDefaultsWithReader(t *testing.T) {
  690. // This test _should_ still run the slice based string table because we haven't configured
  691. // bingen to use the file string table
  692. config := DefaultBingenConfiguration()
  693. ConfigureBingen(config)
  694. // we use the reader to unmarshal instead of []bytes
  695. RunAllOpencostBingenCodecTests(t, UnmarshalBingenReader)
  696. }
  697. func TestOpencostBingenFileStringTableEnabledWithReader(t *testing.T) {
  698. // This test _should_ use the file backed string table because we have enabled it AND
  699. // we're using a reader
  700. config := DefaultBingenConfiguration()
  701. config.FileBackedStringTableEnabled = true
  702. config.FileBackedStringTableDir = t.TempDir()
  703. ConfigureBingen(config)
  704. // reset configuration to default on completion
  705. defer ConfigureBingen(DefaultBingenConfiguration())
  706. RunAllOpencostBingenCodecTests(t, UnmarshalBingenReader)
  707. }