Files
swift-mirror/test/stdlib/POSIX.swift
2025-07-23 10:10:47 +01:00

271 lines
6.6 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// RUN: %target-run-simple-swift %t
// REQUIRES: executable_test
// UNSUPPORTED: OS=windows-msvc
// UNSUPPORTED: OS=wasip1
// UNSUPPORTED: OS=freebsd
import StdlibUnittest
import SwiftPrivateLibcExtras
#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Android)
import Android
#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 doesnt 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 doesnt 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 doesnt 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 doesnt 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 doesnt 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()