| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 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-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 "BaseJsTest.h" | 18 #include "BaseJsTest.h" |
| 19 #include <thread> | 19 #include <thread> |
| 20 #include <condition_variable> | |
| 20 | 21 |
| 21 using namespace AdblockPlus; | 22 using namespace AdblockPlus; |
| 22 | 23 |
| 24 namespace AdblockPlus | |
| 25 { | |
| 26 namespace Utils | |
| 27 { | |
| 28 inline bool BeginsWith(const std::string& str, const std::string& beginning) | |
| 29 { | |
| 30 return 0 == str.compare(0, beginning.size(), beginning); | |
| 31 } | |
| 32 } | |
| 33 } | |
| 34 | |
| 23 namespace | 35 namespace |
| 24 { | 36 { |
| 25 typedef std::shared_ptr<AdblockPlus::FilterEngine> FilterEnginePtr; | |
| 26 | |
| 27 class VeryLazyFileSystem : public LazyFileSystem | 37 class VeryLazyFileSystem : public LazyFileSystem |
| 28 { | 38 { |
| 29 public: | 39 public: |
| 30 StatResult Stat(const std::string& path) const | 40 StatResult Stat(const std::string& path) const |
| 31 { | 41 { |
| 32 return StatResult(); | 42 return StatResult(); |
| 33 } | 43 } |
| 34 }; | 44 }; |
| 35 | 45 |
| 36 template<class FileSystem, class LogSystem> | 46 template<class FileSystem, class LogSystem> |
| 37 class FilterEngineTestGeneric : public BaseJsTest | 47 class FilterEngineTestGeneric : public BaseJsTest |
| 38 { | 48 { |
| 39 protected: | 49 protected: |
| 40 FilterEnginePtr filterEngine; | 50 FilterEnginePtr filterEngine; |
| 41 | 51 |
| 42 void SetUp() | 52 void SetUp() |
| 43 { | 53 { |
| 44 BaseJsTest::SetUp(); | 54 BaseJsTest::SetUp(); |
| 45 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new FileSystem)); | 55 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new FileSystem)); |
| 46 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(new LazyWebRequest)); | 56 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(new LazyWebRequest)); |
| 47 jsEngine->SetLogSystem(AdblockPlus::LogSystemPtr(new LogSystem)); | 57 jsEngine->SetLogSystem(AdblockPlus::LogSystemPtr(new LogSystem)); |
| 48 filterEngine = FilterEnginePtr(new AdblockPlus::FilterEngine(jsEngine)); | 58 filterEngine = AdblockPlus::FilterEngine::Create(jsEngine); |
| 49 } | 59 } |
| 50 }; | 60 }; |
| 51 | 61 |
| 52 typedef FilterEngineTestGeneric<LazyFileSystem, AdblockPlus::DefaultLogSystem> FilterEngineTest; | 62 typedef FilterEngineTestGeneric<LazyFileSystem, AdblockPlus::DefaultLogSystem> FilterEngineTest; |
| 53 typedef FilterEngineTestGeneric<VeryLazyFileSystem, LazyLogSystem> FilterEngin eTestNoData; | 63 typedef FilterEngineTestGeneric<VeryLazyFileSystem, LazyLogSystem> FilterEngin eTestNoData; |
| 54 | 64 |
| 55 struct MockFilterChangeCallback | 65 struct MockFilterChangeCallback |
| 56 { | 66 { |
| 57 MockFilterChangeCallback(int& timesCalled) : timesCalled(timesCalled) {} | 67 MockFilterChangeCallback(int& timesCalled) : timesCalled(timesCalled) {} |
| 58 | 68 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 85 | 95 |
| 86 void SetUp() | 96 void SetUp() |
| 87 { | 97 { |
| 88 AdblockPlus::AppInfo appInfo; | 98 AdblockPlus::AppInfo appInfo; |
| 89 appInfo.name = "test"; | 99 appInfo.name = "test"; |
| 90 appInfo.version = "1.0.1"; | 100 appInfo.version = "1.0.1"; |
| 91 AdblockPlus::JsEnginePtr jsEngine = CreateJsEngine(appInfo); | 101 AdblockPlus::JsEnginePtr jsEngine = CreateJsEngine(appInfo); |
| 92 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new LazyFileSystem)); | 102 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new LazyFileSystem)); |
| 93 mockWebRequest = new MockWebRequest; | 103 mockWebRequest = new MockWebRequest; |
| 94 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(mockWebRequest)); | 104 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(mockWebRequest)); |
| 95 filterEngine = FilterEnginePtr(new AdblockPlus::FilterEngine(jsEngine)); | 105 filterEngine = AdblockPlus::FilterEngine::Create(jsEngine); |
| 96 } | 106 } |
| 97 }; | 107 }; |
| 98 | |
| 99 struct MockUpdateAvailableCallback | |
| 100 { | |
| 101 MockUpdateAvailableCallback(int& timesCalled) : timesCalled(timesCalled) {} | |
| 102 | |
| 103 void operator()(const std::string&) | |
| 104 { | |
| 105 timesCalled++; | |
| 106 } | |
| 107 | |
| 108 private: | |
| 109 // We currently cannot store timesCalled in the functor, see: | |
| 110 // https://issues.adblockplus.org/ticket/1378. | |
| 111 int& timesCalled; | |
| 112 }; | |
| 113 | |
| 114 // Workaround for https://issues.adblockplus.org/ticket/1397. | |
| 115 void NoOpUpdaterCallback(const std::string&) {} | |
| 116 | 108 |
| 117 class FilterEngineWithFreshFolder : public ::testing::Test | 109 class FilterEngineWithFreshFolder : public ::testing::Test |
| 118 { | 110 { |
| 119 protected: | 111 protected: |
| 120 FileSystemPtr fileSystem; | 112 FileSystemPtr fileSystem; |
| 121 std::weak_ptr<JsEngine> weakJsEngine; | 113 std::weak_ptr<JsEngine> weakJsEngine; |
| 122 | 114 |
| 123 void SetUp() override | 115 void SetUp() override |
| 124 { | 116 { |
| 125 fileSystem.reset(new DefaultFileSystem()); | 117 fileSystem.reset(new DefaultFileSystem()); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 156 return true; | 148 return true; |
| 157 } | 149 } |
| 158 catch (...) | 150 catch (...) |
| 159 { | 151 { |
| 160 return false; | 152 return false; |
| 161 } | 153 } |
| 162 }; | 154 }; |
| 163 int i = 5; | 155 int i = 5; |
| 164 while ((i-- > 0 && weakJsEngine.lock()) || !safeRemove()) | 156 while ((i-- > 0 && weakJsEngine.lock()) || !safeRemove()) |
| 165 std::this_thread::sleep_for(std::chrono::seconds(2)); | 157 std::this_thread::sleep_for(std::chrono::seconds(2)); |
| 158 } | |
| 159 }; | |
| 160 | |
| 161 class FilterEngineIsAllowedConnectionTest : public BaseJsTest | |
| 162 { | |
| 163 class MockWebRequest : public LazyWebRequest | |
| 164 { | |
| 165 public: | |
| 166 std::map</*beginning of url*/std::string, AdblockPlus::ServerResponse> res ponses; | |
| 167 | |
| 168 AdblockPlus::ServerResponse GET(const std::string& url, | |
| 169 const AdblockPlus::HeaderList& requestHeaders) const | |
| 170 { | |
| 171 for (const auto& response : responses) | |
| 172 { | |
| 173 if (Utils::BeginsWith(url, response.first)) | |
| 174 { | |
| 175 return response.second; | |
| 176 } | |
| 177 } | |
| 178 return LazyWebRequest::GET(url, requestHeaders); | |
| 179 } | |
| 180 }; | |
| 181 class SyncStrings | |
| 182 { | |
| 183 public: | |
| 184 void Add(const std::string* value) | |
| 185 { | |
| 186 std::lock_guard<std::mutex> lock(mutex); | |
| 187 strings.emplace_back(!!value, value ? *value : ""); | |
| 188 } | |
| 189 std::vector<std::pair<bool, std::string>> GetStrings() const | |
| 190 { | |
| 191 std::lock_guard<std::mutex> lock(mutex); | |
| 192 return strings; | |
| 193 } | |
| 194 void Clear() | |
| 195 { | |
| 196 std::lock_guard<std::mutex> lock(mutex); | |
| 197 strings.clear(); | |
| 198 } | |
| 199 private: | |
| 200 mutable std::mutex mutex; | |
| 201 std::vector<std::pair<bool, std::string>> strings; | |
| 202 }; | |
| 203 protected: | |
| 204 MockWebRequest* webRequest; | |
| 205 std::string subscriptionUrlPrefix; | |
| 206 FilterEngine::CreationParameters createParams; | |
| 207 SyncStrings capturedConnectionTypes; | |
| 208 bool isConnectionAllowed; | |
| 209 FilterEnginePtr filterEngine; | |
| 210 | |
| 211 struct | |
| 212 { | |
| 213 std::string url; | |
| 214 std::mutex mutex; | |
| 215 std::condition_variable cv; | |
| 216 } downloadStatusChanged; | |
| 217 | |
| 218 void SetUp() | |
| 219 { | |
| 220 BaseJsTest::SetUp(); | |
| 221 jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(new LazyFileSystem())); | |
| 222 jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(webRequest = new MockWe bRequest())); | |
| 223 jsEngine->SetLogSystem(AdblockPlus::LogSystemPtr(new LazyLogSystem())); | |
| 224 | |
| 225 subscriptionUrlPrefix = "http://example"; | |
| 226 ServerResponse exampleSubscriptionResponse; | |
| 227 exampleSubscriptionResponse.responseStatus = 200; | |
| 228 exampleSubscriptionResponse.status = WebRequest::NS_OK; | |
| 229 exampleSubscriptionResponse.responseText = "[Adblock Plus 2.0]\n||example. com"; | |
| 230 webRequest->responses.emplace(subscriptionUrlPrefix, exampleSubscriptionRe sponse); | |
| 231 createParams.preconfiguredPrefs["first_run_subscription_auto_select"] = js Engine->NewValue(false); | |
| 232 isConnectionAllowed = true; | |
| 233 createParams.isConnectionAllowedCallback = [this](const std::string* allow edConnectionType)->bool{ | |
| 234 capturedConnectionTypes.Add(allowedConnectionType); | |
| 235 return isConnectionAllowed; | |
| 236 }; | |
| 237 jsEngine->SetEventCallback("filterChange", [this](const JsValueList& param s/*action, item*/) | |
| 238 { | |
| 239 ASSERT_EQ(2u, params.size()); | |
| 240 if (params[0]->AsString() == "subscription.downloadStatus") | |
| 241 { | |
| 242 { | |
| 243 std::lock_guard<std::mutex> lock(downloadStatusChanged.mutex); | |
| 244 downloadStatusChanged.url = params[1]->GetProperty("url")->AsString( ); | |
| 245 } | |
| 246 downloadStatusChanged.cv.notify_one(); | |
| 247 } | |
| 248 }); | |
| 249 } | |
| 250 | |
| 251 SubscriptionPtr EnsureExampleSubscriptionAndForceUpdate(const std::string& a pppendToUrl = std::string()) | |
| 252 { | |
| 253 if (!filterEngine) | |
| 254 filterEngine = FilterEngine::Create(jsEngine, createParams); | |
| 255 auto subscriptionUrl = subscriptionUrlPrefix + apppendToUrl; | |
| 256 auto subscription = filterEngine->GetSubscription(subscriptionUrl); | |
| 257 EXPECT_EQ(0u, subscription->GetProperty("filters")->AsList().size()) << su bscriptionUrl; | |
| 258 EXPECT_TRUE(subscription->GetProperty("downloadStatus")->IsNull()) << subs criptionUrl; | |
| 259 subscription->UpdateFilters(); | |
| 260 { | |
| 261 std::unique_lock<std::mutex> lock(downloadStatusChanged.mutex); | |
| 262 downloadStatusChanged.cv.wait_for(lock, | |
| 263 /*don't block tests forever*/std::chrono::seconds(5), | |
| 264 [this, subscriptionUrl]()->bool | |
| 265 { | |
| 266 return subscriptionUrl == downloadStatusChanged.url; | |
| 267 }); | |
| 268 // Basically it's enough to wait only for downloadStatus although there | |
| 269 // is still some JS code being executed. Any following attempt to work | |
| 270 // with subscription object will result in execution of JS, which will | |
| 271 // be blocked until finishing of currently running code. | |
| 272 } | |
| 273 return subscription; | |
| 166 } | 274 } |
| 167 }; | 275 }; |
| 168 } | 276 } |
| 169 | 277 |
| 170 TEST_F(FilterEngineTest, FilterCreation) | 278 TEST_F(FilterEngineTest, FilterCreation) |
| 171 { | 279 { |
| 172 AdblockPlus::FilterPtr filter1 = filterEngine->GetFilter("foo"); | 280 AdblockPlus::FilterPtr filter1 = filterEngine->GetFilter("foo"); |
| 173 ASSERT_EQ(AdblockPlus::Filter::TYPE_BLOCKING, filter1->GetType()); | 281 ASSERT_EQ(AdblockPlus::Filter::TYPE_BLOCKING, filter1->GetType()); |
| 174 AdblockPlus::FilterPtr filter2 = filterEngine->GetFilter("@@foo"); | 282 AdblockPlus::FilterPtr filter2 = filterEngine->GetFilter("@@foo"); |
| 175 ASSERT_EQ(AdblockPlus::Filter::TYPE_EXCEPTION, filter2->GetType()); | 283 ASSERT_EQ(AdblockPlus::Filter::TYPE_EXCEPTION, filter2->GetType()); |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 | 596 |
| 489 TEST_F(FilterEngineTestNoData, FirstRunFlag) | 597 TEST_F(FilterEngineTestNoData, FirstRunFlag) |
| 490 { | 598 { |
| 491 ASSERT_TRUE(filterEngine->IsFirstRun()); | 599 ASSERT_TRUE(filterEngine->IsFirstRun()); |
| 492 } | 600 } |
| 493 | 601 |
| 494 TEST_F(FilterEngineTest, SetRemoveFilterChangeCallback) | 602 TEST_F(FilterEngineTest, SetRemoveFilterChangeCallback) |
| 495 { | 603 { |
| 496 int timesCalled = 0; | 604 int timesCalled = 0; |
| 497 MockFilterChangeCallback mockFilterChangeCallback(timesCalled); | 605 MockFilterChangeCallback mockFilterChangeCallback(timesCalled); |
| 498 | 606 std::this_thread::sleep_for(std::chrono::milliseconds(200)); |
| 499 filterEngine->SetFilterChangeCallback(mockFilterChangeCallback); | 607 filterEngine->SetFilterChangeCallback(mockFilterChangeCallback); |
| 500 filterEngine->GetFilter("foo")->AddToList(); | 608 filterEngine->GetFilter("foo")->AddToList(); |
| 501 EXPECT_EQ(1, timesCalled); | 609 EXPECT_EQ(1, timesCalled); |
| 502 | 610 |
| 503 filterEngine->RemoveFilterChangeCallback(); | 611 filterEngine->RemoveFilterChangeCallback(); |
| 504 filterEngine->GetFilter("foo")->RemoveFromList(); | 612 filterEngine->GetFilter("foo")->RemoveFromList(); |
| 505 EXPECT_EQ(1, timesCalled); | 613 EXPECT_EQ(1, timesCalled); |
| 506 } | 614 } |
| 507 | 615 |
| 508 TEST_F(UpdaterTest, SetRemoveUpdateAvailableCallback) | 616 TEST_F(UpdaterTest, SetRemoveUpdateAvailableCallback) |
| 509 { | 617 { |
| 510 mockWebRequest->response.status = 0; | 618 mockWebRequest->response.status = 0; |
| 511 mockWebRequest->response.responseStatus = 200; | 619 mockWebRequest->response.responseStatus = 200; |
| 512 mockWebRequest->response.responseText = "\ | 620 mockWebRequest->response.responseText = "\ |
| 513 {\ | 621 {\ |
| 514 \"test\": {\ | 622 \"test\": {\ |
| 515 \"version\": \"1.0.2\",\ | 623 \"version\": \"1.0.2\",\ |
| 516 \"url\": \"https://downloads.adblockplus.org/test-1.0.2.tar.gz?update\"\ | 624 \"url\": \"https://downloads.adblockplus.org/test-1.0.2.tar.gz?update\"\ |
| 517 }\ | 625 }\ |
| 518 }"; | 626 }"; |
| 519 | 627 |
| 520 int timesCalled = 0; | 628 int timesCalled = 0; |
| 521 MockUpdateAvailableCallback mockUpdateAvailableCallback(timesCalled); | 629 filterEngine->SetUpdateAvailableCallback([×Called](const std::string&)->v oid |
| 522 | 630 { |
| 523 filterEngine->SetUpdateAvailableCallback(mockUpdateAvailableCallback); | 631 ++timesCalled; |
| 524 filterEngine->ForceUpdateCheck(&NoOpUpdaterCallback); | 632 }); |
| 633 filterEngine->ForceUpdateCheck(); | |
| 525 AdblockPlus::Sleep(100); | 634 AdblockPlus::Sleep(100); |
| 526 ASSERT_EQ(1, timesCalled); | 635 EXPECT_EQ(1, timesCalled); |
| 527 | 636 |
| 528 filterEngine->RemoveUpdateAvailableCallback(); | 637 filterEngine->RemoveUpdateAvailableCallback(); |
| 529 filterEngine->ForceUpdateCheck(&NoOpUpdaterCallback); | 638 filterEngine->ForceUpdateCheck(); |
| 530 AdblockPlus::Sleep(100); | 639 AdblockPlus::Sleep(100); |
| 531 ASSERT_EQ(1, timesCalled); | 640 EXPECT_EQ(1, timesCalled); |
| 641 } | |
| 642 | |
| 643 TEST_F(UpdaterTest, ForceUpdateCheck) | |
| 644 { | |
| 645 mockWebRequest->response.status = 0; | |
| 646 mockWebRequest->response.responseStatus = 200; | |
| 647 mockWebRequest->response.responseText = "\ | |
| 648 {\ | |
| 649 \"test\": {\ | |
| 650 \"version\": \"1.0.2\",\ | |
| 651 \"url\": \"https://downloads.adblockplus.org/test-1.0.2.tar.gz?update\"\ | |
| 652 }\ | |
| 653 }"; | |
| 654 | |
| 655 int called = 0; // 0 - not called; 1 - once, no error; 2 - error | |
| 656 filterEngine->ForceUpdateCheck([&called](const std::string& error)->void | |
| 657 { | |
| 658 called = error.empty() ? 1 : 2; | |
| 659 }); | |
| 660 AdblockPlus::Sleep(100); | |
| 661 EXPECT_EQ(1, called); | |
| 532 } | 662 } |
| 533 | 663 |
| 534 TEST_F(FilterEngineTest, DocumentWhitelisting) | 664 TEST_F(FilterEngineTest, DocumentWhitelisting) |
| 535 { | 665 { |
| 536 filterEngine->GetFilter("@@||example.org^$document")->AddToList(); | 666 filterEngine->GetFilter("@@||example.org^$document")->AddToList(); |
| 537 filterEngine->GetFilter("@@||example.com^$document,domain=example.de")->AddToL ist(); | 667 filterEngine->GetFilter("@@||example.com^$document,domain=example.de")->AddToL ist(); |
| 538 | 668 |
| 539 ASSERT_TRUE(filterEngine->IsDocumentWhitelisted( | 669 ASSERT_TRUE(filterEngine->IsDocumentWhitelisted( |
| 540 "http://example.org", | 670 "http://example.org", |
| 541 std::vector<std::string>())); | 671 std::vector<std::string>())); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 "http://example.co.uk", | 718 "http://example.co.uk", |
| 589 documentUrls1)); | 719 documentUrls1)); |
| 590 } | 720 } |
| 591 | 721 |
| 592 TEST_F(FilterEngineWithFreshFolder, LangAndAASubscriptionsAreChosenOnFirstRun) | 722 TEST_F(FilterEngineWithFreshFolder, LangAndAASubscriptionsAreChosenOnFirstRun) |
| 593 { | 723 { |
| 594 AppInfo appInfo; | 724 AppInfo appInfo; |
| 595 appInfo.locale = "zh"; | 725 appInfo.locale = "zh"; |
| 596 const std::string langSubscriptionUrl = "https://easylist-downloads.adblockplu s.org/easylistchina+easylist.txt"; | 726 const std::string langSubscriptionUrl = "https://easylist-downloads.adblockplu s.org/easylistchina+easylist.txt"; |
| 597 auto jsEngine = createJsEngine(appInfo); | 727 auto jsEngine = createJsEngine(appInfo); |
| 598 auto filterEngine = FilterEnginePtr(new AdblockPlus::FilterEngine(jsEngine)); | 728 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine); |
| 599 const auto subscriptions = filterEngine->GetListedSubscriptions(); | 729 const auto subscriptions = filterEngine->GetListedSubscriptions(); |
| 600 ASSERT_EQ(2u, subscriptions.size()); | 730 ASSERT_EQ(2u, subscriptions.size()); |
| 601 SubscriptionPtr aaSubscription; | 731 SubscriptionPtr aaSubscription; |
| 602 SubscriptionPtr langSubscription; | 732 SubscriptionPtr langSubscription; |
| 603 if (subscriptions[0]->IsAA()) | 733 if (subscriptions[0]->IsAA()) |
| 604 { | 734 { |
| 605 aaSubscription = subscriptions[0]; | 735 aaSubscription = subscriptions[0]; |
| 606 langSubscription = subscriptions[1]; | 736 langSubscription = subscriptions[1]; |
| 607 } else if (subscriptions[1]->IsAA()) | 737 } |
| 738 else if (subscriptions[1]->IsAA()) | |
| 608 { | 739 { |
| 609 aaSubscription = subscriptions[1]; | 740 aaSubscription = subscriptions[1]; |
| 610 langSubscription = subscriptions[0]; | 741 langSubscription = subscriptions[0]; |
| 611 } | 742 } |
| 612 ASSERT_NE(nullptr, aaSubscription); | 743 ASSERT_NE(nullptr, aaSubscription); |
| 613 ASSERT_NE(nullptr, langSubscription); | 744 ASSERT_NE(nullptr, langSubscription); |
| 614 EXPECT_EQ(langSubscriptionUrl, langSubscription->GetProperty("url")->AsString( )); | 745 EXPECT_EQ(langSubscriptionUrl, langSubscription->GetProperty("url")->AsString( )); |
| 615 EXPECT_TRUE(filterEngine->IsAAEnabled()); | 746 EXPECT_TRUE(filterEngine->IsAAEnabled()); |
| 616 } | 747 } |
| 617 | 748 |
| 618 TEST_F(FilterEngineWithFreshFolder, DisableSubscriptionsAutoSelectOnFirstRun) | 749 TEST_F(FilterEngineWithFreshFolder, DisableSubscriptionsAutoSelectOnFirstRun) |
| 619 { | 750 { |
| 620 auto jsEngine = createJsEngine(); | 751 auto jsEngine = createJsEngine(); |
| 621 FilterEngine::Prefs preSettings; | 752 FilterEngine::CreationParameters createParams; |
| 622 preSettings["first_run_subscription_auto_select"] = jsEngine->NewValue(false); | 753 createParams.preconfiguredPrefs["first_run_subscription_auto_select"] = jsEngi ne->NewValue(false); |
| 623 auto filterEngine = FilterEnginePtr(new AdblockPlus::FilterEngine(jsEngine, pr eSettings)); | 754 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine, createParams); |
| 624 const auto subscriptions = filterEngine->GetListedSubscriptions(); | 755 const auto subscriptions = filterEngine->GetListedSubscriptions(); |
| 625 EXPECT_EQ(0u, subscriptions.size()); | 756 EXPECT_EQ(0u, subscriptions.size()); |
| 626 EXPECT_FALSE(filterEngine->IsAAEnabled()); | 757 EXPECT_FALSE(filterEngine->IsAAEnabled()); |
| 627 } | 758 } |
| 628 | 759 |
| 629 TEST_F(FilterEngineTest, IsAAEnabled) | 760 namespace AA_ApiTest |
| 630 { | 761 { |
| 631 // no subscription (because of preconfigured prefs.json and patterns.ini) | 762 const std::string kOtherSubscriptionUrl = "https://non-existing-subscription.t xt"; |
| 632 EXPECT_FALSE(filterEngine->IsAAEnabled()); | 763 enum class AAStatus |
| 633 // add subscription and enable | 764 { |
| 634 filterEngine->SetAAEnabled(true); | 765 absent, |
| 635 EXPECT_TRUE(filterEngine->IsAAEnabled()); | 766 enabled, |
| 636 // disable | 767 disabled_present |
| 637 filterEngine->SetAAEnabled(false); | 768 }; |
| 638 EXPECT_FALSE(filterEngine->IsAAEnabled()); | 769 |
| 639 // only enable already existing disabled | 770 ::std::ostream& operator<<(std::ostream& os, AAStatus aaStatus) |
| 640 filterEngine->SetAAEnabled(true); | 771 { |
| 641 EXPECT_TRUE(filterEngine->IsAAEnabled()); | 772 switch (aaStatus) |
| 642 // remove | 773 { |
| 643 filterEngine->GetSubscription(filterEngine->GetAAURL())->RemoveFromList(); | 774 case AAStatus::absent: |
| 644 EXPECT_FALSE(filterEngine->IsAAEnabled()); | 775 os << "absent"; |
| 645 // no subscription | 776 break; |
| 646 EXPECT_FALSE(filterEngine->IsAAEnabled()); | 777 case AAStatus::enabled: |
| 778 os << "enabled"; | |
| 779 break; | |
| 780 case AAStatus::disabled_present: | |
| 781 os << "disabled_present"; | |
| 782 break; | |
| 783 default: | |
| 784 ; | |
| 785 } | |
| 786 return os; | |
| 787 } | |
| 788 | |
| 789 enum class Action | |
| 790 { | |
| 791 disable, enable, remove | |
| 792 }; | |
| 793 | |
| 794 ::std::ostream& operator<<(std::ostream& os, Action action) | |
| 795 { | |
| 796 switch (action) | |
| 797 { | |
| 798 case Action::disable: | |
| 799 os << "disable"; | |
| 800 break; | |
| 801 case Action::enable: | |
| 802 os << "enable"; | |
| 803 break; | |
| 804 case Action::remove: | |
| 805 os << "remove"; | |
| 806 break; | |
| 807 default: | |
| 808 ; | |
| 809 } | |
| 810 return os; | |
| 811 } | |
| 812 | |
| 813 struct Parameters | |
| 814 { | |
| 815 AAStatus initialAAStatus; | |
| 816 Action action; | |
| 817 AAStatus expectedAAStatus; | |
| 818 Parameters(AAStatus aaStatus, Action action) | |
| 819 { | |
| 820 // if `expect` is not called then no effect is expected, initialize it now | |
| 821 initialAAStatus = expectedAAStatus = aaStatus; | |
| 822 this->action = action; | |
| 823 } | |
| 824 Parameters& expect(AAStatus aaStatus) | |
| 825 { | |
| 826 expectedAAStatus = aaStatus; | |
| 827 return *this; | |
| 828 } | |
| 829 // it's merely to satisfy compiler (std::tuple requires default ctr) and | |
| 830 // testing internals even calls it. | |
| 831 Parameters() | |
| 832 { | |
| 833 } | |
| 834 }; | |
| 835 | |
| 836 // human readable printing for failed tests | |
| 837 ::std::ostream& operator<<(::std::ostream& os, const Parameters& params) | |
| 838 { | |
| 839 os << "initial AA: " << params.initialAAStatus | |
| 840 << " action: " << params.action | |
| 841 << " expected AA: " << params.expectedAAStatus; | |
| 842 return os; | |
| 843 } | |
| 844 class Test : public FilterEngineTest | |
| 845 , public ::testing::WithParamInterface<::testing::tuple<Parameters, /*number of other subscriptions*/uint8_t>> | |
| 846 { | |
| 847 public: | |
| 848 static std::vector<Parameters> VaryPossibleCases() | |
| 849 { | |
| 850 // AA API test matrix | |
| 851 // each column but other-subs is about AA subscription | |
| 852 // enabled exists other-subs action => expected | |
| 853 // => everywhere no effect on other subs | |
| 854 // 1. | |
| 855 // false false false disable => no effect | |
| 856 // false false false enable => add and enable | |
| 857 // | |
| 858 // false false true disable => no effect | |
| 859 // false false true enable => add and enable | |
| 860 // 2. | |
| 861 // false true false disable => no effect | |
| 862 // false true false enable => enable | |
| 863 // | |
| 864 // false true true disable => no effect | |
| 865 // false true true enable => enable | |
| 866 // 3. | |
| 867 // true true false disable => disable | |
| 868 // ture true false enable => no effect | |
| 869 // | |
| 870 // true true true disable => disable | |
| 871 // ture true true enable => no effect | |
| 872 // 4. | |
| 873 // false true false remove => remove | |
| 874 // false true true remove => remove | |
| 875 // ture true false remove => remove | |
| 876 // ture true true remove => remove | |
| 877 std::vector<Parameters> retValue; | |
| 878 // 1. | |
| 879 retValue.emplace_back(Parameters(AAStatus::absent, Action::disable)); | |
| 880 retValue.emplace_back(Parameters(AAStatus::absent, Action::enable).expect( AAStatus::enabled)); | |
| 881 // 2. | |
| 882 retValue.emplace_back(Parameters(AAStatus::disabled_present, Action::disab le)); | |
| 883 retValue.emplace_back(Parameters(AAStatus::disabled_present, Action::enabl e).expect(AAStatus::enabled)); | |
| 884 // 3. | |
| 885 retValue.emplace_back(Parameters(AAStatus::enabled, Action::disable).expec t(AAStatus::disabled_present)); | |
| 886 retValue.emplace_back(Parameters(AAStatus::enabled, Action::enable)); | |
| 887 // 4. | |
| 888 retValue.emplace_back(Parameters(AAStatus::disabled_present, Action::remov e).expect(AAStatus::absent)); | |
| 889 retValue.emplace_back(Parameters(AAStatus::enabled, Action::remove).expect (AAStatus::absent)); | |
| 890 // since AA should not affect other subscriptions, the number of other | |
| 891 // subscriptions is not specified here, it goes as another item in test pa rameters tuple. | |
| 892 return retValue; | |
| 893 } | |
| 894 protected: | |
| 895 void init(AAStatus aaStatus, uint8_t otherSubscriptionsNumber) | |
| 896 { | |
| 897 // for the sake of simplicity test only with one suplimentary subscription | |
| 898 ASSERT_TRUE(otherSubscriptionsNumber == 0u || otherSubscriptionsNumber == 1u); | |
| 899 | |
| 900 // this method also tests the result of intermediate steps. | |
| 901 | |
| 902 { | |
| 903 // no subscription (because of preconfigured prefs.json and patterns.ini ), | |
| 904 // though it should be enabled by default in a non-test environment, it' s tested in | |
| 905 // corresponding tests. | |
| 906 const auto subscriptions = filterEngine->GetListedSubscriptions(); | |
| 907 EXPECT_EQ(0u, subscriptions.size()); // no any subscription including AA | |
| 908 EXPECT_FALSE(filterEngine->IsAAEnabled()); | |
| 909 } | |
| 910 if (otherSubscriptionsNumber == 1u) | |
| 911 { | |
| 912 auto subscription = filterEngine->GetSubscription(kOtherSubscriptionUrl) ; | |
| 913 ASSERT_TRUE(subscription); | |
| 914 subscription->AddToList(); | |
| 915 const auto subscriptions = filterEngine->GetListedSubscriptions(); | |
| 916 ASSERT_EQ(1u, subscriptions.size()); | |
| 917 EXPECT_FALSE(subscriptions[0]->IsAA()); | |
| 918 EXPECT_EQ(kOtherSubscriptionUrl, subscriptions[0]->GetProperty("url")->A sString()); | |
| 919 } | |
| 920 if (isAASatusPresent(aaStatus)) | |
| 921 { | |
| 922 filterEngine->SetAAEnabled(true); // add AA by enabling it | |
| 923 if (aaStatus == AAStatus::disabled_present) | |
| 924 { | |
| 925 filterEngine->SetAAEnabled(false); | |
| 926 } | |
| 927 testSubscriptionState(aaStatus, otherSubscriptionsNumber); | |
| 928 } | |
| 929 } | |
| 930 bool isAASatusPresent(AAStatus aaStatus) | |
| 931 { | |
| 932 return aaStatus != AAStatus::absent; | |
| 933 } | |
| 934 void testSubscriptionState(AAStatus aaStatus, int otherSubscriptionsNumber) | |
| 935 { | |
| 936 if (aaStatus == AAStatus::enabled) | |
| 937 EXPECT_TRUE(filterEngine->IsAAEnabled()); | |
| 938 else | |
| 939 EXPECT_FALSE(filterEngine->IsAAEnabled()); | |
| 940 | |
| 941 SubscriptionPtr aaSubscription; | |
| 942 SubscriptionPtr otherSubscription; | |
| 943 const auto subscriptions = filterEngine->GetListedSubscriptions(); | |
| 944 for (const auto& subscription : subscriptions) | |
| 945 { | |
| 946 (subscription->IsAA() ? aaSubscription : otherSubscription) = subscripti on; | |
| 947 } | |
| 948 if (otherSubscriptionsNumber == 1u) | |
| 949 { | |
| 950 if (isAASatusPresent(aaStatus)) | |
| 951 { | |
| 952 EXPECT_EQ(2u, subscriptions.size()); | |
| 953 EXPECT_TRUE(aaSubscription); | |
| 954 EXPECT_TRUE(otherSubscription); | |
| 955 } | |
| 956 else | |
| 957 { | |
| 958 EXPECT_EQ(1u, subscriptions.size()); | |
| 959 EXPECT_FALSE(aaSubscription); | |
| 960 EXPECT_TRUE(otherSubscription); | |
| 961 } | |
| 962 } | |
| 963 else if (otherSubscriptionsNumber == 0u) | |
| 964 { | |
| 965 if (isAASatusPresent(aaStatus)) | |
| 966 { | |
| 967 EXPECT_EQ(1u, subscriptions.size()); | |
| 968 EXPECT_TRUE(aaSubscription); | |
| 969 EXPECT_FALSE(otherSubscription); | |
| 970 } | |
| 971 else | |
| 972 { | |
| 973 EXPECT_EQ(0u, subscriptions.size()); | |
| 974 } | |
| 975 } | |
| 976 } | |
| 977 }; | |
| 978 | |
| 979 INSTANTIATE_TEST_CASE_P(AA_ApiTests, Test, | |
| 980 ::testing::Combine(::testing::ValuesIn(Test::VaryPossibleCases()), ::testing ::Values<uint8_t>(0, 1))); | |
| 981 | |
| 982 TEST_P(Test, VaryPossibleCases) { | |
| 983 const auto parameter = ::testing::get<0>(GetParam()); | |
| 984 uint8_t otherSubscriptionsNumber = ::testing::get<1>(GetParam()); | |
| 985 init(parameter.initialAAStatus, otherSubscriptionsNumber); | |
| 986 | |
| 987 if (parameter.action == Action::enable) | |
| 988 filterEngine->SetAAEnabled(true); | |
| 989 else if (parameter.action == Action::disable) | |
| 990 filterEngine->SetAAEnabled(false); | |
| 991 else if (parameter.action == Action::remove) | |
| 992 { | |
| 993 SubscriptionPtr aaSubscription; | |
| 994 for (const auto& subscription : filterEngine->GetListedSubscriptions()) | |
| 995 { | |
| 996 if (subscription->IsAA()) | |
| 997 { | |
| 998 aaSubscription = subscription; | |
| 999 break; | |
| 1000 } | |
| 1001 } | |
| 1002 ASSERT_TRUE(aaSubscription); | |
| 1003 aaSubscription->RemoveFromList(); | |
| 1004 } | |
| 1005 | |
| 1006 testSubscriptionState(parameter.expectedAAStatus, otherSubscriptionsNumber); | |
| 1007 } | |
| 1008 } | |
| 1009 | |
| 1010 TEST_F(FilterEngineIsAllowedConnectionTest, AbsentCallbackAllowsUpdating) | |
| 1011 { | |
| 1012 createParams.isConnectionAllowedCallback = FilterEngine::IsConnectionAllowedCa llback(); | |
| 1013 auto subscription = EnsureExampleSubscriptionAndForceUpdate(); | |
| 1014 EXPECT_EQ("synchronize_ok", subscription->GetProperty("downloadStatus")->AsStr ing()); | |
| 1015 EXPECT_EQ(1u, subscription->GetProperty("filters")->AsList().size()); | |
| 1016 } | |
| 1017 | |
| 1018 TEST_F(FilterEngineIsAllowedConnectionTest, AllowingCallbackAllowsUpdating) | |
| 1019 { | |
| 1020 // no stored allowed_connection_type preference | |
| 1021 auto subscription = EnsureExampleSubscriptionAndForceUpdate(); | |
| 1022 EXPECT_EQ("synchronize_ok", subscription->GetProperty("downloadStatus")->AsStr ing()); | |
| 1023 EXPECT_EQ(1u, subscription->GetProperty("filters")->AsList().size()); | |
| 1024 auto capturedConnectionTypes = this->capturedConnectionTypes.GetStrings(); | |
| 1025 ASSERT_EQ(1u, capturedConnectionTypes.size()); | |
| 1026 EXPECT_FALSE(capturedConnectionTypes[0].first); | |
| 1027 } | |
| 1028 | |
| 1029 TEST_F(FilterEngineIsAllowedConnectionTest, NotAllowingCallbackDoesNotAllowUpdat ing) | |
| 1030 { | |
| 1031 isConnectionAllowed = false; | |
| 1032 // no stored allowed_connection_type preference | |
| 1033 auto subscription = EnsureExampleSubscriptionAndForceUpdate(); | |
| 1034 EXPECT_EQ("synchronize_connection_error", subscription->GetProperty("downloadS tatus")->AsString()); | |
| 1035 EXPECT_EQ(0u, subscription->GetProperty("filters")->AsList().size()); | |
| 1036 auto capturedConnectionTypes = this->capturedConnectionTypes.GetStrings(); | |
| 1037 EXPECT_EQ(1u, capturedConnectionTypes.size()); | |
| 1038 } | |
| 1039 | |
| 1040 TEST_F(FilterEngineIsAllowedConnectionTest, PredefinedAllowedConnectionTypeIsPas sedToCallback) | |
| 1041 { | |
| 1042 std::string predefinedAllowedConnectionType = "non-metered"; | |
| 1043 createParams.preconfiguredPrefs["allowed_connection_type"] = jsEngine->NewValu e(predefinedAllowedConnectionType); | |
| 1044 auto subscription = EnsureExampleSubscriptionAndForceUpdate(); | |
| 1045 EXPECT_EQ("synchronize_ok", subscription->GetProperty("downloadStatus")->AsStr ing()); | |
| 1046 EXPECT_EQ(1u, subscription->GetProperty("filters")->AsList().size()); | |
| 1047 auto capturedConnectionTypes = this->capturedConnectionTypes.GetStrings(); | |
| 1048 ASSERT_EQ(1u, capturedConnectionTypes.size()); | |
| 1049 EXPECT_TRUE(capturedConnectionTypes[0].first); | |
| 1050 EXPECT_EQ(predefinedAllowedConnectionType, capturedConnectionTypes[0].second); | |
| 1051 } | |
| 1052 | |
| 1053 TEST_F(FilterEngineIsAllowedConnectionTest, ConfiguredConnectionTypeIsPassedToCa llback) | |
| 1054 { | |
| 1055 // FilterEngine->RemoveSubscription is not usable here because subscriptions | |
| 1056 // are cached internally by URL. So, different URLs are used in diffirent | |
| 1057 // checks. | |
| 1058 { | |
| 1059 std::string predefinedAllowedConnectionType = "non-metered"; | |
| 1060 createParams.preconfiguredPrefs["allowed_connection_type"] = jsEngine->NewVa lue(predefinedAllowedConnectionType); | |
| 1061 auto subscription = EnsureExampleSubscriptionAndForceUpdate(); | |
| 1062 EXPECT_EQ("synchronize_ok", subscription->GetProperty("downloadStatus")->AsS tring()); | |
| 1063 EXPECT_EQ(1u, subscription->GetProperty("filters")->AsList().size()); | |
| 1064 auto capturedConnectionTypes = this->capturedConnectionTypes.GetStrings(); | |
| 1065 ASSERT_EQ(1u, capturedConnectionTypes.size()); | |
| 1066 EXPECT_TRUE(capturedConnectionTypes[0].first); | |
| 1067 EXPECT_EQ(predefinedAllowedConnectionType, capturedConnectionTypes[0].second ); | |
| 1068 } | |
| 1069 capturedConnectionTypes.Clear(); | |
| 1070 { | |
| 1071 // set no value | |
| 1072 filterEngine->SetAllowedConnectionType(nullptr); | |
| 1073 auto subscription = EnsureExampleSubscriptionAndForceUpdate("subA"); | |
| 1074 EXPECT_EQ("synchronize_ok", subscription->GetProperty("downloadStatus")->AsS tring()); | |
| 1075 EXPECT_EQ(1u, subscription->GetProperty("filters")->AsList().size()); | |
| 1076 auto capturedConnectionTypes = this->capturedConnectionTypes.GetStrings(); | |
| 1077 ASSERT_EQ(1u, capturedConnectionTypes.size()); | |
| 1078 EXPECT_FALSE(capturedConnectionTypes[0].first); | |
| 1079 subscription->RemoveFromList(); | |
| 1080 this->capturedConnectionTypes.Clear(); | |
| 1081 } | |
| 1082 capturedConnectionTypes.Clear(); | |
| 1083 { | |
| 1084 // set some value | |
| 1085 std::string testConnection = "test connection"; | |
| 1086 filterEngine->SetAllowedConnectionType(&testConnection); | |
| 1087 auto subscription = EnsureExampleSubscriptionAndForceUpdate("subB"); | |
| 1088 EXPECT_EQ("synchronize_ok", subscription->GetProperty("downloadStatus")->AsS tring()); | |
| 1089 EXPECT_EQ(1u, subscription->GetProperty("filters")->AsList().size()); | |
| 1090 auto capturedConnectionTypes = this->capturedConnectionTypes.GetStrings(); | |
| 1091 ASSERT_EQ(1u, capturedConnectionTypes.size()); | |
| 1092 EXPECT_TRUE(capturedConnectionTypes[0].first); | |
| 1093 EXPECT_EQ(testConnection, capturedConnectionTypes[0].second); | |
| 1094 } | |
| 647 } | 1095 } |
|
Eric
2016/12/05 14:40:58
This is a bunch of unit tests all combined into on
sergei
2017/03/17 15:55:25
Added more tests and they run in each separate tes
| |
| LEFT | RIGHT |