Skip to content

Commit ed5b3ca

Browse files
committed
[stdlib] Add basic unit tests for InlineArray
FIXME: Empty array literals aren't supported.
1 parent 30e167b commit ed5b3ca

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

Diff for: test/stdlib/InlineArray.swift

+232
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// RUN: %target-run-simple-swift( \
14+
// RUN: -enable-experimental-feature ValueGenerics \
15+
// RUN: -parse-as-library \
16+
// RUN: )
17+
// REQUIRES: executable_test
18+
// REQUIRES: swift_feature_ValueGenerics
19+
// UNSUPPORTED: use_os_stdlib
20+
// END.
21+
//
22+
//===----------------------------------------------------------------------===//
23+
24+
import StdlibUnittest
25+
import Synchronization
26+
27+
@available(SwiftStdlib 6.2, *)
28+
@main
29+
enum InlineArrayTests {
30+
31+
@available(SwiftStdlib 6.2, *)
32+
static func main() {
33+
let testSuite = TestSuite("InlineArrayTests")
34+
testSuite.test("Empty", testEmpty)
35+
testSuite.test("Nonempty", testNonempty)
36+
testSuite.test("Copyable", testCopyable)
37+
testSuite.test("Noncopyable", testNoncopyable)
38+
testSuite.test("Uninhabited", testUninhabited)
39+
runAllTests()
40+
}
41+
42+
/// An *empty* array's size is zero. Its stride and alignment are one byte.
43+
@available(SwiftStdlib 6.2, *)
44+
static func testEmpty() {
45+
expectEqual(MemoryLayout<InlineArray<0, Int>>.size, 0)
46+
expectEqual(MemoryLayout<InlineArray<0, Int>>.stride, 1)
47+
expectEqual(MemoryLayout<InlineArray<0, Int>>.alignment, 1)
48+
}
49+
50+
/// A *nonempty* array's size and stride are equal to the element's stride
51+
/// multiplied by the number of elements. Its alignment is equal to the
52+
/// element's alignment.
53+
@available(SwiftStdlib 6.2, *)
54+
static func testNonempty() {
55+
// StaticString has { Word, Word, Byte } stored properties.
56+
let _ = MemoryLayout<StaticString>.size // e.g. 17 bytes.
57+
let s = MemoryLayout<StaticString>.stride // e.g. 24 bytes.
58+
let a = MemoryLayout<StaticString>.alignment // e.g. 8 bytes.
59+
expectEqual(MemoryLayout<InlineArray<1, StaticString>>.size, s * 1)
60+
expectEqual(MemoryLayout<InlineArray<1, StaticString>>.stride, s * 1)
61+
expectEqual(MemoryLayout<InlineArray<1, StaticString>>.alignment, a)
62+
expectEqual(MemoryLayout<InlineArray<2, StaticString>>.size, s * 2)
63+
expectEqual(MemoryLayout<InlineArray<2, StaticString>>.stride, s * 2)
64+
expectEqual(MemoryLayout<InlineArray<2, StaticString>>.alignment, a)
65+
}
66+
67+
/// An array and its elements can be of *copyable* type.
68+
@available(SwiftStdlib 6.2, *)
69+
static func testCopyable() {
70+
do {
71+
let a: InlineArray<4, Int> = [1, 2, 4, 8]
72+
let b: InlineArray<_, Int> = [1, 2, 4, 8]
73+
let c: InlineArray<4, _> = [1, 2, 4, 8]
74+
let d: InlineArray = [1, 2, 4, 8]
75+
_checkInlineArray(a, oracle: [1, 2, 4, 8])
76+
_checkInlineArray(b, oracle: [1, 2, 4, 8])
77+
_checkInlineArray(c, oracle: [1, 2, 4, 8])
78+
_checkInlineArray(d, oracle: [1, 2, 4, 8])
79+
}
80+
do {
81+
let a = InlineArray<4, Int> { 1 << $0 }
82+
let b = InlineArray<4, Int>(first: 1) { $0 << 1 }
83+
var c = InlineArray<4, Int>(repeating: 9)
84+
var d = InlineArray<4, Int>(repeating: 9)
85+
_checkInlineArray(c, oracle: [9, 9, 9, 9])
86+
_checkInlineArray(d, oracle: [9, 9, 9, 9])
87+
c[0] = 1
88+
c[1] = 2
89+
c[2] = 4
90+
c[3] = 8
91+
d[unchecked: 0] = 1
92+
d[unchecked: 1] = 2
93+
d[unchecked: 2] = 4
94+
d[unchecked: 3] = 8
95+
_checkInlineArray(a, oracle: [1, 2, 4, 8])
96+
_checkInlineArray(b, oracle: [1, 2, 4, 8])
97+
_checkInlineArray(c, oracle: [1, 2, 4, 8])
98+
_checkInlineArray(d, oracle: [1, 2, 4, 8])
99+
}
100+
}
101+
102+
/// An array and its elements can be of *noncopyable* type.
103+
@available(SwiftStdlib 6.2, *)
104+
static func testNoncopyable() {
105+
var a = InlineArray<4, Atomic<Int>> { Atomic(1 << $0) }
106+
var b = InlineArray<4, Atomic<Int>>(first: Atomic(1)) {
107+
Atomic($0.load(ordering: .relaxed) << 1)
108+
}
109+
let c: InlineArray = [Atomic(8), Atomic(4), Atomic(2), Atomic(1)]
110+
expectEqual(a.indices, c.indices)
111+
expectEqual(b.indices, c.indices)
112+
// Perform in-place reversals to test the `swapAt(_:_:)` method.
113+
a._reverse()
114+
b._reverse()
115+
for i in c.indices {
116+
expectEqual(
117+
a[i].load(ordering: .relaxed),
118+
c[i].load(ordering: .relaxed)
119+
)
120+
expectEqual(
121+
b[i].load(ordering: .relaxed),
122+
c[i].load(ordering: .relaxed)
123+
)
124+
expectEqual(
125+
a[unchecked: i].load(ordering: .relaxed),
126+
c[unchecked: i].load(ordering: .relaxed)
127+
)
128+
expectEqual(
129+
b[unchecked: i].load(ordering: .relaxed),
130+
c[unchecked: i].load(ordering: .relaxed)
131+
)
132+
}
133+
}
134+
135+
/// An *empty* array's elements can be of *uninhabited* type.
136+
@available(SwiftStdlib 6.2, *)
137+
static func testUninhabited() {
138+
#if false // FIXME: Empty array literals aren't supported.
139+
do {
140+
let e: InlineArray<0, Never> = []
141+
let f: InlineArray<_, Never> = []
142+
_checkInlineArray(e, oracle: [])
143+
_checkInlineArray(f, oracle: [])
144+
}
145+
#endif
146+
do {
147+
let e = InlineArray<0, Never> { _ in fatalError() }
148+
let f = InlineArray<0, _> { _ in fatalError() }
149+
_checkInlineArray(e, oracle: [])
150+
_checkInlineArray(f, oracle: [])
151+
}
152+
}
153+
}
154+
155+
//===----------------------------------------------------------------------===//
156+
// MARK: - InlineArray Additions
157+
//===----------------------------------------------------------------------===//
158+
159+
@available(SwiftStdlib 6.2, *)
160+
extension InlineArray where Element: ~Copyable {
161+
162+
/// Reverses the elements of the array in place.
163+
///
164+
/// - Complexity: O(*n*), where *n* is the number of elements in the array.
165+
@available(SwiftStdlib 6.2, *)
166+
mutating func _reverse() {
167+
if isEmpty { return }
168+
var i = startIndex
169+
var j = index(before: endIndex)
170+
while i < j {
171+
swapAt(i, j)
172+
i = index(after: i)
173+
j = index(before: j)
174+
}
175+
}
176+
}
177+
178+
//===----------------------------------------------------------------------===//
179+
// MARK: - StdlibUnittest Additions
180+
//===----------------------------------------------------------------------===//
181+
182+
/// Tests the properties and subscripts of an `InlineArray` instance, by
183+
/// comparing them against an `Array` oracle with the expected elements.
184+
@available(SwiftStdlib 6.2, *)
185+
func _checkInlineArray<let count: Int, Element: Equatable>(
186+
_ inlineArray: InlineArray<count, Element>,
187+
oracle: [Element],
188+
stackTrace: SourceLocStack = SourceLocStack(),
189+
showFrame: Bool = true,
190+
file: String = #file,
191+
line: UInt = #line
192+
) {
193+
// Check the properties.
194+
expectEqual(
195+
inlineArray.count,
196+
oracle.count,
197+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
198+
)
199+
expectEqual(
200+
inlineArray.isEmpty,
201+
oracle.isEmpty,
202+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
203+
)
204+
expectEqual(
205+
inlineArray.startIndex,
206+
oracle.startIndex,
207+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
208+
)
209+
expectEqual(
210+
inlineArray.endIndex,
211+
oracle.endIndex,
212+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
213+
)
214+
expectEqual(
215+
inlineArray.indices,
216+
oracle.indices,
217+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
218+
)
219+
// Check the subscripts.
220+
for (i, j) in zip(inlineArray.indices, oracle.indices) {
221+
expectEqual(
222+
inlineArray[i],
223+
oracle[j],
224+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
225+
)
226+
expectEqual(
227+
inlineArray[unchecked: i],
228+
oracle[j],
229+
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
230+
)
231+
}
232+
}

0 commit comments

Comments
 (0)