OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/supervised_user/experimental/supervised_user_async_url_
checker.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <memory> | |
10 #include <string> | |
11 #include <utility> | |
12 | |
13 #include "base/callback.h" | |
14 #include "base/json/json_writer.h" | |
15 #include "base/macros.h" | |
16 #include "base/message_loop/message_loop.h" | |
17 #include "base/threading/thread_task_runner_handle.h" | |
18 #include "base/values.h" | |
19 #include "net/base/net_errors.h" | |
20 #include "net/url_request/test_url_fetcher_factory.h" | |
21 #include "net/url_request/url_request_test_util.h" | |
22 #include "testing/gmock/include/gmock/gmock.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 #include "url/gurl.h" | |
25 | |
26 using testing::_; | |
27 | |
28 namespace { | |
29 | |
30 const size_t kCacheSize = 2; | |
31 | |
32 const int kSupervisedUserAsyncURLCheckerURLFetcherID = 0; | |
33 | |
34 const char* kURLs[] = { | |
35 "http://www.randomsite1.com", | |
36 "http://www.randomsite2.com", | |
37 "http://www.randomsite3.com", | |
38 "http://www.randomsite4.com", | |
39 "http://www.randomsite5.com", | |
40 "http://www.randomsite6.com", | |
41 "http://www.randomsite7.com", | |
42 "http://www.randomsite8.com", | |
43 "http://www.randomsite9.com", | |
44 }; | |
45 | |
46 std::string BuildResponse(bool is_porn) { | |
47 base::DictionaryValue dict; | |
48 std::unique_ptr<base::DictionaryValue> classification_dict( | |
49 new base::DictionaryValue); | |
50 if (is_porn) | |
51 classification_dict->SetBoolean("pornography", is_porn); | |
52 base::ListValue* classifications_list = new base::ListValue; | |
53 classifications_list->Append(std::move(classification_dict)); | |
54 dict.SetWithoutPathExpansion("classifications", classifications_list); | |
55 std::string result; | |
56 base::JSONWriter::Write(dict, &result); | |
57 return result; | |
58 } | |
59 | |
60 } // namespace | |
61 | |
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) {} | |
69 | |
70 MOCK_METHOD3(OnCheckDone, | |
71 void(const GURL& url, | |
72 SupervisedUserURLFilter::FilteringBehavior behavior, | |
73 bool uncertain)); | |
74 | |
75 protected: | |
76 GURL GetNewURL() { | |
77 CHECK(next_url_ < arraysize(kURLs)); | |
78 return GURL(kURLs[next_url_++]); | |
79 } | |
80 | |
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))); | |
87 } | |
88 | |
89 net::TestURLFetcher* GetURLFetcher() { | |
90 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID( | |
91 kSupervisedUserAsyncURLCheckerURLFetcherID); | |
92 EXPECT_TRUE(url_fetcher); | |
93 return url_fetcher; | |
94 } | |
95 | |
96 void SendResponse(net::Error error, const std::string& response) { | |
97 net::TestURLFetcher* url_fetcher = GetURLFetcher(); | |
98 url_fetcher->set_status(net::URLRequestStatus::FromError(error)); | |
99 url_fetcher->set_response_code(net::HTTP_OK); | |
100 url_fetcher->SetResponseString(response); | |
101 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | |
102 } | |
103 | |
104 void SendValidResponse(bool is_porn) { | |
105 SendResponse(net::OK, BuildResponse(is_porn)); | |
106 } | |
107 | |
108 void SendFailedResponse() { | |
109 SendResponse(net::ERR_ABORTED, std::string()); | |
110 } | |
111 | |
112 size_t next_url_; | |
113 base::MessageLoop message_loop_; | |
114 scoped_refptr<net::TestURLRequestContextGetter> request_context_; | |
115 net::TestURLFetcherFactory url_fetcher_factory_; | |
116 SupervisedUserAsyncURLChecker checker_; | |
117 }; | |
118 | |
119 TEST_F(SupervisedUserAsyncURLCheckerTest, Simple) { | |
120 { | |
121 GURL url(GetNewURL()); | |
122 ASSERT_FALSE(CheckURL(url)); | |
123 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false)); | |
124 SendValidResponse(false); | |
125 } | |
126 { | |
127 GURL url(GetNewURL()); | |
128 ASSERT_FALSE(CheckURL(url)); | |
129 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::BLOCK, false)); | |
130 SendValidResponse(true); | |
131 } | |
132 { | |
133 GURL url(GetNewURL()); | |
134 ASSERT_FALSE(CheckURL(url)); | |
135 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, true)); | |
136 SendFailedResponse(); | |
137 } | |
138 } | |
139 | |
140 TEST_F(SupervisedUserAsyncURLCheckerTest, Equivalence) { | |
141 // Leading "www." in the response should be ignored. | |
142 { | |
143 GURL url("http://example.com"); | |
144 GURL url_response("http://www.example.com"); | |
145 ASSERT_FALSE(CheckURL(url)); | |
146 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false)); | |
147 SendValidResponse(false); | |
148 } | |
149 // Scheme should be ignored. | |
150 { | |
151 GURL url("http://www.example2.com"); | |
152 GURL url_response("https://www.example2.com"); | |
153 ASSERT_FALSE(CheckURL(url)); | |
154 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false)); | |
155 SendValidResponse(false); | |
156 } | |
157 // Both at the same time should work as well. | |
158 { | |
159 GURL url("http://example3.com"); | |
160 GURL url_response("https://www.example3.com"); | |
161 ASSERT_FALSE(CheckURL(url)); | |
162 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false)); | |
163 SendValidResponse(false); | |
164 } | |
165 } | |
166 | |
167 TEST_F(SupervisedUserAsyncURLCheckerTest, Cache) { | |
168 // One more URL than fit in the cache. | |
169 ASSERT_EQ(2u, kCacheSize); | |
170 GURL url1(GetNewURL()); | |
171 GURL url2(GetNewURL()); | |
172 GURL url3(GetNewURL()); | |
173 | |
174 // Populate the cache. | |
175 ASSERT_FALSE(CheckURL(url1)); | |
176 EXPECT_CALL(*this, OnCheckDone(url1, SupervisedUserURLFilter::ALLOW, false)); | |
177 SendValidResponse(false); | |
178 ASSERT_FALSE(CheckURL(url2)); | |
179 EXPECT_CALL(*this, OnCheckDone(url2, SupervisedUserURLFilter::ALLOW, false)); | |
180 SendValidResponse(false); | |
181 | |
182 // Now we should get results synchronously. | |
183 EXPECT_CALL(*this, OnCheckDone(url2, SupervisedUserURLFilter::ALLOW, false)); | |
184 ASSERT_TRUE(CheckURL(url2)); | |
185 EXPECT_CALL(*this, OnCheckDone(url1, SupervisedUserURLFilter::ALLOW, false)); | |
186 ASSERT_TRUE(CheckURL(url1)); | |
187 | |
188 // Now |url2| is the LRU and should be evicted on the next check. | |
189 ASSERT_FALSE(CheckURL(url3)); | |
190 EXPECT_CALL(*this, OnCheckDone(url3, SupervisedUserURLFilter::ALLOW, false)); | |
191 SendValidResponse(false); | |
192 | |
193 ASSERT_FALSE(CheckURL(url2)); | |
194 EXPECT_CALL(*this, OnCheckDone(url2, SupervisedUserURLFilter::ALLOW, false)); | |
195 SendValidResponse(false); | |
196 } | |
197 | |
198 TEST_F(SupervisedUserAsyncURLCheckerTest, CoalesceRequestsToSameURL) { | |
199 GURL url(GetNewURL()); | |
200 // Start two checks for the same URL. | |
201 ASSERT_FALSE(CheckURL(url)); | |
202 ASSERT_FALSE(CheckURL(url)); | |
203 // A single response should answer both checks. | |
204 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false)) | |
205 .Times(2); | |
206 SendValidResponse(false); | |
207 } | |
208 | |
209 TEST_F(SupervisedUserAsyncURLCheckerTest, CacheTimeout) { | |
210 GURL url(GetNewURL()); | |
211 | |
212 checker_.SetCacheTimeoutForTesting(base::TimeDelta::FromSeconds(0)); | |
213 | |
214 ASSERT_FALSE(CheckURL(url)); | |
215 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::ALLOW, false)); | |
216 SendValidResponse(false); | |
217 | |
218 // Since the cache timeout is zero, the cache entry should be invalidated | |
219 // immediately. | |
220 ASSERT_FALSE(CheckURL(url)); | |
221 EXPECT_CALL(*this, OnCheckDone(url, SupervisedUserURLFilter::BLOCK, false)); | |
222 SendValidResponse(true); | |
223 } | |
OLD | NEW |