Age | Commit message (Expand) | Author |
2020-03-08 | test: file-descriptor: Fix undefined O_TMPFILE compilation error | Laurent Pinchart |
2020-03-06 | test: v4l2_videodevice: Add test for V4L2BufferCache | Niklas Söderlund |
2020-03-06 | test: Extract BufferSource class out of camera tests to libtest | Niklas Söderlund |
2020-03-06 | test: camera: buffer_import: Fix error messages | Niklas Söderlund |
2020-03-06 | test: controls: control_value: Expand test to cover array controls | Laurent Pinchart |
2020-03-06 | test: controls: control_value: Expand test to cover all control types | Laurent Pinchart |
2020-03-06 | test: Add Span test | Laurent Pinchart |
2020-02-24 | tests: Remove IPA_MODULE_PATH environment variable | Kieran Bingham |
2020-02-24 | libcamera: utils: Add a C++ dirname implementation | Kieran Bingham |
2020-02-18 | test: camera: buffer_import: Don't include <random> | Laurent Pinchart |
2020-02-14 | test: thread: Test waiting on a thread that is not running | Laurent Pinchart |
2020-02-14 | test: threads: Add wait() timeout test | Laurent Pinchart |
2020-02-13 | test: Add a utils::split() test | Laurent Pinchart |
2020-01-22 | test: signal: Add additional disconnection tests for Object | Laurent Pinchart |
e> |
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* Threads test
*/
#include <chrono>
#include <iostream>
#include <memory>
#include <pthread.h>
#include <thread>
#include <time.h>
#include <libcamera/base/thread.h>
#include "test.h"
using namespace std;
using namespace libcamera;
class DelayThread : public Thread
{
public:
DelayThread(chrono::steady_clock::duration duration)
: duration_(duration)
{
}
protected:
void run()
{
this_thread::sleep_for(duration_);
}
private:
chrono::steady_clock::duration duration_;
};
class CancelThread : public Thread
{
public:
CancelThread(bool &cancelled)
: cancelled_(cancelled)
{
}
protected:
void run()
{
cancelled_ = true;
/*
* Cancel the thread and call a guaranteed cancellation point
* (nanosleep).
*/
pthread_cancel(pthread_self());
struct timespec req{ 0, 100*000*000 };
nanosleep(&req, nullptr);
cancelled_ = false;
}
private:
bool &cancelled_;
};
class ThreadTest : public Test
{
protected:
int init()
{
return 0;
}
int run()
{
/* Test Thread() retrieval for the main thread. */
Thread *mainThread = Thread::current();
if (!mainThread) {
cout << "Thread::current() failed to main thread"
<< endl;
return TestFail;
}
if (!mainThread->isRunning()) {
cout << "Main thread is not running" << endl;
return TestFail;
}
/* Test starting the main thread, the test shall not crash. */
mainThread->start();
/* Test the running state of a custom thread. */
std::unique_ptr<Thread> thread = std::make_unique<Thread>();
thread->start();
if (!thread->isRunning()) {
cout << "Thread is not running after being started"
<< endl;
return TestFail;
}
thread->exit(0);
thread->wait();
if (thread->isRunning()) {
cout << "Thread is still running after finishing"
<< endl;
return TestFail;
}
/* Test waiting for completion with a timeout. */
thread = std::make_unique<DelayThread>(chrono::milliseconds(500));
thread->start();
thread->exit(0);
bool timeout = !thread->wait(chrono::milliseconds(100));
if (!timeout) {
cout << "Waiting for thread didn't time out" << endl;
return TestFail;
}
timeout = !thread->wait(chrono::milliseconds(1000));
if (timeout) {
cout << "Waiting for thread timed out" << endl;
return TestFail;
}
/* Test waiting on a thread that isn't running. */
thread = std::make_unique<Thread>();
timeout = !thread->wait();
if (timeout) {
cout << "Waiting for non-started thread timed out" << endl;
return TestFail;
}
thread->start();
thread->exit(0);
thread->wait();
timeout = !thread->wait();
if (timeout) {
cout << "Waiting for already stopped thread timed out" << endl;
return TestFail;
}
/* Test thread cleanup upon abnormal termination. */
bool cancelled = false;
bool finished = false;
thread = std::make_unique<CancelThread>(cancelled);
thread->finished.connect(this, [&finished]() { finished = true; });
thread->start();
thread->exit(0);
thread->wait(chrono::milliseconds(1000));
if (!cancelled || !finished) {
cout << "Cleanup failed upon abnormal termination" << endl;
return TestFail;
}
return TestPass;
}
void cleanup()
{
}
};
TEST_REGISTER(ThreadTest)
|