Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: test/WebRequest.cpp

Issue 29377064: Issue 4944 - Make creation of FilterEngine asynchronous. (Closed)
Left Patch Set: Created Feb. 28, 2017, 2:21 p.m.
Right Patch Set: rebase and address comments Created March 16, 2017, 3:47 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « test/UpdateCheck.cpp ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 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 <sstream> 18 #include <sstream>
19 #include "BaseJsTest.h" 19 #include "BaseJsTest.h"
20 #include "../src/Thread.h" 20 #include "../src/Thread.h"
21 21
22 namespace 22 namespace
23 { 23 {
24 class MockWebRequest : public AdblockPlus::WebRequest 24 class MockWebRequest : public AdblockPlus::WebRequest
25 { 25 {
26 public: 26 public:
27 AdblockPlus::ServerResponse GET(const std::string& url, const AdblockPlus::H eaderList& requestHeaders) const 27 AdblockPlus::ServerResponse GET(const std::string& url, const AdblockPlus::H eaderList& requestHeaders) const
28 { 28 {
29 lastRequestHeaders.clear();
30 for (auto header : requestHeaders)
31 {
32 lastRequestHeaders.insert(header.first);
33 }
34
29 AdblockPlus::Sleep(50); 35 AdblockPlus::Sleep(50);
30 36
31 AdblockPlus::ServerResponse result; 37 AdblockPlus::ServerResponse result;
32 result.status = NS_OK; 38 result.status = NS_OK;
33 result.responseStatus = 123; 39 result.responseStatus = 123;
34 result.responseHeaders.push_back(std::pair<std::string, std::string>("Foo" , "Bar")); 40 result.responseHeaders.push_back(std::pair<std::string, std::string>("Foo" , "Bar"));
35 result.responseText = url + "\n" + requestHeaders[0].first + "\n" + reques tHeaders[0].second; 41 result.responseText = url + "\n";
42 if (!requestHeaders.empty())
43 {
44 result.responseText += requestHeaders[0].first + "\n" + requestHeaders[0 ].second;
45 }
36 return result; 46 return result;
37 } 47 }
48
49 // mutable. Very Ugly. But we are testing and need to change this in GET whi ch is const.
50 mutable std::set<std::string> lastRequestHeaders;
38 }; 51 };
39 52
40 template<class T> 53 template<class T>
41 class WebRequestTest : public BaseJsTest 54 class WebRequestTest : public BaseJsTest
42 { 55 {
43 protected: 56 protected:
44 void SetUp() 57 void SetUp()
45 { 58 {
46 BaseJsTest::SetUp(); 59 BaseJsTest::SetUp();
47 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(new T)); 60 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(new T));
48 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new LazyFileSystem)); 61 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new LazyFileSystem));
49 } 62 }
50 }; 63 };
51 64
52 typedef WebRequestTest<MockWebRequest> MockWebRequestTest; 65 typedef WebRequestTest<MockWebRequest> MockWebRequestTest;
53 typedef WebRequestTest<AdblockPlus::DefaultWebRequest> DefaultWebRequestTest; 66 typedef WebRequestTest<AdblockPlus::DefaultWebRequest> DefaultWebRequestTest;
67 typedef WebRequestTest<MockWebRequest> XMLHttpRequestTest;
68
69 void ResetTestXHR(const AdblockPlus::JsEnginePtr& jsEngine)
70 {
71 jsEngine->Evaluate("\
72 var result;\
73 var request = new XMLHttpRequest();\
74 request.open('GET', 'https://easylist-downloads.adblockplus.org/easylist.t xt');\
75 request.overrideMimeType('text/plain');\
76 request.addEventListener('load', function() {result = request.responseText ;}, false);\
77 request.addEventListener('error', function() {result = 'error';}, false);\
78 ");
79 }
80
81 void WaitForVariable(const std::string& variable, const AdblockPlus::JsEngineP tr& jsEngine)
82 {
83 do
84 {
85 AdblockPlus::Sleep(60);
86 } while (jsEngine->Evaluate(variable)->IsUndefined());
87 }
88
54 } 89 }
55 90
56 TEST_F(MockWebRequestTest, BadCall) 91 TEST_F(MockWebRequestTest, BadCall)
57 { 92 {
58 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET()")); 93 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET()"));
59 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('', {}, function(){})")); 94 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('', {}, function(){})"));
60 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET({toString: false}, {}, fu nction(){})")); 95 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET({toString: false}, {}, fu nction(){})"));
61 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('http://example.com/', nu ll, function(){})")); 96 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('http://example.com/', nu ll, function(){})"));
62 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('http://example.com/', {} , null)")); 97 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('http://example.com/', {} , null)"));
63 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('http://example.com/', {} , function(){}, 0)")); 98 ASSERT_ANY_THROW(jsEngine->Evaluate("_webRequest.GET('http://example.com/', {} , function(){}, 0)"));
64 } 99 }
65 100
66 TEST_F(MockWebRequestTest, SuccessfulRequest) 101 TEST_F(MockWebRequestTest, SuccessfulRequest)
67 { 102 {
68 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function( result) {foo = result;} )"); 103 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function( result) {foo = result;} )");
69 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); 104 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined());
70 AdblockPlus::Sleep(200); 105 AdblockPlus::Sleep(200);
71 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As Int()); 106 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As Int());
72 ASSERT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); 107 ASSERT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt());
73 ASSERT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")- >AsString()); 108 ASSERT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")- >AsString());
74 ASSERT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response Headers)")->AsString()); 109 ASSERT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response Headers)")->AsString());
75 } 110 }
76 111
77 #if defined(HAVE_CURL) || defined(_WIN32) 112 #if defined(HAVE_CURL) || defined(_WIN32)
78 TEST_F(DefaultWebRequestTest, RealWebRequest) 113 TEST_F(DefaultWebRequestTest, RealWebRequest)
79 { 114 {
80 // This URL should redirect to easylist-downloads.adblockplus.org and we 115 // This URL should redirect to easylist-downloads.adblockplus.org and we
81 // should get the actual filter list back. 116 // should get the actual filter list back.
82 jsEngine->Evaluate("_webRequest.GET('https://easylist-downloads.adblockplus.or g/easylist.txt', {}, function(result) {foo = result;} )"); 117 jsEngine->Evaluate("_webRequest.GET('https://easylist-downloads.adblockplus.or g/easylist.txt', {}, function(result) {foo = result;} )");
83 do 118 WaitForVariable("this.foo", jsEngine);
84 {
85 AdblockPlus::Sleep(200);
86 } while (jsEngine->Evaluate("this.foo")->IsUndefined());
87 ASSERT_EQ("text/plain", jsEngine->Evaluate("foo.responseHeaders['content-type' ].substr(0, 10)")->AsString()); 119 ASSERT_EQ("text/plain", jsEngine->Evaluate("foo.responseHeaders['content-type' ].substr(0, 10)")->AsString());
88 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As Int()); 120 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As Int());
89 ASSERT_EQ(200, jsEngine->Evaluate("foo.responseStatus")->AsInt()); 121 ASSERT_EQ(200, jsEngine->Evaluate("foo.responseStatus")->AsInt());
90 ASSERT_EQ("[Adblock Plus ", jsEngine->Evaluate("foo.responseText.substr(0, 14) ")->AsString()); 122 ASSERT_EQ("[Adblock Plus ", jsEngine->Evaluate("foo.responseText.substr(0, 14) ")->AsString());
91 ASSERT_EQ("text/plain", jsEngine->Evaluate("foo.responseHeaders['content-type' ].substr(0, 10)")->AsString()); 123 ASSERT_EQ("text/plain", jsEngine->Evaluate("foo.responseHeaders['content-type' ].substr(0, 10)")->AsString());
124 #if defined(HAVE_CURL)
125 ASSERT_EQ("gzip", jsEngine->Evaluate("foo.responseHeaders['content-encoding']. substr(0, 4)")->AsString());
126 #endif
92 ASSERT_TRUE(jsEngine->Evaluate("foo.responseHeaders['location']")->IsUndefined ()); 127 ASSERT_TRUE(jsEngine->Evaluate("foo.responseHeaders['location']")->IsUndefined ());
93 } 128 }
94 129
95 TEST_F(DefaultWebRequestTest, XMLHttpRequest) 130 TEST_F(DefaultWebRequestTest, XMLHttpRequest)
96 { 131 {
97 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine); 132 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine);
98 133
99 jsEngine->Evaluate("\ 134 ResetTestXHR(jsEngine);
100 var result;\ 135 jsEngine->Evaluate("\
101 var request = new XMLHttpRequest();\
102 request.open('GET', 'https://easylist-downloads.adblockplus.org/easylist.txt ');\
103 request.setRequestHeader('X', 'Y');\ 136 request.setRequestHeader('X', 'Y');\
104 request.setRequestHeader('X2', 'Y2');\ 137 request.setRequestHeader('X2', 'Y2');\
105 request.overrideMimeType('text/plain');\
106 request.addEventListener('load', function() {result = request.responseText;} , false);\
107 request.addEventListener('error', function() {result = 'error';}, false);\
108 request.send(null);"); 138 request.send(null);");
109 do 139 WaitForVariable("result", jsEngine);
110 {
111 AdblockPlus::Sleep(200);
112 } while (jsEngine->Evaluate("result")->IsUndefined());
113 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("request.channel. status")->AsInt()); 140 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("request.channel. status")->AsInt());
114 ASSERT_EQ(200, jsEngine->Evaluate("request.status")->AsInt()); 141 ASSERT_EQ(200, jsEngine->Evaluate("request.status")->AsInt());
115 ASSERT_EQ("[Adblock Plus ", jsEngine->Evaluate("result.substr(0, 14)")->AsStri ng()); 142 ASSERT_EQ("[Adblock Plus ", jsEngine->Evaluate("result.substr(0, 14)")->AsStri ng());
116 ASSERT_EQ("text/plain", jsEngine->Evaluate("request.getResponseHeader('Content -Type').substr(0, 10)")->AsString()); 143 ASSERT_EQ("text/plain", jsEngine->Evaluate("request.getResponseHeader('Content -Type').substr(0, 10)")->AsString());
144 #if defined(HAVE_CURL)
145 ASSERT_EQ("gzip", jsEngine->Evaluate("request.getResponseHeader('Content-Encod ing').substr(0, 4)")->AsString());
146 #endif
117 ASSERT_TRUE(jsEngine->Evaluate("request.getResponseHeader('Location')")->IsNul l()); 147 ASSERT_TRUE(jsEngine->Evaluate("request.getResponseHeader('Location')")->IsNul l());
118 } 148 }
119 #else 149 #else
120 TEST_F(DefaultWebRequestTest, DummyWebRequest) 150 TEST_F(DefaultWebRequestTest, DummyWebRequest)
121 { 151 {
122 jsEngine->Evaluate("_webRequest.GET('https://easylist-downloads.adblockplus.or g/easylist.txt', {}, function(result) {foo = result;} )"); 152 jsEngine->Evaluate("_webRequest.GET('https://easylist-downloads.adblockplus.or g/easylist.txt', {}, function(result) {foo = result;} )");
123 do 153 WaitForVariable("this.foo", jsEngine);
124 {
125 AdblockPlus::Sleep(200);
126 } while (jsEngine->Evaluate("this.foo")->IsUndefined());
127 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("foo.s tatus")->AsInt()); 154 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("foo.s tatus")->AsInt());
128 ASSERT_EQ(0, jsEngine->Evaluate("foo.responseStatus")->AsInt()); 155 ASSERT_EQ(0, jsEngine->Evaluate("foo.responseStatus")->AsInt());
129 ASSERT_EQ("", jsEngine->Evaluate("foo.responseText")->AsString()); 156 ASSERT_EQ("", jsEngine->Evaluate("foo.responseText")->AsString());
130 ASSERT_EQ("{}", jsEngine->Evaluate("JSON.stringify(foo.responseHeaders)")->AsS tring()); 157 ASSERT_EQ("{}", jsEngine->Evaluate("JSON.stringify(foo.responseHeaders)")->AsS tring());
131 } 158 }
132 159
133 TEST_F(DefaultWebRequestTest, XMLHttpRequest) 160 TEST_F(DefaultWebRequestTest, XMLHttpRequest)
134 { 161 {
135 AdblockPlus::FilterEngine filterEngine(jsEngine); 162 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine);
136 163
137 jsEngine->Evaluate("\ 164 ResetTestXHR(jsEngine);
138 var result;\ 165 jsEngine->Evaluate("\
139 var request = new XMLHttpRequest();\
140 request.open('GET', 'https://easylist-downloads.adblockplus.org/easylist.txt ');\
141 request.setRequestHeader('X', 'Y');\ 166 request.setRequestHeader('X', 'Y');\
142 request.overrideMimeType('text/plain');\
143 request.addEventListener('load', function() {result = request.responseText;} , false);\
144 request.addEventListener('error', function() {result = 'error';}, false);\
145 request.send(null);"); 167 request.send(null);");
146 do 168 WaitForVariable("result", jsEngine);
147 {
148 AdblockPlus::Sleep(200);
149 } while (jsEngine->Evaluate("result")->IsUndefined());
150 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("reque st.channel.status")->AsInt()); 169 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("reque st.channel.status")->AsInt());
151 ASSERT_EQ(0, jsEngine->Evaluate("request.status")->AsInt()); 170 ASSERT_EQ(0, jsEngine->Evaluate("request.status")->AsInt());
152 ASSERT_EQ("error", jsEngine->Evaluate("result")->AsString()); 171 ASSERT_EQ("error", jsEngine->Evaluate("result")->AsString());
153 ASSERT_TRUE(jsEngine->Evaluate("request.getResponseHeader('Content-Type')")->I sNull()); 172 ASSERT_TRUE(jsEngine->Evaluate("request.getResponseHeader('Content-Type')")->I sNull());
154 } 173 }
155 174
156 #endif 175 #endif
176
177 namespace
178 {
179 class CatchLogSystem : public AdblockPlus::LogSystem
180 {
181 public:
182 AdblockPlus::LogSystem::LogLevel lastLogLevel;
183 std::string lastMessage;
184
185 CatchLogSystem()
186 : AdblockPlus::LogSystem(),
187 lastLogLevel(AdblockPlus::LogSystem::LOG_LEVEL_TRACE)
188 {
189 }
190
191 void operator()(AdblockPlus::LogSystem::LogLevel logLevel,
192 const std::string& message, const std::string&)
193 {
194 lastLogLevel = logLevel;
195 lastMessage = message;
196 }
197
198 void clear()
199 {
200 lastLogLevel = AdblockPlus::LogSystem::LOG_LEVEL_TRACE;
201 lastMessage.clear();
202 }
203 };
204
205 typedef std::shared_ptr<CatchLogSystem> CatchLogSystemPtr;
206 }
207
208 TEST_F(XMLHttpRequestTest, RequestHeaderValidation)
209 {
210 auto catchLogSystem = CatchLogSystemPtr(new CatchLogSystem);
211 jsEngine->SetLogSystem(catchLogSystem);
212
213 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine);
214 auto webRequest =
215 std::static_pointer_cast<MockWebRequest>(jsEngine->GetWebRequest());
216
217 ASSERT_TRUE(webRequest);
218
219 const std::string msg = "Attempt to set a forbidden header was denied: ";
220
221 // The test will check that console.warn has been called when the
222 // header is rejected. While this is an implementation detail, we
223 // have no other way to check this
224
225 // test 'Accept-Encoding' is rejected
226 catchLogSystem->clear();
227 ResetTestXHR(jsEngine);
228 jsEngine->Evaluate("\
229 request.setRequestHeader('Accept-Encoding', 'gzip');\nrequest.send();");
230 EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel );
231 EXPECT_EQ(msg + "Accept-Encoding", catchLogSystem->lastMessage);
232 WaitForVariable("result", jsEngine);
233 EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
234 webRequest->lastRequestHeaders.find("Accept-Encoding"));
235
236 // test 'DNT' is rejected
237 catchLogSystem->clear();
238 ResetTestXHR(jsEngine);
239 jsEngine->Evaluate("\
240 request.setRequestHeader('DNT', '1');\nrequest.send();");
241 EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel );
242 EXPECT_EQ(msg + "DNT", catchLogSystem->lastMessage);
243 WaitForVariable("result", jsEngine);
244 EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
245 webRequest->lastRequestHeaders.find("DNT"));
246
247 // test random 'X' header is accepted
248 catchLogSystem->clear();
249 ResetTestXHR(jsEngine);
250 jsEngine->Evaluate("\
251 request.setRequestHeader('X', 'y');\nrequest.send();");
252 EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_TRACE, catchLogSystem->lastLogLeve l);
253 EXPECT_EQ("", catchLogSystem->lastMessage);
254 WaitForVariable("result", jsEngine);
255 EXPECT_FALSE(webRequest->lastRequestHeaders.cend() ==
256 webRequest->lastRequestHeaders.find("X"));
257
258 // test /^Proxy-/ is rejected.
259 catchLogSystem->clear();
260 ResetTestXHR(jsEngine);
261 jsEngine->Evaluate("\
262 request.setRequestHeader('Proxy-foo', 'bar');\nrequest.send();");
263 EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel );
264 EXPECT_EQ(msg + "Proxy-foo", catchLogSystem->lastMessage);
265 WaitForVariable("result", jsEngine);
266 EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
267 webRequest->lastRequestHeaders.find("Proxy-foo"));
268
269 // test /^Sec-/ is rejected.
270 catchLogSystem->clear();
271 ResetTestXHR(jsEngine);
272 jsEngine->Evaluate("\
273 request.setRequestHeader('Sec-foo', 'bar');\nrequest.send();");
274 EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel );
275 EXPECT_EQ(msg + "Sec-foo", catchLogSystem->lastMessage);
276 WaitForVariable("result", jsEngine);
277 EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
278 webRequest->lastRequestHeaders.find("Sec-foo"));
279
280 // test 'Security' is accepted.
281 catchLogSystem->clear();
282 ResetTestXHR(jsEngine);
283 jsEngine->Evaluate("\
284 request.setRequestHeader('Security', 'theater');\nrequest.send();");
285 EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_TRACE, catchLogSystem->lastLogLeve l);
286 EXPECT_EQ("", catchLogSystem->lastMessage);
287 WaitForVariable("result", jsEngine);
288 EXPECT_FALSE(webRequest->lastRequestHeaders.cend() ==
289 webRequest->lastRequestHeaders.find("Security"));
290 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld