mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Different tests used different os checks for importing Darwin, Glibc and MSVCRT. This commit use the same pattern for importing those libraries, in order to avoid the #else branches of the incorrect patterns to be applied to the wrong platform. This was very normal for Android, which normally should follow the Linux branches, but sometimes was trying to import Darwin or not importing anything. The standarized pattern imports Darwin for macOS, iOS, tvOS and watchOS. It imports Glibc for Linux, FreeBSD, PS4, Android, Cygwin and Haiku; and imports MSVCRT for Windows. If a new platform is introduced, the else branch will report an error, so the new platform can be added to one of the branches (or maybe add a new specific branch). In some cases the standard pattern was modified because some test required it (importing extra modules, or extra type aliases), and in some other cases some branches were removed because the test will not have used them (but it is not exhaustive, so there might be some unnecessary branches). This should, at least, fix three tests for Android (the three dynamic_replacement*.swift ones).
272 lines
6.8 KiB
Swift
272 lines
6.8 KiB
Swift
// RUN: %target-run-simple-swift %t
|
||
// REQUIRES: executable_test
|
||
// UNSUPPORTED: OS=windows-msvc
|
||
|
||
import StdlibUnittest
|
||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||
import Darwin
|
||
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
|
||
import Glibc
|
||
#else
|
||
#error("Unsupported platform")
|
||
#endif
|
||
|
||
chdir(CommandLine.arguments[1])
|
||
|
||
var POSIXTests = TestSuite("POSIXTests")
|
||
|
||
let semaphoreName = "TestSem"
|
||
#if os(Android)
|
||
// In Android, the cwd is the root directory, which is not writable.
|
||
let fn: String = {
|
||
let capacity = Int(PATH_MAX)
|
||
let resolvedPath = UnsafeMutablePointer<Int8>.allocate(capacity: capacity)
|
||
resolvedPath.initialize(repeating: 0, count: capacity)
|
||
defer {
|
||
resolvedPath.deinitialize(count: capacity)
|
||
resolvedPath.deallocate()
|
||
}
|
||
guard let _ = realpath("/proc/self/exe", resolvedPath) else {
|
||
fatalError("Couldn't obtain executable path")
|
||
}
|
||
|
||
let length = strlen(resolvedPath)
|
||
precondition(length != 0, "Couldn't obtain valid executable path")
|
||
|
||
// Search backwards for the last /, and turn it into a null byte.
|
||
for idx in stride(from: length-1, through: 0, by: -1) {
|
||
if Unicode.Scalar(UInt8(resolvedPath[idx])) == Unicode.Scalar("/") {
|
||
resolvedPath[idx] = 0
|
||
break
|
||
}
|
||
|
||
precondition(idx != 0, "Couldn't obtain valid executable directory")
|
||
}
|
||
|
||
return String(cString: resolvedPath) + "/test.txt"
|
||
}()
|
||
#else
|
||
let fn = "test.txt"
|
||
#endif
|
||
|
||
POSIXTests.setUp {
|
||
sem_unlink(semaphoreName)
|
||
unlink(fn)
|
||
}
|
||
|
||
// Failed semaphore creation.
|
||
#if !os(Android) // Android doesn’t implement sem_open and always return ENOSYS
|
||
POSIXTests.test("sem_open fail") {
|
||
let sem = sem_open(semaphoreName, 0)
|
||
expectEqual(SEM_FAILED, sem)
|
||
expectEqual(ENOENT, errno)
|
||
}
|
||
#endif
|
||
|
||
// Successful semaphore creation.
|
||
#if !os(Android) // Android doesn’t implement sem_open and always return ENOSYS
|
||
POSIXTests.test("sem_open success") {
|
||
let sem = sem_open(semaphoreName, O_CREAT, 0o777, 1)
|
||
expectNotEqual(SEM_FAILED, sem)
|
||
|
||
let res = sem_close(sem)
|
||
expectEqual(0, res)
|
||
|
||
let res2 = sem_unlink(semaphoreName)
|
||
expectEqual(0, res2)
|
||
}
|
||
#endif
|
||
|
||
// Successful semaphore creation with O_EXCL.
|
||
#if !os(Android) // Android doesn’t implement sem_open and always return ENOSYS
|
||
POSIXTests.test("sem_open O_EXCL success") {
|
||
let sem = sem_open(semaphoreName, O_CREAT | O_EXCL, 0o777, 1)
|
||
expectNotEqual(SEM_FAILED, sem)
|
||
|
||
let res = sem_close(sem)
|
||
expectEqual(0, res)
|
||
|
||
let res2 = sem_unlink(semaphoreName)
|
||
expectEqual(0, res2)
|
||
}
|
||
#endif
|
||
|
||
// Successful creation and re-obtaining of existing semaphore.
|
||
#if !os(Android) // Android doesn’t implement sem_open and always return ENOSYS
|
||
POSIXTests.test("sem_open existing") {
|
||
let sem = sem_open(semaphoreName, O_CREAT, 0o777, 1)
|
||
expectNotEqual(SEM_FAILED, sem)
|
||
|
||
let sem2 = sem_open(semaphoreName, 0)
|
||
// Here, we'd like to test that the semaphores are the same, but it's quite
|
||
// difficult.
|
||
expectNotEqual(SEM_FAILED, sem2)
|
||
|
||
let res = sem_close(sem)
|
||
expectEqual(0, res)
|
||
|
||
let res2 = sem_unlink(semaphoreName)
|
||
expectEqual(0, res2)
|
||
}
|
||
#endif
|
||
|
||
// Fail because the semaphore already exists.
|
||
#if !os(Android) // Android doesn’t implement sem_open and always return ENOSYS
|
||
POSIXTests.test("sem_open existing O_EXCL fail") {
|
||
let sem = sem_open(semaphoreName, O_CREAT, 0o777, 1)
|
||
expectNotEqual(SEM_FAILED, sem)
|
||
|
||
let sem2 = sem_open(semaphoreName, O_CREAT | O_EXCL, 0o777, 1)
|
||
expectEqual(SEM_FAILED, sem2)
|
||
expectEqual(EEXIST, errno)
|
||
|
||
let res = sem_close(sem)
|
||
expectEqual(0, res)
|
||
|
||
let res2 = sem_unlink(semaphoreName)
|
||
expectEqual(0, res2)
|
||
}
|
||
#endif
|
||
|
||
// Fail because the file descriptor is invalid.
|
||
POSIXTests.test("ioctl(CInt, UInt, CInt): fail") {
|
||
let fd = open(fn, 0)
|
||
expectEqual(-1, fd)
|
||
expectEqual(ENOENT, errno)
|
||
|
||
// A simple check to verify that ioctl is available
|
||
let _ = ioctl(fd, 0, 0)
|
||
expectEqual(EBADF, errno)
|
||
}
|
||
|
||
#if os(Linux) || os(Android)
|
||
// Successful creation of a socket and listing interfaces
|
||
POSIXTests.test("ioctl(CInt, UInt, UnsafeMutableRawPointer): listing interfaces success") {
|
||
// Create a socket
|
||
let sock = socket(PF_INET, 1, 0)
|
||
expectGT(Int(sock), 0)
|
||
|
||
// List interfaces
|
||
var ic = ifconf()
|
||
let io = ioctl(sock, UInt(SIOCGIFCONF), &ic);
|
||
expectGE(io, 0)
|
||
|
||
//Cleanup
|
||
let res = close(sock)
|
||
expectEqual(0, res)
|
||
}
|
||
#endif
|
||
|
||
// Fail because file doesn't exist.
|
||
POSIXTests.test("fcntl(CInt, CInt): fail") {
|
||
let fd = open(fn, 0)
|
||
expectEqual(-1, fd)
|
||
expectEqual(ENOENT, errno)
|
||
|
||
let _ = fcntl(fd, F_GETFL)
|
||
expectEqual(EBADF, errno)
|
||
}
|
||
|
||
// Change modes on existing file.
|
||
POSIXTests.test("fcntl(CInt, CInt): F_GETFL/F_SETFL success with file") {
|
||
// Create and open file.
|
||
let fd = open(fn, O_CREAT, 0o666)
|
||
expectGT(Int(fd), 0)
|
||
|
||
var flags = fcntl(fd, F_GETFL)
|
||
expectGE(Int(flags), 0)
|
||
|
||
// Change to APPEND mode...
|
||
var rc = fcntl(fd, F_SETFL, O_APPEND)
|
||
expectEqual(0, rc)
|
||
|
||
flags = fcntl(fd, F_GETFL)
|
||
expectEqual(flags | O_APPEND, flags)
|
||
|
||
// Change back...
|
||
rc = fcntl(fd, F_SETFL, 0)
|
||
expectEqual(0, rc)
|
||
|
||
flags = fcntl(fd, F_GETFL)
|
||
expectGE(Int(flags), 0)
|
||
|
||
// Clean up...
|
||
rc = close(fd)
|
||
expectEqual(0, rc)
|
||
|
||
rc = unlink(fn)
|
||
expectEqual(0, rc)
|
||
}
|
||
|
||
POSIXTests.test("fcntl(CInt, CInt, CInt): block and unblocking sockets success") {
|
||
// Create socket, note: socket created by default in blocking mode...
|
||
let sock = socket(PF_INET, 1, 0)
|
||
expectGT(Int(sock), 0)
|
||
|
||
var flags = fcntl(sock, F_GETFL)
|
||
expectGE(Int(flags), 0)
|
||
|
||
// Change mode of socket to non-blocking...
|
||
var rc = fcntl(sock, F_SETFL, flags | O_NONBLOCK)
|
||
expectEqual(0, rc)
|
||
|
||
flags = fcntl(sock, F_GETFL)
|
||
expectEqual((flags | O_NONBLOCK), flags)
|
||
|
||
// Change back to blocking...
|
||
rc = fcntl(sock, F_SETFL, flags & ~O_NONBLOCK)
|
||
expectEqual(0, rc)
|
||
|
||
flags = fcntl(sock, F_GETFL)
|
||
expectGE(Int(flags), 0)
|
||
|
||
// Clean up...
|
||
rc = close(sock)
|
||
expectEqual(0, rc)
|
||
}
|
||
|
||
POSIXTests.test("fcntl(CInt, CInt, UnsafeMutableRawPointer): locking and unlocking success") {
|
||
// Create the file and add data to it...
|
||
var fd = open(fn, O_CREAT | O_WRONLY, 0o666)
|
||
expectGT(Int(fd), 0)
|
||
|
||
let data = "Testing 1 2 3"
|
||
let bytesWritten = write(fd, data, data.utf8.count)
|
||
expectEqual(data.utf8.count, bytesWritten)
|
||
|
||
var rc = close(fd)
|
||
expectEqual(0, rc)
|
||
|
||
// Re-open the file...
|
||
fd = open(fn, 0)
|
||
expectGT(Int(fd), 0)
|
||
|
||
// Lock for reading...
|
||
var flck = flock()
|
||
flck.l_type = Int16(F_RDLCK)
|
||
#if os(Android)
|
||
// In Android l_len is __kernel_off_t which is not the same size as off_t in
|
||
// 64 bits.
|
||
flck.l_len = __kernel_off_t(data.utf8.count)
|
||
#else
|
||
flck.l_len = off_t(data.utf8.count)
|
||
#endif
|
||
rc = fcntl(fd, F_SETLK, &flck)
|
||
expectEqual(0, rc)
|
||
|
||
// Unlock for reading...
|
||
flck = flock()
|
||
flck.l_type = Int16(F_UNLCK)
|
||
rc = fcntl(fd, F_SETLK, &flck)
|
||
expectEqual(0, rc)
|
||
|
||
// Clean up...
|
||
rc = close(fd)
|
||
expectEqual(0, rc)
|
||
|
||
rc = unlink(fn)
|
||
expectEqual(0, rc)
|
||
}
|
||
|
||
runAllTests()
|