Skip to content

Commit 7c7c42c

Browse files
committed
stdlib: add basic tests for _UnsafeBitMap
1 parent 0b4162b commit 7c7c42c

File tree

2 files changed

+147
-10
lines changed

2 files changed

+147
-10
lines changed

stdlib/public/core/UnsafeBitMap.swift

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,51 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
/// A wrapper around a bitmap storage with room for at least `bitCount` bits.
14-
internal struct _UnsafeBitMap {
15-
internal let values: UnsafeMutablePointer<UInt>
16-
internal let bitCount: Int
14+
public // @testable
15+
struct _UnsafeBitMap {
16+
public // @testable
17+
let values: UnsafeMutablePointer<UInt>
1718

18-
internal static func wordIndex(_ i: Int) -> Int {
19+
public // @testable
20+
let bitCount: Int
21+
22+
public // @testable
23+
static func wordIndex(_ i: Int) -> Int {
1924
// Note: We perform the operation on UInts to get faster unsigned math
2025
// (shifts).
2126
return Int(bitPattern: UInt(bitPattern: i) / UInt(UInt._sizeInBits))
2227
}
2328

24-
internal static func bitIndex(_ i: Int) -> UInt {
29+
public // @testable
30+
static func bitIndex(_ i: Int) -> UInt {
2531
// Note: We perform the operation on UInts to get faster unsigned math
2632
// (shifts).
2733
return UInt(bitPattern: i) % UInt(UInt._sizeInBits)
2834
}
2935

30-
internal static func sizeInWords(forSizeInBits bitCount: Int) -> Int {
36+
public // @testable
37+
static func sizeInWords(forSizeInBits bitCount: Int) -> Int {
3138
return bitCount + Int._sizeInBytes - 1 / Int._sizeInBytes
3239
}
3340

34-
internal init(storage: UnsafeMutablePointer<UInt>, bitCount: Int) {
41+
public // @testable
42+
init(storage: UnsafeMutablePointer<UInt>, bitCount: Int) {
3543
self.bitCount = bitCount
3644
self.values = storage
3745
}
3846

39-
internal var numberOfWords: Int {
47+
public // @testable
48+
var numberOfWords: Int {
4049
return _UnsafeBitMap.sizeInWords(forSizeInBits: bitCount)
4150
}
4251

43-
internal func initializeToZero() {
52+
public // @testable
53+
func initializeToZero() {
4454
values.initialize(with: 0, count: numberOfWords)
4555
}
4656

47-
internal subscript(i: Int) -> Bool {
57+
public // @testable
58+
subscript(i: Int) -> Bool {
4859
get {
4960
_sanityCheck(i < Int(bitCount) && i >= 0, "index out of bounds")
5061
let word = values[_UnsafeBitMap.wordIndex(i)]
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
4+
import StdlibUnittest
5+
6+
var UnsafeBitMapTests = TestSuite("UnsafeBitMap")
7+
8+
UnsafeBitMapTests.test("wordIndex(_:), bitIndex(_:)") {
9+
#if arch(i386) || arch(arm)
10+
for i in 0...31 {
11+
expectEqual(0, _UnsafeBitMap.wordIndex(i), "i=\(i)")
12+
expectEqual(i, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
13+
}
14+
for i in 32...63 {
15+
expectEqual(1, _UnsafeBitMap.wordIndex(i), "i=\(i)")
16+
expectEqual(i - 32, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
17+
}
18+
for i in 64...95 {
19+
expectEqual(2, _UnsafeBitMap.wordIndex(i), "i=\(i)")
20+
expectEqual(i - 64, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
21+
}
22+
for i in 96...127 {
23+
expectEqual(3, _UnsafeBitMap.wordIndex(i), "i=\(i)")
24+
expectEqual(i - 96, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
25+
}
26+
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le)
27+
for i in 0...63 {
28+
expectEqual(0, _UnsafeBitMap.wordIndex(i), "i=\(i)")
29+
expectEqual(i, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
30+
}
31+
for i in 64...127 {
32+
expectEqual(1, _UnsafeBitMap.wordIndex(i), "i=\(i)")
33+
expectEqual(i - 64, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
34+
}
35+
for i in 192...255 {
36+
expectEqual(3, _UnsafeBitMap.wordIndex(i), "i=\(i)")
37+
expectEqual(i - 192, Int(_UnsafeBitMap.bitIndex(i)), "i=\(i)")
38+
}
39+
#else
40+
_UnimplementedError()
41+
#endif
42+
}
43+
44+
UnsafeBitMapTests.test("sizeInWords(forSizeInBits:)")
45+
.xfail(.always("the API is buggy")).code {
46+
expectEqual(0, _UnsafeBitMap.sizeInWords(forSizeInBits: 0))
47+
#if arch(i386) || arch(arm)
48+
for i in 1...32 {
49+
expectEqual(1, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
50+
}
51+
for i in 33...64 {
52+
expectEqual(2, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
53+
}
54+
for i in 65...96 {
55+
expectEqual(3, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
56+
}
57+
for i in 97...128 {
58+
expectEqual(4, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
59+
}
60+
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le)
61+
for i in 1...64 {
62+
expectEqual(1, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
63+
}
64+
for i in 65...128 {
65+
expectEqual(2, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
66+
}
67+
for i in 193...256 {
68+
expectEqual(4, _UnsafeBitMap.sizeInWords(forSizeInBits: i), "i=\(i)")
69+
}
70+
#else
71+
_UnimplementedError()
72+
#endif
73+
}
74+
75+
let sizes = [
76+
0, 1, 2, 3, 7, 8, 9, 31, 32, 33, 48, 63, 64, 65, 127, 128, 129, 1024, 10000
77+
]
78+
79+
func make(sizeInBits: Int) -> _UnsafeBitMap {
80+
let sizeInWords = _UnsafeBitMap.sizeInWords(forSizeInBits: sizeInBits)
81+
let storage = UnsafeMutablePointer<UInt>(allocatingCapacity: sizeInWords)
82+
let bitMap = _UnsafeBitMap(storage: storage, bitCount: sizeInBits)
83+
expectEqual(sizeInWords, bitMap.numberOfWords)
84+
return bitMap
85+
}
86+
87+
UnsafeBitMapTests.test("initializeToZero()")
88+
.forEach(in: sizes) {
89+
sizeInBits in
90+
let bitMap = make(sizeInBits: sizeInBits)
91+
defer { bitMap.values.deallocateCapacity(bitMap.numberOfWords) }
92+
93+
bitMap.initializeToZero()
94+
for i in 0..<sizeInBits {
95+
expectEqual(false, bitMap[i])
96+
}
97+
}
98+
99+
UnsafeBitMapTests.test("subscript")
100+
.forEach(in: sizes) {
101+
sizeInBits in
102+
let bitMap = make(sizeInBits: sizeInBits)
103+
defer { bitMap.values.deallocateCapacity(bitMap.numberOfWords) }
104+
105+
if sizeInBits != 0 {
106+
bitMap.initializeToZero()
107+
let index = 7882627 % sizeInBits
108+
bitMap[index] = true
109+
for i in 0..<sizeInBits {
110+
expectEqual(i == index, bitMap[i])
111+
}
112+
}
113+
114+
if sizeInBits < 500 {
115+
for i in 0..<sizeInBits {
116+
bitMap.initializeToZero()
117+
bitMap[i] = true
118+
for j in 0..<sizeInBits {
119+
expectEqual(i == j, bitMap[j])
120+
}
121+
}
122+
}
123+
}
124+
125+
runAllTests()
126+

0 commit comments

Comments
 (0)