| Index: test/FilterEngine.cpp |
| diff --git a/test/FilterEngine.cpp b/test/FilterEngine.cpp |
| index d486335cda6f54ab1eff7efb91a9adca623084cc..28004417bf313874d490de731c3df7229eb68594 100644 |
| --- a/test/FilterEngine.cpp |
| +++ b/test/FilterEngine.cpp |
| @@ -155,130 +155,86 @@ namespace |
| } |
| }; |
| - class FilterEngineIsAllowedConnectionTest : public ::testing::Test |
| + class FilterEngineIsSubscriptionDownloadAllowedTest : public ::testing::Test |
| { |
| - class MockWebRequest : public LazyWebRequest |
| - { |
| - public: |
| - std::map</*beginning of url*/std::string, AdblockPlus::ServerResponse> responses; |
| - |
| - AdblockPlus::ServerResponse GET(const std::string& url, |
| - const AdblockPlus::HeaderList& requestHeaders) const |
| - { |
| - for (const auto& response : responses) |
| - { |
| - if (Utils::BeginsWith(url, response.first)) |
| - { |
| - return response.second; |
| - } |
| - } |
| - return LazyWebRequest::GET(url, requestHeaders); |
| - } |
| - }; |
| - class SyncStrings |
|
sergei
2017/05/10 17:04:40
since there are no threads there is no need for so
|
| - { |
| - public: |
| - void Add(const std::string* value) |
| - { |
| - std::lock_guard<std::mutex> lock(mutex); |
| - strings.emplace_back(!!value, value ? *value : ""); |
|
sergei
2017/05/10 17:04:40
this functionality is in the callback body now.
|
| - } |
| - std::vector<std::pair<bool, std::string>> GetStrings() const |
| - { |
| - std::lock_guard<std::mutex> lock(mutex); |
| - return strings; |
| - } |
| - void Clear() |
| - { |
| - std::lock_guard<std::mutex> lock(mutex); |
| - strings.clear(); |
| - } |
| - private: |
| - mutable std::mutex mutex; |
| - std::vector<std::pair<bool, std::string>> strings; |
| - }; |
| protected: |
| - std::shared_ptr<MockWebRequest> webRequest; |
| - std::string subscriptionUrlPrefix; |
| + typedef std::vector<std::pair<bool, std::string>> ConnectionTypes; |
| + DelayedWebRequest::SharedTasks webRequestTasks; |
| + DelayedTimer::SharedTasks timerTasks; |
| FilterEngine::CreationParameters createParams; |
| - // HACK: it's a shared pointer to keep it available in |
| - // isConnectionAllowedCallback after destroying of the test. |
| - struct SharedData |
| - { |
| - SyncStrings capturedConnectionTypes; |
| - bool isConnectionAllowed; |
| - struct |
| - { |
| - std::string url; |
| - std::mutex mutex; |
| - std::condition_variable cv; |
| - } downloadStatusChanged; |
| - }; |
| - std::shared_ptr<SharedData> data; |
| + ConnectionTypes capturedConnectionTypes; |
| + bool isConnectionAllowed; |
| + std::vector<std::function<void(bool)>> isSubscriptionDowloadAllowedCallbacks; |
| FilterEnginePtr filterEngine; |
| JsEnginePtr jsEngine; |
| void SetUp() |
| { |
| - data = std::make_shared<SharedData>(); |
| + isConnectionAllowed = true; |
| + |
| JsEngineCreationParameters jsEngineParams; |
| jsEngineParams.logSystem.reset(new LazyLogSystem()); |
| jsEngineParams.fileSystem.reset(new LazyFileSystem()); |
| - jsEngineParams.timer = CreateDefaultTimer(); |
| + jsEngineParams.timer = DelayedTimer::New(timerTasks); |
| + jsEngineParams.webRequest = DelayedWebRequest::New(webRequestTasks); |
| jsEngine = CreateJsEngine(std::move(jsEngineParams)); |
| - jsEngine->SetWebRequest(webRequest = std::make_shared<MockWebRequest>()); |
| - |
| - subscriptionUrlPrefix = "http://example"; |
| - ServerResponse exampleSubscriptionResponse; |
| - exampleSubscriptionResponse.responseStatus = 200; |
| - exampleSubscriptionResponse.status = IWebRequest::NS_OK; |
| - exampleSubscriptionResponse.responseText = "[Adblock Plus 2.0]\n||example.com"; |
| - webRequest->responses.emplace(subscriptionUrlPrefix, exampleSubscriptionResponse); |
| + |
| createParams.preconfiguredPrefs.emplace("first_run_subscription_auto_select", jsEngine->NewValue(false)); |
| - data->isConnectionAllowed = true; |
| - auto closure = data; |
| - createParams.isConnectionAllowedCallback = [closure](const std::string* allowedConnectionType)->bool{ |
| - closure->capturedConnectionTypes.Add(allowedConnectionType); |
| - return closure->isConnectionAllowed; |
| + |
| + createParams.isSubscriptionDowloadAllowedCallback = [this](const std::string* allowedConnectionType, |
| + const std::function<void(bool)>& isSubscriptionDowloadAllowedCallback){ |
| + capturedConnectionTypes.emplace_back(!!allowedConnectionType, allowedConnectionType ? *allowedConnectionType : std::string()); |
| + isSubscriptionDowloadAllowedCallbacks.emplace_back(isSubscriptionDowloadAllowedCallback); |
| }; |
| } |
| Subscription EnsureExampleSubscriptionAndForceUpdate(const std::string& apppendToUrl = std::string()) |
| { |
| + auto subscriptionUrl = "http://example" + apppendToUrl; |
| + bool isSubscriptionDownloadStatusReceived = false; |
| if (!filterEngine) |
| { |
| filterEngine = FilterEngine::Create(jsEngine, createParams); |
| - auto closure = data; |
| - filterEngine->SetFilterChangeCallback([closure](const std::string& action, JsValue&& item) |
| + filterEngine->SetFilterChangeCallback([&isSubscriptionDownloadStatusReceived, &subscriptionUrl](const std::string& action, JsValue&& item) |
| { |
| - if (action == "subscription.downloadStatus") |
| - { |
| - { |
| - std::lock_guard<std::mutex> lock(closure->downloadStatusChanged.mutex); |
| - closure->downloadStatusChanged.url = item.GetProperty("url").AsString(); |
| - } |
| - closure->downloadStatusChanged.cv.notify_one(); |
| - } |
| + if (action == "subscription.downloadStatus" && item.GetProperty("url").AsString() == subscriptionUrl) |
| + isSubscriptionDownloadStatusReceived = true; |
| }); |
| } |
| - auto subscriptionUrl = subscriptionUrlPrefix + apppendToUrl; |
| auto subscription = filterEngine->GetSubscription(subscriptionUrl); |
| EXPECT_EQ(0u, subscription.GetProperty("filters").AsList().size()) << subscriptionUrl; |
| EXPECT_TRUE(subscription.GetProperty("downloadStatus").IsNull()) << subscriptionUrl; |
| subscription.UpdateFilters(); |
| + |
| + // Since currently the check is called from implemenation of web request |
| + // they have to been firstly scheduled, namely before processing of |
| + // 'is subscription download allowed' callbacks; |
| + DelayedTimer::ProcessImmediateTimers(timerTasks); |
| + |
| + for (const auto& isSubscriptionDowloadAllowedCallback : isSubscriptionDowloadAllowedCallbacks) |
|
sergei
2017/05/10 17:04:40
actually, there should be only one callback and on
|
| + { |
| + isSubscriptionDowloadAllowedCallback(isConnectionAllowed); |
| + } |
| + isSubscriptionDowloadAllowedCallbacks.clear(); |
| + |
| { |
| - std::unique_lock<std::mutex> lock(data->downloadStatusChanged.mutex); |
| - data->downloadStatusChanged.cv.wait_for(lock, |
| - /*don't block tests forever*/std::chrono::seconds(300), |
| - [this, subscriptionUrl]()->bool |
| + auto ii_webRequest = std::find_if(webRequestTasks->begin(), webRequestTasks->end(), [&subscriptionUrl](const DelayedWebRequest::Task& task)->bool |
| { |
| - return subscriptionUrl == data->downloadStatusChanged.url; |
| + return Utils::BeginsWith(task.url, subscriptionUrl); |
| }); |
| - // Basically it's enough to wait only for downloadStatus although there |
| - // is still some JS code being executed. Any following attempt to work |
| - // with subscription object will result in execution of JS, which will |
| - // be blocked until finishing of currently running code. |
| + |
| + // if download is allowed then there should be a web request |
| + EXPECT_EQ(isConnectionAllowed, ii_webRequest != webRequestTasks->end()); |
| + if (ii_webRequest != webRequestTasks->end()) |
| + { |
| + ServerResponse exampleSubscriptionResponse; |
| + exampleSubscriptionResponse.responseStatus = 200; |
| + exampleSubscriptionResponse.status = IWebRequest::NS_OK; |
| + exampleSubscriptionResponse.responseText = "[Adblock Plus 2.0]\n||example.com"; |
| + ii_webRequest->getCallback(exampleSubscriptionResponse); |
| + } |
| } |
| + EXPECT_TRUE(isSubscriptionDownloadStatusReceived); |
| return subscription; |
| } |
| }; |
| @@ -1059,37 +1015,35 @@ namespace AA_ApiTest |
| } |
| } |
| -TEST_F(FilterEngineIsAllowedConnectionTest, AbsentCallbackAllowsUpdating) |
| +TEST_F(FilterEngineIsSubscriptionDownloadAllowedTest, AbsentCallbackAllowsUpdating) |
| { |
| - createParams.isConnectionAllowedCallback = FilterEngine::IsConnectionAllowedCallback(); |
| + createParams.isSubscriptionDowloadAllowedCallback = FilterEngine::IsConnectionAllowedAsyncCallback(); |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate(); |
| EXPECT_EQ("synchronize_ok", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(1u, subscription.GetProperty("filters").AsList().size()); |
| } |
| -TEST_F(FilterEngineIsAllowedConnectionTest, AllowingCallbackAllowsUpdating) |
| +TEST_F(FilterEngineIsSubscriptionDownloadAllowedTest, AllowingCallbackAllowsUpdating) |
| { |
| // no stored allowed_connection_type preference |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate(); |
| EXPECT_EQ("synchronize_ok", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(1u, subscription.GetProperty("filters").AsList().size()); |
| - auto capturedConnectionTypes = data->capturedConnectionTypes.GetStrings(); |
| ASSERT_EQ(1u, capturedConnectionTypes.size()); |
| EXPECT_FALSE(capturedConnectionTypes[0].first); |
| } |
| -TEST_F(FilterEngineIsAllowedConnectionTest, NotAllowingCallbackDoesNotAllowUpdating) |
| +TEST_F(FilterEngineIsSubscriptionDownloadAllowedTest, NotAllowingCallbackDoesNotAllowUpdating) |
| { |
| - data->isConnectionAllowed = false; |
| + isConnectionAllowed = false; |
| // no stored allowed_connection_type preference |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate(); |
| EXPECT_EQ("synchronize_connection_error", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(0u, subscription.GetProperty("filters").AsList().size()); |
| - auto capturedConnectionTypes = data->capturedConnectionTypes.GetStrings(); |
| EXPECT_EQ(1u, capturedConnectionTypes.size()); |
| } |
| -TEST_F(FilterEngineIsAllowedConnectionTest, PredefinedAllowedConnectionTypeIsPassedToCallback) |
| +TEST_F(FilterEngineIsSubscriptionDownloadAllowedTest, PredefinedAllowedConnectionTypeIsPassedToCallback) |
| { |
| std::string predefinedAllowedConnectionType = "non-metered"; |
| createParams.preconfiguredPrefs.insert(std::make_pair("allowed_connection_type", |
| @@ -1097,13 +1051,12 @@ TEST_F(FilterEngineIsAllowedConnectionTest, PredefinedAllowedConnectionTypeIsPas |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate(); |
| EXPECT_EQ("synchronize_ok", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(1u, subscription.GetProperty("filters").AsList().size()); |
| - auto capturedConnectionTypes = data->capturedConnectionTypes.GetStrings(); |
| ASSERT_EQ(1u, capturedConnectionTypes.size()); |
| EXPECT_TRUE(capturedConnectionTypes[0].first); |
| EXPECT_EQ(predefinedAllowedConnectionType, capturedConnectionTypes[0].second); |
| } |
| -TEST_F(FilterEngineIsAllowedConnectionTest, ConfiguredConnectionTypeIsPassedToCallback) |
| +TEST_F(FilterEngineIsSubscriptionDownloadAllowedTest, ConfiguredConnectionTypeIsPassedToCallback) |
| { |
| // FilterEngine->RemoveSubscription is not usable here because subscriptions |
| // are cached internally by URL. So, different URLs are used in diffirent |
| @@ -1115,25 +1068,22 @@ TEST_F(FilterEngineIsAllowedConnectionTest, ConfiguredConnectionTypeIsPassedToCa |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate(); |
| EXPECT_EQ("synchronize_ok", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(1u, subscription.GetProperty("filters").AsList().size()); |
| - auto capturedConnectionTypes = data->capturedConnectionTypes.GetStrings(); |
| ASSERT_EQ(1u, capturedConnectionTypes.size()); |
| EXPECT_TRUE(capturedConnectionTypes[0].first); |
| EXPECT_EQ(predefinedAllowedConnectionType, capturedConnectionTypes[0].second); |
| } |
| - data->capturedConnectionTypes.Clear(); |
| + capturedConnectionTypes.clear(); |
| { |
| // set no value |
| filterEngine->SetAllowedConnectionType(nullptr); |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate("subA"); |
| EXPECT_EQ("synchronize_ok", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(1u, subscription.GetProperty("filters").AsList().size()); |
| - auto capturedConnectionTypes = data->capturedConnectionTypes.GetStrings(); |
| ASSERT_EQ(1u, capturedConnectionTypes.size()); |
| EXPECT_FALSE(capturedConnectionTypes[0].first); |
| subscription.RemoveFromList(); |
| - data->capturedConnectionTypes.Clear(); |
| } |
| - data->capturedConnectionTypes.Clear(); |
| + capturedConnectionTypes.clear(); |
| { |
| // set some value |
| std::string testConnection = "test connection"; |
| @@ -1141,7 +1091,6 @@ TEST_F(FilterEngineIsAllowedConnectionTest, ConfiguredConnectionTypeIsPassedToCa |
| auto subscription = EnsureExampleSubscriptionAndForceUpdate("subB"); |
| EXPECT_EQ("synchronize_ok", subscription.GetProperty("downloadStatus").AsString()); |
| EXPECT_EQ(1u, subscription.GetProperty("filters").AsList().size()); |
| - auto capturedConnectionTypes = data->capturedConnectionTypes.GetStrings(); |
| ASSERT_EQ(1u, capturedConnectionTypes.size()); |
| EXPECT_TRUE(capturedConnectionTypes[0].first); |
| EXPECT_EQ(testConnection, capturedConnectionTypes[0].second); |