diff options
author | Jim Carroll <thecarrolls@jiminger.com> | 2011-07-11 09:31:51 -0400 |
---|---|---|
committer | Jim Carroll <thecarrolls@jiminger.com> | 2011-07-20 00:58:28 -0400 |
commit | 7c17463d76f8015ba8339df973b47d78c1ff9817 (patch) | |
tree | 96375d229819c6101332fbc03a1c0c191674a97b | |
parent | 99c10f107ea7edefbd5eeebedc55d48380964887 (diff) |
All testing is now much less time sensitive and should avoid spurious failures.
-rw-r--r-- | xbmc/threads/test/TestEvent.cpp | 73 | ||||
-rw-r--r-- | xbmc/threads/test/TestSharedSection.cpp | 138 |
2 files changed, 168 insertions, 43 deletions
diff --git a/xbmc/threads/test/TestEvent.cpp b/xbmc/threads/test/TestEvent.cpp index 42df6361a7..659b3dd42a 100644 --- a/xbmc/threads/test/TestEvent.cpp +++ b/xbmc/threads/test/TestEvent.cpp @@ -22,6 +22,7 @@ #include <boost/test/unit_test.hpp> #include "threads/Event.h" +#include "threads/Atomics.h" #include <boost/thread/thread.hpp> #include <boost/shared_array.hpp> @@ -97,7 +98,7 @@ public: static void Sleep(unsigned int millis) { boost::thread::sleep(BOOST_MILLIS(millis)); } -template<class E> bool waitForWaiters(E& event, int numWaiters, int milliseconds) +template<class E> static bool waitForWaiters(E& event, int numWaiters, int milliseconds) { for( int i = 0; i < milliseconds; i++) { @@ -178,7 +179,7 @@ BOOST_AUTO_TEST_CASE(TestEventTimedWaitsTimeoutCase) timed_waiter w1(event,result1,50); boost::thread waitThread1(w1); - BOOST_CHECK(waitForWaiters(event,1,10000)); + BOOST_CHECK(waitForWaiters(event,1,100)); BOOST_CHECK(result1 == 0); @@ -542,10 +543,19 @@ BOOST_AUTO_TEST_CASE(TestEventGroupTimedWait) BOOST_CHECK(waitThread2.timed_join(BOOST_MILLIS(10000))); } +class AtomicGuard +{ + volatile long* val; +public: + inline AtomicGuard(volatile long* val_) : val(val_) { if (val) AtomicIncrement(val); } + inline ~AtomicGuard() { if (val) AtomicDecrement(val); } +}; + #define TESTNUM 100000l #define NUMTHREADS 100l -CEvent g_event(true); +CEvent* g_event = NULL; +volatile long g_mutex; class mass_waiter { @@ -555,11 +565,12 @@ public: volatile bool waiting; - mass_waiter() : event(g_event), waiting(false) {} + mass_waiter() : event(*g_event), waiting(false) {} void operator()() { waiting = true; + AtomicGuard g(&g_mutex); result = event.Wait(); waiting = false; } @@ -573,38 +584,54 @@ public: volatile bool waiting; - poll_mass_waiter() : event(g_event), waiting(false) {} + poll_mass_waiter() : event(*g_event), waiting(false) {} void operator()() { waiting = true; + AtomicGuard g(&g_mutex); while ((result = event.WaitMSec(0)) == false); waiting = false; } }; - -BOOST_AUTO_TEST_CASE(TestMassEvent) +static bool waitForThread(volatile long& mutex, int numWaiters, int milliseconds) { - boost::shared_array<mass_waiter> m; - m.reset(new mass_waiter[NUMTHREADS]); + CCriticalSection sec; + for( int i = 0; i < milliseconds; i++) + { + if (mutex == (long)numWaiters) + return true; + + { + CSingleLock tmplock(sec); // kick any memory syncs + } + Sleep(1); + } + return false; +} +template <class W> void RunMassEventTest(boost::shared_array<W>& m, bool canWaitOnEvent) +{ boost::shared_array<boost::thread> t; t.reset(new boost::thread[NUMTHREADS]); for(size_t i=0; i<NUMTHREADS; i++) t[i] = boost::thread(boost::ref(m[i])); - for(size_t i=0; i<NUMTHREADS; i++) + BOOST_CHECK(waitForThread(g_mutex,NUMTHREADS,10000)); + if (canWaitOnEvent) { - BOOST_CHECK(waitForWaiters(g_event,NUMTHREADS,10000)); + BOOST_CHECK(waitForWaiters(*g_event,NUMTHREADS,10000)); } + Sleep(100);// give them a little more time + for(size_t i=0; i<NUMTHREADS; i++) { BOOST_CHECK(m[i].waiting); } - g_event.Set(); + g_event->Set(); for(size_t i=0; i<NUMTHREADS; i++) { @@ -616,5 +643,27 @@ BOOST_AUTO_TEST_CASE(TestMassEvent) BOOST_CHECK(!m[i].waiting); BOOST_CHECK(m[i].result); } +} + + +BOOST_AUTO_TEST_CASE(TestMassEvent) +{ + g_event = new CEvent(); + + boost::shared_array<mass_waiter> m; + m.reset(new mass_waiter[NUMTHREADS]); + + RunMassEventTest(m,true); + delete g_event; +} + +BOOST_AUTO_TEST_CASE(TestMassEventPolling) +{ + g_event = new CEvent(true); // polling needs to avoid the auto-reset + + boost::shared_array<poll_mass_waiter> m; + m.reset(new poll_mass_waiter[NUMTHREADS]); + RunMassEventTest(m,false); + delete g_event; } diff --git a/xbmc/threads/test/TestSharedSection.cpp b/xbmc/threads/test/TestSharedSection.cpp index 9cdf942b89..0eea876c4d 100644 --- a/xbmc/threads/test/TestSharedSection.cpp +++ b/xbmc/threads/test/TestSharedSection.cpp @@ -23,6 +23,8 @@ #include "threads/SharedSection.h" #include "threads/SingleLock.h" +#include "threads/Event.h" +#include "threads/Atomics.h" #include <boost/thread/thread.hpp> #include <stdio.h> @@ -31,26 +33,70 @@ // Helper classes //============================================================================= +#define BOOST_MILLIS(x) (boost::get_system_time() + boost::posix_time::milliseconds(x)) + static void Sleep(unsigned int millis) { boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(millis)); } +static bool waitForThread(volatile long& mutex, int numWaiters, int milliseconds) +{ + CCriticalSection sec; + for( int i = 0; i < milliseconds; i++) + { + if (mutex == (long)numWaiters) + return true; + + { + CSingleLock tmplock(sec); // kick any memory syncs + } + Sleep(1); + } + return false; +} + +template<class E> static bool waitForWaiters(E& event, int numWaiters, int milliseconds) +{ + for( int i = 0; i < milliseconds; i++) + { + if (event.getNumWaits() == numWaiters) + return true; + Sleep(1); + } + return false; +} + +class AtomicGuard +{ + volatile long* val; +public: + inline AtomicGuard(volatile long* val_) : val(val_) { if (val) AtomicIncrement(val); } + inline ~AtomicGuard() { if (val) AtomicDecrement(val); } +}; + template<class L> class locker { CSharedSection& sec; - unsigned int wait; + CEvent* wait; + + volatile long* mutex; public: volatile bool haslock; volatile bool obtainedlock; - locker(CSharedSection& o, unsigned int waitTime = 0) : sec(o), wait(waitTime), haslock(false), obtainedlock(false) {} + inline locker(CSharedSection& o, volatile long* mutex_ = NULL, CEvent* wait_ = NULL) : + sec(o), wait(wait_), mutex(mutex_), haslock(false), obtainedlock(false) {} + + inline locker(CSharedSection& o, CEvent* wait_ = NULL) : + sec(o), wait(wait_), mutex(NULL), haslock(false), obtainedlock(false) {} void operator()() { + AtomicGuard g(mutex); L lock(sec); haslock = true; obtainedlock = true; if (wait) - Sleep(wait); + wait->Wait(); haslock = false; } }; @@ -73,23 +119,32 @@ BOOST_AUTO_TEST_CASE(TestSharedSectionCase) BOOST_AUTO_TEST_CASE(TestGetSharedLockWhileTryingExclusiveLock) { + volatile long mutex = 0; + CEvent event; + CSharedSection sec; CSharedLock l1(sec); // get a shared lock - locker<CExclusiveLock> l2(sec); + locker<CExclusiveLock> l2(sec,&mutex); boost::thread waitThread1(boost::ref(l2)); // try to get an exclusive lock - Sleep(10); + + BOOST_CHECK(waitForThread(mutex,1,10000)); + Sleep(10); // still need to give it a chance to move ahead + BOOST_CHECK(!l2.haslock); // this thread is waiting ... BOOST_CHECK(!l2.obtainedlock); // this thread is waiting ... // now try and get a SharedLock - locker<CSharedLock> l3(sec,50); + locker<CSharedLock> l3(sec,&mutex,&event); boost::thread waitThread3(boost::ref(l3)); // try to get a shared lock + BOOST_CHECK(waitForThread(mutex,2,10000)); Sleep(10); BOOST_CHECK(l3.haslock); - Sleep(50); + event.Set(); + BOOST_CHECK(waitThread3.timed_join(BOOST_MILLIS(10000))); + // l3 should have released. BOOST_CHECK(!l3.haslock); @@ -100,43 +155,52 @@ BOOST_AUTO_TEST_CASE(TestGetSharedLockWhileTryingExclusiveLock) // let it go l1.Leave(); // the last shared lock leaves. - Sleep(10); // give the exclusive lock some time + BOOST_CHECK(waitThread1.timed_join(BOOST_MILLIS(10000))); BOOST_CHECK(l2.obtainedlock); // the exclusive lock was captured BOOST_CHECK(!l2.haslock); // ... but it doesn't have it anymore - - Sleep(50); } BOOST_AUTO_TEST_CASE(TestSharedSection2Case) { CSharedSection sec; - locker<CSharedLock> l1(sec,20); + CEvent event; + volatile long mutex = 0; + + locker<CSharedLock> l1(sec,&mutex,&event); { CSharedLock lock(sec); boost::thread waitThread1(boost::ref(l1)); - Sleep(10); + BOOST_CHECK(waitForWaiters(event,1,10000)); BOOST_CHECK(l1.haslock); - waitThread1.join(); + event.Set(); + + BOOST_CHECK(waitThread1.timed_join(BOOST_MILLIS(10000))); } - locker<CSharedLock> l2(sec,20); + locker<CSharedLock> l2(sec,&mutex,&event); { - CExclusiveLock lock(sec); - boost::thread waitThread1(boost::ref(l2)); + CExclusiveLock lock(sec); // get exclusive lock + boost::thread waitThread2(boost::ref(l2)); // thread should block + + BOOST_CHECK(waitForThread(mutex,1,10000)); + Sleep(10); - Sleep(5); BOOST_CHECK(!l2.haslock); lock.Leave(); - Sleep(5); + + BOOST_CHECK(waitForWaiters(event,1,10000)); + Sleep(10); BOOST_CHECK(l2.haslock); + + event.Set(); - waitThread1.join(); + BOOST_CHECK(waitThread2.timed_join(BOOST_MILLIS(10000))); } } @@ -144,22 +208,29 @@ BOOST_AUTO_TEST_CASE(TestMultipleSharedSectionCase) { CSharedSection sec; - locker<CSharedLock> l1(sec,20); + CEvent event; + volatile long mutex = 0; + + locker<CSharedLock> l1(sec,&mutex, &event); { CSharedLock lock(sec); boost::thread waitThread1(boost::ref(l1)); + BOOST_CHECK(waitForThread(mutex,1,10000)); Sleep(10); + BOOST_CHECK(l1.haslock); - waitThread1.join(); + event.Set(); + + BOOST_CHECK(waitThread1.timed_join(BOOST_MILLIS(10000))); } - locker<CSharedLock> l2(sec,50); - locker<CSharedLock> l3(sec,50); - locker<CSharedLock> l4(sec,50); - locker<CSharedLock> l5(sec,50); + locker<CSharedLock> l2(sec,&mutex,&event); + locker<CSharedLock> l3(sec,&mutex,&event); + locker<CSharedLock> l4(sec,&mutex,&event); + locker<CSharedLock> l5(sec,&mutex,&event); { CExclusiveLock lock(sec); boost::thread waitThread1(boost::ref(l2)); @@ -167,7 +238,9 @@ BOOST_AUTO_TEST_CASE(TestMultipleSharedSectionCase) boost::thread waitThread3(boost::ref(l4)); boost::thread waitThread4(boost::ref(l5)); - Sleep(5); + BOOST_CHECK(waitForThread(mutex,4,10000)); + Sleep(10); + BOOST_CHECK(!l2.haslock); BOOST_CHECK(!l3.haslock); BOOST_CHECK(!l4.haslock); @@ -175,16 +248,19 @@ BOOST_AUTO_TEST_CASE(TestMultipleSharedSectionCase) lock.Leave(); - Sleep(5); + BOOST_CHECK(waitForWaiters(event,4,10000)); + BOOST_CHECK(l2.haslock); BOOST_CHECK(l3.haslock); BOOST_CHECK(l4.haslock); BOOST_CHECK(l5.haslock); + + event.Set(); - waitThread1.join(); - waitThread2.join(); - waitThread3.join(); - waitThread4.join(); + BOOST_CHECK(waitThread1.timed_join(BOOST_MILLIS(10000))); + BOOST_CHECK(waitThread2.timed_join(BOOST_MILLIS(10000))); + BOOST_CHECK(waitThread3.timed_join(BOOST_MILLIS(10000))); + BOOST_CHECK(waitThread4.timed_join(BOOST_MILLIS(10000))); } } |