Description
The following test, run from the command line in a loop, will eventually fail at random because the String constructor returns an empty string:
import Foundation
import Testing
@Suite struct FormatTest {
@Test(arguments: [
(input: 0o000, expected: "000000"),
(input: 0o555, expected: "000555"),
(input: 0o750, expected: "000750"),
(input: 0o777, expected: "000777"),
(input: 0o1777, expected: "001777"),
])
func testStringFormat(input: Int, expected: String) async throws {
#expect(String(format: "%06o", input) == expected)
}
}
On my machine it fails roughly once in every 20 runs, on different test inputs. The error is always that the constructor returns an empty string. The inputs are fixed and always in a range which can be represented in a 6 character octal string.
Test testStringFormat(input:expected:) recorded an issue with 2 arguments input → 1023, expected → "001777" at StringTests.swift:13:9: Expectation failed: (String(format: "%06o", input) → "") == (expected → "001777")
I only noticed this when I started to use swift-testing
, which runs test cases in parallel by default. It has never come up in actual use, as far as I'm aware, because I only use this constructor in single-threaded sequential code.
Could there be a shared buffer somewhere in the CFString
underpinnings which makes this constructor not threadsafe? I didn't see anything warning about this in the docs: https://developer.apple.com/documentation/swift/string/init(format:_:).
XCode 16.2 / 16C5032a
macOS 15.1.1 (24B91)
% swift -version
swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
Target: arm64-apple-macosx15.0