bitmask_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /*
  2. Copyright 2019 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package bitmask
  14. import (
  15. "reflect"
  16. "testing"
  17. )
  18. func TestNewEmptyiBitMask(t *testing.T) {
  19. tcases := []struct {
  20. name string
  21. expectedMask string
  22. }{
  23. {
  24. name: "New empty BitMask",
  25. expectedMask: "00",
  26. },
  27. }
  28. for _, tc := range tcases {
  29. bm := NewEmptyBitMask()
  30. if bm.String() != tc.expectedMask {
  31. t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, bm)
  32. }
  33. }
  34. }
  35. func TestNewBitMask(t *testing.T) {
  36. tcases := []struct {
  37. name string
  38. bits []int
  39. expectedMask string
  40. }{
  41. {
  42. name: "New BitMask with bit 0 set",
  43. bits: []int{0},
  44. expectedMask: "01",
  45. },
  46. {
  47. name: "New BitMask with bit 1 set",
  48. bits: []int{1},
  49. expectedMask: "10",
  50. },
  51. {
  52. name: "New BitMask with bit 0 and bit 1 set",
  53. bits: []int{0, 1},
  54. expectedMask: "11",
  55. },
  56. }
  57. for _, tc := range tcases {
  58. mask, _ := NewBitMask(tc.bits...)
  59. if mask.String() != tc.expectedMask {
  60. t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, mask)
  61. }
  62. }
  63. }
  64. func TestAdd(t *testing.T) {
  65. tcases := []struct {
  66. name string
  67. bits []int
  68. expectedMask string
  69. }{
  70. {
  71. name: "Add BitMask with bit 0 set",
  72. bits: []int{0},
  73. expectedMask: "01",
  74. },
  75. {
  76. name: "Add BitMask with bit 1 set",
  77. bits: []int{1},
  78. expectedMask: "10",
  79. },
  80. {
  81. name: "Add BitMask with bits 0 and 1 set",
  82. bits: []int{0, 1},
  83. expectedMask: "11",
  84. },
  85. {
  86. name: "Add BitMask with bits outside range 0-63",
  87. bits: []int{-1, 64},
  88. expectedMask: "00",
  89. },
  90. }
  91. for _, tc := range tcases {
  92. mask, _ := NewBitMask()
  93. mask.Add(tc.bits...)
  94. if mask.String() != tc.expectedMask {
  95. t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, mask)
  96. }
  97. }
  98. }
  99. func TestRemove(t *testing.T) {
  100. tcases := []struct {
  101. name string
  102. bitsSet []int
  103. bitsRemove []int
  104. expectedMask string
  105. }{
  106. {
  107. name: "Set bit 0. Remove bit 0",
  108. bitsSet: []int{0},
  109. bitsRemove: []int{0},
  110. expectedMask: "00",
  111. },
  112. {
  113. name: "Set bits 0 and 1. Remove bit 1",
  114. bitsSet: []int{0, 1},
  115. bitsRemove: []int{1},
  116. expectedMask: "01",
  117. },
  118. {
  119. name: "Set bits 0 and 1. Remove bits 0 and 1",
  120. bitsSet: []int{0, 1},
  121. bitsRemove: []int{0, 1},
  122. expectedMask: "00",
  123. },
  124. {
  125. name: "Set bit 0. Attempt to remove bits outside range 0-63",
  126. bitsSet: []int{0},
  127. bitsRemove: []int{-1, 64},
  128. expectedMask: "01",
  129. },
  130. }
  131. for _, tc := range tcases {
  132. mask, _ := NewBitMask(tc.bitsSet...)
  133. mask.Remove(tc.bitsRemove...)
  134. if mask.String() != tc.expectedMask {
  135. t.Errorf("Expected mask to be %v, got %v", tc.expectedMask, mask)
  136. }
  137. }
  138. }
  139. func TestAnd(t *testing.T) {
  140. tcases := []struct {
  141. name string
  142. masks [][]int
  143. andMask string
  144. }{
  145. {
  146. name: "Mask 11 AND mask 11",
  147. masks: [][]int{{0, 1}, {0, 1}},
  148. andMask: "11",
  149. },
  150. {
  151. name: "Mask 11 AND mask 10",
  152. masks: [][]int{{0, 1}, {1}},
  153. andMask: "10",
  154. },
  155. {
  156. name: "Mask 01 AND mask 11",
  157. masks: [][]int{{0}, {0, 1}},
  158. andMask: "01",
  159. },
  160. {
  161. name: "Mask 11 AND mask 11 AND mask 10",
  162. masks: [][]int{{0, 1}, {0, 1}, {1}},
  163. andMask: "10",
  164. },
  165. {
  166. name: "Mask 01 AND mask 01 AND mask 10 AND mask 11",
  167. masks: [][]int{{0}, {0}, {1}, {0, 1}},
  168. andMask: "00",
  169. },
  170. {
  171. name: "Mask 1111 AND mask 1110 AND mask 1100 AND mask 1000",
  172. masks: [][]int{{0, 1, 2, 3}, {1, 2, 3}, {2, 3}, {3}},
  173. andMask: "1000",
  174. },
  175. }
  176. for _, tc := range tcases {
  177. var bitMasks []BitMask
  178. for i := range tc.masks {
  179. bitMask, _ := NewBitMask(tc.masks[i]...)
  180. bitMasks = append(bitMasks, bitMask)
  181. }
  182. resultMask := And(bitMasks[0], bitMasks...)
  183. if resultMask.String() != string(tc.andMask) {
  184. t.Errorf("Expected mask to be %v, got %v", tc.andMask, resultMask)
  185. }
  186. }
  187. }
  188. func TestOr(t *testing.T) {
  189. tcases := []struct {
  190. name string
  191. masks [][]int
  192. orMask string
  193. }{
  194. {
  195. name: "Mask 01 OR mask 00",
  196. masks: [][]int{{0}, {}},
  197. orMask: "01",
  198. },
  199. {
  200. name: "Mask 10 OR mask 10",
  201. masks: [][]int{{1}, {1}},
  202. orMask: "10",
  203. },
  204. {
  205. name: "Mask 01 OR mask 10",
  206. masks: [][]int{{0}, {1}},
  207. orMask: "11",
  208. },
  209. {
  210. name: "Mask 11 OR mask 11",
  211. masks: [][]int{{0, 1}, {0, 1}},
  212. orMask: "11",
  213. },
  214. {
  215. name: "Mask 01 OR mask 10 OR mask 11",
  216. masks: [][]int{{0}, {1}, {0, 1}},
  217. orMask: "11",
  218. },
  219. {
  220. name: "Mask 1000 OR mask 0100 OR mask 0010 OR mask 0001",
  221. masks: [][]int{{3}, {2}, {1}, {0}},
  222. orMask: "1111",
  223. },
  224. }
  225. for _, tc := range tcases {
  226. var bitMasks []BitMask
  227. for i := range tc.masks {
  228. bitMask, _ := NewBitMask(tc.masks[i]...)
  229. bitMasks = append(bitMasks, bitMask)
  230. }
  231. resultMask := Or(bitMasks[0], bitMasks...)
  232. if resultMask.String() != string(tc.orMask) {
  233. t.Errorf("Expected mask to be %v, got %v", tc.orMask, resultMask)
  234. }
  235. }
  236. }
  237. func TestClear(t *testing.T) {
  238. tcases := []struct {
  239. name string
  240. mask []int
  241. clearedMask string
  242. }{
  243. {
  244. name: "Clear mask 01",
  245. mask: []int{0},
  246. clearedMask: "00",
  247. },
  248. {
  249. name: "Clear mask 10",
  250. mask: []int{1},
  251. clearedMask: "00",
  252. },
  253. {
  254. name: "Clear mask 11",
  255. mask: []int{0, 1},
  256. clearedMask: "00",
  257. },
  258. }
  259. for _, tc := range tcases {
  260. mask, _ := NewBitMask(tc.mask...)
  261. mask.Clear()
  262. if mask.String() != string(tc.clearedMask) {
  263. t.Errorf("Expected mask to be %v, got %v", tc.clearedMask, mask)
  264. }
  265. }
  266. }
  267. func TestFill(t *testing.T) {
  268. tcases := []struct {
  269. name string
  270. mask []int
  271. filledMask string
  272. }{
  273. {
  274. name: "Fill empty mask",
  275. mask: nil,
  276. filledMask: "1111111111111111111111111111111111111111111111111111111111111111",
  277. },
  278. {
  279. name: "Fill mask 10",
  280. mask: []int{0},
  281. filledMask: "1111111111111111111111111111111111111111111111111111111111111111",
  282. },
  283. {
  284. name: "Fill mask 11",
  285. mask: []int{0, 1},
  286. filledMask: "1111111111111111111111111111111111111111111111111111111111111111",
  287. },
  288. }
  289. for _, tc := range tcases {
  290. mask, _ := NewBitMask(tc.mask...)
  291. mask.Fill()
  292. if mask.String() != string(tc.filledMask) {
  293. t.Errorf("Expected mask to be %v, got %v", tc.filledMask, mask)
  294. }
  295. }
  296. }
  297. func TestIsEmpty(t *testing.T) {
  298. tcases := []struct {
  299. name string
  300. mask []int
  301. expectedEmpty bool
  302. }{
  303. {
  304. name: "Check if mask 00 is empty",
  305. mask: nil,
  306. expectedEmpty: true,
  307. },
  308. {
  309. name: "Check if mask 01 is empty",
  310. mask: []int{0},
  311. expectedEmpty: false,
  312. },
  313. {
  314. name: "Check if mask 11 is empty",
  315. mask: []int{0, 1},
  316. expectedEmpty: false,
  317. },
  318. }
  319. for _, tc := range tcases {
  320. mask, _ := NewBitMask(tc.mask...)
  321. empty := mask.IsEmpty()
  322. if empty != tc.expectedEmpty {
  323. t.Errorf("Expected value to be %v, got %v", tc.expectedEmpty, empty)
  324. }
  325. }
  326. }
  327. func TestIsSet(t *testing.T) {
  328. tcases := []struct {
  329. name string
  330. mask []int
  331. checkBit int
  332. expectedSet bool
  333. }{
  334. {
  335. name: "Check if bit 0 in mask 00 is set",
  336. mask: nil,
  337. checkBit: 0,
  338. expectedSet: false,
  339. },
  340. {
  341. name: "Check if bit 0 in mask 01 is set",
  342. mask: []int{0},
  343. checkBit: 0,
  344. expectedSet: true,
  345. },
  346. {
  347. name: "Check if bit 1 in mask 11 is set",
  348. mask: []int{0, 1},
  349. checkBit: 1,
  350. expectedSet: true,
  351. },
  352. {
  353. name: "Check if bit outside range 0-63 is set",
  354. mask: []int{0, 1},
  355. checkBit: 64,
  356. expectedSet: false,
  357. },
  358. }
  359. for _, tc := range tcases {
  360. mask, _ := NewBitMask(tc.mask...)
  361. set := mask.IsSet(tc.checkBit)
  362. if set != tc.expectedSet {
  363. t.Errorf("Expected value to be %v, got %v", tc.expectedSet, set)
  364. }
  365. }
  366. }
  367. func TestIsEqual(t *testing.T) {
  368. tcases := []struct {
  369. name string
  370. firstMask []int
  371. secondMask []int
  372. expectedEqual bool
  373. }{
  374. {
  375. name: "Check if mask 00 equals mask 00",
  376. firstMask: nil,
  377. secondMask: nil,
  378. expectedEqual: true,
  379. },
  380. {
  381. name: "Check if mask 00 equals mask 01",
  382. firstMask: nil,
  383. secondMask: []int{0},
  384. expectedEqual: false,
  385. },
  386. {
  387. name: "Check if mask 01 equals mask 01",
  388. firstMask: []int{0},
  389. secondMask: []int{0},
  390. expectedEqual: true,
  391. },
  392. {
  393. name: "Check if mask 01 equals mask 10",
  394. firstMask: []int{0},
  395. secondMask: []int{1},
  396. expectedEqual: false,
  397. },
  398. {
  399. name: "Check if mask 11 equals mask 11",
  400. firstMask: []int{0, 1},
  401. secondMask: []int{0, 1},
  402. expectedEqual: true,
  403. },
  404. }
  405. for _, tc := range tcases {
  406. firstMask, _ := NewBitMask(tc.firstMask...)
  407. secondMask, _ := NewBitMask(tc.secondMask...)
  408. isEqual := firstMask.IsEqual(secondMask)
  409. if isEqual != tc.expectedEqual {
  410. t.Errorf("Expected mask to be %v, got %v", tc.expectedEqual, isEqual)
  411. }
  412. }
  413. }
  414. func TestCount(t *testing.T) {
  415. tcases := []struct {
  416. name string
  417. bits []int
  418. expectedCount int
  419. }{
  420. {
  421. name: "Count number of bits set in mask 00",
  422. bits: nil,
  423. expectedCount: 0,
  424. },
  425. {
  426. name: "Count number of bits set in mask 01",
  427. bits: []int{0},
  428. expectedCount: 1,
  429. },
  430. {
  431. name: "Count number of bits set in mask 11",
  432. bits: []int{0, 1},
  433. expectedCount: 2,
  434. },
  435. }
  436. for _, tc := range tcases {
  437. mask, _ := NewBitMask(tc.bits...)
  438. count := mask.Count()
  439. if count != tc.expectedCount {
  440. t.Errorf("Expected value to be %v, got %v", tc.expectedCount, count)
  441. }
  442. }
  443. }
  444. func TestGetBits(t *testing.T) {
  445. tcases := []struct {
  446. name string
  447. bits []int
  448. expectedBits []int
  449. }{
  450. {
  451. name: "Get bits of mask 00",
  452. bits: nil,
  453. expectedBits: nil,
  454. },
  455. {
  456. name: "Get bits of mask 01",
  457. bits: []int{0},
  458. expectedBits: []int{0},
  459. },
  460. {
  461. name: "Get bits of mask 11",
  462. bits: []int{0, 1},
  463. expectedBits: []int{0, 1},
  464. },
  465. }
  466. for _, tc := range tcases {
  467. mask, _ := NewBitMask(tc.bits...)
  468. bits := mask.GetBits()
  469. if !reflect.DeepEqual(bits, tc.expectedBits) {
  470. t.Errorf("Expected value to be %v, got %v", tc.expectedBits, bits)
  471. }
  472. }
  473. }
  474. func TestIsNarrowerThan(t *testing.T) {
  475. tcases := []struct {
  476. name string
  477. firstMask []int
  478. secondMask []int
  479. expectedFirstNarrower bool
  480. }{
  481. {
  482. name: "Check narrowness of masks with unequal bits set 1/2",
  483. firstMask: []int{0},
  484. secondMask: []int{0, 1},
  485. expectedFirstNarrower: true,
  486. },
  487. {
  488. name: "Check narrowness of masks with unequal bits set 2/2",
  489. firstMask: []int{0, 1},
  490. secondMask: []int{0},
  491. expectedFirstNarrower: false,
  492. },
  493. {
  494. name: "Check narrowness of masks with equal bits set 1/2",
  495. firstMask: []int{0},
  496. secondMask: []int{1},
  497. expectedFirstNarrower: true,
  498. },
  499. {
  500. name: "Check narrowness of masks with equal bits set 2/2",
  501. firstMask: []int{1},
  502. secondMask: []int{0},
  503. expectedFirstNarrower: false,
  504. },
  505. }
  506. for _, tc := range tcases {
  507. firstMask, _ := NewBitMask(tc.firstMask...)
  508. secondMask, _ := NewBitMask(tc.secondMask...)
  509. expectedFirstNarrower := firstMask.IsNarrowerThan(secondMask)
  510. if expectedFirstNarrower != tc.expectedFirstNarrower {
  511. t.Errorf("Expected value to be %v, got %v", tc.expectedFirstNarrower, expectedFirstNarrower)
  512. }
  513. }
  514. }
  515. func TestIterateBitMasks(t *testing.T) {
  516. tcases := []struct {
  517. name string
  518. numbits int
  519. }{
  520. {
  521. name: "1 bit",
  522. numbits: 1,
  523. },
  524. {
  525. name: "2 bits",
  526. numbits: 2,
  527. },
  528. {
  529. name: "4 bits",
  530. numbits: 4,
  531. },
  532. {
  533. name: "8 bits",
  534. numbits: 8,
  535. },
  536. {
  537. name: "16 bits",
  538. numbits: 16,
  539. },
  540. }
  541. for _, tc := range tcases {
  542. // Generate a list of bits from tc.numbits.
  543. var bits []int
  544. for i := 0; i < tc.numbits; i++ {
  545. bits = append(bits, i)
  546. }
  547. // Calculate the expected number of masks. Since we always have masks
  548. // with bits from 0..n, this is just (2^n - 1) since we want 1 mask
  549. // represented by each integer between 1 and 2^n-1.
  550. expectedNumMasks := (1 << uint(tc.numbits)) - 1
  551. // Iterate all masks and count them.
  552. numMasks := 0
  553. IterateBitMasks(bits, func(BitMask) {
  554. numMasks++
  555. })
  556. // Compare the number of masks generated to the expected amount.
  557. if expectedNumMasks != numMasks {
  558. t.Errorf("Expected to iterate %v masks, got %v", expectedNumMasks, numMasks)
  559. }
  560. }
  561. }