OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-2017 eyeo GmbH | 3 * Copyright (C) 2006-2017 eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 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/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 #include <stdexcept> | 18 #include <stdexcept> |
19 #include "BaseJsTest.h" | 19 #include "BaseJsTest.h" |
20 | 20 |
21 using namespace AdblockPlus; | 21 using namespace AdblockPlus; |
22 | 22 |
23 namespace | 23 namespace |
24 { | 24 { |
25 class JsEngineTest : public BaseJsTest | 25 typedef BaseJsTest JsEngineTest; |
26 { | |
27 protected: | |
28 JsEnginePtr jsEngine; | |
29 void SetUp() override | |
30 { | |
31 BaseJsTest::SetUp(); | |
32 jsEngine = platform->GetJsEngine(); | |
33 } | |
34 }; | |
35 } | 26 } |
36 | 27 |
37 TEST_F(JsEngineTest, Evaluate) | 28 TEST_F(JsEngineTest, Evaluate) |
38 { | 29 { |
39 jsEngine->Evaluate("function hello() { return 'Hello'; }"); | 30 GetJsEngine().Evaluate("function hello() { return 'Hello'; }"); |
40 auto result = jsEngine->Evaluate("hello()"); | 31 auto result = GetJsEngine().Evaluate("hello()"); |
41 ASSERT_TRUE(result.IsString()); | 32 ASSERT_TRUE(result.IsString()); |
42 ASSERT_EQ("Hello", result.AsString()); | 33 ASSERT_EQ("Hello", result.AsString()); |
43 } | 34 } |
44 | 35 |
45 TEST_F(JsEngineTest, RuntimeExceptionIsThrown) | 36 TEST_F(JsEngineTest, RuntimeExceptionIsThrown) |
46 { | 37 { |
47 ASSERT_THROW(jsEngine->Evaluate("doesnotexist()"), std::runtime_error); | 38 ASSERT_THROW(GetJsEngine().Evaluate("doesnotexist()"), std::runtime_error); |
48 } | 39 } |
49 | 40 |
50 TEST_F(JsEngineTest, CompileTimeExceptionIsThrown) | 41 TEST_F(JsEngineTest, CompileTimeExceptionIsThrown) |
51 { | 42 { |
52 ASSERT_THROW(jsEngine->Evaluate("'foo'bar'"), std::runtime_error); | 43 ASSERT_THROW(GetJsEngine().Evaluate("'foo'bar'"), std::runtime_error); |
53 } | 44 } |
54 | 45 |
55 TEST_F(JsEngineTest, ValueCreation) | 46 TEST_F(JsEngineTest, ValueCreation) |
56 { | 47 { |
57 auto value = jsEngine->NewValue("foo"); | 48 auto value = GetJsEngine().NewValue("foo"); |
58 ASSERT_TRUE(value.IsString()); | 49 ASSERT_TRUE(value.IsString()); |
59 ASSERT_EQ("foo", value.AsString()); | 50 ASSERT_EQ("foo", value.AsString()); |
60 | 51 |
61 value = jsEngine->NewValue(12345678901234); | 52 value = GetJsEngine().NewValue(12345678901234); |
62 ASSERT_TRUE(value.IsNumber()); | 53 ASSERT_TRUE(value.IsNumber()); |
63 ASSERT_EQ(12345678901234, value.AsInt()); | 54 ASSERT_EQ(12345678901234, value.AsInt()); |
64 | 55 |
65 value = jsEngine->NewValue(true); | 56 value = GetJsEngine().NewValue(true); |
66 ASSERT_TRUE(value.IsBool()); | 57 ASSERT_TRUE(value.IsBool()); |
67 ASSERT_TRUE(value.AsBool()); | 58 ASSERT_TRUE(value.AsBool()); |
68 | 59 |
69 value = jsEngine->NewObject(); | 60 value = GetJsEngine().NewObject(); |
70 ASSERT_TRUE(value.IsObject()); | 61 ASSERT_TRUE(value.IsObject()); |
71 ASSERT_EQ(0u, value.GetOwnPropertyNames().size()); | 62 ASSERT_EQ(0u, value.GetOwnPropertyNames().size()); |
72 } | 63 } |
73 | 64 |
74 namespace { | 65 namespace { |
75 | 66 |
76 bool IsSame(AdblockPlus::JsEngine& jsEngine, | 67 bool IsSame(AdblockPlus::JsEngine& jsEngine, |
77 const AdblockPlus::JsValue& v1, const AdblockPlus::JsValue& v2) | 68 const AdblockPlus::JsValue& v1, const AdblockPlus::JsValue& v2) |
78 { | 69 { |
79 AdblockPlus::JsValueList params; | 70 AdblockPlus::JsValueList params; |
80 params.push_back(v1); | 71 params.push_back(v1); |
81 params.push_back(v2); | 72 params.push_back(v2); |
82 return jsEngine.Evaluate("f = function(a, b) { return a == b };").Call(param
s).AsBool(); | 73 return jsEngine.Evaluate("f = function(a, b) { return a == b };").Call(param
s).AsBool(); |
83 } | 74 } |
84 | 75 |
85 } | 76 } |
86 | 77 |
87 TEST_F(JsEngineTest, ValueCopy) | 78 TEST_F(JsEngineTest, ValueCopy) |
88 { | 79 { |
89 { | 80 { |
90 auto value = jsEngine->NewValue("foo"); | 81 auto value = GetJsEngine().NewValue("foo"); |
91 ASSERT_TRUE(value.IsString()); | 82 ASSERT_TRUE(value.IsString()); |
92 ASSERT_EQ("foo", value.AsString()); | 83 ASSERT_EQ("foo", value.AsString()); |
93 | 84 |
94 AdblockPlus::JsValue value2(value); | 85 AdblockPlus::JsValue value2(value); |
95 ASSERT_TRUE(value2.IsString()); | 86 ASSERT_TRUE(value2.IsString()); |
96 ASSERT_EQ("foo", value2.AsString()); | 87 ASSERT_EQ("foo", value2.AsString()); |
97 | 88 |
98 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); | 89 ASSERT_TRUE(IsSame(GetJsEngine(), value, value2)); |
99 } | 90 } |
100 { | 91 { |
101 auto value = jsEngine->NewValue(12345678901234); | 92 auto value = GetJsEngine().NewValue(12345678901234); |
102 ASSERT_TRUE(value.IsNumber()); | 93 ASSERT_TRUE(value.IsNumber()); |
103 ASSERT_EQ(12345678901234, value.AsInt()); | 94 ASSERT_EQ(12345678901234, value.AsInt()); |
104 | 95 |
105 AdblockPlus::JsValue value2(value); | 96 AdblockPlus::JsValue value2(value); |
106 ASSERT_TRUE(value2.IsNumber()); | 97 ASSERT_TRUE(value2.IsNumber()); |
107 ASSERT_EQ(12345678901234, value2.AsInt()); | 98 ASSERT_EQ(12345678901234, value2.AsInt()); |
108 | 99 |
109 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); | 100 ASSERT_TRUE(IsSame(GetJsEngine(), value, value2)); |
110 } | 101 } |
111 { | 102 { |
112 auto value = jsEngine->NewValue(true); | 103 auto value = GetJsEngine().NewValue(true); |
113 ASSERT_TRUE(value.IsBool()); | 104 ASSERT_TRUE(value.IsBool()); |
114 ASSERT_TRUE(value.AsBool()); | 105 ASSERT_TRUE(value.AsBool()); |
115 | 106 |
116 AdblockPlus::JsValue value2(value); | 107 AdblockPlus::JsValue value2(value); |
117 ASSERT_TRUE(value2.IsBool()); | 108 ASSERT_TRUE(value2.IsBool()); |
118 ASSERT_TRUE(value2.AsBool()); | 109 ASSERT_TRUE(value2.AsBool()); |
119 | 110 |
120 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); | 111 ASSERT_TRUE(IsSame(GetJsEngine(), value, value2)); |
121 } | 112 } |
122 { | 113 { |
123 auto value = jsEngine->NewObject(); | 114 auto value = GetJsEngine().NewObject(); |
124 ASSERT_TRUE(value.IsObject()); | 115 ASSERT_TRUE(value.IsObject()); |
125 ASSERT_EQ(0u, value.GetOwnPropertyNames().size()); | 116 ASSERT_EQ(0u, value.GetOwnPropertyNames().size()); |
126 | 117 |
127 AdblockPlus::JsValue value2(value); | 118 AdblockPlus::JsValue value2(value); |
128 ASSERT_TRUE(value2.IsObject()); | 119 ASSERT_TRUE(value2.IsObject()); |
129 ASSERT_EQ(0u, value2.GetOwnPropertyNames().size()); | 120 ASSERT_EQ(0u, value2.GetOwnPropertyNames().size()); |
130 | 121 |
131 ASSERT_TRUE(IsSame(*jsEngine, value, value2)); | 122 ASSERT_TRUE(IsSame(GetJsEngine(), value, value2)); |
132 } | 123 } |
133 } | 124 } |
134 | 125 |
135 TEST_F(JsEngineTest, EventCallbacks) | 126 TEST_F(JsEngineTest, EventCallbacks) |
136 { | 127 { |
137 bool callbackCalled = false; | 128 bool callbackCalled = false; |
138 AdblockPlus::JsValueList callbackParams; | 129 AdblockPlus::JsValueList callbackParams; |
139 auto Callback = [&callbackCalled, &callbackParams](JsValueList&& params) | 130 auto Callback = [&callbackCalled, &callbackParams](JsValueList&& params) |
140 { | 131 { |
141 callbackCalled = true; | 132 callbackCalled = true; |
142 callbackParams = move(params); | 133 callbackParams = move(params); |
143 }; | 134 }; |
144 | 135 |
145 // Trigger event without a callback | 136 // Trigger event without a callback |
146 callbackCalled = false; | 137 callbackCalled = false; |
147 jsEngine->Evaluate("_triggerEvent('foobar')"); | 138 GetJsEngine().Evaluate("_triggerEvent('foobar')"); |
148 ASSERT_FALSE(callbackCalled); | 139 ASSERT_FALSE(callbackCalled); |
149 | 140 |
150 // Set callback | 141 // Set callback |
151 jsEngine->SetEventCallback("foobar", Callback); | 142 GetJsEngine().SetEventCallback("foobar", Callback); |
152 callbackCalled = false; | 143 callbackCalled = false; |
153 jsEngine->Evaluate("_triggerEvent('foobar', 1, 'x', true)"); | 144 GetJsEngine().Evaluate("_triggerEvent('foobar', 1, 'x', true)"); |
154 ASSERT_TRUE(callbackCalled); | 145 ASSERT_TRUE(callbackCalled); |
155 ASSERT_EQ(callbackParams.size(), 3u); | 146 ASSERT_EQ(callbackParams.size(), 3u); |
156 ASSERT_EQ(callbackParams[0].AsInt(), 1); | 147 ASSERT_EQ(callbackParams[0].AsInt(), 1); |
157 ASSERT_EQ(callbackParams[1].AsString(), "x"); | 148 ASSERT_EQ(callbackParams[1].AsString(), "x"); |
158 ASSERT_TRUE(callbackParams[2].AsBool()); | 149 ASSERT_TRUE(callbackParams[2].AsBool()); |
159 | 150 |
160 // Trigger a different event | 151 // Trigger a different event |
161 callbackCalled = false; | 152 callbackCalled = false; |
162 jsEngine->Evaluate("_triggerEvent('barfoo')"); | 153 GetJsEngine().Evaluate("_triggerEvent('barfoo')"); |
163 ASSERT_FALSE(callbackCalled); | 154 ASSERT_FALSE(callbackCalled); |
164 | 155 |
165 // Remove callback | 156 // Remove callback |
166 jsEngine->RemoveEventCallback("foobar"); | 157 GetJsEngine().RemoveEventCallback("foobar"); |
167 callbackCalled = false; | 158 callbackCalled = false; |
168 jsEngine->Evaluate("_triggerEvent('foobar')"); | 159 GetJsEngine().Evaluate("_triggerEvent('foobar')"); |
169 ASSERT_FALSE(callbackCalled); | 160 ASSERT_FALSE(callbackCalled); |
170 } | 161 } |
171 | 162 |
172 TEST(NewJsEngineTest, GlobalPropertyTest) | 163 TEST(NewJsEngineTest, GlobalPropertyTest) |
173 { | 164 { |
174 Platform platform{ThrowingPlatformCreationParameters()}; | 165 Platform platform{ThrowingPlatformCreationParameters()}; |
175 auto jsEngine = platform.GetJsEngine(); | 166 auto& jsEngine = platform.GetJsEngine(); |
176 jsEngine->SetGlobalProperty("foo", jsEngine->NewValue("bar")); | 167 jsEngine.SetGlobalProperty("foo", jsEngine.NewValue("bar")); |
177 auto foo = jsEngine->Evaluate("foo"); | 168 auto foo = jsEngine.Evaluate("foo"); |
178 ASSERT_TRUE(foo.IsString()); | 169 ASSERT_TRUE(foo.IsString()); |
179 ASSERT_EQ(foo.AsString(), "bar"); | 170 ASSERT_EQ(foo.AsString(), "bar"); |
180 } | 171 } |
181 | 172 |
182 TEST(NewJsEngineTest, MemoryLeak_NoCircularReferences) | 173 TEST(NewJsEngineTest, MemoryLeak_NoCircularReferences) |
183 { | 174 { |
| 175 Platform platform{ThrowingPlatformCreationParameters()}; |
184 std::weak_ptr<AdblockPlus::JsEngine> weakJsEngine; | 176 std::weak_ptr<AdblockPlus::JsEngine> weakJsEngine; |
185 { | 177 { |
186 weakJsEngine = Platform{ThrowingPlatformCreationParameters()}.GetJsEngine(); | 178 weakJsEngine = JsEngine::New(AppInfo(), platform); |
187 } | 179 } |
188 EXPECT_FALSE(weakJsEngine.lock()); | 180 EXPECT_FALSE(weakJsEngine.lock()); |
189 } | 181 } |
190 | 182 |
191 #if UINTPTR_MAX == UINT32_MAX // detection of 32-bit platform | 183 #if UINTPTR_MAX == UINT32_MAX // detection of 32-bit platform |
192 static_assert(sizeof(intptr_t) == 4, "It should be 32bit platform"); | 184 static_assert(sizeof(intptr_t) == 4, "It should be 32bit platform"); |
193 TEST(NewJsEngineTest, 32bitsOnly_MemoryLeak_NoLeak) | 185 TEST(NewJsEngineTest, 32bitsOnly_MemoryLeak_NoLeak) |
194 #else | 186 #else |
195 TEST(NewJsEngineTest, DISABLED_32bitsOnly_MemoryLeak_NoLeak) | 187 TEST(NewJsEngineTest, DISABLED_32bitsOnly_MemoryLeak_NoLeak) |
196 #endif | 188 #endif |
197 { | 189 { |
| 190 Platform platform{ThrowingPlatformCreationParameters()}; |
198 // v8::Isolate by default requires 32MB (depends on platform), so if there is | 191 // v8::Isolate by default requires 32MB (depends on platform), so if there is |
199 // a memory leak than we will run out of memory on 32 bit platform because it | 192 // a memory leak than we will run out of memory on 32 bit platform because it |
200 // will allocate 32000 MB which is less than 2GB where it reaches out of | 193 // will allocate 32000 MB which is less than 2GB where it reaches out of |
201 // memory. Even on android where it allocates initially 16MB, the test still | 194 // memory. Even on android where it allocates initially 16MB, the test still |
202 // makes sense. | 195 // makes sense. |
203 for (int i = 0; i < 1000; ++i) | 196 for (int i = 0; i < 1000; ++i) |
204 { | 197 { |
205 Platform{ThrowingPlatformCreationParameters()}.GetJsEngine(); | 198 JsEngine::New(AppInfo(), platform); |
206 } | 199 } |
207 } | 200 } |
OLD | NEW |