Files
wxWidgets/tests/thread/atomic.cpp
Vadim Zeitlin 44131b044d Use the same number of iterations in atomic unit test
Use reasonably, but not too, big number, so that the test doesn't run
too long, even when TSAN is used.

This also simplifies the code.
2022-05-10 23:54:21 +02:00

192 lines
4.9 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: tests/thread/atomic.cpp
// Purpose: wxAtomic??? unit test
// Author: Armel Asselin
// Created: 2006-12-14
// Copyright: (c) 2006 Armel Asselin
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#ifndef WX_PRECOMP
#endif // WX_PRECOMP
#include "wx/atomic.h"
#include "wx/thread.h"
#include "wx/dynarray.h"
#include "wx/log.h"
WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
static const wxInt32 ITERATIONS_NUM = 10000;
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class AtomicTestCase : public CppUnit::TestCase
{
public:
AtomicTestCase() { }
enum ETestType
{
IncAndDecMixed,
IncOnly,
DecOnly
};
private:
class MyThread : public wxThread
{
public:
MyThread(wxAtomicInt &operateOn, ETestType testType) : wxThread(wxTHREAD_JOINABLE),
m_operateOn(operateOn), m_testType(testType) {}
// thread execution starts here
virtual void *Entry() wxOVERRIDE;
public:
wxAtomicInt &m_operateOn;
ETestType m_testType;
};
CPPUNIT_TEST_SUITE( AtomicTestCase );
CPPUNIT_TEST( TestNoThread );
CPPUNIT_TEST( TestDecReturn );
CPPUNIT_TEST( TestTwoThreadsMix );
CPPUNIT_TEST( TestTenThreadsMix );
CPPUNIT_TEST( TestTwoThreadsSeparate );
CPPUNIT_TEST( TestTenThreadsSeparate );
CPPUNIT_TEST_SUITE_END();
void TestNoThread();
void TestDecReturn();
void TestTenThreadsMix() { TestWithThreads(10, IncAndDecMixed); }
void TestTwoThreadsMix() { TestWithThreads(2, IncAndDecMixed); }
void TestTenThreadsSeparate() { TestWithThreads(10, IncOnly); }
void TestTwoThreadsSeparate() { TestWithThreads(2, IncOnly); }
void TestWithThreads(int count, ETestType testtype);
wxDECLARE_NO_COPY_CLASS(AtomicTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( AtomicTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
void AtomicTestCase::TestNoThread()
{
wxAtomicInt int1 = 0,
int2 = 0;
for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
{
wxAtomicInc(int1);
wxAtomicDec(int2);
}
CPPUNIT_ASSERT( int1 == ITERATIONS_NUM );
CPPUNIT_ASSERT( int2 == -ITERATIONS_NUM );
}
void AtomicTestCase::TestDecReturn()
{
wxAtomicInt i(0);
wxAtomicInc(i);
wxAtomicInc(i);
CPPUNIT_ASSERT( i == 2 );
CPPUNIT_ASSERT( wxAtomicDec(i) > 0 );
CPPUNIT_ASSERT( wxAtomicDec(i) == 0 );
}
void AtomicTestCase::TestWithThreads(int count, ETestType testType)
{
wxAtomicInt int1=0;
wxArrayThread threads;
int i;
for ( i = 0; i < count; ++i )
{
ETestType actualThreadType;
switch(testType)
{
default:
actualThreadType = testType;
break;
case IncOnly:
actualThreadType = (i&1)==0 ? IncOnly : DecOnly;
break;
}
MyThread *thread = new MyThread(int1, actualThreadType);
if ( thread->Create() != wxTHREAD_NO_ERROR )
{
wxLogError(wxT("Can't create thread!"));
delete thread;
}
else
threads.Add(thread);
}
for ( i = 0; i < count; ++i )
{
threads[i]->Run();
}
for ( i = 0; i < count; ++i )
{
// each thread should return 0, else it detected some problem
CPPUNIT_ASSERT (threads[i]->Wait() == (wxThread::ExitCode)0);
delete threads[i];
}
CPPUNIT_ASSERT( int1 == 0 );
}
// ----------------------------------------------------------------------------
void *AtomicTestCase::MyThread::Entry()
{
wxInt32 negativeValuesSeen = 0;
for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
{
switch ( m_testType )
{
case AtomicTestCase::IncAndDecMixed:
wxAtomicInc(m_operateOn);
wxAtomicDec(m_operateOn);
if (m_operateOn < 0)
++negativeValuesSeen;
break;
case AtomicTestCase::IncOnly:
wxAtomicInc(m_operateOn);
break;
case AtomicTestCase::DecOnly:
wxAtomicDec(m_operateOn);
break;
}
}
return wxUIntToPtr(negativeValuesSeen);
}