2000 lines
66 KiB
C++
2000 lines
66 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#ifdef _WIN32
|
|
#if !defined WIN32_LEAN_AND_MEAN
|
|
# define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
// include files
|
|
|
|
#include <sal/types.h>
|
|
#include <rtl/string.hxx>
|
|
#include <osl/thread.hxx>
|
|
#include <osl/mutex.hxx>
|
|
#include <osl/time.h>
|
|
|
|
#include <string.h>
|
|
#include <memory>
|
|
|
|
#include <cppunit/TestFixture.h>
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#define t_print printf
|
|
|
|
using namespace osl;
|
|
|
|
namespace {
|
|
|
|
// Small stopwatch
|
|
class StopWatch {
|
|
TimeValue t1,t2; // Start and stoptime
|
|
|
|
protected:
|
|
sal_Int32 m_nNanoSec;
|
|
sal_Int32 m_nSeconds;
|
|
|
|
bool m_bIsValid; // TRUE, when started and stopped
|
|
bool m_bIsRunning; // TRUE, when started
|
|
|
|
public:
|
|
StopWatch();
|
|
|
|
void start(); // Starts time
|
|
void stop(); // Stops time
|
|
|
|
double getSeconds() const;
|
|
double getTenthSec() const;
|
|
};
|
|
|
|
}
|
|
|
|
// ================================= Stop Watch =================================
|
|
|
|
// A small stopwatch for internal use
|
|
// (c) Lars Langhans 29.12.1996 22:10
|
|
|
|
StopWatch::StopWatch()
|
|
: m_nNanoSec(0)
|
|
, m_nSeconds(0)
|
|
, m_bIsValid(false)
|
|
, m_bIsRunning(false)
|
|
{
|
|
t1.Seconds = 0;
|
|
t1.Nanosec = 0;
|
|
t2.Seconds = 0;
|
|
t2.Nanosec = 0;
|
|
}
|
|
|
|
void StopWatch::start()
|
|
{
|
|
// pre: %
|
|
// post: Start Timer
|
|
|
|
m_bIsValid = false;
|
|
m_bIsRunning = true;
|
|
osl_getSystemTime( &t1 );
|
|
t_print("# %u %u nsecs\n", static_cast<unsigned>(t1.Seconds), static_cast<unsigned>(t1.Nanosec));
|
|
// gettimeofday(&t1, 0);
|
|
}
|
|
|
|
void StopWatch::stop()
|
|
{
|
|
// pre: Timer should be started
|
|
// post: Timer will stopped
|
|
|
|
osl_getSystemTime( &t2 );
|
|
t_print("# %u %u nsecs\n", static_cast<unsigned>(t2.Seconds), static_cast<unsigned>(t2.Nanosec));
|
|
|
|
if (m_bIsRunning)
|
|
{ // check if started.
|
|
m_nSeconds = static_cast<sal_Int32>(t2.Seconds) - static_cast<sal_Int32>(t1.Seconds);
|
|
if ( t2.Nanosec > t1.Nanosec )
|
|
m_nNanoSec = static_cast<sal_Int32>(t2.Nanosec) - static_cast<sal_Int32>(t1.Nanosec);
|
|
else
|
|
{
|
|
m_nNanoSec = 1000000000 + static_cast<sal_Int32>(t2.Nanosec) - static_cast<sal_Int32>(t1.Nanosec);
|
|
m_nSeconds -= 1;
|
|
}
|
|
t_print("# %u %u nsecs\n", static_cast<unsigned>(m_nSeconds), static_cast<unsigned>(m_nNanoSec) );
|
|
m_bIsValid = true;
|
|
m_bIsRunning = false;
|
|
}
|
|
}
|
|
|
|
double StopWatch::getSeconds() const
|
|
{
|
|
// pre: valid = TRUE
|
|
// BACK: time in seconds
|
|
|
|
double nValue = 0.0;
|
|
if (m_bIsValid)
|
|
{
|
|
nValue = double(m_nNanoSec) / 1000000000.0 + m_nSeconds; // milli micro nano
|
|
}
|
|
return nValue;
|
|
}
|
|
|
|
double StopWatch::getTenthSec() const
|
|
{
|
|
double nValue = 0.0;
|
|
if (m_bIsValid)
|
|
{
|
|
nValue = double(m_nNanoSec) / 100000000.0 + m_nSeconds * 10;
|
|
}
|
|
return nValue ;
|
|
}
|
|
|
|
namespace {
|
|
|
|
template <class T>
|
|
class ThreadSafeValue
|
|
{
|
|
T m_nFlag;
|
|
Mutex m_aMutex;
|
|
public:
|
|
explicit ThreadSafeValue(T n = 0): m_nFlag(n) {}
|
|
T getValue()
|
|
{
|
|
//block if already acquired by another thread.
|
|
osl::MutexGuard g(m_aMutex);
|
|
return m_nFlag;
|
|
}
|
|
void incValue()
|
|
{
|
|
//only one thread operate on the flag.
|
|
osl::MutexGuard g(m_aMutex);
|
|
m_nFlag++;
|
|
}
|
|
void acquire() {m_aMutex.acquire();}
|
|
void release() {m_aMutex.release();}
|
|
};
|
|
|
|
}
|
|
|
|
namespace ThreadHelper
|
|
{
|
|
static void thread_sleep_tenth_sec(sal_Int32 _nTenthSec)
|
|
{
|
|
osl::Thread::wait(std::chrono::milliseconds(_nTenthSec * 100));
|
|
}
|
|
|
|
static void outputPriority(oslThreadPriority const& _aPriority)
|
|
{
|
|
// LLA: output the priority
|
|
if (_aPriority == osl_Thread_PriorityHighest)
|
|
{
|
|
t_print("Prio is High\n");
|
|
}
|
|
else if (_aPriority == osl_Thread_PriorityAboveNormal)
|
|
{
|
|
t_print("Prio is above normal\n");
|
|
}
|
|
else if (_aPriority == osl_Thread_PriorityNormal)
|
|
{
|
|
t_print("Prio is normal\n");
|
|
}
|
|
else if (_aPriority == osl_Thread_PriorityBelowNormal)
|
|
{
|
|
t_print("Prio is below normal\n");
|
|
}
|
|
else if (_aPriority == osl_Thread_PriorityLowest)
|
|
{
|
|
t_print("Prio is lowest\n");
|
|
}
|
|
else
|
|
{
|
|
t_print("Prio is unknown\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
|
|
/** Simple thread for testing Thread-create.
|
|
|
|
Just add 1 of value 0, and after running, result is 1.
|
|
*/
|
|
class myThread : public Thread
|
|
{
|
|
ThreadSafeValue<sal_Int32> m_aFlag;
|
|
public:
|
|
sal_Int32 getValue() { return m_aFlag.getValue(); }
|
|
protected:
|
|
/** guarded value which initialized 0
|
|
|
|
@see ThreadSafeValue
|
|
*/
|
|
void SAL_CALL run() override
|
|
{
|
|
while(schedule())
|
|
{
|
|
m_aFlag.incValue();
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
virtual void SAL_CALL suspend() override
|
|
{
|
|
m_aFlag.acquire();
|
|
::osl::Thread::suspend();
|
|
m_aFlag.release();
|
|
}
|
|
|
|
virtual ~myThread() override
|
|
{
|
|
if (isRunning())
|
|
{
|
|
t_print("error: not terminated.\n");
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
/** Thread which has a flag add 1 every second until 20
|
|
*/
|
|
class OCountThread : public Thread
|
|
{
|
|
ThreadSafeValue<sal_Int32> m_aFlag;
|
|
public:
|
|
OCountThread() : m_nWaitSec(0)
|
|
{
|
|
t_print("new OCountThread thread %u!\n", static_cast<unsigned>(getIdentifier()));
|
|
}
|
|
sal_Int32 getValue() { return m_aFlag.getValue(); }
|
|
|
|
void setWait(sal_Int32 nSec)
|
|
{
|
|
m_nWaitSec = nSec;
|
|
//m_bWait = sal_True;
|
|
}
|
|
|
|
virtual void SAL_CALL suspend() override
|
|
{
|
|
m_aFlag.acquire();
|
|
::osl::Thread::suspend();
|
|
m_aFlag.release();
|
|
}
|
|
|
|
protected:
|
|
//sal_Bool m_bWait;
|
|
sal_Int32 m_nWaitSec;
|
|
|
|
void SAL_CALL run() override
|
|
{
|
|
/// if the thread should terminate, schedule return false
|
|
while (m_aFlag.getValue() < 20 && schedule())
|
|
{
|
|
m_aFlag.incValue();
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
|
|
if (m_nWaitSec != 0)
|
|
{
|
|
TimeValue nTV;
|
|
nTV.Seconds = m_nWaitSec / 10 ;
|
|
nTV.Nanosec = ( m_nWaitSec%10 ) * 100000000 ;
|
|
wait( nTV );
|
|
m_nWaitSec = 0;
|
|
}
|
|
}
|
|
}
|
|
void SAL_CALL onTerminated() override
|
|
{
|
|
t_print("normally terminate this thread %u!\n", static_cast<unsigned>(getIdentifier()));
|
|
}
|
|
public:
|
|
|
|
virtual ~OCountThread() override
|
|
{
|
|
if (isRunning())
|
|
{
|
|
t_print("error: not terminated.\n");
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
/** no call schedule in the run method
|
|
*/
|
|
class ONoScheduleThread : public Thread
|
|
{
|
|
ThreadSafeValue<sal_Int32> m_aFlag;
|
|
public:
|
|
sal_Int32 getValue() { return m_aFlag.getValue(); }
|
|
|
|
virtual void SAL_CALL suspend() override
|
|
{
|
|
m_aFlag.acquire();
|
|
::osl::Thread::suspend();
|
|
m_aFlag.release();
|
|
}
|
|
protected:
|
|
void SAL_CALL run() override
|
|
{
|
|
while (m_aFlag.getValue() < 10)
|
|
{
|
|
m_aFlag.incValue();
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
}
|
|
}
|
|
void SAL_CALL onTerminated() override
|
|
{
|
|
t_print("normally terminate this thread %u!\n", static_cast<unsigned>(getIdentifier()));
|
|
}
|
|
public:
|
|
ONoScheduleThread()
|
|
{
|
|
t_print("new thread id %u!\n", static_cast<unsigned>(getIdentifier()));
|
|
}
|
|
virtual ~ONoScheduleThread() override
|
|
{
|
|
if (isRunning())
|
|
{
|
|
t_print("error: not terminated.\n");
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
|
|
class OAddThread : public Thread
|
|
{
|
|
ThreadSafeValue<sal_Int32> m_aFlag;
|
|
public:
|
|
//oslThreadIdentifier m_id, m_CurId;
|
|
OAddThread(){}
|
|
sal_Int32 getValue() { return m_aFlag.getValue(); }
|
|
|
|
virtual void SAL_CALL suspend() override
|
|
{
|
|
m_aFlag.acquire();
|
|
::osl::Thread::suspend();
|
|
m_aFlag.release();
|
|
}
|
|
protected:
|
|
void SAL_CALL run() override
|
|
{
|
|
//if the thread should terminate, schedule return false
|
|
while (schedule())
|
|
{
|
|
m_aFlag.incValue();
|
|
}
|
|
}
|
|
void SAL_CALL onTerminated() override
|
|
{
|
|
// t_print("normally terminate this thread %d!\n", getIdentifier());
|
|
}
|
|
public:
|
|
|
|
virtual ~OAddThread() override
|
|
{
|
|
if (isRunning())
|
|
{
|
|
// t_print("error: not terminated.\n");
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
namespace osl_Thread
|
|
{
|
|
|
|
static void resumeAndWaitThread(Thread* _pThread)
|
|
{
|
|
// This function starts a thread, wait a second and suspends the thread
|
|
// Due to the fact, that a suspend and never run thread never really exists.
|
|
|
|
// Note: on UNX, after createSuspended, and then terminate the thread, it performs well;
|
|
// while on Windows, after createSuspended, the thread can not terminate, wait endlessly,
|
|
// so here call resume at first, then call terminate.
|
|
#ifdef _WIN32
|
|
t_print("resumeAndWaitThread\n");
|
|
_pThread->resume();
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
#else
|
|
_pThread->resume();
|
|
#endif
|
|
}
|
|
|
|
// kill a running thread and join it, if it has terminated, do nothing
|
|
static void termAndJoinThread(Thread* _pThread)
|
|
{
|
|
_pThread->terminate();
|
|
|
|
// LLA: Windows feature???, a suspended thread can not terminated, so we have to weak it up
|
|
#ifdef _WIN32
|
|
_pThread->resume();
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
#endif
|
|
t_print("#wait for join.\n");
|
|
_pThread->join();
|
|
}
|
|
/** Test of the osl::Thread::create method
|
|
*/
|
|
|
|
class create : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** Simple create a thread.
|
|
|
|
Create a simple thread, it just does add 1 to value(which initialized 0),
|
|
if the thread run, the value should be 1.
|
|
*/
|
|
void create_001()
|
|
{
|
|
myThread* newthread = new myThread;
|
|
bool bRes = newthread->create();
|
|
CPPUNIT_ASSERT_MESSAGE("Can not creates a new thread!\n", bRes);
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(1); // wait short
|
|
bool isRunning = newthread->isRunning(); // check if thread is running
|
|
/// wait for the new thread to assure it has run
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
sal_Int32 nValue = newthread->getValue();
|
|
/// to assure the new thread has terminated
|
|
termAndJoinThread(newthread);
|
|
delete newthread;
|
|
|
|
t_print(" nValue = %d\n", static_cast<int>(nValue));
|
|
t_print("isRunning = %s\n", isRunning ? "true" : "false");
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new thread",
|
|
nValue >= 1
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new thread",
|
|
isRunning
|
|
);
|
|
|
|
}
|
|
|
|
/** only one running thread per instance, return false if create secondly
|
|
*/
|
|
void create_002()
|
|
{
|
|
myThread* newthread = new myThread;
|
|
bool res1 = newthread->create();
|
|
bool res2 = newthread->create();
|
|
t_print("In non pro, an assertion should occurred. This behaviour is right.\n");
|
|
termAndJoinThread(newthread);
|
|
delete newthread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new thread: can not create two threads per instance",
|
|
res1
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new thread: can not create two threads per instance",
|
|
!res2
|
|
);
|
|
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(create);
|
|
CPPUNIT_TEST(create_001);
|
|
CPPUNIT_TEST(create_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class create
|
|
|
|
/** Test of the osl::Thread::createSuspended method
|
|
*/
|
|
class createSuspended : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** Create a suspended thread, use the same class as create_001
|
|
|
|
after create, wait enough time, check the value, if it's still the initial value, pass
|
|
*/
|
|
void createSuspended_001()
|
|
{
|
|
myThread* newthread = new myThread;
|
|
bool bRes = newthread->createSuspended();
|
|
CPPUNIT_ASSERT_MESSAGE("Can not creates a new thread!", bRes);
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
bool isRunning = newthread->isRunning();
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
sal_Int32 nValue = newthread->getValue();
|
|
|
|
resumeAndWaitThread(newthread);
|
|
|
|
termAndJoinThread(newthread);
|
|
delete newthread;
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"Creates a new suspended thread",
|
|
sal_Int32(0), nValue
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new suspended thread",
|
|
isRunning
|
|
);
|
|
}
|
|
|
|
void createSuspended_002()
|
|
{
|
|
myThread* newthread = new myThread;
|
|
bool res1 = newthread->createSuspended();
|
|
bool res2 = newthread->createSuspended();
|
|
|
|
resumeAndWaitThread(newthread);
|
|
|
|
termAndJoinThread(newthread);
|
|
|
|
delete newthread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new thread: can not create two threads per instance",
|
|
res1
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a new thread: can not create two threads per instance",
|
|
!res2
|
|
);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(createSuspended);
|
|
CPPUNIT_TEST(createSuspended_001);
|
|
// LLA: Deadlocked!!!
|
|
CPPUNIT_TEST(createSuspended_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class createSuspended
|
|
|
|
/** when the count value equal to or more than 3, suspend the thread.
|
|
*/
|
|
static void suspendCountThread(OCountThread* _pCountThread)
|
|
{
|
|
sal_Int32 nValue = 0;
|
|
while (true)
|
|
{
|
|
nValue = _pCountThread->getValue();
|
|
if (nValue >= 3)
|
|
{
|
|
_pCountThread->suspend();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Test of the osl::Thread::suspend method
|
|
*/
|
|
class suspend : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** Use a thread which has a flag added 1 every second
|
|
|
|
ALGORITHM:
|
|
create the thread, after running special time, record value of flag, then suspend it,
|
|
wait a long time, check the flag, if it remains unchanged during suspending
|
|
*/
|
|
void suspend_001()
|
|
{
|
|
OCountThread* aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
// the thread run for some seconds, but not terminate
|
|
suspendCountThread( aCountThread );
|
|
|
|
// the value just after calling suspend
|
|
sal_Int32 nValue = aCountThread->getValue(); // (2)
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
|
|
// the value after waiting 3 seconds
|
|
sal_Int32 nLaterValue = aCountThread->getValue(); // (3)
|
|
|
|
resumeAndWaitThread(aCountThread);
|
|
termAndJoinThread(aCountThread);
|
|
delete aCountThread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Suspend the thread",
|
|
bRes
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"Suspend the thread",
|
|
nValue, nLaterValue
|
|
);
|
|
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(suspend);
|
|
CPPUNIT_TEST(suspend_001);
|
|
// LLA: Deadlocked!!!
|
|
// CPPUNIT_TEST(createSuspended_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class suspend
|
|
|
|
/** Test of the osl::Thread::resume method
|
|
*/
|
|
class resume : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** check if the thread run samely as usual after suspend and resume
|
|
|
|
ALGORITHM:
|
|
compare the values before and after suspend, they should be same,
|
|
then compare values before and after resume, the difference should be same as the sleep seconds number
|
|
*/
|
|
void resume_001()
|
|
{
|
|
OCountThread* pCountThread = new OCountThread();
|
|
bool bRes = pCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
suspendCountThread(pCountThread);
|
|
|
|
sal_Int32 nSuspendValue = pCountThread->getValue(); // (2)
|
|
// suspend for 3 seconds
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
pCountThread->resume();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
sal_Int32 nResumeValue = pCountThread->getValue();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
sal_Int32 nLaterValue = pCountThread->getValue();
|
|
|
|
termAndJoinThread(pCountThread);
|
|
delete pCountThread;
|
|
|
|
t_print("SuspendValue: %d\n", static_cast<int>(nSuspendValue));
|
|
t_print("ResumeValue: %d\n", static_cast<int>(nResumeValue));
|
|
t_print("LaterValue: %d\n", static_cast<int>(nLaterValue));
|
|
|
|
/* LLA: this assumption is no longer relevant: nResumeValue == nSuspendValue && */
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Suspend then resume the thread",
|
|
nLaterValue >= 9
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Suspend then resume the thread",
|
|
nResumeValue > nSuspendValue
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Suspend then resume the thread",
|
|
nLaterValue > nResumeValue
|
|
);
|
|
|
|
}
|
|
|
|
/** Create a suspended thread then resume, check if the thread has run
|
|
*/
|
|
void resume_002()
|
|
{
|
|
myThread* newthread = new myThread;
|
|
bool bRes = newthread->createSuspended();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't create thread!", bRes );
|
|
|
|
newthread->resume();
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
sal_Int32 nValue = newthread->getValue();
|
|
|
|
termAndJoinThread(newthread);
|
|
delete newthread;
|
|
|
|
t_print(" nValue = %d\n", static_cast<int>(nValue));
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Creates a suspended thread, then resume",
|
|
nValue >= 1
|
|
);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(resume);
|
|
CPPUNIT_TEST(resume_001);
|
|
CPPUNIT_TEST(resume_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class resume
|
|
|
|
/** Test of the osl::Thread::terminate method
|
|
*/
|
|
class terminate : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** Check after call terminate if the running thread running go on executing
|
|
|
|
ALGORITHM:
|
|
before and after call terminate, the values should be the same
|
|
*/
|
|
void terminate_001()
|
|
{
|
|
OCountThread* aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
sal_Int32 nValue = aCountThread->getValue();
|
|
aCountThread->terminate();
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
sal_Int32 nLaterValue = aCountThread->getValue();
|
|
|
|
// isRunning should be false after terminate
|
|
bool isRunning = aCountThread->isRunning();
|
|
aCountThread->join();
|
|
delete aCountThread;
|
|
|
|
t_print(" nValue = %d\n", static_cast<int>(nValue));
|
|
t_print("nLaterValue = %d\n", static_cast<int>(nLaterValue));
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Terminate the thread",
|
|
!isRunning
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Terminate the thread",
|
|
nLaterValue >= nValue
|
|
);
|
|
}
|
|
/** Check if a suspended thread will terminate after call terminate, different on w32 and on UNX
|
|
*/
|
|
void terminate_002()
|
|
{
|
|
OCountThread* aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
suspendCountThread(aCountThread);
|
|
sal_Int32 nValue = aCountThread->getValue();
|
|
|
|
// seems a suspended thread can not be terminated on W32, while on Solaris can
|
|
resumeAndWaitThread(aCountThread);
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
|
|
termAndJoinThread(aCountThread);
|
|
sal_Int32 nLaterValue = aCountThread->getValue();
|
|
delete aCountThread;
|
|
|
|
t_print(" nValue = %d\n", static_cast<int>(nValue));
|
|
t_print("nLaterValue = %d\n", static_cast<int>(nLaterValue));
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Suspend then resume the thread",
|
|
nLaterValue > nValue );
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(terminate);
|
|
CPPUNIT_TEST(terminate_001);
|
|
CPPUNIT_TEST(terminate_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class terminate
|
|
|
|
/** Test of the osl::Thread::join method
|
|
*/
|
|
class join : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** Check after call terminate if the thread running function will not go on executing
|
|
|
|
the next statement after join will not exec before the thread terminates
|
|
ALGORITHM:
|
|
recode system time at the beginning of the thread run, call join, then record system time again,
|
|
the difference of the two times should be equal or more than 20 seconds, the CountThread normally terminates
|
|
*/
|
|
void join_001()
|
|
{
|
|
OCountThread *aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
StopWatch aStopWatch;
|
|
aStopWatch.start();
|
|
// TimeValue aTimeVal_befor;
|
|
// osl_getSystemTime( &aTimeVal_befor );
|
|
//t_print("#join:the system time is %d,%d\n", pTimeVal_befor->Seconds,pTimeVal_befor->Nanosec);
|
|
|
|
aCountThread->join();
|
|
|
|
//the below line will be executed after aCountThread terminate
|
|
// TimeValue aTimeVal_after;
|
|
// osl_getSystemTime( &aTimeVal_after );
|
|
aStopWatch.stop();
|
|
// sal_uInt32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
|
|
double nSec = aStopWatch.getSeconds();
|
|
t_print("join_001 nSec=%f\n", nSec);
|
|
delete aCountThread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Join the thread: after the thread terminate",
|
|
nSec >= 2
|
|
);
|
|
|
|
}
|
|
/** after terminated by another thread, join exited immediately
|
|
|
|
ALGORITHM:
|
|
terminate the thread when value>=3, call join, check the beginning time and time after join,
|
|
the difference should be 3 seconds, join costs little time
|
|
*/
|
|
void join_002()
|
|
{
|
|
OCountThread *aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
//record the time when the running begin
|
|
// TimeValue aTimeVal_befor;
|
|
// osl_getSystemTime( &aTimeVal_befor );
|
|
StopWatch aStopWatch;
|
|
aStopWatch.start();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(10);
|
|
termAndJoinThread(aCountThread);
|
|
|
|
//the below line will be executed after aCountThread terminate
|
|
// TimeValue aTimeVal_after;
|
|
// osl_getSystemTime( &aTimeVal_after );
|
|
// sal_uInt32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
|
|
aStopWatch.stop();
|
|
double nSec = aStopWatch.getSeconds();
|
|
t_print("join_002 nSec=%f\n", nSec);
|
|
|
|
delete aCountThread;
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Join the thread: after thread terminate by another thread",
|
|
nSec >= 1
|
|
);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(join);
|
|
CPPUNIT_TEST(join_001);
|
|
CPPUNIT_TEST(join_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class join
|
|
|
|
/** Test of the osl::Thread::isRunning method
|
|
*/
|
|
class isRunning : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
void isRunning_001()
|
|
{
|
|
OCountThread *aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
bool bRun = aCountThread->isRunning();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
termAndJoinThread(aCountThread);
|
|
bool bTer = aCountThread->isRunning();
|
|
delete aCountThread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Test isRunning",
|
|
bRun
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Test isRunning",
|
|
!bTer
|
|
);
|
|
}
|
|
/** check the value of isRunning when suspending and after resume
|
|
*/
|
|
void isRunning_002()
|
|
{
|
|
OCountThread *aCountThread = new OCountThread();
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
// sal_Bool bRunning = aCountThread->isRunning();
|
|
// sal_Int32 nValue = 0;
|
|
suspendCountThread(aCountThread);
|
|
|
|
bool bRunning_sup = aCountThread->isRunning();
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
aCountThread->resume();
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
bool bRunning_res = aCountThread->isRunning();
|
|
termAndJoinThread(aCountThread);
|
|
bool bRunning_ter = aCountThread->isRunning();
|
|
delete aCountThread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Test isRunning",
|
|
bRes );
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Test isRunning",
|
|
bRunning_sup );
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Test isRunning",
|
|
bRunning_res );
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Test isRunning",
|
|
!bRunning_ter );
|
|
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(isRunning);
|
|
CPPUNIT_TEST(isRunning_001);
|
|
CPPUNIT_TEST(isRunning_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class isRunning
|
|
|
|
/// check osl::Thread::setPriority
|
|
class setPriority : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
// insert your test code here.
|
|
OString getPrioName(oslThreadPriority _aPriority)
|
|
{
|
|
OString sPrioStr;
|
|
switch (_aPriority)
|
|
{
|
|
case osl_Thread_PriorityHighest:
|
|
sPrioStr = "Highest"_ostr;
|
|
break;
|
|
|
|
case osl_Thread_PriorityAboveNormal:
|
|
sPrioStr = "AboveNormal"_ostr;
|
|
break;
|
|
|
|
case osl_Thread_PriorityNormal:
|
|
sPrioStr = "Normal"_ostr;
|
|
break;
|
|
|
|
case osl_Thread_PriorityBelowNormal:
|
|
sPrioStr = "BelowNormal"_ostr;
|
|
break;
|
|
|
|
case osl_Thread_PriorityLowest:
|
|
sPrioStr = "Lowest"_ostr;
|
|
break;
|
|
default:
|
|
sPrioStr = "unknown"_ostr;
|
|
}
|
|
return sPrioStr;
|
|
}
|
|
|
|
/** check 2 threads.
|
|
|
|
ALGORITHM:
|
|
Here the function should show, that 2 different threads,
|
|
which only increase a value, should run at the same time with same prio.
|
|
The test fails, if the difference between the two values is more than 5%
|
|
but IMHO this isn't a failure, it's only a feature of the OS.
|
|
*/
|
|
|
|
void check2Threads(oslThreadPriority _aPriority)
|
|
{
|
|
// initial 5 threads with different priorities
|
|
OAddThread* pThread = new OAddThread();
|
|
OAddThread* p2Thread = new OAddThread();
|
|
|
|
//Create them and start running at the same time
|
|
pThread->create();
|
|
pThread->setPriority(_aPriority);
|
|
p2Thread->create();
|
|
p2Thread->setPriority(_aPriority);
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(5);
|
|
|
|
pThread->terminate();
|
|
p2Thread->terminate();
|
|
|
|
sal_Int32 nValueNormal = pThread->getValue();
|
|
|
|
sal_Int32 nValueNormal2 = p2Thread->getValue();
|
|
|
|
OString sPrio = getPrioName(_aPriority);
|
|
t_print("After 10 tenth seconds\n");
|
|
|
|
t_print("nValue in %s Prio Thread is %d\n",sPrio.getStr(), static_cast<int>(nValueNormal));
|
|
t_print("nValue in %s Prio Thread is %d\n", sPrio.getStr(), static_cast<int>(nValueNormal2));
|
|
|
|
// ThreadHelper::thread_sleep_tenth_sec(1);
|
|
pThread->join();
|
|
p2Thread->join();
|
|
|
|
delete pThread;
|
|
delete p2Thread;
|
|
|
|
sal_Int32 nDelta = abs(nValueNormal - nValueNormal2);
|
|
double nQuotient = std::max(nValueNormal, nValueNormal2);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Quotient is zero, which means, there exist no right values.",
|
|
nQuotient != 0
|
|
);
|
|
double nDeltaPercent = nDelta / nQuotient * 100;
|
|
|
|
t_print("Delta value %d, percent %f\n", static_cast<int>(nDelta), nDeltaPercent);
|
|
|
|
// LLA: it's not a bug if the current OS is not able to handle thread scheduling right and good.
|
|
// like Windows XP
|
|
// LLA: CPPUNIT_ASSERT_MESSAGE(
|
|
// LLA: "Run 2 normal threads, the count diff more than 5 percent.",
|
|
// LLA: nDeltaPercent <= 5
|
|
// LLA: );
|
|
}
|
|
|
|
void setPriority_001_1()
|
|
{
|
|
check2Threads(osl_Thread_PriorityHighest);
|
|
}
|
|
void setPriority_001_2()
|
|
{
|
|
check2Threads(osl_Thread_PriorityAboveNormal);
|
|
}
|
|
void setPriority_001_3()
|
|
{
|
|
check2Threads(osl_Thread_PriorityNormal);
|
|
}
|
|
void setPriority_001_4()
|
|
{
|
|
check2Threads(osl_Thread_PriorityBelowNormal);
|
|
}
|
|
void setPriority_001_5()
|
|
{
|
|
check2Threads(osl_Thread_PriorityLowest);
|
|
}
|
|
|
|
void setPriority_002()
|
|
{
|
|
// initial 5 threads with different priorities
|
|
|
|
OAddThread aHighestThread;
|
|
OAddThread aAboveNormalThread;
|
|
OAddThread aNormalThread;
|
|
//OAddThread *aBelowNormalThread = new OAddThread();
|
|
//OAddThread *aLowestThread = new OAddThread();
|
|
|
|
//Create them and start running at the same time
|
|
aHighestThread.createSuspended();
|
|
aHighestThread.setPriority(osl_Thread_PriorityHighest);
|
|
|
|
aAboveNormalThread.createSuspended();
|
|
aAboveNormalThread.setPriority(osl_Thread_PriorityAboveNormal);
|
|
|
|
aNormalThread.createSuspended();
|
|
aNormalThread.setPriority(osl_Thread_PriorityNormal);
|
|
/*aBelowNormalThread->create();
|
|
aBelowNormalThread->setPriority(osl_Thread_PriorityBelowNormal);
|
|
aLowestThread->create();
|
|
aLowestThread->setPriority(osl_Thread_PriorityLowest);
|
|
*/
|
|
|
|
aHighestThread.resume();
|
|
aAboveNormalThread.resume();
|
|
aNormalThread.resume();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(5);
|
|
|
|
aHighestThread.suspend();
|
|
aAboveNormalThread.suspend();
|
|
aNormalThread.suspend();
|
|
|
|
termAndJoinThread(&aNormalThread);
|
|
termAndJoinThread(&aAboveNormalThread);
|
|
termAndJoinThread(&aHighestThread);
|
|
//aBelowNormalThread->terminate();
|
|
//aLowestThread->terminate();
|
|
|
|
sal_Int32 nValueHighest = aHighestThread.getValue();
|
|
|
|
sal_Int32 nValueAboveNormal = aAboveNormalThread.getValue();
|
|
|
|
sal_Int32 nValueNormal = aNormalThread.getValue();
|
|
|
|
t_print("After 10 tenth seconds\n");
|
|
t_print("nValue in Highest Prio Thread is %d\n", static_cast<int>(nValueHighest));
|
|
t_print("nValue in AboveNormal Prio Thread is %d\n", static_cast<int>(nValueAboveNormal));
|
|
t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
|
|
|
|
#ifndef _WIN32
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueHighest > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueAboveNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueNormal > 0
|
|
);
|
|
#endif
|
|
}
|
|
|
|
void setPriority_003()
|
|
{
|
|
// initial 5 threads with different priorities
|
|
OAddThread pHighestThread;
|
|
OAddThread pAboveNormalThread;
|
|
OAddThread pNormalThread;
|
|
OAddThread pBelowNormalThread;
|
|
OAddThread pLowestThread;
|
|
|
|
//Create them and start running at the same time
|
|
pHighestThread.createSuspended();
|
|
pHighestThread.setPriority(osl_Thread_PriorityHighest);
|
|
|
|
pAboveNormalThread.createSuspended();
|
|
pAboveNormalThread.setPriority(osl_Thread_PriorityAboveNormal);
|
|
|
|
pNormalThread.createSuspended();
|
|
pNormalThread.setPriority(osl_Thread_PriorityNormal);
|
|
|
|
pBelowNormalThread.createSuspended();
|
|
pBelowNormalThread.setPriority(osl_Thread_PriorityBelowNormal);
|
|
|
|
pLowestThread.createSuspended();
|
|
pLowestThread.setPriority(osl_Thread_PriorityLowest);
|
|
|
|
pHighestThread.resume();
|
|
pAboveNormalThread.resume();
|
|
pNormalThread.resume();
|
|
pBelowNormalThread.resume();
|
|
pLowestThread.resume();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(5);
|
|
|
|
pHighestThread.suspend();
|
|
pAboveNormalThread.suspend();
|
|
pNormalThread.suspend();
|
|
pBelowNormalThread.suspend();
|
|
pLowestThread.suspend();
|
|
|
|
termAndJoinThread(&pHighestThread);
|
|
termAndJoinThread(&pAboveNormalThread);
|
|
termAndJoinThread(&pNormalThread);
|
|
termAndJoinThread(&pBelowNormalThread);
|
|
termAndJoinThread(&pLowestThread);
|
|
|
|
sal_Int32 nValueHighest = pHighestThread.getValue();
|
|
|
|
sal_Int32 nValueAboveNormal = pAboveNormalThread.getValue();
|
|
|
|
sal_Int32 nValueNormal = pNormalThread.getValue();
|
|
|
|
sal_Int32 nValueBelowNormal = pBelowNormalThread.getValue();
|
|
|
|
sal_Int32 nValueLowest = pLowestThread.getValue();
|
|
|
|
t_print("After 10 tenth seconds\n");
|
|
t_print("nValue in Highest Prio Thread is %d\n", static_cast<int>(nValueHighest));
|
|
t_print("nValue in AboveNormal Prio Thread is %d\n", static_cast<int>(nValueAboveNormal));
|
|
t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
|
|
t_print("nValue in BelowNormal Prio Thread is %d\n", static_cast<int>(nValueBelowNormal));
|
|
t_print("nValue in Lowest Prio Thread is %d\n", static_cast<int>(nValueLowest));
|
|
|
|
#ifndef _WIN32
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueHighest > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueAboveNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueBelowNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueLowest > 0
|
|
);
|
|
#endif
|
|
}
|
|
|
|
void setPriority_004()
|
|
{
|
|
// initial 5 threads with different priorities
|
|
// OAddThread *pHighestThread = new OAddThread();
|
|
OAddThread pAboveNormalThread;
|
|
OAddThread pNormalThread;
|
|
OAddThread pBelowNormalThread;
|
|
OAddThread pLowestThread;
|
|
|
|
//Create them and start running at the same time
|
|
// pHighestThread->createSuspended();
|
|
// pHighestThread->setPriority(osl_Thread_PriorityHighest);
|
|
|
|
pAboveNormalThread.createSuspended();
|
|
pAboveNormalThread.setPriority(osl_Thread_PriorityAboveNormal);
|
|
|
|
pNormalThread.createSuspended();
|
|
pNormalThread.setPriority(osl_Thread_PriorityNormal);
|
|
|
|
pBelowNormalThread.createSuspended();
|
|
pBelowNormalThread.setPriority(osl_Thread_PriorityBelowNormal);
|
|
|
|
pLowestThread.createSuspended();
|
|
pLowestThread.setPriority(osl_Thread_PriorityLowest);
|
|
|
|
// pHighestThread->resume();
|
|
pAboveNormalThread.resume();
|
|
pNormalThread.resume();
|
|
pBelowNormalThread.resume();
|
|
pLowestThread.resume();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(5);
|
|
|
|
// pHighestThread->suspend();
|
|
pAboveNormalThread.suspend();
|
|
pNormalThread.suspend();
|
|
pBelowNormalThread.suspend();
|
|
pLowestThread.suspend();
|
|
|
|
// termAndJoinThread(pHighestThread);
|
|
termAndJoinThread(&pAboveNormalThread);
|
|
termAndJoinThread(&pNormalThread);
|
|
termAndJoinThread(&pBelowNormalThread);
|
|
termAndJoinThread(&pLowestThread);
|
|
|
|
// sal_Int32 nValueHighest = 0;
|
|
// nValueHighest = pHighestThread->getValue();
|
|
|
|
sal_Int32 nValueAboveNormal = pAboveNormalThread.getValue();
|
|
|
|
sal_Int32 nValueNormal = pNormalThread.getValue();
|
|
|
|
sal_Int32 nValueBelowNormal = pBelowNormalThread.getValue();
|
|
|
|
sal_Int32 nValueLowest = pLowestThread.getValue();
|
|
|
|
t_print("After 5 tenth seconds\n");
|
|
t_print("nValue in AboveNormal Prio Thread is %d\n", static_cast<int>(nValueAboveNormal));
|
|
t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
|
|
t_print("nValue in BelowNormal Prio Thread is %d\n", static_cast<int>(nValueBelowNormal));
|
|
t_print("nValue in Lowest Prio Thread is %d\n", static_cast<int>(nValueLowest));
|
|
|
|
// delete pHighestThread;
|
|
|
|
#ifndef _WIN32
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
/* nValueHighest > 0 && */
|
|
nValueAboveNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueBelowNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueLowest > 0
|
|
);
|
|
#endif
|
|
}
|
|
void setPriority_005()
|
|
{
|
|
// initial 5 threads with different priorities
|
|
// OAddThread *pHighestThread = new OAddThread();
|
|
// OAddThread *pAboveNormalThread = new OAddThread();
|
|
OAddThread pNormalThread;
|
|
OAddThread pBelowNormalThread;
|
|
OAddThread pLowestThread;
|
|
|
|
//Create them and start running at the same time
|
|
// pHighestThread->createSuspended();
|
|
// pHighestThread->setPriority(osl_Thread_PriorityHighest);
|
|
|
|
// pAboveNormalThread->createSuspended();
|
|
// pAboveNormalThread->setPriority(osl_Thread_PriorityAboveNormal);
|
|
|
|
pNormalThread.createSuspended();
|
|
pNormalThread.setPriority(osl_Thread_PriorityNormal);
|
|
|
|
pBelowNormalThread.createSuspended();
|
|
pBelowNormalThread.setPriority(osl_Thread_PriorityBelowNormal);
|
|
|
|
pLowestThread.createSuspended();
|
|
pLowestThread.setPriority(osl_Thread_PriorityLowest);
|
|
|
|
// pHighestThread->resume();
|
|
// pAboveNormalThread->resume();
|
|
pNormalThread.resume();
|
|
pBelowNormalThread.resume();
|
|
pLowestThread.resume();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(5);
|
|
|
|
// pHighestThread->suspend();
|
|
// pAboveNormalThread->suspend();
|
|
pNormalThread.suspend();
|
|
pBelowNormalThread.suspend();
|
|
pLowestThread.suspend();
|
|
|
|
// termAndJoinThread(pHighestThread);
|
|
// termAndJoinThread(pAboveNormalThread);
|
|
termAndJoinThread(&pNormalThread);
|
|
termAndJoinThread(&pBelowNormalThread);
|
|
termAndJoinThread(&pLowestThread);
|
|
|
|
// sal_Int32 nValueHighest = 0;
|
|
// nValueHighest = pHighestThread->getValue();
|
|
|
|
// sal_Int32 nValueAboveNormal = 0;
|
|
// nValueAboveNormal = pAboveNormalThread->getValue();
|
|
|
|
sal_Int32 nValueNormal = pNormalThread.getValue();
|
|
|
|
sal_Int32 nValueBelowNormal = pBelowNormalThread.getValue();
|
|
|
|
sal_Int32 nValueLowest = pLowestThread.getValue();
|
|
|
|
t_print("After 5 tenth seconds\n");
|
|
t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
|
|
t_print("nValue in BelowNormal Prio Thread is %d\n", static_cast<int>(nValueBelowNormal));
|
|
t_print("nValue in Lowest Prio Thread is %d\n", static_cast<int>(nValueLowest));
|
|
|
|
#ifndef _WIN32
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
/* nValueHighest > 0 && */
|
|
/* nValueAboveNormal > 0 && */
|
|
nValueNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueBelowNormal > 0
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"SetPriority",
|
|
nValueLowest > 0
|
|
);
|
|
#endif
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(setPriority);
|
|
#ifndef __sun
|
|
CPPUNIT_TEST(setPriority_002);
|
|
CPPUNIT_TEST(setPriority_003);
|
|
CPPUNIT_TEST(setPriority_004);
|
|
CPPUNIT_TEST(setPriority_005);
|
|
#endif
|
|
CPPUNIT_TEST(setPriority_001_1);
|
|
CPPUNIT_TEST(setPriority_001_2);
|
|
CPPUNIT_TEST(setPriority_001_3);
|
|
CPPUNIT_TEST(setPriority_001_4);
|
|
CPPUNIT_TEST(setPriority_001_5);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class setPriority
|
|
|
|
/** Test of the osl::Thread::getPriority method
|
|
*/
|
|
class getPriority : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
// insert your test code here.
|
|
void getPriority_001()
|
|
{
|
|
OAddThread *pHighestThread = new OAddThread();
|
|
|
|
//Create them and start running at the same time
|
|
pHighestThread->create();
|
|
pHighestThread->setPriority(osl_Thread_PriorityHighest);
|
|
|
|
oslThreadPriority aPriority = pHighestThread->getPriority();
|
|
termAndJoinThread(pHighestThread);
|
|
delete pHighestThread;
|
|
|
|
ThreadHelper::outputPriority(aPriority);
|
|
|
|
// LLA: Priority settings may not work within some OS versions.
|
|
#if defined(_WIN32) || defined(__sun)
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"getPriority",
|
|
osl_Thread_PriorityHighest, aPriority
|
|
);
|
|
#else
|
|
// LLA: Linux
|
|
// NO_PTHREAD_PRIORITY ???
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"getPriority",
|
|
osl_Thread_PriorityNormal, aPriority
|
|
);
|
|
#endif
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(getPriority);
|
|
CPPUNIT_TEST(getPriority_001);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class getPriority
|
|
|
|
class getIdentifier : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
// initialise your test code values here.
|
|
|
|
void getIdentifier_001()
|
|
{
|
|
// insert your test code here.
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(getIdentifier);
|
|
CPPUNIT_TEST(getIdentifier_001);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class getIdentifier
|
|
|
|
/** Test of the osl::Thread::getCurrentIdentifier method
|
|
*/
|
|
class getCurrentIdentifier : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
void getCurrentIdentifier_001()
|
|
{
|
|
oslThreadIdentifier oId;
|
|
OCountThread* pCountThread = new OCountThread;
|
|
pCountThread->create();
|
|
pCountThread->setWait(3);
|
|
oId = Thread::getCurrentIdentifier();
|
|
oslThreadIdentifier oIdChild = pCountThread->getIdentifier();
|
|
termAndJoinThread(pCountThread);
|
|
delete pCountThread;
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Get the identifier for the current active thread.",
|
|
oId != oIdChild);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(getCurrentIdentifier);
|
|
CPPUNIT_TEST(getCurrentIdentifier_001);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class getCurrentIdentifier
|
|
|
|
/** Test of the osl::Thread::wait method
|
|
*/
|
|
class waittest : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
/** call wait in the run method
|
|
|
|
ALGORITHM:
|
|
tested thread wait nWaitSec seconds, main thread sleep (2) seconds,
|
|
then terminate the tested thread, due to the fact that the thread do a sleep(1) + wait(5)
|
|
it's finish after 6 seconds.
|
|
*/
|
|
void wait_001()
|
|
{
|
|
OCountThread *aCountThread = new OCountThread();
|
|
sal_Int32 nWaitSec = 5;
|
|
aCountThread->setWait(nWaitSec);
|
|
// thread runs at least 5 seconds.
|
|
bool bRes = aCountThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
//record the time when the running begin
|
|
StopWatch aStopWatch;
|
|
aStopWatch.start();
|
|
|
|
// wait a little bit, to let the thread the time, to start
|
|
ThreadHelper::thread_sleep_tenth_sec( 4 );
|
|
|
|
// if wait works,
|
|
// this function returns, after 4 sec. later
|
|
termAndJoinThread(aCountThread);
|
|
|
|
// value should be one.
|
|
sal_Int32 nValue = aCountThread->getValue();
|
|
|
|
aStopWatch.stop();
|
|
|
|
// sal_uInt32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
|
|
double nTenthSec = aStopWatch.getTenthSec();
|
|
double nSec = aStopWatch.getSeconds();
|
|
delete aCountThread;
|
|
t_print("nTenthSec = %f \n", nTenthSec);
|
|
t_print("nSec = %f \n", nSec);
|
|
t_print("nValue = %d \n", static_cast<int>(nValue));
|
|
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Wait: Blocks the calling thread for the given number of time.",
|
|
nTenthSec >= 5
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"Wait: Blocks the calling thread for the given number of time.",
|
|
sal_Int32(1), nValue
|
|
);
|
|
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(waittest);
|
|
CPPUNIT_TEST(wait_001);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class waittest
|
|
|
|
/** osl::Thread::yield method: can not design good test scenario to test up to now
|
|
*/
|
|
class yield : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
void yield_001()
|
|
{
|
|
// insert your test code here.
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(yield);
|
|
CPPUNIT_TEST(yield_001);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class yield
|
|
|
|
/** Test of the osl::Thread::schedule method
|
|
*/
|
|
class schedule : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
|
|
/** The requested thread will get terminate the next time schedule() is called.
|
|
|
|
Note: on UNX, if call suspend thread is not the to be suspended thread, the to be
|
|
suspended thread will get suspended the next time schedule() is called,
|
|
while on w32, it's nothing with schedule.
|
|
|
|
check if suspend and terminate work well via schedule
|
|
*/
|
|
void schedule_001()
|
|
{
|
|
OAddThread* aThread = new OAddThread();
|
|
bool bRes = aThread->create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
aThread->suspend();
|
|
ThreadHelper::thread_sleep_tenth_sec(1);
|
|
sal_Int32 nValue = aThread->getValue();
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
sal_Int32 nLaterValue = aThread->getValue();
|
|
// resumeAndWaitThread(aThread);
|
|
t_print(" value = %d\n", static_cast<int>(nValue));
|
|
t_print("later value = %d\n", static_cast<int>(nLaterValue));
|
|
// if value and latervalue not equal, then the thread would not suspended
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"Schedule: suspend works.",
|
|
nValue, nLaterValue
|
|
);
|
|
|
|
aThread->resume();
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
|
|
aThread->terminate();
|
|
sal_Int32 nValue_term = aThread->getValue();
|
|
|
|
aThread->join();
|
|
sal_Int32 nValue_join = aThread->getValue();
|
|
|
|
t_print("value after term = %d\n", static_cast<int>(nValue_term));
|
|
t_print("value after join = %d\n", static_cast<int>(nValue_join));
|
|
|
|
// nValue_term and nValue_join should be the same
|
|
// but should be differ from nValue
|
|
|
|
delete aThread;
|
|
//check if thread really terminate after call terminate, if join immediately return
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Schedule: Returns False if the thread should terminate.",
|
|
nValue_join - nValue_term <= 1
|
|
);
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Schedule: Returns False if the thread should terminate.",
|
|
nValue_join - nValue_term >= 0
|
|
);
|
|
|
|
}
|
|
|
|
/** design a thread that has not call schedule in the workfunction--run method
|
|
*/
|
|
void schedule_002()
|
|
{
|
|
ONoScheduleThread aThread; // this thread runs 10 sec. (no schedule() used)
|
|
bool bRes = aThread.create();
|
|
CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(2);
|
|
aThread.suspend();
|
|
sal_Int32 nValue = aThread.getValue();
|
|
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
sal_Int32 nLaterValue = aThread.getValue();
|
|
ThreadHelper::thread_sleep_tenth_sec(5);
|
|
|
|
resumeAndWaitThread(&aThread);
|
|
|
|
t_print(" value = %d\n", static_cast<int>(nValue));
|
|
t_print("later value = %d\n", static_cast<int>(nLaterValue));
|
|
|
|
//On windows, suspend works, so the values are same
|
|
#ifdef _WIN32
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"Schedule: don't schedule in thread run method, suspend works.",
|
|
nValue, nLaterValue
|
|
);
|
|
#endif
|
|
|
|
//On UNX, suspend does not work, so the difference of the values equals to sleep seconds number
|
|
#ifdef UNX
|
|
aThread.resume();
|
|
CPPUNIT_ASSERT_MESSAGE(
|
|
"Schedule: don't schedule in thread run method, suspend does not work too.",
|
|
nLaterValue > nValue
|
|
);
|
|
#endif
|
|
|
|
// terminate will not work if no schedule in thread's work function
|
|
termAndJoinThread(&aThread);
|
|
sal_Int32 nValue_term = aThread.getValue();
|
|
|
|
t_print(" value term = %d\n", static_cast<int>(nValue_term));
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"Schedule: don't schedule in thread run method, terminate failed.",
|
|
static_cast<sal_Int32>(10), nValue_term
|
|
);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(schedule);
|
|
CPPUNIT_TEST(schedule_001);
|
|
CPPUNIT_TEST(schedule_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class schedule
|
|
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::create, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::createSuspended, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::suspend, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::resume, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::terminate, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::join, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::isRunning, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::setPriority, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::getPriority, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::getIdentifier, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::getCurrentIdentifier, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::waittest, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::yield, "osl_Thread");
|
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::schedule, "osl_Thread");
|
|
} // namespace osl_Thread
|
|
|
|
// destroy function when the binding thread terminate
|
|
static void destroyCallback(void * data)
|
|
{
|
|
delete[] static_cast<char *>(data);
|
|
}
|
|
|
|
static ThreadData myThreadData(destroyCallback);
|
|
|
|
namespace {
|
|
|
|
class myKeyThread : public Thread
|
|
{
|
|
public:
|
|
// a public char member for test result checking
|
|
char m_Char_Test;
|
|
// for pass thread-special data to thread
|
|
explicit myKeyThread(const char cData)
|
|
: m_Char_Test(0)
|
|
{
|
|
m_nData = cData;
|
|
}
|
|
private:
|
|
char m_nData;
|
|
|
|
void SAL_CALL run() override
|
|
{
|
|
char * pc = new char[2];
|
|
// strcpy(pc, &m_nData);
|
|
memcpy(pc, &m_nData, 1);
|
|
pc[1] = '\0';
|
|
|
|
myThreadData.setData(pc);
|
|
char* pData = static_cast<char*>(myThreadData.getData());
|
|
m_Char_Test = *pData;
|
|
// wait for long time to check the data value in main thread
|
|
ThreadHelper::thread_sleep_tenth_sec(3);
|
|
}
|
|
public:
|
|
virtual ~myKeyThread() override
|
|
{
|
|
if (isRunning())
|
|
{
|
|
t_print("error: not terminated.\n");
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
static ThreadData idData;
|
|
|
|
namespace {
|
|
|
|
class idThread: public Thread
|
|
{
|
|
public:
|
|
oslThreadIdentifier m_Id;
|
|
private:
|
|
void SAL_CALL run() override
|
|
{
|
|
std::unique_ptr<oslThreadIdentifier> pId( new oslThreadIdentifier );
|
|
*pId = getIdentifier();
|
|
idData.setData(pId.get());
|
|
oslThreadIdentifier* pIdData = static_cast<oslThreadIdentifier*>(idData.getData());
|
|
//t_print("Thread %d has Data %d\n", getIdentifier(), *pIdData);
|
|
m_Id = *pIdData;
|
|
}
|
|
|
|
public:
|
|
virtual ~idThread() override
|
|
{
|
|
if (isRunning())
|
|
{
|
|
t_print("error: not terminated.\n");
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
namespace osl_ThreadData
|
|
{
|
|
|
|
class ctors : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
|
|
// insert your test code here.
|
|
void ctor_001()
|
|
{
|
|
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(ctors);
|
|
CPPUNIT_TEST(ctor_001);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class ctors
|
|
|
|
class setData : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
|
|
/** the same instance of the class can have different values in different threads
|
|
*/
|
|
void setData_001()
|
|
{
|
|
idThread aThread1;
|
|
aThread1.create();
|
|
idThread aThread2;
|
|
aThread2.create();
|
|
|
|
aThread1.join();
|
|
aThread2.join();
|
|
|
|
oslThreadIdentifier aThreadId1 = aThread1.getIdentifier();
|
|
oslThreadIdentifier aThreadId2 = aThread2.getIdentifier();
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
aThread1.m_Id, aThreadId1
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
aThread2.m_Id, aThreadId2
|
|
);
|
|
|
|
}
|
|
|
|
void setData_002()
|
|
{
|
|
// at first, set the data a value
|
|
char* pc = new char[2];
|
|
char nData = 'm';
|
|
pc[0] = nData;
|
|
pc[1] = '\0';
|
|
|
|
myThreadData.setData(pc);
|
|
|
|
myKeyThread aThread1('a');
|
|
aThread1.create();
|
|
myKeyThread aThread2('b');
|
|
aThread2.create();
|
|
// aThread1 and aThread2 should have not terminated yet, check current data, not 'a' 'b'
|
|
char* pChar = static_cast<char*>(myThreadData.getData());
|
|
char aChar = *pChar;
|
|
|
|
aThread1.join();
|
|
aThread2.join();
|
|
|
|
// the saved thread data of aThread1 & aThread2, different
|
|
char cData1 = aThread1.m_Char_Test;
|
|
char cData2 = aThread2.m_Char_Test;
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'a', cData1
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'b', cData2
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'm', aChar
|
|
);
|
|
|
|
}
|
|
/** setData the second time, and then getData
|
|
*/
|
|
void setData_003()
|
|
{
|
|
// at first, set the data a value
|
|
char* pc = new char[2];
|
|
char nData = 'm';
|
|
memcpy(pc, &nData, 1);
|
|
pc[1] = '\0';
|
|
myThreadData.setData(pc);
|
|
|
|
myKeyThread aThread1('a');
|
|
aThread1.create();
|
|
myKeyThread aThread2('b');
|
|
aThread2.create();
|
|
// aThread1 and aThread2 should have not terminated yet
|
|
// setData the second time
|
|
char* pc2 = new char[2];
|
|
nData = 'o';
|
|
memcpy(pc2, &nData, 1);
|
|
pc2[1] = '\0';
|
|
|
|
myThreadData.setData(pc2);
|
|
char* pChar = static_cast<char*>(myThreadData.getData());
|
|
char aChar = *pChar;
|
|
|
|
aThread1.join();
|
|
aThread2.join();
|
|
|
|
// the saved thread data of aThread1 & aThread2, different
|
|
char cData1 = aThread1.m_Char_Test;
|
|
char cData2 = aThread2.m_Char_Test;
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'a', cData1
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'b', cData2
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'o', aChar
|
|
);
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(setData);
|
|
CPPUNIT_TEST(setData_001);
|
|
CPPUNIT_TEST(setData_002);
|
|
CPPUNIT_TEST(setData_003);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class setData
|
|
|
|
class getData : public CppUnit::TestFixture
|
|
{
|
|
public:
|
|
|
|
// After setData in child threads, get Data in the main thread, should be independent
|
|
void getData_001()
|
|
{
|
|
char* pc = new char[2];
|
|
strcpy(pc, "i");
|
|
myThreadData.setData(pc);
|
|
|
|
myKeyThread aThread1('c');
|
|
aThread1.create();
|
|
myKeyThread aThread2('d');
|
|
aThread2.create();
|
|
|
|
aThread1.join();
|
|
aThread2.join();
|
|
|
|
char cData1 = aThread1.m_Char_Test;
|
|
char cData2 = aThread2.m_Char_Test;
|
|
|
|
char* pChar = static_cast<char*>(myThreadData.getData());
|
|
char aChar = *pChar;
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'c', cData1
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'd', cData2
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'i', aChar
|
|
);
|
|
}
|
|
|
|
// setData then change the value in the address data pointer points,
|
|
// and then getData, should get the new value
|
|
void getData_002()
|
|
{
|
|
char* pc = new char[2];
|
|
char nData = 'i';
|
|
memcpy(pc, &nData, 1);
|
|
pc[1] = '\0';
|
|
|
|
myThreadData.setData(pc);
|
|
|
|
myKeyThread aThread1('a');
|
|
aThread1.create();
|
|
myKeyThread aThread2('b');
|
|
aThread2.create();
|
|
|
|
// change the value which pc points
|
|
char nData2 = 'j';
|
|
memcpy(pc, &nData2, 1);
|
|
pc[1] = '\0';
|
|
|
|
void* pChar = myThreadData.getData();
|
|
char aChar = *static_cast<char*>(pChar);
|
|
|
|
aThread1.join();
|
|
aThread2.join();
|
|
|
|
char cData1 = aThread1.m_Char_Test;
|
|
char cData2 = aThread2.m_Char_Test;
|
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'a', cData1
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'b', cData2
|
|
);
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
|
"ThreadData setData: ",
|
|
'j', aChar
|
|
);
|
|
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE(getData);
|
|
CPPUNIT_TEST(getData_001);
|
|
CPPUNIT_TEST(getData_002);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
}; // class getData
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(osl_ThreadData::ctors);
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(osl_ThreadData::setData);
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(osl_ThreadData::getData);
|
|
} // namespace osl_ThreadData
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|