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.
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/base/net_errors.h"
15 #include "net/url_request/test_url_fetcher_factory.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
25 const size_t kCacheSize
= 2;
27 const int kSupervisedUserAsyncURLCheckerURLFetcherID
= 0;
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(bool is_porn
) {
42 base::DictionaryValue dict
;
43 base::DictionaryValue
* classification_dict
= new base::DictionaryValue
;
45 classification_dict
->SetBoolean("pornography", is_porn
);
46 base::ListValue
* classifications_list
= new base::ListValue
;
47 classifications_list
->Append(classification_dict
);
48 dict
.SetWithoutPathExpansion("classifications", classifications_list
);
50 base::JSONWriter::Write(dict
, &result
);
56 class SupervisedUserAsyncURLCheckerTest
: public testing::Test
{
58 SupervisedUserAsyncURLCheckerTest()
60 request_context_(new net::TestURLRequestContextGetter(
61 base::ThreadTaskRunnerHandle::Get())),
62 checker_(request_context_
.get(), kCacheSize
) {}
64 MOCK_METHOD3(OnCheckDone
,
66 SupervisedUserURLFilter::FilteringBehavior behavior
,
71 CHECK(next_url_
< arraysize(kURLs
));
72 return GURL(kURLs
[next_url_
++]);
75 // Returns true if the result was returned synchronously (cache hit).
76 bool CheckURL(const GURL
& url
) {
77 return checker_
.CheckURL(
79 base::Bind(&SupervisedUserAsyncURLCheckerTest::OnCheckDone
,
80 base::Unretained(this)));
83 net::TestURLFetcher
* GetURLFetcher() {
84 net::TestURLFetcher
* url_fetcher
= url_fetcher_factory_
.GetFetcherByID(
85 kSupervisedUserAsyncURLCheckerURLFetcherID
);
86 EXPECT_TRUE(url_fetcher
);
90 void SendResponse(net::Error error
, const std::string
& response
) {
91 net::TestURLFetcher
* url_fetcher
= GetURLFetcher();
92 url_fetcher
->set_status(net::URLRequestStatus::FromError(error
));
93 url_fetcher
->set_response_code(net::HTTP_OK
);
94 url_fetcher
->SetResponseString(response
);
95 url_fetcher
->delegate()->OnURLFetchComplete(url_fetcher
);
98 void SendValidResponse(bool is_porn
) {
99 SendResponse(net::OK
, BuildResponse(is_porn
));
102 void SendFailedResponse() {
103 SendResponse(net::ERR_ABORTED
, std::string());
107 base::MessageLoop message_loop_
;
108 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
109 net::TestURLFetcherFactory url_fetcher_factory_
;
110 SupervisedUserAsyncURLChecker checker_
;
113 TEST_F(SupervisedUserAsyncURLCheckerTest
, Simple
) {
115 GURL
url(GetNewURL());
116 EXPECT_FALSE(CheckURL(url
));
117 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::ALLOW
, false));
118 SendValidResponse(false);
121 GURL
url(GetNewURL());
122 EXPECT_FALSE(CheckURL(url
));
123 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::BLOCK
, false));
124 SendValidResponse(true);
127 GURL
url(GetNewURL());
128 EXPECT_FALSE(CheckURL(url
));
129 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::ALLOW
, true));
130 SendFailedResponse();
134 TEST_F(SupervisedUserAsyncURLCheckerTest
, Equivalence
) {
135 // Leading "www." in the response should be ignored.
137 GURL
url("http://example.com");
138 GURL
url_response("http://www.example.com");
139 EXPECT_FALSE(CheckURL(url
));
140 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::ALLOW
, false));
141 SendValidResponse(false);
143 // Scheme should be ignored.
145 GURL
url("http://www.example2.com");
146 GURL
url_response("https://www.example2.com");
147 EXPECT_FALSE(CheckURL(url
));
148 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::ALLOW
, false));
149 SendValidResponse(false);
151 // Both at the same time should work as well.
153 GURL
url("http://example3.com");
154 GURL
url_response("https://www.example3.com");
155 EXPECT_FALSE(CheckURL(url
));
156 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::ALLOW
, false));
157 SendValidResponse(false);
161 TEST_F(SupervisedUserAsyncURLCheckerTest
, Cache
) {
162 // One more URL than fit in the cache.
163 ASSERT_EQ(2u, kCacheSize
);
164 GURL
url1(GetNewURL());
165 GURL
url2(GetNewURL());
166 GURL
url3(GetNewURL());
168 // Populate the cache.
169 EXPECT_FALSE(CheckURL(url1
));
170 EXPECT_CALL(*this, OnCheckDone(url1
, SupervisedUserURLFilter::ALLOW
, false));
171 SendValidResponse(false);
172 EXPECT_FALSE(CheckURL(url2
));
173 EXPECT_CALL(*this, OnCheckDone(url2
, SupervisedUserURLFilter::ALLOW
, false));
174 SendValidResponse(false);
176 // Now we should get results synchronously.
177 EXPECT_CALL(*this, OnCheckDone(url2
, SupervisedUserURLFilter::ALLOW
, false));
178 EXPECT_TRUE(CheckURL(url2
));
179 EXPECT_CALL(*this, OnCheckDone(url1
, SupervisedUserURLFilter::ALLOW
, false));
180 EXPECT_TRUE(CheckURL(url1
));
182 // Now |url2| is the LRU and should be evicted on the next check.
183 EXPECT_FALSE(CheckURL(url3
));
184 EXPECT_CALL(*this, OnCheckDone(url3
, SupervisedUserURLFilter::ALLOW
, false));
185 SendValidResponse(false);
187 EXPECT_FALSE(CheckURL(url2
));
188 EXPECT_CALL(*this, OnCheckDone(url2
, SupervisedUserURLFilter::ALLOW
, false));
189 SendValidResponse(false);
192 TEST_F(SupervisedUserAsyncURLCheckerTest
, CoalesceRequestsToSameURL
) {
193 GURL
url(GetNewURL());
194 // Start two checks for the same URL.
195 EXPECT_FALSE(CheckURL(url
));
196 EXPECT_FALSE(CheckURL(url
));
197 // A single response should answer both checks.
198 EXPECT_CALL(*this, OnCheckDone(url
, SupervisedUserURLFilter::ALLOW
, false))
200 SendValidResponse(false);