//===--- MutableSpanTests.swift -------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2025 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // RUN: %target-run-stdlib-swift // REQUIRES: executable_test import StdlibUnittest var suite = TestSuite("MutableSpan Tests") defer { runAllTests() } suite.test("Initialize with ordinary element") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } let capacity = 4 var s = (0..(_unsafeStart: rp, byteCount: bc) expectEqual(b.count, capacity) let stride = MemoryLayout.stride let r = MutableSpan(_unsafeBytes: $0.dropFirst(stride)) expectEqual(r.count, (capacity-1)*stride) expectEqual(r.count, bc-stride) } let v = UnsafeMutableRawBufferPointer(start: nil, count: 0) let m = MutableSpan(_unsafeBytes: v) expectEqual(m.count, 0) } suite.test("isEmpty") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } var array = [0, 1, 2] array.withUnsafeMutableBufferPointer { let span = MutableSpan(_unsafeElements: $0) let e = span.isEmpty expectFalse(e) } array = [] array.withUnsafeMutableBufferPointer { let span = MutableSpan(_unsafeElements: $0) let e = span.isEmpty expectTrue(e) } } suite.test("Span from MutableSpan") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } var array = [0, 1, 2] array.withUnsafeMutableBufferPointer { let mutable = MutableSpan(_unsafeElements: $0) let immutable = Span(_mutableSpan: mutable) expectEqual(mutable.count, immutable.count) } } suite.test("RawSpan from MutableSpan") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } let count = 4 var array = Array(0...stride) let v = bytes.unsafeLoad( fromByteOffset: MemoryLayout.stride, as: Int.self ) expectEqual(v, 1) } } suite.test("MutableRawSpan from MutableSpan") .require(.stdlib_6_2).code { guard #available(SwiftStdlib 6.2, *) else { return } let count = 4 var array = Array(0...stride) bytes.storeBytes(of: 1, as: Int.self) } expectEqual(array[0], 1) } suite.test("indices property") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } let capacity = 4 var a = Array(0..(start: nil, count: 0) var span = MutableSpan(_unsafeElements: empty) var (iterator, updated) = span.update(from: 0..<0) expectNil(iterator.next()) expectEqual(updated, 0) span = MutableSpan(_unsafeElements: $0) (iterator, updated) = span.update(from: 0..<0) expectNil(iterator.next()) expectEqual(updated, 0) (iterator, updated) = span.update(from: 0..<10000) expectNotNil(iterator.next()) expectEqual(updated, capacity) } expectEqual(a.elementsEqual(0...allocate(capacity: 2*capacity) let i = b.initialize(fromContentsOf: (0..<2*capacity).map(ID.init(id:))) expectEqual(i, 2*capacity) a.withUnsafeMutableBufferPointer { var span = MutableSpan(_unsafeElements: $0) let updated = span.moveUpdate(fromContentsOf: b.suffix(capacity)) expectEqual(updated, capacity) } expectEqual(a.map(\.id).elementsEqual(capacity..<2*capacity), true) a = [] b.prefix(capacity).deinitialize() b.deallocate() } suite.test("span property") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } let count = 8 let b = UnsafeMutableBufferPointer.allocate(capacity: count) _ = b.initialize(fromContentsOf: 0..(start: nil, count: 0) defer { _ = e } var m = MutableSpan(_unsafeElements: b) m[0] = 100 expectEqual(m.count, count) expectEqual(m[0], 100) var s = m.span expectEqual(s.count, m.count) expectEqual(s[0], m[0]) // we're done using `s` before it gets reassigned m.update(repeating: 7) s = m.span // m[0] = -1 // exclusivity violation expectEqual(s.count, m.count) expectEqual(s[0], m[0]) } suite.test("swapAt") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } let count = 8 var array = Array(0.. var span = MutableSpan(_unsafeElements: $0) expectEqual(span.count, capacity) prefix = span.extracting(first: 1) expectEqual(prefix[0], 0) prefix = span.extracting(first: capacity) expectEqual(prefix[capacity-1], UInt8(capacity-1)) prefix = span.extracting(droppingLast: capacity) expectEqual(prefix.isEmpty, true) prefix = span.extracting(droppingLast: 1) expectEqual(prefix[capacity-2], UInt8(capacity-2)) } do { let b = UnsafeMutableBufferPointer(start: nil, count: 0) var span = MutableSpan(_unsafeElements: b) expectEqual(span.count, b.count) expectEqual(span.extracting(first: 1).count, b.count) expectEqual(span.extracting(droppingLast: 1).count, b.count) } } suite.test("extracting suffixes") .skip(.custom( { if #available(SwiftStdlib 6.2, *) { false } else { true } }, reason: "Requires Swift 6.2's standard library" )) .code { guard #available(SwiftStdlib 6.2, *) else { return } let capacity = 4 var a = Array(0.. var span = MutableSpan(_unsafeElements: $0) expectEqual(span.count, capacity) suffix = span.extracting(last: capacity) expectEqual(suffix[0], 0) suffix = span.extracting(last: capacity-1) expectEqual(suffix[0], 1) suffix = span.extracting(last: 1) expectEqual(suffix[0], UInt8(capacity-1)) suffix = span.extracting(droppingFirst: capacity) expectTrue(suffix.isEmpty) suffix = span.extracting(droppingFirst: 1) expectEqual(suffix[0], 1) } do { let b = UnsafeMutableBufferPointer(start: nil, count: 0) var span = MutableSpan(_unsafeElements: b) expectEqual(span.count, b.count) expectEqual(span.extracting(last: 1).count, b.count) expectEqual(span.extracting(droppingFirst: 1).count, b.count) } }