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