Skip to content

Commit f2c8ee1

Browse files
grynspancompnerd
andauthored
Add basic platform support for Android. (#653)
This PR seeks out all the nooks and crannies where we have platform-specific code or logic and adds Android. In most cases, it's as simple as changing `os(Linux)` to `os(Linux) || os(Android)` but there are a few spots where they diverge. The PR should be _mostly_ self-explanatory. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated. Co-authored-by: Saleem Abdulrasool <[email protected]>
1 parent 4c1286e commit f2c8ee1

File tree

19 files changed

+70
-31
lines changed

19 files changed

+70
-31
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ extension Array where Element == PackageDescription.SwiftSetting {
130130

131131
.define("SWT_TARGET_OS_APPLE", .when(platforms: [.macOS, .iOS, .macCatalyst, .watchOS, .tvOS, .visionOS])),
132132

133-
.define("SWT_NO_EXIT_TESTS", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi])),
133+
.define("SWT_NO_EXIT_TESTS", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android])),
134134
.define("SWT_NO_SNAPSHOT_TYPES", .when(platforms: [.linux, .windows, .wasi])),
135135
.define("SWT_NO_DYNAMIC_LINKING", .when(platforms: [.wasi])),
136136
]

Sources/Testing/ABI/EntryPoints/EntryPoint.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ extension Event.ConsoleOutputRecorder.Options {
651651
/// Whether or not the system terminal claims to support 16-color ANSI escape
652652
/// codes.
653653
private static var _terminalSupports16ColorANSIEscapeCodes: Bool {
654-
#if SWT_TARGET_OS_APPLE || os(Linux)
654+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
655655
if let termVariable = Environment.variable(named: "TERM") {
656656
return termVariable != "dumb"
657657
}
@@ -673,7 +673,7 @@ extension Event.ConsoleOutputRecorder.Options {
673673
/// Whether or not the system terminal claims to support 256-color ANSI escape
674674
/// codes.
675675
private static var _terminalSupports256ColorANSIEscapeCodes: Bool {
676-
#if SWT_TARGET_OS_APPLE || os(Linux)
676+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
677677
if let termVariable = Environment.variable(named: "TERM") {
678678
return strstr(termVariable, "256") != nil
679679
}
@@ -695,7 +695,7 @@ extension Event.ConsoleOutputRecorder.Options {
695695
/// Whether or not the system terminal claims to support true-color ANSI
696696
/// escape codes.
697697
private static var _terminalSupportsTrueColorANSIEscapeCodes: Bool {
698-
#if SWT_TARGET_OS_APPLE || os(Linux)
698+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
699699
if let colortermVariable = Environment.variable(named: "COLORTERM") {
700700
return strstr(colortermVariable, "truecolor") != nil
701701
}

Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private import _TestingInternals
2424
///
2525
/// This constant is not part of the public interface of the testing library.
2626
var EXIT_NO_TESTS_FOUND: CInt {
27-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
27+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
2828
EX_UNAVAILABLE
2929
#elseif os(Windows)
3030
CInt(ERROR_NOT_FOUND)

Sources/Testing/Events/Recorder/Event.Symbol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ extension Event.Symbol {
100100
/// be used to represent it in text-based output. The value of this property
101101
/// is platform-dependent.
102102
public var unicodeCharacter: Character {
103-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
103+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
104104
switch self {
105105
case .default:
106106
// Unicode: WHITE DIAMOND

Sources/Testing/SourceAttribution/Backtrace.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ public struct Backtrace: Sendable {
7171
}
7272
#elseif os(Linux)
7373
initializedCount = .init(backtrace(addresses.baseAddress!, .init(addresses.count)))
74+
#elseif os(Android)
75+
addresses.withMemoryRebound(to: UnsafeMutableRawPointer.self) { addresses in
76+
initializedCount = .init(backtrace(addresses.baseAddress!, .init(addresses.count)))
77+
}
7478
#elseif os(Windows)
7579
initializedCount = Int(RtlCaptureStackBackTrace(0, ULONG(addresses.count), addresses.baseAddress!, nil))
7680
#elseif os(WASI)

Sources/Testing/Support/Additions/CommandLineAdditions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ extension CommandLine {
2929
}
3030
}
3131
return result!
32-
#elseif os(Linux)
32+
#elseif os(Linux) || os(Android)
3333
return try withUnsafeTemporaryAllocation(of: CChar.self, capacity: Int(PATH_MAX) * 2) { buffer in
34-
let readCount = readlink("/proc/\(getpid())/exe", buffer.baseAddress!, buffer.count - 1)
34+
let readCount = readlink("/proc/self/exe", buffer.baseAddress!, buffer.count - 1)
3535
guard readCount >= 0 else {
3636
throw CError(rawValue: swt_errno())
3737
}

Sources/Testing/Support/Environment.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ enum Environment {
4242
}
4343
}
4444

45-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
45+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
4646
/// Get all environment variables from a POSIX environment block.
4747
///
4848
/// - Parameters:
@@ -103,7 +103,7 @@ enum Environment {
103103
}
104104
#endif
105105
return _get(fromEnviron: _NSGetEnviron()!.pointee!)
106-
#elseif os(Linux)
106+
#elseif os(Linux) || os(Android)
107107
_get(fromEnviron: swt_environ())
108108
#elseif os(WASI)
109109
_get(fromEnviron: __wasilibc_get_environ())
@@ -170,7 +170,7 @@ enum Environment {
170170
}
171171
return nil
172172
}
173-
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
173+
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
174174
getenv(name).flatMap { String(validatingCString: $0) }
175175
#elseif os(Windows)
176176
name.withCString(encodedAs: UTF16.self) { name in

Sources/Testing/Support/FileHandle.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ struct FileHandle: ~Copyable, Sendable {
156156
/// descriptor, `nil` is passed to `body`.
157157
borrowing func withUnsafePOSIXFileDescriptor<R>(_ body: (CInt?) throws -> R) rethrows -> R {
158158
try withUnsafeCFILEHandle { handle in
159-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
159+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
160160
let fd = fileno(handle)
161161
#elseif os(Windows)
162162
let fd = _fileno(handle)
@@ -215,7 +215,7 @@ struct FileHandle: ~Copyable, Sendable {
215215
/// other threads.
216216
borrowing func withLock<R>(_ body: () throws -> R) rethrows -> R {
217217
try withUnsafeCFILEHandle { handle in
218-
#if SWT_TARGET_OS_APPLE || os(Linux)
218+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
219219
flockfile(handle)
220220
defer {
221221
funlockfile(handle)
@@ -250,7 +250,7 @@ extension FileHandle {
250250
// If possible, reserve enough space in the resulting buffer to contain
251251
// the contents of the file being read.
252252
var size: Int?
253-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
253+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
254254
withUnsafePOSIXFileDescriptor { fd in
255255
var s = stat()
256256
if let fd, 0 == fstat(fd, &s) {
@@ -388,7 +388,7 @@ extension FileHandle {
388388
extension FileHandle {
389389
/// Is this file handle a TTY or PTY?
390390
var isTTY: Bool {
391-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
391+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
392392
// If stderr is a TTY and TERM is set, that's good enough for us.
393393
withUnsafePOSIXFileDescriptor { fd in
394394
if let fd, 0 != isatty(fd), let term = Environment.variable(named: "TERM"), !term.isEmpty {
@@ -414,7 +414,7 @@ extension FileHandle {
414414

415415
/// Is this file handle a pipe or FIFO?
416416
var isPipe: Bool {
417-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
417+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || os(WASI)
418418
withUnsafePOSIXFileDescriptor { fd in
419419
guard let fd else {
420420
return false

Sources/Testing/Support/GetSymbol.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal import _TestingInternals
1313
#if !SWT_NO_DYNAMIC_LINKING
1414

1515
/// The platform-specific type of a loaded image handle.
16-
#if SWT_TARGET_OS_APPLE || os(Linux)
16+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
1717
typealias ImageAddress = UnsafeMutableRawPointer
1818
#elseif os(Windows)
1919
typealias ImageAddress = HMODULE
@@ -30,7 +30,9 @@ typealias ImageAddress = Never
3030
/// declare a wrapper function in the internal module's Stubs.h file.
3131
#if SWT_TARGET_OS_APPLE
3232
private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: -2)
33-
#elseif os(Linux)
33+
#elseif os(Android) && _pointerBitWidth(_32)
34+
private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: 0xFFFFFFFF)
35+
#elseif os(Linux) || os(Android)
3436
private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: 0)
3537
#endif
3638

@@ -57,7 +59,7 @@ private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: 0)
5759
/// calling `EnumProcessModules()` and iterating over the returned handles
5860
/// looking for one containing the given function.
5961
func symbol(in handle: ImageAddress? = nil, named symbolName: String) -> UnsafeRawPointer? {
60-
#if SWT_TARGET_OS_APPLE || os(Linux)
62+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
6163
dlsym(handle ?? RTLD_DEFAULT, symbolName).map(UnsafeRawPointer.init)
6264
#elseif os(Windows)
6365
symbolName.withCString { symbolName in

Sources/Testing/Support/Locked.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
3636
/// To keep the implementation of this type as simple as possible,
3737
/// `pthread_mutex_t` is used on Apple platforms instead of `os_unfair_lock`
3838
/// or `OSAllocatedUnfairLock`.
39-
#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
39+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
4040
private typealias _Lock = pthread_mutex_t
4141
#elseif os(Windows)
4242
private typealias _Lock = SRWLOCK
@@ -52,7 +52,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
5252
private final class _Storage: ManagedBuffer<T, _Lock> {
5353
deinit {
5454
withUnsafeMutablePointerToElements { lock in
55-
#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
55+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
5656
_ = pthread_mutex_destroy(lock)
5757
#elseif os(Windows)
5858
// No deinitialization needed.
@@ -71,7 +71,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
7171
init(rawValue: T) {
7272
_storage = _Storage.create(minimumCapacity: 1, makingHeaderWith: { _ in rawValue })
7373
_storage.withUnsafeMutablePointerToElements { lock in
74-
#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
74+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
7575
_ = pthread_mutex_init(lock, nil)
7676
#elseif os(Windows)
7777
InitializeSRWLock(lock)
@@ -101,7 +101,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
101101
/// concurrency tools.
102102
nonmutating func withLock<R>(_ body: (inout T) throws -> R) rethrows -> R {
103103
try _storage.withUnsafeMutablePointers { rawValue, lock in
104-
#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
104+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
105105
_ = pthread_mutex_lock(lock)
106106
defer {
107107
_ = pthread_mutex_unlock(lock)
@@ -121,7 +121,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
121121
}
122122
}
123123

124-
#if SWT_TARGET_OS_APPLE || os(Linux) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
124+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
125125
/// Acquire the lock and invoke a function while it is held, yielding both the
126126
/// protected value and a reference to the lock itself.
127127
///

0 commit comments

Comments
 (0)