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 |