Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 #include <gtest/gtest.h> | |
2 #include <queue> | |
3 | |
4 #include "../src/Thread.h" | |
5 | |
6 namespace | |
7 { | |
8 #ifndef WIN32 | |
9 void Sleep(const int millis) | |
10 { | |
11 usleep(millis * 1000); | |
12 } | |
13 #endif | |
14 | |
15 class Mock : public AdblockPlus::Thread | |
16 { | |
17 public: | |
18 int timesCalled; | |
19 | |
20 Mock() : timesCalled(0) | |
21 { | |
22 } | |
23 | |
24 void Run() | |
25 { | |
26 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
| |
27 } | |
28 }; | |
29 | |
30 class LockingMock : public AdblockPlus::Thread | |
31 { | |
32 public: | |
33 bool working; | |
34 | |
35 LockingMock(AdblockPlus::Thread::Mutex& mutex, const int millisToSleep) | |
36 : mutex(mutex), millisToSleep(millisToSleep) | |
37 { | |
38 } | |
39 | |
40 void Run() | |
41 { | |
42 mutex.Lock(); | |
43 working = true; | |
44 Sleep(millisToSleep); | |
45 working = false; | |
46 mutex.Unlock(); | |
47 } | |
48 | |
49 private: | |
50 AdblockPlus::Thread::Mutex& mutex; | |
51 int millisToSleep; | |
52 }; | |
53 | |
54 class Enqueuer : public AdblockPlus::Thread | |
55 { | |
56 public: | |
57 Enqueuer(std::queue<int>& queue, AdblockPlus::Thread::Mutex& mutex, | |
58 AdblockPlus::Thread::Condition& notEmpty) | |
59 : queue(queue), mutex(mutex), notEmpty(notEmpty) | |
60 { | |
61 } | |
62 | |
63 void Run() | |
64 { | |
65 Sleep(5); | |
66 mutex.Lock(); | |
67 queue.push(1); | |
68 Sleep(10); | |
69 notEmpty.Signal(); | |
70 mutex.Unlock(); | |
71 } | |
72 | |
73 private: | |
74 std::queue<int>& queue; | |
75 AdblockPlus::Thread::Mutex& mutex; | |
76 AdblockPlus::Thread::Condition& notEmpty; | |
77 }; | |
78 | |
79 class Dequeuer : public AdblockPlus::Thread | |
80 { | |
81 public: | |
82 Dequeuer(std::queue<int>& queue, AdblockPlus::Thread::Mutex& mutex, | |
83 AdblockPlus::Thread::Condition& notEmpty) | |
84 : queue(queue), mutex(mutex), notEmpty(notEmpty) | |
85 { | |
86 } | |
87 | |
88 void Run() | |
89 { | |
90 mutex.Lock(); | |
91 if (!queue.size()) | |
92 notEmpty.Wait(mutex); | |
93 queue.pop(); | |
94 mutex.Unlock(); | |
95 } | |
96 | |
97 private: | |
98 std::queue<int>& queue; | |
99 AdblockPlus::Thread::Mutex& mutex; | |
100 AdblockPlus::Thread::Condition& notEmpty; | |
101 }; | |
102 } | |
103 | |
104 TEST(ThreadTest, Run) | |
105 { | |
106 Mock mock; | |
107 ASSERT_EQ(0, mock.timesCalled); | |
108 mock.Start(); | |
109 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
| |
110 mock.Join(); | |
111 ASSERT_EQ(1, mock.timesCalled); | |
112 } | |
113 | |
114 TEST(ThreadTest, Mutex) | |
115 { | |
116 AdblockPlus::Thread::Mutex mutex; | |
117 LockingMock mock1(mutex, 10); | |
118 LockingMock mock2(mutex, 20); | |
119 mock1.Start(); | |
120 mock2.Start(); | |
121 Sleep(5); | |
122 ASSERT_TRUE(mock1.working); | |
123 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.
| |
124 Sleep(10); | |
125 ASSERT_TRUE(mock2.working); | |
126 ASSERT_FALSE(mock1.working); | |
127 mock1.Join(); | |
128 mock2.Join(); | |
129 } | |
130 | |
131 TEST(ThreadTest, ConditionVariable) | |
132 { | |
133 std::queue<int> queue; | |
134 AdblockPlus::Thread::Mutex mutex; | |
135 AdblockPlus::Thread::Condition notEmpty; | |
136 Enqueuer enqueuer(queue, mutex, notEmpty); | |
137 Dequeuer dequeuer(queue, mutex, notEmpty); | |
138 enqueuer.Start(); | |
139 dequeuer.Start(); | |
140 Sleep(10); | |
141 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.
| |
142 Sleep(15); | |
143 ASSERT_EQ(0, queue.size()); | |
144 enqueuer.Join(); | |
145 dequeuer.Join(); | |
146 } | |
OLD | NEW |