Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / supervised_user / experimental / supervised_user_async_url_checker_unittest.cc
blobbc3dfd1ba5f5c367572f850d09eaa714632cb726
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/callback.h"
8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/values.h"
13 #include "chrome/browser/supervised_user/experimental/supervised_user_async_url_checker.h"
14 #include "net/url_request/test_url_fetcher_factory.h"
15 #include "net/url_request/url_request_test_util.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "url/gurl.h"
20 using testing::_;
22 namespace {
24 const size_t kCacheSize = 2;
26 const int kSupervisedUserAsyncURLCheckerSafeURLFetcherID = 0;
27 const int kSupervisedUserAsyncURLCheckerUnsafeURLFetcherID = 1;
29 const char* kURLs[] = {
30 "http://www.randomsite1.com",
31 "http://www.randomsite2.com",
32 "http://www.randomsite3.com",
33 "http://www.randomsite4.com",
34 "http://www.randomsite5.com",
35 "http://www.randomsite6.com",
36 "http://www.randomsite7.com",
37 "http://www.randomsite8.com",
38 "http://www.randomsite9.com",
41 std::string BuildResponse(const GURL& url) {
42 base::DictionaryValue dict;
43 base::DictionaryValue* search_info_dict = new base::DictionaryValue;
44 std::string result_count = url.is_valid() ? "1" : "0";
45 search_info_dict->SetStringWithoutPathExpansion("totalResults",
46 result_count);
47 dict.SetWithoutPathExpansion("searchInformation", search_info_dict);
48 if (result_count != "0") {
49 base::ListValue* results_list = new base::ListValue;
50 base::DictionaryValue* result_dict = new base::DictionaryValue;
51 result_dict->SetStringWithoutPathExpansion("link", url.spec());
52 results_list->Append(result_dict);
53 dict.SetWithoutPathExpansion("items", results_list);
55 std::string result;
56 base::JSONWriter::Write(dict, &result);
57 return result;
60 } // namespace
62 class SupervisedUserAsyncURLCheckerTest : public testing::Test {
63 public:
64 SupervisedUserAsyncURLCheckerTest()
65 : next_url_(0),
66 request_context_(new net::TestURLRequestContextGetter(
67 base::ThreadTaskRunnerHandle::Get())),
68 checker_(request_context_.get(), kCacheSize) {}
70 MOCK_METHOD3(OnCheckDone,
71 void(const GURL& url,
72 SupervisedUserURLFilter::FilteringBehavior behavior,
73 bool uncertain));
75 protected:
76 GURL GetNewURL() {
77 CHECK(next_url_ < arraysize(kURLs));
78 return GURL(kURLs[next_url_++]);
81 // Returns true if the result was returned synchronously (cache hit).
82 bool CheckURL(const GURL& url) {
83 return checker_.CheckURL(
84 url,
85 base::Bind(&SupervisedUserAsyncURLCheckerTest::OnCheckDone,
86 base::Unretained(this)));
89 net::TestURLFetcher* GetURLFetcher(bool safe) {
90 int id = safe ? kSupervisedUserAsyncURLCheckerSafeURLFetcherID
91 : kSupervisedUserAsyncURLCheckerUnsafeURLFetcherID;
92 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(id);
93 EXPECT_TRUE(url_fetcher);
94 return url_fetcher;
97 void SendResponse(bool safe,
98 net::URLRequestStatus::Status status,
99 const std::string& response) {
100 net::TestURLFetcher* url_fetcher = GetURLFetcher(safe);
101 url_fetcher->set_status(net::URLRequestStatus(status, 0));
102 url_fetcher->set_response_code(net::HTTP_OK);
103 url_fetcher->SetResponseString(response);
104 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
107 void SendValidResponse(bool safe, const GURL& url) {
108 SendResponse(safe, net::URLRequestStatus::SUCCESS, BuildResponse(url));
111 void SendFailedResponse(bool safe) {
112 SendResponse(safe, net::URLRequestStatus::CANCELED, std::string());
115 size_t next_url_;
116 base::MessageLoop message_loop_;
117 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
118 net::TestURLFetcherFactory url_fetcher_factory_;
119 SupervisedUserAsyncURLChecker checker_;
122 TEST_F(SupervisedUserAsyncURLCheckerTest, Simple) {
124 GURL url(GetNewURL());
125 EXPECT_FALSE(CheckURL(url));
126 // "URL found" response from safe fetcher should immediately give a
127 // "not blocked" result.
128 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false));
129 SendValidResponse(true, url);
132 GURL url(GetNewURL());
133 EXPECT_FALSE(CheckURL(url));
134 // "URL not found" response from safe fetcher should not immediately give a
135 // result.
136 EXPECT_CALL(*this, OnCheckDone(_, _, _)).Times(0);
137 SendValidResponse(true, GURL());
138 // "URL found" response from unsafe fetcher should give a "blocked" result.
139 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::BLOCK, false));
140 SendValidResponse(false, url);
143 GURL url(GetNewURL());
144 EXPECT_FALSE(CheckURL(url));
145 // "URL found" response from unsafe fetcher should not immediately give a
146 // result.
147 EXPECT_CALL(*this, OnCheckDone(_, _, _)).Times(0);
148 SendValidResponse(false, url);
149 // "URL not found" response from safe fetcher should give a "blocked"
150 // result.
151 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::BLOCK, false));
152 SendValidResponse(true, GURL());
155 GURL url(GetNewURL());
156 EXPECT_FALSE(CheckURL(url));
157 // "URL not found" response from unsafe fetcher should immediately give a
158 // "not blocked (but uncertain)" result.
159 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, true));
160 SendValidResponse(false, GURL());
164 TEST_F(SupervisedUserAsyncURLCheckerTest, Equivalence) {
165 // Leading "www." in the response should be ignored.
167 GURL url("http://example.com");
168 GURL url_response("http://www.example.com");
169 EXPECT_FALSE(CheckURL(url));
170 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false));
171 SendValidResponse(true, url_response);
173 // Scheme should be ignored.
175 GURL url("http://www.example2.com");
176 GURL url_response("https://www.example2.com");
177 EXPECT_FALSE(CheckURL(url));
178 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false));
179 SendValidResponse(true, url_response);
181 // Both at the same time should work as well.
183 GURL url("http://example3.com");
184 GURL url_response("https://www.example3.com");
185 EXPECT_FALSE(CheckURL(url));
186 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false));
187 SendValidResponse(true, url_response);
191 TEST_F(SupervisedUserAsyncURLCheckerTest, Cache) {
192 // One more URL than fit in the cache.
193 ASSERT_EQ(2u, kCacheSize);
194 GURL url1(GetNewURL());
195 GURL url2(GetNewURL());
196 GURL url3(GetNewURL());
198 // Populate the cache.
199 EXPECT_FALSE(CheckURL(url1));
200 EXPECT_CALL(*this, OnCheckDone(url1, SupervisedUserURLFilter::ALLOW, false));
201 SendValidResponse(true, url1);
202 EXPECT_FALSE(CheckURL(url2));
203 EXPECT_CALL(*this, OnCheckDone(url2, SupervisedUserURLFilter::ALLOW, false));
204 SendValidResponse(true, url2);
206 // Now we should get results synchronously.
207 EXPECT_CALL(*this, OnCheckDone(url2, SupervisedUserURLFilter::ALLOW, false));
208 EXPECT_TRUE(CheckURL(url2));
209 EXPECT_CALL(*this, OnCheckDone(url1, SupervisedUserURLFilter::ALLOW, false));
210 EXPECT_TRUE(CheckURL(url1));
212 // Now |url2| is the LRU and should be evicted on the next check.
213 EXPECT_FALSE(CheckURL(url3));
214 EXPECT_CALL(*this, OnCheckDone(url3, SupervisedUserURLFilter::ALLOW, false));
215 SendValidResponse(true, url3);
217 EXPECT_FALSE(CheckURL(url2));
218 EXPECT_CALL(*this, OnCheckDone(url2, SupervisedUserURLFilter::ALLOW, false));
219 SendValidResponse(true, url2);
222 TEST_F(SupervisedUserAsyncURLCheckerTest, CoalesceRequestsToSameURL) {
223 GURL url(GetNewURL());
224 // Start two checks for the same URL.
225 EXPECT_FALSE(CheckURL(url));
226 EXPECT_FALSE(CheckURL(url));
227 // A single response should answer both checks.
228 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false))
229 .Times(2);
230 SendValidResponse(true, url);