Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: test/Thread.cpp

Issue 10026001: Cross-platform thread primitives (Closed)
Patch Set: Created March 29, 2013, 5:26 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/Thread.cpp ('K') | « src/Thread.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/Thread.cpp
===================================================================
new file mode 100644
--- /dev/null
+++ b/test/Thread.cpp
@@ -0,0 +1,146 @@
+#include <gtest/gtest.h>
+#include <queue>
+
+#include "../src/Thread.h"
+
+namespace
+{
+#ifndef WIN32
+ void Sleep(const int millis)
+ {
+ usleep(millis * 1000);
+ }
+#endif
+
+ class Mock : public AdblockPlus::Thread
+ {
+ public:
+ int timesCalled;
+
+ Mock() : timesCalled(0)
+ {
+ }
+
+ void Run()
+ {
+ timesCalled++;
Wladimir Palant 2013/04/03 13:14:47 This statement isn't thread-safe, you need a mutex
Felix Dahlke 2013/04/03 16:27:59 I thought that's pretty unlikely here, but fair en
+ }
+ };
+
+ class LockingMock : public AdblockPlus::Thread
+ {
+ public:
+ bool working;
+
+ LockingMock(AdblockPlus::Thread::Mutex& mutex, const int millisToSleep)
+ : mutex(mutex), millisToSleep(millisToSleep)
+ {
+ }
+
+ void Run()
+ {
+ mutex.Lock();
+ working = true;
+ Sleep(millisToSleep);
+ working = false;
+ mutex.Unlock();
+ }
+
+ private:
+ AdblockPlus::Thread::Mutex& mutex;
+ int millisToSleep;
+ };
+
+ class Enqueuer : public AdblockPlus::Thread
+ {
+ public:
+ Enqueuer(std::queue<int>& queue, AdblockPlus::Thread::Mutex& mutex,
+ AdblockPlus::Thread::Condition& notEmpty)
+ : queue(queue), mutex(mutex), notEmpty(notEmpty)
+ {
+ }
+
+ void Run()
+ {
+ Sleep(5);
+ mutex.Lock();
+ queue.push(1);
+ Sleep(10);
+ notEmpty.Signal();
+ mutex.Unlock();
+ }
+
+ private:
+ std::queue<int>& queue;
+ AdblockPlus::Thread::Mutex& mutex;
+ AdblockPlus::Thread::Condition& notEmpty;
+ };
+
+ class Dequeuer : public AdblockPlus::Thread
+ {
+ public:
+ Dequeuer(std::queue<int>& queue, AdblockPlus::Thread::Mutex& mutex,
+ AdblockPlus::Thread::Condition& notEmpty)
+ : queue(queue), mutex(mutex), notEmpty(notEmpty)
+ {
+ }
+
+ void Run()
+ {
+ mutex.Lock();
+ if (!queue.size())
+ notEmpty.Wait(mutex);
+ queue.pop();
+ mutex.Unlock();
+ }
+
+ private:
+ std::queue<int>& queue;
+ AdblockPlus::Thread::Mutex& mutex;
+ AdblockPlus::Thread::Condition& notEmpty;
+ };
+}
+
+TEST(ThreadTest, Run)
+{
+ Mock mock;
+ ASSERT_EQ(0, mock.timesCalled);
+ mock.Start();
+ ASSERT_EQ(0, mock.timesCalled);
Wladimir Palant 2013/04/03 13:14:47 This is a race condition - by the time you check t
Felix Dahlke 2013/04/03 16:27:59 Yes indeed, made it a bit more robust. It's still
+ mock.Join();
+ ASSERT_EQ(1, mock.timesCalled);
+}
+
+TEST(ThreadTest, Mutex)
+{
+ AdblockPlus::Thread::Mutex mutex;
+ LockingMock mock1(mutex, 10);
+ LockingMock mock2(mutex, 20);
+ mock1.Start();
+ mock2.Start();
+ Sleep(5);
+ ASSERT_TRUE(mock1.working);
+ ASSERT_FALSE(mock2.working);
Wladimir Palant 2013/04/03 13:14:47 Please note that Sleep() (both the Windows and the
Felix Dahlke 2013/04/03 16:27:59 Agreed, much more robust that way.
+ Sleep(10);
+ ASSERT_TRUE(mock2.working);
+ ASSERT_FALSE(mock1.working);
+ mock1.Join();
+ mock2.Join();
+}
+
+TEST(ThreadTest, ConditionVariable)
+{
+ std::queue<int> queue;
+ AdblockPlus::Thread::Mutex mutex;
+ AdblockPlus::Thread::Condition notEmpty;
+ Enqueuer enqueuer(queue, mutex, notEmpty);
+ Dequeuer dequeuer(queue, mutex, notEmpty);
+ enqueuer.Start();
+ dequeuer.Start();
+ Sleep(10);
+ ASSERT_EQ(1, queue.size());
Wladimir Palant 2013/04/03 13:14:47 Same flaw here as above.
Felix Dahlke 2013/04/03 16:27:59 Fixed as well.
+ Sleep(15);
+ ASSERT_EQ(0, queue.size());
+ enqueuer.Join();
+ dequeuer.Join();
+}
« src/Thread.cpp ('K') | « src/Thread.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld