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

Delta Between Two Patch Sets: test/FilterEngine.cpp

Issue 29366747: Issue 4657 - Add Acceptable Ads API (Closed)
Left Patch Set: Created Dec. 2, 2016, 4:27 p.m.
Right Patch Set: fix typo Created April 5, 2017, 4:53 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/FilterEngine.cpp ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 Eyeo GmbH 3 * Copyright (C) 2006-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
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
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
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([&timesCalled](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
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
LEFTRIGHT

Powered by Google App Engine
This is Rietveld