LEFT | RIGHT |
| 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2017 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 <stdexcept> |
| 19 #include "BaseJsTest.h" |
| 20 |
| 21 using namespace AdblockPlus; |
| 22 |
| 23 namespace |
| 24 { |
| 25 class JsEngineTest : public BaseJsTest |
| 26 { |
| 27 }; |
| 28 } |
| 29 |
| 30 TEST_F(JsEngineTest, Evaluate) |
| 31 { |
| 32 jsEngine->Evaluate("function hello() { return 'Hello'; }"); |
| 33 auto result = jsEngine->Evaluate("hello()"); |
| 34 ASSERT_TRUE(result.IsString()); |
| 35 ASSERT_EQ("Hello", result.AsString()); |
| 36 } |
| 37 |
| 38 TEST_F(JsEngineTest, RuntimeExceptionIsThrown) |
| 39 { |
| 40 ASSERT_THROW(jsEngine->Evaluate("doesnotexist()"), std::runtime_error); |
| 41 } |
| 42 |
| 43 TEST_F(JsEngineTest, CompileTimeExceptionIsThrown) |
| 44 { |
| 45 ASSERT_THROW(jsEngine->Evaluate("'foo'bar'"), std::runtime_error); |
| 46 } |
| 47 |
| 48 TEST_F(JsEngineTest, ValueCreation) |
| 49 { |
| 50 auto value = jsEngine->NewValue("foo"); |
| 51 ASSERT_TRUE(value.IsString()); |
| 52 ASSERT_EQ("foo", value.AsString()); |
| 53 |
| 54 value = jsEngine->NewValue(12345678901234); |
| 55 ASSERT_TRUE(value.IsNumber()); |
| 56 ASSERT_EQ(12345678901234, value.AsInt()); |
| 57 |
| 58 value = jsEngine->NewValue(true); |
| 59 ASSERT_TRUE(value.IsBool()); |
| 60 ASSERT_TRUE(value.AsBool()); |
| 61 |
| 62 value = jsEngine->NewObject(); |
| 63 ASSERT_TRUE(value.IsObject()); |
| 64 ASSERT_EQ(0u, value.GetOwnPropertyNames().size()); |
| 65 } |
| 66 |
| 67 namespace { |
| 68 |
| 69 bool IsSame(AdblockPlus::JsEngine& jsEngine, |
| 70 const AdblockPlus::JsValue& v1, const AdblockPlus::JsValue& v2) |
| 71 { |
| 72 AdblockPlus::JsValueList params; |
| 73 params.push_back(v1); |
| 74 params.push_back(v2); |
| 75 return jsEngine.Evaluate("f = function(a, b) { return a == b };").Call(param
s).AsBool(); |
| 76 } |
| 77 |
| 78 } |
| 79 |
| 80 TEST_F(JsEngineTest, ValueCopy) |
| 81 { |
| 82 { |
| 83 auto value = jsEngine->NewValue("foo"); |
| 84 ASSERT_TRUE(value.IsString()); |
| 85 ASSERT_EQ("foo", value.AsString()); |
| 86 |
| 87 AdblockPlus::JsValue value2(value); |
| 88 ASSERT_TRUE(value2.IsString()); |
| 89 ASSERT_EQ("foo", value2.AsString()); |
| 90 |
| 91 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); |
| 92 } |
| 93 { |
| 94 auto value = jsEngine->NewValue(12345678901234); |
| 95 ASSERT_TRUE(value.IsNumber()); |
| 96 ASSERT_EQ(12345678901234, value.AsInt()); |
| 97 |
| 98 AdblockPlus::JsValue value2(value); |
| 99 ASSERT_TRUE(value2.IsNumber()); |
| 100 ASSERT_EQ(12345678901234, value2.AsInt()); |
| 101 |
| 102 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); |
| 103 } |
| 104 { |
| 105 auto value = jsEngine->NewValue(true); |
| 106 ASSERT_TRUE(value.IsBool()); |
| 107 ASSERT_TRUE(value.AsBool()); |
| 108 |
| 109 AdblockPlus::JsValue value2(value); |
| 110 ASSERT_TRUE(value2.IsBool()); |
| 111 ASSERT_TRUE(value2.AsBool()); |
| 112 |
| 113 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); |
| 114 } |
| 115 { |
| 116 auto value = jsEngine->NewObject(); |
| 117 ASSERT_TRUE(value.IsObject()); |
| 118 ASSERT_EQ(0u, value.GetOwnPropertyNames().size()); |
| 119 |
| 120 AdblockPlus::JsValue value2(value); |
| 121 ASSERT_TRUE(value2.IsObject()); |
| 122 ASSERT_EQ(0u, value2.GetOwnPropertyNames().size()); |
| 123 |
| 124 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); |
| 125 } |
| 126 } |
| 127 |
| 128 TEST_F(JsEngineTest, EventCallbacks) |
| 129 { |
| 130 bool callbackCalled = false; |
| 131 AdblockPlus::JsValueList callbackParams; |
| 132 auto Callback = [&callbackCalled, &callbackParams](JsValueList&& params) |
| 133 { |
| 134 callbackCalled = true; |
| 135 callbackParams = move(params); |
| 136 }; |
| 137 |
| 138 // Trigger event without a callback |
| 139 callbackCalled = false; |
| 140 jsEngine->Evaluate("_triggerEvent('foobar')"); |
| 141 ASSERT_FALSE(callbackCalled); |
| 142 |
| 143 // Set callback |
| 144 jsEngine->SetEventCallback("foobar", Callback); |
| 145 callbackCalled = false; |
| 146 jsEngine->Evaluate("_triggerEvent('foobar', 1, 'x', true)"); |
| 147 ASSERT_TRUE(callbackCalled); |
| 148 ASSERT_EQ(callbackParams.size(), 3u); |
| 149 ASSERT_EQ(callbackParams[0].AsInt(), 1); |
| 150 ASSERT_EQ(callbackParams[1].AsString(), "x"); |
| 151 ASSERT_TRUE(callbackParams[2].AsBool()); |
| 152 |
| 153 // Trigger a different event |
| 154 callbackCalled = false; |
| 155 jsEngine->Evaluate("_triggerEvent('barfoo')"); |
| 156 ASSERT_FALSE(callbackCalled); |
| 157 |
| 158 // Remove callback |
| 159 jsEngine->RemoveEventCallback("foobar"); |
| 160 callbackCalled = false; |
| 161 jsEngine->Evaluate("_triggerEvent('foobar')"); |
| 162 ASSERT_FALSE(callbackCalled); |
| 163 } |
| 164 |
| 165 TEST(NewJsEngineTest, CallbackGetSet) |
| 166 { |
| 167 AdblockPlus::JsEnginePtr jsEngine(AdblockPlus::JsEngine::New()); |
| 168 |
| 169 ASSERT_TRUE(jsEngine->GetLogSystem()); |
| 170 ASSERT_ANY_THROW(jsEngine->SetLogSystem(AdblockPlus::LogSystemPtr())); |
| 171 AdblockPlus::LogSystemPtr logSystem(new AdblockPlus::DefaultLogSystem()); |
| 172 jsEngine->SetLogSystem(logSystem); |
| 173 ASSERT_EQ(logSystem, jsEngine->GetLogSystem()); |
| 174 |
| 175 ASSERT_TRUE(jsEngine->GetFileSystem()); |
| 176 ASSERT_ANY_THROW(jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr())); |
| 177 AdblockPlus::FileSystemPtr fileSystem(new AdblockPlus::DefaultFileSystem()); |
| 178 jsEngine->SetFileSystem(fileSystem); |
| 179 ASSERT_EQ(fileSystem, jsEngine->GetFileSystem()); |
| 180 } |
| 181 |
| 182 TEST(NewJsEngineTest, GlobalPropertyTest) |
| 183 { |
| 184 AdblockPlus::JsEnginePtr jsEngine(AdblockPlus::JsEngine::New()); |
| 185 jsEngine->SetGlobalProperty("foo", jsEngine->NewValue("bar")); |
| 186 auto foo = jsEngine->Evaluate("foo"); |
| 187 ASSERT_TRUE(foo.IsString()); |
1 ASSERT_EQ(foo.AsString(), "bar"); | 188 ASSERT_EQ(foo.AsString(), "bar"); |
2 } | 189 } |
3 | 190 |
| 191 TEST(NewJsEngineTest, MemoryLeak_NoCircularReferences) |
| 192 { |
| 193 std::weak_ptr<AdblockPlus::JsEngine> weakJsEngine; |
| 194 { |
| 195 weakJsEngine = AdblockPlus::JsEngine::New(); |
| 196 } |
| 197 EXPECT_FALSE(weakJsEngine.lock()); |
| 198 } |
| 199 |
| 200 #if UINTPTR_MAX == UINT32_MAX // detection of 32-bit platform |
| 201 static_assert(sizeof(intptr_t) == 4, "It should be 32bit platform"); |
| 202 TEST(NewJsEngineTest, 32bitsOnly_MemoryLeak_NoLeak) |
| 203 #else |
| 204 TEST(NewJsEngineTest, DISABLED_32bitsOnly_MemoryLeak_NoLeak) |
| 205 #endif |
| 206 { |
| 207 // v8::Isolate by default requires 32MB (depends on platform), so if there is |
| 208 // a memory leak than we will run out of memory on 32 bit platform because it |
| 209 // will allocate 32000 MB which is less than 2GB where it reaches out of |
| 210 // memory. Even on android where it allocates initially 16MB, the test still |
| 211 // makes sense. |
| 212 for (int i = 0; i < 1000; ++i) |
| 213 { |
| 214 AdblockPlus::JsEngine::New(); |
| 215 } |
| 216 } |
LEFT | RIGHT |