| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 /* | 
|  | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
|  | 3  * Copyright (C) 2006-2015 Eyeo GmbH | 
|  | 4  * | 
|  | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
|  | 6  * it under the terms of the GNU General Public License version 3 as | 
|  | 7  * published by the Free Software Foundation. | 
|  | 8  * | 
|  | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
|  | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 12  * GNU General Public License for more details. | 
|  | 13  * | 
|  | 14  * You should have received a copy of the GNU General Public License | 
|  | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 16  */ | 
|  | 17 #include <gtest/gtest.h> | 
|  | 18 #include "../../src/plugin/ActiveQueue.h" | 
|  | 19 #include <ostream> | 
|  | 20 #include <memory> | 
|  | 21 | 
|  | 22 class TrivialIntMessageQueue | 
|  | 23   : public MessageQueue<int> | 
|  | 24 { | 
|  | 25 public: | 
|  | 26   TrivialIntMessageQueue() | 
|  | 27     : MessageQueue() | 
|  | 28   {} | 
|  | 29 }; | 
|  | 30 | 
|  | 31 TEST(MessageQueue, Instance) | 
|  | 32 { | 
|  | 33   TrivialIntMessageQueue mq; | 
|  | 34 } | 
|  | 35 | 
|  | 36 TEST(MessageQueue, Insert) | 
|  | 37 { | 
|  | 38   TrivialIntMessageQueue mq; | 
|  | 39   mq.Insert(5); | 
|  | 40 } | 
|  | 41 | 
|  | 42 TEST(MessageQueue, RvalueInsertRemove) | 
|  | 43 { | 
|  | 44   TrivialIntMessageQueue mq; | 
|  | 45   mq.Insert(2+3); // int&& | 
|  | 46   int result; | 
|  | 47   auto haveResult = mq.Remove([&](int x) { result = x; }); | 
|  | 48   ASSERT_TRUE(haveResult); | 
|  | 49   ASSERT_EQ(5, result); | 
|  | 50 } | 
|  | 51 | 
|  | 52 TEST(MessageQueue, ConstInsertRemove) | 
|  | 53 { | 
|  | 54   TrivialIntMessageQueue mq; | 
|  | 55   const int value = 4; | 
|  | 56   mq.Insert(value); // const int& | 
|  | 57   int result; | 
|  | 58   auto haveResult = mq.Remove([&](int x) { result = x; }); | 
|  | 59   ASSERT_TRUE(haveResult); | 
|  | 60   ASSERT_EQ(4, result); | 
|  | 61 } | 
|  | 62 | 
|  | 63 TEST(MessageQueue, Thread) | 
|  | 64 { | 
|  | 65   bool threadTimeout = false; | 
|  | 66   std::string threadFailMessage; | 
|  | 67   MessageQueue<unsigned int> mq; | 
|  | 68   static const unsigned int numberOfElements = 1000; | 
|  | 69   unsigned int counter = 1; | 
|  | 70 | 
|  | 71   std::thread th([&]() -> void { | 
|  | 72     // Begin body of notice thread | 
|  | 73     try | 
|  | 74     { | 
|  | 75       /* | 
|  | 76        * We use a nested loop with the same predicate because notice and wait ar
     e not related one-to-one. | 
|  | 77        * Multiple calls to notify_one() may happen before the wait_for() stateme
     nt is active. | 
|  | 78        * Thus the outer loop manages the condition variable. | 
|  | 79        * The inner loop removes all available queue elements, since there may be
      more than one per notice. | 
|  | 80        */ | 
|  | 81       while (counter < numberOfElements) | 
|  | 82       { | 
|  | 83         if (mq.WaitFor(std::chrono::seconds(10)) == std::cv_status::timeout) | 
|  | 84         { | 
|  | 85           threadFailMessage = "Thread timed out."; | 
|  | 86           return; | 
|  | 87         } | 
|  | 88         bool noticeIsFresh = true; | 
|  | 89         while (counter < numberOfElements) | 
|  | 90         { | 
|  | 91           unsigned int element; | 
|  | 92           auto f = [&](unsigned int x) -> void { element = x; }; | 
|  | 93           if (mq.Remove(f)) | 
|  | 94           { | 
|  | 95             if (element != counter) | 
|  | 96             { | 
|  | 97               std::ostringstream ss; | 
|  | 98               ss << "Counter mismatch. expected = " << counter << ". actual = " 
     << element; | 
|  | 99               threadFailMessage = ss.str(); | 
|  | 100               return; | 
|  | 101             } | 
|  | 102             noticeIsFresh = false; | 
|  | 103             ++counter; // counter represents the number of elements removed, so 
     only increment when remove() returns true | 
|  | 104           } | 
|  | 105           else if (noticeIsFresh) | 
|  | 106           { | 
|  | 107             threadFailMessage = "Notice received, but no element to remove from 
     queue."; | 
|  | 108             return; | 
|  | 109           } | 
|  | 110         } | 
|  | 111       } | 
|  | 112     } | 
|  | 113     catch (std::exception &e) | 
|  | 114     { | 
|  | 115       threadFailMessage = std::string("Exception: ") + e.what(); | 
|  | 116     } | 
|  | 117     // End body of notice thread | 
|  | 118   }); | 
|  | 119 | 
|  | 120   // Body of test thread | 
|  | 121   for (unsigned int j = 1; j <= numberOfElements ; ++j) | 
|  | 122   { | 
|  | 123     mq.Insert(j); | 
|  | 124   }; | 
|  | 125   th.join(); | 
|  | 126   if (!threadFailMessage.empty()) | 
|  | 127   { | 
|  | 128     FAIL() << threadFailMessage; | 
|  | 129   } | 
|  | 130   ASSERT_EQ(numberOfElements, counter); | 
|  | 131 } | 
|  | 132 | 
|  | 133 /* | 
|  | 134  * All the ActiveQueue tests instantiante the ActiveQueue in a separate block. | 
|  | 135  * This ensures its internal thread has terminated before the end of the test, | 
|  | 136  *   and that the test will hang if it has not. | 
|  | 137  */ | 
|  | 138 | 
|  | 139 TEST(ActiveQueue, Instance) | 
|  | 140 { | 
|  | 141   bool seen = false; | 
|  | 142   auto process = [&](unsigned int) { seen = true; }; | 
|  | 143   { | 
|  | 144     ActiveQueue<unsigned int, decltype(process)> aq(process); | 
|  | 145   } | 
|  | 146   ASSERT_FALSE(seen); | 
|  | 147 } | 
|  | 148 | 
|  | 149 TEST(ActiveQueue, Single) | 
|  | 150 { | 
|  | 151   bool seen = false; | 
|  | 152   auto process = [&](unsigned int) { seen = true; }; | 
|  | 153   { | 
|  | 154     ActiveQueue<unsigned int, decltype(process)> aq(process); | 
|  | 155     aq.Insert(0); | 
|  | 156   } | 
|  | 157   ASSERT_TRUE(seen); | 
|  | 158 } | 
|  | 159 | 
|  | 160 TEST(ActiveQueue, Multiple) | 
|  | 161 { | 
|  | 162   static const unsigned int numberOfElements = 1000; | 
|  | 163   unsigned int counter = 0; | 
|  | 164   std::string threadFailMessage; | 
|  | 165   auto process = [&](unsigned int x) -> void { | 
|  | 166     ++counter; | 
|  | 167     if (x != counter) | 
|  | 168     { | 
|  | 169       std::ostringstream os; | 
|  | 170       os << "Mismatch: expected counter=" << counter << ", received queue elemen
     t=" << x << "."; | 
|  | 171       threadFailMessage = os.str(); | 
|  | 172     } | 
|  | 173   }; | 
|  | 174   { | 
|  | 175     ActiveQueue<unsigned int, decltype(process)> aq(process); | 
|  | 176     for (unsigned int j = 1; j <= numberOfElements; ++j) | 
|  | 177     { | 
|  | 178       aq.Insert(j); | 
|  | 179       ASSERT_EQ("", threadFailMessage); | 
|  | 180     }; | 
|  | 181   } | 
|  | 182   ASSERT_EQ(numberOfElements, counter); | 
|  | 183 } | 
| OLD | NEW | 
|---|