| 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 | 
|  | 18 #include <exception> | 
|  | 19 #include <gtest/gtest.h> | 
|  | 20 #include "../../src/plugin/DetachedInitialization.h" | 
|  | 21 | 
|  | 22 // Initializer that does nothing | 
|  | 23 void NullFunction() | 
|  | 24 {} | 
|  | 25 | 
|  | 26 // Initializer that always throws | 
|  | 27 const std::string failMessage = "initializer failed on purpose"; | 
|  | 28 void FailFunction() | 
|  | 29 { | 
|  | 30   throw std::runtime_error(failMessage); | 
|  | 31 } | 
|  | 32 | 
|  | 33 /* | 
|  | 34  * The destructor has to be able to block to wait for the initializer | 
|  | 35  * This test ensures that it doesn't block unnecessarily. | 
|  | 36  */ | 
|  | 37 TEST(DetachedInitializer, DestructorDoesNotBlockAfterNoActivity) | 
|  | 38 { | 
|  | 39   DetachedInitializer<NullFunction> x; | 
|  | 40 } | 
|  | 41 | 
|  | 42 TEST(DetachedInitializer, NullInstance) | 
|  | 43 { | 
|  | 44   ASSERT_NO_THROW( | 
|  | 45     { | 
|  | 46       DetachedInitializer<NullFunction> x; | 
|  | 47       x.SpawnInitializer(); | 
|  | 48       x.EnsureInitialized(); | 
|  | 49     } | 
|  | 50   ); | 
|  | 51 } | 
|  | 52 | 
|  | 53 /* | 
|  | 54  * This test illustrates a defect in Google Test. | 
|  | 55  * This test fails with a message that the test threw an exception. | 
|  | 56  * The exception message is the one thrown by FailFunction. | 
|  | 57  * It does not fail, importantly, because SpawnInitializer() throws. | 
|  | 58  * This can be verified in the debugger. | 
|  | 59  * | 
|  | 60  * It's disabled in the present code base so it doesn't break the unit test. | 
|  | 61  * Check this test again when we upgrade past GTest 1.60 and the VS 2012 toolset
     . | 
|  | 62  */ | 
|  | 63 TEST(DetachedInitializer, DISABLED_EnsureInitializedThrowingGtestDefectIllustrat
     ion) | 
|  | 64 { | 
|  | 65   DetachedInitializer<FailFunction> x; | 
|  | 66   bool threw = false; | 
|  | 67   try | 
|  | 68   { | 
|  | 69     x.SpawnInitializer(); | 
|  | 70   } | 
|  | 71   catch (...) | 
|  | 72   { | 
|  | 73     threw = true; | 
|  | 74     FAIL() << "SpawnInitializer() threw"; | 
|  | 75   } | 
|  | 76   ASSERT_FALSE(threw); | 
|  | 77 } | 
|  | 78 | 
|  | 79 /* | 
|  | 80  * This test fails because of a defect in Google Test. | 
|  | 81  * It's disabled at present, but should be enabled when the previous test is wor
     king. | 
|  | 82  */ | 
|  | 83 TEST(DetachedInitializer, DISABLED_EnsureInitializedThrowing) | 
|  | 84 { | 
|  | 85   DetachedInitializer<FailFunction> x; | 
|  | 86   try | 
|  | 87   { | 
|  | 88     x.SpawnInitializer(); | 
|  | 89   } | 
|  | 90   catch (...) | 
|  | 91   { | 
|  | 92     FAIL() << "SpawnInitializer() threw"; | 
|  | 93     return; | 
|  | 94   } | 
|  | 95   try | 
|  | 96   { | 
|  | 97     x.EnsureInitialized(); | 
|  | 98     FAIL() << "EnsureInitialized() did not throw"; | 
|  | 99   } | 
|  | 100   catch (std::runtime_error& e) | 
|  | 101   { | 
|  | 102     ASSERT_EQ(failMessage, e.what()); | 
|  | 103   } | 
|  | 104 } | 
|  | 105 | 
|  | 106 /* | 
|  | 107  * Resetable version of DetachedInitializer | 
|  | 108  */ | 
|  | 109 template<void(&F)()> | 
|  | 110 class DidReset | 
|  | 111   : public DetachedInitializer<F> | 
|  | 112 { | 
|  | 113 public: | 
|  | 114   void Reset() | 
|  | 115   { | 
|  | 116     isInitializationComplete.store(false, std::memory_order_relaxed); | 
|  | 117     hasInitializerStarted.store(false, std::memory_order_relaxed); | 
|  | 118     initializerException = nullptr; | 
|  | 119     // Lock and unlock the mutex to clear any previous state | 
|  | 120     // It will also detect a locked mutex left over from a previous test. | 
|  | 121     mutex.lock(); | 
|  | 122     mutex.unlock(); | 
|  | 123   } | 
|  | 124 }; | 
|  | 125 | 
|  | 126 /* | 
|  | 127  * Uses designated implementation pattern of DetachedInitializer | 
|  | 128  */ | 
|  | 129 struct DeferredIncrementingInitializer | 
|  | 130 { | 
|  | 131   static int initializedCount; | 
|  | 132 | 
|  | 133   static void Incrementer() | 
|  | 134   { | 
|  | 135     ++initializedCount; | 
|  | 136   } | 
|  | 137 | 
|  | 138   typedef DidReset<Incrementer> InitializerType; | 
|  | 139   static InitializerType di; | 
|  | 140 | 
|  | 141 public: | 
|  | 142   DeferredIncrementingInitializer() | 
|  | 143   { | 
|  | 144     di.SpawnInitializer(); | 
|  | 145   } | 
|  | 146 | 
|  | 147   static void ResetClass() | 
|  | 148   { | 
|  | 149     initializedCount = 0; | 
|  | 150     di.Reset(); | 
|  | 151   } | 
|  | 152 | 
|  | 153   static int GetInitializerCount () | 
|  | 154   { | 
|  | 155     di.EnsureInitialized(); | 
|  | 156     return initializedCount; | 
|  | 157   } | 
|  | 158 }; | 
|  | 159 DeferredIncrementingInitializer::InitializerType DeferredIncrementingInitializer
     ::di; | 
|  | 160 int DeferredIncrementingInitializer::initializedCount = 0; | 
|  | 161 | 
|  | 162 TEST(DetachedInitializer, Single) | 
|  | 163 { | 
|  | 164   DeferredIncrementingInitializer::ResetClass(); | 
|  | 165   DeferredIncrementingInitializer x; | 
|  | 166   ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount()); | 
|  | 167 } | 
|  | 168 | 
|  | 169 TEST(DetachedInitializer, Two) | 
|  | 170 { | 
|  | 171   DeferredIncrementingInitializer::ResetClass(); | 
|  | 172   DeferredIncrementingInitializer x; | 
|  | 173   DeferredIncrementingInitializer y; | 
|  | 174   ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount()); | 
|  | 175 } | 
|  | 176 | 
|  | 177 /* | 
|  | 178  * This test implicitly calls EnsureInitialized before the second call to SpawnI
     nitializer. | 
|  | 179  */ | 
|  | 180 TEST(DetachedInitializer, TwoInterleaved) | 
|  | 181 { | 
|  | 182   DeferredIncrementingInitializer::ResetClass(); | 
|  | 183   DeferredIncrementingInitializer x; | 
|  | 184   EXPECT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount()); | 
|  | 185   DeferredIncrementingInitializer y; | 
|  | 186   ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount()); | 
|  | 187 } | 
|  | 188 | 
|  | 189 TEST(DetachedInitializer, Many) | 
|  | 190 { | 
|  | 191   DeferredIncrementingInitializer::ResetClass(); | 
|  | 192   const int many = 1000000; | 
|  | 193   for (int j = 0; j < many;++j) | 
|  | 194   { | 
|  | 195     DeferredIncrementingInitializer x; | 
|  | 196   } | 
|  | 197   ASSERT_EQ(1, DeferredIncrementingInitializer::GetInitializerCount()); | 
|  | 198 } | 
| OLD | NEW | 
|---|