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

Unified Diff: test/WebRequest.cpp

Issue 29408721: Issue 5002 - Fix potential concurrency issues in WebRequest tests. (Closed) Base URL: https://hg.adblockplus.org/libadblockplus/
Patch Set: Fixed the last nits. Created April 19, 2017, 2:54 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/WebRequest.cpp
===================================================================
--- a/test/WebRequest.cpp
+++ b/test/WebRequest.cpp
@@ -25,66 +25,101 @@
namespace
{
class MockWebRequest : public AdblockPlus::WebRequest
{
public:
AdblockPlus::ServerResponse GET(const std::string& url, const AdblockPlus::HeaderList& requestHeaders) const
{
- lastRequestHeaders.clear();
+ std::set<std::string> headerNames;
for (auto header : requestHeaders)
{
- lastRequestHeaders.insert(header.first);
+ headerNames.insert(header.first);
+ }
+ {
+ std::lock_guard<std::mutex> lock(requestHeaderNamesMutex);
+ // we currently ignore the result. We should check it actually gets inserted.
+ requestHeaderNames.insert(std::make_pair(url, std::move(headerNames)));
}
AdblockPlus::Sleep(50);
AdblockPlus::ServerResponse result;
result.status = NS_OK;
result.responseStatus = 123;
result.responseHeaders.push_back(std::pair<std::string, std::string>("Foo", "Bar"));
result.responseText = url + "\n";
if (!requestHeaders.empty())
{
result.responseText += requestHeaders[0].first + "\n" + requestHeaders[0].second;
}
return result;
}
+ // Testing method
+ // Get the headers for the request. Return a pair of a bool (found
+ // or not) and the actual header names
+ std::pair<bool, std::set<std::string>> headersForRequest(const std::string& url)
+ {
+ std::lock_guard<std::mutex> lock(requestHeaderNamesMutex);
+ auto iter = requestHeaderNames.find(url);
+ if (iter != requestHeaderNames.end())
+ {
+ auto result = std::make_pair(true, iter->second);
+ requestHeaderNames.erase(iter);
+ return result;
+ }
+ return std::make_pair(false, std::set<std::string>());
+ }
+
// mutable. Very Ugly. But we are testing and need to change this in GET which is const.
- mutable std::set<std::string> lastRequestHeaders;
+ mutable std::mutex requestHeaderNamesMutex;
+ mutable std::map<std::string, std::set<std::string>> requestHeaderNames;
};
template<class T>
class WebRequestTest : public BaseJsTest
{
protected:
void SetUp()
{
BaseJsTest::SetUp();
- jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(new T()));
+ webRequest = std::make_shared<T>();
+ jsEngine->SetWebRequest(webRequest);
jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new LazyFileSystem()));
}
+
+ std::shared_ptr<T> webRequest;
};
typedef WebRequestTest<MockWebRequest> MockWebRequestTest;
typedef WebRequestTest<AdblockPlus::DefaultWebRequest> DefaultWebRequestTest;
typedef WebRequestTest<MockWebRequest> XMLHttpRequestTest;
- void ResetTestXHR(const AdblockPlus::JsEnginePtr& jsEngine)
+ // we return the url of the XHR.
+ std::string ResetTestXHR(const AdblockPlus::JsEnginePtr& jsEngine, const std::string& defaultUrl = "")
{
- jsEngine->Evaluate("\
+ std::string url = defaultUrl;
+ // make up a unique URL if we don't have one.
+ if (url == "")
+ {
+ url = "https://tests.adblockplus.org/easylist.txt-";
+ url += std::to_string(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
+ }
+
+ jsEngine->Evaluate(std::string("\
var result;\
var request = new XMLHttpRequest();\
- request.open('GET', 'https://easylist-downloads.adblockplus.org/easylist.txt');\
+ request.open('GET', '") + url + "'); \
request.overrideMimeType('text/plain');\
request.addEventListener('load', function() {result = request.responseText;}, false);\
request.addEventListener('error', function() {result = 'error';}, false);\
");
+ return url;
}
void WaitForVariable(const std::string& variable, const AdblockPlus::JsEnginePtr& jsEngine)
{
do
{
AdblockPlus::Sleep(60);
} while (jsEngine->Evaluate(variable)->IsUndefined());
@@ -130,17 +165,17 @@
#endif
ASSERT_TRUE(jsEngine->Evaluate("foo.responseHeaders['location']")->IsUndefined());
}
TEST_F(DefaultWebRequestTest, XMLHttpRequest)
{
auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine);
- ResetTestXHR(jsEngine);
+ ResetTestXHR(jsEngine, "https://easylist-downloads.adblockplus.org/easylist.txt");
jsEngine->Evaluate("\
request.setRequestHeader('X', 'Y');\
request.setRequestHeader('X2', 'Y2');\
request.send(null);");
WaitForVariable("result", jsEngine);
ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("request.channel.status")->AsInt());
ASSERT_EQ(200, jsEngine->Evaluate("request.status")->AsInt());
ASSERT_EQ("[Adblock Plus ", jsEngine->Evaluate("result.substr(0, 14)")->AsString());
@@ -210,85 +245,105 @@
}
TEST_F(XMLHttpRequestTest, RequestHeaderValidation)
{
auto catchLogSystem = CatchLogSystemPtr(new CatchLogSystem());
jsEngine->SetLogSystem(catchLogSystem);
auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine);
- auto webRequest =
- std::static_pointer_cast<MockWebRequest>(jsEngine->GetWebRequest());
-
- ASSERT_TRUE(webRequest);
const std::string msg = "Attempt to set a forbidden header was denied: ";
// The test will check that console.warn has been called when the
// header is rejected. While this is an implementation detail, we
// have no other way to check this
// test 'Accept-Encoding' is rejected
catchLogSystem->clear();
- ResetTestXHR(jsEngine);
+ std::string url = ResetTestXHR(jsEngine);
jsEngine->Evaluate("\
request.setRequestHeader('Accept-Encoding', 'gzip');\nrequest.send();");
EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel);
EXPECT_EQ(msg + "Accept-Encoding", catchLogSystem->lastMessage);
WaitForVariable("result", jsEngine);
- EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
- webRequest->lastRequestHeaders.find("Accept-Encoding"));
+ {
+ auto headersRequest = webRequest->headersForRequest(url);
+ EXPECT_TRUE(headersRequest.first);
+ const auto& headers = headersRequest.second;
+ EXPECT_TRUE(headers.cend() == headers.find("Accept-Encoding"));
+ }
// test 'DNT' is rejected
catchLogSystem->clear();
- ResetTestXHR(jsEngine);
+ url = ResetTestXHR(jsEngine);
jsEngine->Evaluate("\
request.setRequestHeader('DNT', '1');\nrequest.send();");
EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel);
EXPECT_EQ(msg + "DNT", catchLogSystem->lastMessage);
WaitForVariable("result", jsEngine);
- EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
- webRequest->lastRequestHeaders.find("DNT"));
+ {
+ auto headersRequest = webRequest->headersForRequest(url);
+ EXPECT_TRUE(headersRequest.first);
+ const auto& headers = headersRequest.second;
+ EXPECT_TRUE(headers.cend() == headers.find("DNT"));
+ }
// test random 'X' header is accepted
catchLogSystem->clear();
- ResetTestXHR(jsEngine);
+ url = ResetTestXHR(jsEngine);
jsEngine->Evaluate("\
request.setRequestHeader('X', 'y');\nrequest.send();");
EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_TRACE, catchLogSystem->lastLogLevel);
EXPECT_EQ("", catchLogSystem->lastMessage);
WaitForVariable("result", jsEngine);
- EXPECT_FALSE(webRequest->lastRequestHeaders.cend() ==
- webRequest->lastRequestHeaders.find("X"));
+ {
+ auto headersRequest = webRequest->headersForRequest(url);
+ EXPECT_TRUE(headersRequest.first);
+ const auto& headers = headersRequest.second;
+ EXPECT_FALSE(headers.cend() == headers.find("X"));
+ }
// test /^Proxy-/ is rejected.
catchLogSystem->clear();
- ResetTestXHR(jsEngine);
+ url = ResetTestXHR(jsEngine);
jsEngine->Evaluate("\
request.setRequestHeader('Proxy-foo', 'bar');\nrequest.send();");
EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel);
EXPECT_EQ(msg + "Proxy-foo", catchLogSystem->lastMessage);
WaitForVariable("result", jsEngine);
- EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
- webRequest->lastRequestHeaders.find("Proxy-foo"));
+ {
+ auto headersRequest = webRequest->headersForRequest(url);
+ EXPECT_TRUE(headersRequest.first);
+ const auto& headers = headersRequest.second;
+ EXPECT_TRUE(headers.cend() == headers.find("Proxy-foo"));
+ }
// test /^Sec-/ is rejected.
catchLogSystem->clear();
- ResetTestXHR(jsEngine);
+ url = ResetTestXHR(jsEngine);
jsEngine->Evaluate("\
request.setRequestHeader('Sec-foo', 'bar');\nrequest.send();");
EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_WARN, catchLogSystem->lastLogLevel);
EXPECT_EQ(msg + "Sec-foo", catchLogSystem->lastMessage);
WaitForVariable("result", jsEngine);
- EXPECT_TRUE(webRequest->lastRequestHeaders.cend() ==
- webRequest->lastRequestHeaders.find("Sec-foo"));
+ {
+ auto headersRequest = webRequest->headersForRequest(url);
+ EXPECT_TRUE(headersRequest.first);
+ const auto& headers = headersRequest.second;
+ EXPECT_TRUE(headers.cend() == headers.find("Sec-foo"));
+ }
// test 'Security' is accepted.
catchLogSystem->clear();
- ResetTestXHR(jsEngine);
+ url = ResetTestXHR(jsEngine);
jsEngine->Evaluate("\
request.setRequestHeader('Security', 'theater');\nrequest.send();");
EXPECT_EQ(AdblockPlus::LogSystem::LOG_LEVEL_TRACE, catchLogSystem->lastLogLevel);
EXPECT_EQ("", catchLogSystem->lastMessage);
WaitForVariable("result", jsEngine);
- EXPECT_FALSE(webRequest->lastRequestHeaders.cend() ==
- webRequest->lastRequestHeaders.find("Security"));
+ {
+ auto headersRequest = webRequest->headersForRequest(url);
+ EXPECT_TRUE(headersRequest.first);
+ const auto& headers = headersRequest.second;
+ EXPECT_FALSE(headers.cend() == headers.find("Security"));
+ }
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld