[android] Adapt POSIX test to Android

Android differs in subtle ways from Linux. For example sem_open is
completely unimplemented, and always returns ENOSYS. None of the
test using sem_open were going to work.

Additionally the l_len field of the flock struct is typed as
__kernel_off_t, which doesn't have the same size as off_t.

Finally, the current working directory is always /, so creating
relative files will fail. We have to find the executable directory
and create the file there.
This commit is contained in:
Daniel Rodríguez Troitiño
2018-10-23 18:44:52 -07:00
parent 5c03a0a1f0
commit a17f45d220

View File

@@ -1,12 +1,8 @@
// RUN: %target-run-simple-swift %t
// REQUIRES: executable_test
// Android Bionic does not provide a working implementation of
// <semaphore.h>.
// XFAIL: OS=linux-androideabi
import StdlibUnittest
#if os(Linux)
#if os(Linux) || os(Android)
import Glibc
#else
import Darwin
@@ -17,7 +13,38 @@ 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)
@@ -25,13 +52,16 @@ POSIXTests.setUp {
}
// 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)
@@ -42,8 +72,10 @@ POSIXTests.test("sem_open success") {
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)
@@ -54,8 +86,10 @@ POSIXTests.test("sem_open O_EXCL success") {
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)
@@ -71,8 +105,10 @@ POSIXTests.test("sem_open existing") {
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)
@@ -87,6 +123,7 @@ POSIXTests.test("sem_open existing O_EXCL fail") {
let res2 = sem_unlink(semaphoreName)
expectEqual(0, res2)
}
#endif
// Fail because the file descriptor is invalid.
POSIXTests.test("ioctl(CInt, UInt, CInt): fail") {
@@ -99,7 +136,7 @@ POSIXTests.test("ioctl(CInt, UInt, CInt): fail") {
expectEqual(EBADF, errno)
}
#if os(Linux)
#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
@@ -204,7 +241,13 @@ POSIXTests.test("fcntl(CInt, CInt, UnsafeMutableRawPointer): locking and unlocki
// 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)
@@ -223,4 +266,3 @@ POSIXTests.test("fcntl(CInt, CInt, UnsafeMutableRawPointer): locking and unlocki
}
runAllTests()