mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 06:57:45 +00:00
Tests: Move the LibPthread tests to the correct namespace
This commit is contained in:
parent
2f3b9c49a5
commit
dac361e330
6 changed files with 3 additions and 10 deletions
|
@ -14,6 +14,9 @@ set(TEST_SOURCES
|
|||
TestMemalign.cpp
|
||||
TestMemmem.cpp
|
||||
TestMkDir.cpp
|
||||
TestPthreadCleanup.cpp
|
||||
TestPthreadSpinLocks.cpp
|
||||
TestPthreadRWLocks.cpp
|
||||
TestQsort.cpp
|
||||
TestRaise.cpp
|
||||
TestRealpath.cpp
|
||||
|
|
86
Tests/LibC/TestPthreadCleanup.cpp
Normal file
86
Tests/LibC/TestPthreadCleanup.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tim Schumacher <timschumi@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static size_t exit_count = 0;
|
||||
|
||||
static void exit_count_test_handler(void* data)
|
||||
{
|
||||
EXPECT_EQ(exit_count, reinterpret_cast<size_t>(data));
|
||||
exit_count++;
|
||||
}
|
||||
|
||||
static void immediate_fail_handler(void*)
|
||||
{
|
||||
FAIL("Called a cleanup handler");
|
||||
}
|
||||
|
||||
static void* cleanup_pthread_exit_inner(void*)
|
||||
{
|
||||
// Push handlers in reverse order as they are taken from the top of the stack on cleanup.
|
||||
pthread_cleanup_push(exit_count_test_handler, reinterpret_cast<void*>(2));
|
||||
pthread_cleanup_push(exit_count_test_handler, reinterpret_cast<void*>(1));
|
||||
pthread_cleanup_push(exit_count_test_handler, reinterpret_cast<void*>(0));
|
||||
|
||||
pthread_exit(nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE(cleanup_pthread_exit)
|
||||
{
|
||||
pthread_t thread;
|
||||
exit_count = 0;
|
||||
|
||||
pthread_create(&thread, nullptr, cleanup_pthread_exit_inner, nullptr);
|
||||
|
||||
pthread_join(thread, nullptr);
|
||||
|
||||
// Ensure that all exit handlers have been called.
|
||||
EXPECT_EQ(exit_count, 3ul);
|
||||
}
|
||||
|
||||
static void* cleanup_return_inner(void*)
|
||||
{
|
||||
// Returning from the main function should not call any cleanup handlers.
|
||||
pthread_cleanup_push(immediate_fail_handler, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TEST_CASE(cleanup_return)
|
||||
{
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, cleanup_return_inner, nullptr);
|
||||
pthread_join(thread, nullptr);
|
||||
}
|
||||
|
||||
static void* cleanup_pop_inner(void*)
|
||||
{
|
||||
pthread_cleanup_push(exit_count_test_handler, reinterpret_cast<void*>(1));
|
||||
pthread_cleanup_push(immediate_fail_handler, nullptr);
|
||||
pthread_cleanup_push(exit_count_test_handler, reinterpret_cast<void*>(0));
|
||||
pthread_cleanup_push(immediate_fail_handler, nullptr);
|
||||
|
||||
// Popping a cleanup handler shouldn't run the callback unless `execute` is given.
|
||||
pthread_cleanup_pop(0);
|
||||
pthread_cleanup_pop(1);
|
||||
pthread_cleanup_pop(0);
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TEST_CASE(cleanup_pop)
|
||||
{
|
||||
pthread_t thread;
|
||||
exit_count = 0;
|
||||
|
||||
pthread_create(&thread, nullptr, cleanup_pop_inner, nullptr);
|
||||
pthread_join(thread, nullptr);
|
||||
|
||||
// Ensure that all exit handlers have been called.
|
||||
EXPECT_EQ(exit_count, 2ul);
|
||||
}
|
90
Tests/LibC/TestPthreadRWLocks.cpp
Normal file
90
Tests/LibC/TestPthreadRWLocks.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Rodrigo Tobar <rtobarc@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <pthread.h>
|
||||
|
||||
TEST_CASE(rwlock_init)
|
||||
{
|
||||
pthread_rwlock_t lock;
|
||||
auto result = pthread_rwlock_init(&lock, nullptr);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
TEST_CASE(rwlock_rdlock)
|
||||
{
|
||||
pthread_rwlock_t lock;
|
||||
auto result = pthread_rwlock_init(&lock, nullptr);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_rwlock_rdlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_rwlock_rdlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_rdlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
TEST_CASE(rwlock_wrlock)
|
||||
{
|
||||
pthread_rwlock_t lock;
|
||||
auto result = pthread_rwlock_init(&lock, nullptr);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_rwlock_wrlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
TEST_CASE(rwlock_rwr_sequence)
|
||||
{
|
||||
pthread_rwlock_t lock;
|
||||
auto result = pthread_rwlock_init(&lock, nullptr);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_rwlock_rdlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_rwlock_wrlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_rwlock_rdlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
TEST_CASE(rwlock_wrlock_init_in_once)
|
||||
{
|
||||
static pthread_rwlock_t lock;
|
||||
static pthread_once_t once1 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t once2 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t once3 = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&once1, []() {
|
||||
pthread_once(&once2, []() {
|
||||
pthread_once(&once3, []() {
|
||||
auto result = pthread_rwlock_init(&lock, nullptr);
|
||||
EXPECT_EQ(0, result);
|
||||
});
|
||||
});
|
||||
});
|
||||
auto result = pthread_rwlock_wrlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_rwlock_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
131
Tests/LibC/TestPthreadSpinLocks.cpp
Normal file
131
Tests/LibC/TestPthreadSpinLocks.cpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
TEST_CASE(spin_init_process_scope)
|
||||
{
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_init(&lock, PTHREAD_SCOPE_PROCESS);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_spin_destroy(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
{
|
||||
pthread_spinlock_t garbage_lock { 0x1337 };
|
||||
auto result = pthread_spin_init(&garbage_lock, PTHREAD_SCOPE_PROCESS);
|
||||
EXPECT_EQ(0, result);
|
||||
result = pthread_spin_destroy(&garbage_lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(spin_init_system_scope)
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_init(&lock, PTHREAD_SCOPE_SYSTEM);
|
||||
EXPECT_EQ(0, result);
|
||||
pthread_spinlock_t garbage_lock { 0x99999 };
|
||||
result = pthread_spin_init(&garbage_lock, PTHREAD_SCOPE_PROCESS);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
TEST_CASE(spin_lock)
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_lock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
// We should detect that this thread already holds this lock.
|
||||
result = pthread_spin_lock(&lock);
|
||||
EXPECT_EQ(EDEADLK, result);
|
||||
}
|
||||
|
||||
TEST_CASE(spin_try_lock)
|
||||
{
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_trylock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_spin_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_trylock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
// We should detect that this thread already holds the lock.
|
||||
result = pthread_spin_trylock(&lock);
|
||||
EXPECT_EQ(EBUSY, result);
|
||||
}
|
||||
}
|
||||
|
||||
static void lock_from_different_thread(pthread_spinlock_t* lock)
|
||||
{
|
||||
pthread_t thread_id {};
|
||||
auto result = pthread_create(
|
||||
&thread_id, nullptr, [](void* param) -> void* {
|
||||
auto lock = (pthread_spinlock_t*)param;
|
||||
pthread_spin_lock(lock);
|
||||
return nullptr;
|
||||
},
|
||||
lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_join(thread_id, nullptr);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
TEST_CASE(spin_unlock)
|
||||
{
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_lock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_spin_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
lock_from_different_thread(&lock);
|
||||
|
||||
auto result = pthread_spin_unlock(&lock);
|
||||
EXPECT_EQ(EPERM, result);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(spin_destroy)
|
||||
{
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
auto result = pthread_spin_lock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
result = pthread_spin_destroy(&lock);
|
||||
EXPECT_EQ(EBUSY, result);
|
||||
|
||||
result = pthread_spin_unlock(&lock);
|
||||
EXPECT_EQ(0, result);
|
||||
}
|
||||
|
||||
{
|
||||
pthread_spinlock_t lock {};
|
||||
lock_from_different_thread(&lock);
|
||||
|
||||
auto result = pthread_spin_destroy(&lock);
|
||||
EXPECT_EQ(EBUSY, result);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue