blob: 91cec1c2e01bd0920dd8f529f8149e8b0a2a09ad [file] [log] [blame]
// 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()