mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Use off_t for a recently failing stdlib test, remove Python hacks for some tests that now work without them, and correct build flag in the docs.
268 lines
6.6 KiB
Swift
268 lines
6.6 KiB
Swift
// RUN: %target-run-simple-swift %t
|
||
// REQUIRES: executable_test
|
||
// UNSUPPORTED: OS=windows-msvc
|
||
// UNSUPPORTED: OS=wasi
|
||
|
||
import StdlibUnittest
|
||
import SwiftPrivateLibcExtras
|
||
#if canImport(Darwin)
|
||
import Darwin
|
||
#elseif canImport(Glibc)
|
||
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)
|
||
flck.l_len = off_t(data.utf8.count)
|
||
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()
|