Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: components/safe_browsing_db/v4_get_hash_protocol_manager_unittest.cc

Issue 2233103002: Move full hash caching logic to v4_get_hash_protocol_manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove more tests from db_manager. Simplify another test. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h" 5 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/run_loop.h"
12 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
13 #include "base/test/simple_test_clock.h" 14 #include "base/test/simple_test_clock.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "components/safe_browsing_db/safebrowsing.pb.h" 16 #include "components/safe_browsing_db/safebrowsing.pb.h"
16 #include "components/safe_browsing_db/testing_util.h" 17 #include "components/safe_browsing_db/testing_util.h"
17 #include "components/safe_browsing_db/util.h" 18 #include "components/safe_browsing_db/util.h"
18 #include "net/base/escape.h" 19 #include "net/base/escape.h"
19 #include "net/base/load_flags.h" 20 #include "net/base/load_flags.h"
20 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
21 #include "net/url_request/test_url_fetcher_factory.h" 22 #include "net/url_request/test_url_fetcher_factory.h"
22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/platform_test.h"
23 24
24 using base::Time; 25 using base::Time;
25 using base::TimeDelta; 26 using base::TimeDelta;
26 27
27 namespace { 28 namespace {
28 29
29 const char kClient[] = "unittest"; 30 const char kClient[] = "unittest";
30 const char kAppVer[] = "1.0"; 31 const char kAppVer[] = "1.0";
31 const char kKeyParam[] = "test_key_param"; 32 const char kKeyParam[] = "test_key_param";
32 33
33 } // namespace 34 } // namespace
34 35
35 namespace safe_browsing { 36 namespace safe_browsing {
36 37
37 class SafeBrowsingV4GetHashProtocolManagerTest : public testing::Test { 38 namespace {
38 protected: 39
40 struct KeyValue {
41 std::string key;
42 std::string value;
43
44 explicit KeyValue(const std::string key, const std::string value)
45 : key(key), value(value){};
46 explicit KeyValue(const KeyValue& other) = default;
47
48 private:
49 KeyValue();
50 };
51
52 struct ResponseInfo {
53 FullHash full_hash;
54 UpdateListIdentifier list_id;
55 std::vector<KeyValue> key_values;
56
57 explicit ResponseInfo(FullHash full_hash, UpdateListIdentifier list_id)
58 : full_hash(full_hash), list_id(list_id){};
59 explicit ResponseInfo(const ResponseInfo& other)
60 : full_hash(other.full_hash),
61 list_id(other.list_id),
62 key_values(other.key_values){};
63
64 private:
65 ResponseInfo();
66 };
67
68 } // namespace
69
70 class V4GetHashProtocolManagerTest : public PlatformTest {
71 public:
72 void SetUp() override {
73 PlatformTest::SetUp();
74 callback_called_ = false;
75 }
76
39 std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager() { 77 std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager() {
40 V4ProtocolConfig config; 78 V4ProtocolConfig config;
41 config.client_name = kClient; 79 config.client_name = kClient;
42 config.version = kAppVer; 80 config.version = kAppVer;
43 config.key_param = kKeyParam; 81 config.key_param = kKeyParam;
44 return std::unique_ptr<V4GetHashProtocolManager>( 82 base::hash_set<UpdateListIdentifier> stores_to_look(
45 V4GetHashProtocolManager::Create(NULL, config)); 83 {GetUrlMalwareId(), GetChromeUrlApiId()});
84 return V4GetHashProtocolManager::Create(NULL, stores_to_look, config);
46 } 85 }
47 86
48 std::string GetStockV4HashResponse() { 87 static void SetupFetcherToReturnOKResponse(
49 FindFullHashesResponse res; 88 const net::TestURLFetcherFactory& factory,
50 res.mutable_negative_cache_duration()->set_seconds(600); 89 const std::vector<ResponseInfo>& infos) {
51 ThreatMatch* m = res.add_matches(); 90 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
52 m->set_threat_type(API_ABUSE); 91 DCHECK(fetcher);
53 m->set_platform_type(CHROME_PLATFORM); 92 fetcher->set_status(net::URLRequestStatus());
54 m->set_threat_entry_type(URL); 93 fetcher->set_response_code(200);
55 m->mutable_cache_duration()->set_seconds(300); 94 fetcher->SetResponseString(GetV4HashResponse(infos));
56 m->mutable_threat()->set_hash( 95 fetcher->delegate()->OnURLFetchComplete(fetcher);
57 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n."))); 96 }
58 ThreatEntryMetadata::MetadataEntry* e =
59 m->mutable_threat_entry_metadata()->add_entries();
60 e->set_key("permission");
61 e->set_value("NOTIFICATIONS");
62 97
63 // Serialize. 98 static std::vector<ResponseInfo> GetStockV4HashResponseInfos() {
64 std::string res_data; 99 ResponseInfo info(FullHash("Everything's shiny, Cap'n."),
65 res.SerializeToString(&res_data); 100 GetChromeUrlApiId());
101 info.key_values.emplace_back("permission", "NOTIFICATIONS");
102 std::vector<ResponseInfo> infos;
103 infos.push_back(info);
104 return infos;
105 }
66 106
67 return res_data; 107 static std::string GetStockV4HashResponse() {
108 return GetV4HashResponse(GetStockV4HashResponseInfos());
68 } 109 }
69 110
70 void SetTestClock(base::Time now, V4GetHashProtocolManager* pm) { 111 void SetTestClock(base::Time now, V4GetHashProtocolManager* pm) {
71 base::SimpleTestClock* clock = new base::SimpleTestClock(); 112 base::SimpleTestClock* clock = new base::SimpleTestClock();
72 clock->SetNow(now); 113 clock->SetNow(now);
73 pm->SetClockForTests(base::WrapUnique(clock)); 114 pm->SetClockForTests(base::WrapUnique(clock));
74 } 115 }
116
117 void ValidateGetV4ApiResults(const ThreatMetadata& expected_md,
118 const ThreatMetadata& actual_md) {
119 EXPECT_EQ(expected_md, actual_md);
120 callback_called_ = true;
121 }
122
123 void ValidateGetV4HashResults(
124 const std::vector<FullHashInfo>& expected_results,
125 const std::vector<FullHashInfo>& actual_results) {
126 EXPECT_EQ(expected_results.size(), actual_results.size());
127 for (size_t i = 0; i < actual_results.size(); i++) {
128 EXPECT_TRUE(expected_results[i] == actual_results[i]);
129 }
130 callback_called_ = true;
131 }
132
133 bool callback_called() { return callback_called_; }
134
135 private:
136 static std::string GetV4HashResponse(
137 std::vector<ResponseInfo> response_infos) {
138 FindFullHashesResponse res;
139 res.mutable_negative_cache_duration()->set_seconds(600);
140 for (const ResponseInfo& info : response_infos) {
141 ThreatMatch* m = res.add_matches();
142 m->set_platform_type(info.list_id.platform_type);
143 m->set_threat_entry_type(info.list_id.threat_entry_type);
144 m->set_threat_type(info.list_id.threat_type);
145 m->mutable_cache_duration()->set_seconds(300);
146 m->mutable_threat()->set_hash(info.full_hash);
147
148 for (const KeyValue& key_value : info.key_values) {
149 ThreatEntryMetadata::MetadataEntry* e =
150 m->mutable_threat_entry_metadata()->add_entries();
151 e->set_key(key_value.key);
152 e->set_value(key_value.value);
153 }
154 }
155
156 // Serialize.
157 std::string res_data;
158 res.SerializeToString(&res_data);
159
160 return res_data;
161 }
162
163 bool callback_called_;
75 }; 164 };
76 165
77 void ValidateGetV4HashResults( 166 TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingNetwork) {
78 const std::vector<SBFullHashResult>& expected_full_hashes,
79 const base::Time& expected_cache_expire,
80 const std::vector<SBFullHashResult>& full_hashes,
81 const base::Time& cache_expire) {
82 EXPECT_EQ(expected_cache_expire, cache_expire);
83 ASSERT_EQ(expected_full_hashes.size(), full_hashes.size());
84
85 for (unsigned int i = 0; i < expected_full_hashes.size(); ++i) {
86 const SBFullHashResult& expected = expected_full_hashes[i];
87 const SBFullHashResult& actual = full_hashes[i];
88 EXPECT_TRUE(SBFullHashEqual(expected.hash, actual.hash));
89 EXPECT_EQ(expected.metadata, actual.metadata);
90 EXPECT_EQ(expected.cache_expire_after, actual.cache_expire_after);
91 }
92 }
93
94 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest,
95 TestGetHashErrorHandlingNetwork) {
96 net::TestURLFetcherFactory factory; 167 net::TestURLFetcherFactory factory;
97 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 168 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
98 169
99 std::vector<SBPrefix> prefixes; 170 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes;
Nathan Parker 2016/09/09 21:26:22 nit: This is a long type name and a long var name.
vakh (use Gerrit instead) 2016/09/09 23:25:18 If you don't mind it too much, I actually prefer t
100 std::vector<SBFullHashResult> expected_full_hashes; 171 full_hash_to_store_and_hash_prefixes[FullHash("AFullHash")].push_back(
101 base::Time expected_cache_expire; 172 StoreAndHashPrefix(GetUrlSocEngId(), HashPrefix("AHashPrefix")));
Nathan Parker 2016/09/09 21:26:22 Is it ok to have the prefix not match the full has
vakh (use Gerrit instead) 2016/09/09 23:25:18 In general not. But in this case it is irrelevant
102 173 std::vector<FullHashInfo> expected_results;
103 pm->GetFullHashesWithApis( 174 pm->GetFullHashes(
104 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes, 175 full_hash_to_store_and_hash_prefixes,
105 expected_cache_expire)); 176 base::Bind(&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
177 base::Unretained(this), expected_results));
106 178
107 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); 179 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
108 DCHECK(fetcher); 180 DCHECK(fetcher);
109 // Failed request status should result in error. 181 // Failed request status should result in error.
110 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, 182 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
111 net::ERR_CONNECTION_RESET)); 183 net::ERR_CONNECTION_RESET));
112 fetcher->set_response_code(200); 184 fetcher->set_response_code(200);
113 fetcher->SetResponseString(GetStockV4HashResponse()); 185 fetcher->SetResponseString(GetStockV4HashResponse());
114 fetcher->delegate()->OnURLFetchComplete(fetcher); 186 fetcher->delegate()->OnURLFetchComplete(fetcher);
115 187
116 // Should have recorded one error, but back off multiplier is unchanged. 188 // Should have recorded one error, but back off multiplier is unchanged.
117 EXPECT_EQ(1ul, pm->gethash_error_count_); 189 EXPECT_EQ(1ul, pm->gethash_error_count_);
118 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); 190 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
191 EXPECT_TRUE(callback_called());
119 } 192 }
120 193
121 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, 194 TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingResponseCode) {
122 TestGetHashErrorHandlingResponseCode) {
123 net::TestURLFetcherFactory factory; 195 net::TestURLFetcherFactory factory;
124 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 196 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
125 197
126 std::vector<SBPrefix> prefixes; 198 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes;
127 std::vector<SBFullHashResult> expected_full_hashes; 199 full_hash_to_store_and_hash_prefixes[FullHash("AFullHash")].push_back(
128 base::Time expected_cache_expire; 200 StoreAndHashPrefix(GetUrlSocEngId(), HashPrefix("AHashPrefix")));
129 201 std::vector<FullHashInfo> expected_results;
130 pm->GetFullHashesWithApis( 202 pm->GetFullHashes(
131 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes, 203 full_hash_to_store_and_hash_prefixes,
132 expected_cache_expire)); 204 base::Bind(&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
205 base::Unretained(this), expected_results));
133 206
134 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); 207 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
135 DCHECK(fetcher); 208 DCHECK(fetcher);
136 fetcher->set_status(net::URLRequestStatus()); 209 fetcher->set_status(net::URLRequestStatus());
137 // Response code of anything other than 200 should result in error. 210 // Response code of anything other than 200 should result in error.
138 fetcher->set_response_code(204); 211 fetcher->set_response_code(204);
139 fetcher->SetResponseString(GetStockV4HashResponse()); 212 fetcher->SetResponseString(GetStockV4HashResponse());
140 fetcher->delegate()->OnURLFetchComplete(fetcher); 213 fetcher->delegate()->OnURLFetchComplete(fetcher);
141 214
142 // Should have recorded one error, but back off multiplier is unchanged. 215 // Should have recorded one error, but back off multiplier is unchanged.
143 EXPECT_EQ(1ul, pm->gethash_error_count_); 216 EXPECT_EQ(1ul, pm->gethash_error_count_);
144 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); 217 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
218 EXPECT_TRUE(callback_called());
145 } 219 }
146 220
147 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK) { 221 TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK) {
148 net::TestURLFetcherFactory factory; 222 net::TestURLFetcherFactory factory;
149 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 223 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
150 224
151 base::Time now = base::Time::UnixEpoch(); 225 base::Time now = base::Time::UnixEpoch();
152 SetTestClock(now, pm.get()); 226 SetTestClock(now, pm.get());
153 227
154 std::vector<SBPrefix> prefixes; 228 HashPrefix prefix("Everything");
155 std::vector<SBFullHashResult> expected_full_hashes; 229 FullHash full_hash("Everything's shiny, Cap'n.");
156 SBFullHashResult hash_result; 230 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes;
157 hash_result.hash = SBFullHashForString("Everything's shiny, Cap'n."); 231 full_hash_to_store_and_hash_prefixes[full_hash].push_back(
158 hash_result.metadata.api_permissions.insert("NOTIFICATIONS"); 232 StoreAndHashPrefix(GetChromeUrlApiId(), prefix));
159 hash_result.cache_expire_after = now + base::TimeDelta::FromSeconds(300); 233 std::vector<FullHashInfo> expected_results;
160 expected_full_hashes.push_back(hash_result); 234 FullHashInfo fhi(full_hash, GetChromeUrlApiId(),
161 base::Time expected_cache_expire = now + base::TimeDelta::FromSeconds(600); 235 now + base::TimeDelta::FromSeconds(300));
236 fhi.metadata.api_permissions.insert("NOTIFICATIONS");
237 expected_results.push_back(fhi);
162 238
163 pm->GetFullHashesWithApis( 239 pm->GetFullHashes(
164 prefixes, base::Bind(&ValidateGetV4HashResults, expected_full_hashes, 240 full_hash_to_store_and_hash_prefixes,
165 expected_cache_expire)); 241 base::Bind(&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
242 base::Unretained(this), expected_results));
166 243
167 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); 244 SetupFetcherToReturnOKResponse(factory, GetStockV4HashResponseInfos());
168 DCHECK(fetcher);
169 fetcher->set_status(net::URLRequestStatus());
170 fetcher->set_response_code(200);
171 fetcher->SetResponseString(GetStockV4HashResponse());
172 fetcher->delegate()->OnURLFetchComplete(fetcher);
173 245
174 // No error, back off multiplier is unchanged. 246 // No error, back off multiplier is unchanged.
175 EXPECT_EQ(0ul, pm->gethash_error_count_); 247 EXPECT_EQ(0ul, pm->gethash_error_count_);
176 EXPECT_EQ(1ul, pm->gethash_back_off_mult_); 248 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
249
250 // Verify the state of the cache.
251 const FullHashCache* cache = pm->full_hash_cache_for_tests();
252 // Check the cache.
253 ASSERT_EQ(1u, cache->size());
254 EXPECT_EQ(1u, cache->count(prefix));
255 const CachedHashPrefixInfo& cached_result = cache->at(prefix);
256 EXPECT_EQ(cached_result.negative_ttl,
257 now + base::TimeDelta::FromSeconds(600));
258 ASSERT_EQ(1u, cached_result.full_hash_infos.size());
259 EXPECT_EQ(FullHash("Everything's shiny, Cap'n."),
260 cached_result.full_hash_infos[0].full_hash);
261 EXPECT_TRUE(callback_called());
177 } 262 }
178 263
179 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashRequest) { 264 TEST_F(V4GetHashProtocolManagerTest,
265 TestResultsNotCachedForNegativeCacheDuration) {
266 net::TestURLFetcherFactory factory;
180 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 267 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
181 268
269 HashPrefix prefix("Everything");
270 std::vector<HashPrefix> prefixes_requested({prefix});
271 base::Time negative_cache_expire;
272 FullHash full_hash("Everything's shiny, Cap'n.");
273 std::vector<FullHashInfo> fhis;
274 fhis.emplace_back(full_hash, GetChromeUrlApiId(), base::Time::UnixEpoch());
275
276 pm->UpdateCache(prefixes_requested, fhis, negative_cache_expire);
277
278 // Verify the state of the cache.
279 const FullHashCache* cache = pm->full_hash_cache_for_tests();
280 // Check the cache.
281 EXPECT_EQ(0u, cache->size());
282 }
283
284 TEST_F(V4GetHashProtocolManagerTest, TestGetHashRequest) {
285 HashPrefix one = "hashone";
286 HashPrefix two = "hashtwo";
287 std::vector<HashPrefix> prefixes_to_request = {one, two};
288
182 FindFullHashesRequest req; 289 FindFullHashesRequest req;
183 ThreatInfo* info = req.mutable_threat_info(); 290 ThreatInfo* info = req.mutable_threat_info();
291 info->add_threat_types(MALWARE_THREAT);
184 info->add_threat_types(API_ABUSE); 292 info->add_threat_types(API_ABUSE);
293
294 info->add_platform_types(GetCurrentPlatformType());
185 info->add_platform_types(CHROME_PLATFORM); 295 info->add_platform_types(CHROME_PLATFORM);
296
186 info->add_threat_entry_types(URL); 297 info->add_threat_entry_types(URL);
187 298
188 SBPrefix one = 1u; 299 info->add_threat_entries()->set_hash(one);
189 SBPrefix two = 2u; 300 info->add_threat_entries()->set_hash(two);
190 SBPrefix three = 3u;
191 std::string hash(reinterpret_cast<const char*>(&one), sizeof(SBPrefix));
192 info->add_threat_entries()->set_hash(hash);
193 hash.clear();
194 hash.append(reinterpret_cast<const char*>(&two), sizeof(SBPrefix));
195 info->add_threat_entries()->set_hash(hash);
196 hash.clear();
197 hash.append(reinterpret_cast<const char*>(&three), sizeof(SBPrefix));
198 info->add_threat_entries()->set_hash(hash);
199 301
200 // Serialize and Base64 encode. 302 // Serialize and Base64 encode.
201 std::string req_data, req_base64; 303 std::string req_data, req_base64;
202 req.SerializeToString(&req_data); 304 req.SerializeToString(&req_data);
203 base::Base64Encode(req_data, &req_base64); 305 base::Base64Encode(req_data, &req_base64);
204 306
205 std::vector<PlatformType> platform; 307 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
206 platform.push_back(CHROME_PLATFORM); 308 EXPECT_EQ(req_base64, pm->GetHashRequest(prefixes_to_request));
207 std::vector<SBPrefix> prefixes;
208 prefixes.push_back(one);
209 prefixes.push_back(two);
210 prefixes.push_back(three);
211 EXPECT_EQ(req_base64, pm->GetHashRequest(prefixes, platform, API_ABUSE));
212 } 309 }
213 310
214 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponse) { 311 TEST_F(V4GetHashProtocolManagerTest, TestParseHashResponse) {
215 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 312 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
216 313
217 base::Time now = base::Time::UnixEpoch(); 314 base::Time now = base::Time::UnixEpoch();
218 SetTestClock(now, pm.get()); 315 SetTestClock(now, pm.get());
219 316
317 FullHash full_hash("Everything's shiny, Cap'n.");
220 FindFullHashesResponse res; 318 FindFullHashesResponse res;
221 res.mutable_negative_cache_duration()->set_seconds(600); 319 res.mutable_negative_cache_duration()->set_seconds(600);
222 res.mutable_minimum_wait_duration()->set_seconds(400); 320 res.mutable_minimum_wait_duration()->set_seconds(400);
223 ThreatMatch* m = res.add_matches(); 321 ThreatMatch* m = res.add_matches();
224 m->set_threat_type(API_ABUSE); 322 m->set_threat_type(API_ABUSE);
225 m->set_platform_type(CHROME_PLATFORM); 323 m->set_platform_type(CHROME_PLATFORM);
226 m->set_threat_entry_type(URL); 324 m->set_threat_entry_type(URL);
227 m->mutable_cache_duration()->set_seconds(300); 325 m->mutable_cache_duration()->set_seconds(300);
228 m->mutable_threat()->set_hash( 326 m->mutable_threat()->set_hash(full_hash);
229 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n.")));
230 ThreatEntryMetadata::MetadataEntry* e = 327 ThreatEntryMetadata::MetadataEntry* e =
231 m->mutable_threat_entry_metadata()->add_entries(); 328 m->mutable_threat_entry_metadata()->add_entries();
232 e->set_key("permission"); 329 e->set_key("permission");
233 e->set_value("NOTIFICATIONS"); 330 e->set_value("NOTIFICATIONS");
234 331
235 // Serialize. 332 // Serialize.
236 std::string res_data; 333 std::string res_data;
237 res.SerializeToString(&res_data); 334 res.SerializeToString(&res_data);
238 335
239 std::vector<SBFullHashResult> full_hashes; 336 std::vector<FullHashInfo> full_hash_infos;
240 base::Time cache_expire; 337 base::Time cache_expire;
241 EXPECT_TRUE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); 338 EXPECT_TRUE(pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire));
242 339
243 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); 340 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire);
244 EXPECT_EQ(1ul, full_hashes.size()); 341 ASSERT_EQ(1ul, full_hash_infos.size());
245 EXPECT_TRUE(SBFullHashEqual(SBFullHashForString("Everything's shiny, Cap'n."), 342 const FullHashInfo& fhi = full_hash_infos[0];
246 full_hashes[0].hash)); 343 EXPECT_EQ(full_hash, fhi.full_hash);
247 EXPECT_EQ(1ul, full_hashes[0].metadata.api_permissions.size()); 344 EXPECT_EQ(GetChromeUrlApiId(), fhi.list_id);
248 EXPECT_EQ(1ul, 345 EXPECT_EQ(1ul, fhi.metadata.api_permissions.size());
249 full_hashes[0].metadata.api_permissions.count("NOTIFICATIONS")); 346 EXPECT_EQ(1ul, fhi.metadata.api_permissions.count("NOTIFICATIONS"));
250 EXPECT_EQ(now + 347 EXPECT_EQ(now + base::TimeDelta::FromSeconds(300), fhi.positive_ttl);
251 base::TimeDelta::FromSeconds(300), full_hashes[0].cache_expire_after);
252 EXPECT_EQ(now + base::TimeDelta::FromSeconds(400), pm->next_gethash_time_); 348 EXPECT_EQ(now + base::TimeDelta::FromSeconds(400), pm->next_gethash_time_);
253 } 349 }
254 350
255 // Adds an entry with an ignored ThreatEntryType. 351 // Adds an entry with an ignored ThreatEntryType.
256 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, 352 TEST_F(V4GetHashProtocolManagerTest,
257 TestParseHashResponseWrongThreatEntryType) { 353 TestParseHashResponseWrongThreatEntryType) {
258 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 354 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
259 355
260 base::Time now = base::Time::UnixEpoch(); 356 base::Time now = base::Time::UnixEpoch();
261 SetTestClock(now, pm.get()); 357 SetTestClock(now, pm.get());
262 358
263 FindFullHashesResponse res; 359 FindFullHashesResponse res;
264 res.mutable_negative_cache_duration()->set_seconds(600); 360 res.mutable_negative_cache_duration()->set_seconds(600);
265 res.add_matches()->set_threat_entry_type(EXECUTABLE); 361 res.add_matches()->set_threat_entry_type(EXECUTABLE);
266 362
267 // Serialize. 363 // Serialize.
268 std::string res_data; 364 std::string res_data;
269 res.SerializeToString(&res_data); 365 res.SerializeToString(&res_data);
270 366
271 std::vector<SBFullHashResult> full_hashes; 367 std::vector<FullHashInfo> full_hash_infos;
272 base::Time cache_expire; 368 base::Time cache_expire;
273 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); 369 EXPECT_FALSE(
370 pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire));
274 371
275 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); 372 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire);
276 // There should be no hash results. 373 // There should be no hash results.
277 EXPECT_EQ(0ul, full_hashes.size()); 374 EXPECT_EQ(0ul, full_hash_infos.size());
278 } 375 }
279 376
280 // Adds entries with a ThreatPatternType metadata. 377 // Adds entries with a ThreatPatternType metadata.
281 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, 378 TEST_F(V4GetHashProtocolManagerTest, TestParseHashThreatPatternType) {
282 TestParseHashThreatPatternType) {
283 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 379 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
284 380
285 base::Time now = base::Time::UnixEpoch(); 381 base::Time now = base::Time::UnixEpoch();
286 SetTestClock(now, pm.get()); 382 SetTestClock(now, pm.get());
287 383
288 // Test social engineering pattern type. 384 {
Nathan Parker 2016/09/09 21:26:22 I'm glad you scoped these separately, and I think
vakh (use Gerrit instead) 2016/09/09 23:25:18 I'm usually in favor of keeping tests small and fo
289 FindFullHashesResponse se_res; 385 // Test social engineering pattern type.
290 se_res.mutable_negative_cache_duration()->set_seconds(600); 386 FindFullHashesResponse se_res;
291 ThreatMatch* se = se_res.add_matches(); 387 se_res.mutable_negative_cache_duration()->set_seconds(600);
292 se->set_threat_type(SOCIAL_ENGINEERING_PUBLIC); 388 ThreatMatch* se = se_res.add_matches();
293 se->set_platform_type(CHROME_PLATFORM); 389 se->set_threat_type(SOCIAL_ENGINEERING_PUBLIC);
294 se->set_threat_entry_type(URL); 390 se->set_platform_type(CHROME_PLATFORM);
295 SBFullHash hash_string = SBFullHashForString("Everything's shiny, Cap'n."); 391 se->set_threat_entry_type(URL);
296 se->mutable_threat()->set_hash(SBFullHashToString(hash_string)); 392 FullHash full_hash("Everything's shiny, Cap'n.");
297 ThreatEntryMetadata::MetadataEntry* se_meta = 393 se->mutable_threat()->set_hash(full_hash);
298 se->mutable_threat_entry_metadata()->add_entries(); 394 ThreatEntryMetadata::MetadataEntry* se_meta =
299 se_meta->set_key("se_pattern_type"); 395 se->mutable_threat_entry_metadata()->add_entries();
300 se_meta->set_value("SOCIAL_ENGINEERING_LANDING"); 396 se_meta->set_key("se_pattern_type");
397 se_meta->set_value("SOCIAL_ENGINEERING_LANDING");
301 398
302 std::string se_data; 399 std::string se_data;
303 se_res.SerializeToString(&se_data); 400 se_res.SerializeToString(&se_data);
304 401
305 std::vector<SBFullHashResult> full_hashes; 402 std::vector<FullHashInfo> full_hash_infos;
306 base::Time cache_expire; 403 base::Time cache_expire;
307 EXPECT_TRUE(pm->ParseHashResponse(se_data, &full_hashes, &cache_expire)); 404 EXPECT_TRUE(
405 pm->ParseHashResponse(se_data, &full_hash_infos, &cache_expire));
406 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire);
308 407
309 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); 408 ASSERT_EQ(1ul, full_hash_infos.size());
310 EXPECT_EQ(1ul, full_hashes.size()); 409 const FullHashInfo& fhi = full_hash_infos[0];
311 EXPECT_TRUE(SBFullHashEqual(hash_string, full_hashes[0].hash)); 410 EXPECT_EQ(full_hash, fhi.full_hash);
312 EXPECT_EQ(ThreatPatternType::SOCIAL_ENGINEERING_LANDING, 411 const UpdateListIdentifier list_id(CHROME_PLATFORM, URL,
313 full_hashes[0].metadata.threat_pattern_type); 412 SOCIAL_ENGINEERING_PUBLIC);
413 EXPECT_EQ(list_id, fhi.list_id);
414 EXPECT_EQ(ThreatPatternType::SOCIAL_ENGINEERING_LANDING,
415 fhi.metadata.threat_pattern_type);
416 }
314 417
315 // Test potentially harmful application pattern type. 418 {
316 FindFullHashesResponse pha_res; 419 // Test potentially harmful application pattern type.
317 pha_res.mutable_negative_cache_duration()->set_seconds(600); 420 FindFullHashesResponse pha_res;
318 ThreatMatch* pha = pha_res.add_matches(); 421 pha_res.mutable_negative_cache_duration()->set_seconds(600);
319 pha->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION); 422 ThreatMatch* pha = pha_res.add_matches();
320 pha->set_threat_entry_type(URL); 423 pha->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION);
321 pha->set_platform_type(CHROME_PLATFORM); 424 pha->set_threat_entry_type(URL);
322 hash_string = SBFullHashForString("Not to fret."); 425 pha->set_platform_type(CHROME_PLATFORM);
323 pha->mutable_threat()->set_hash(SBFullHashToString(hash_string)); 426 FullHash full_hash("Not to fret.");
324 ThreatEntryMetadata::MetadataEntry* pha_meta = 427 pha->mutable_threat()->set_hash(full_hash);
325 pha->mutable_threat_entry_metadata()->add_entries(); 428 ThreatEntryMetadata::MetadataEntry* pha_meta =
326 pha_meta->set_key("pha_pattern_type"); 429 pha->mutable_threat_entry_metadata()->add_entries();
327 pha_meta->set_value("LANDING"); 430 pha_meta->set_key("pha_pattern_type");
431 pha_meta->set_value("LANDING");
328 432
329 std::string pha_data; 433 std::string pha_data;
330 pha_res.SerializeToString(&pha_data); 434 pha_res.SerializeToString(&pha_data);
331 full_hashes.clear(); 435 std::vector<FullHashInfo> full_hash_infos;
332 EXPECT_TRUE(pm->ParseHashResponse(pha_data, &full_hashes, &cache_expire)); 436 base::Time cache_expire;
333 EXPECT_EQ(1ul, full_hashes.size()); 437 EXPECT_TRUE(
334 EXPECT_TRUE(SBFullHashEqual(hash_string, full_hashes[0].hash)); 438 pm->ParseHashResponse(pha_data, &full_hash_infos, &cache_expire));
335 EXPECT_EQ(ThreatPatternType::MALWARE_LANDING, 439 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire);
336 full_hashes[0].metadata.threat_pattern_type);
337 440
338 // Test invalid pattern type. 441 ASSERT_EQ(1ul, full_hash_infos.size());
339 FindFullHashesResponse invalid_res; 442 const FullHashInfo& fhi = full_hash_infos[0];
340 invalid_res.mutable_negative_cache_duration()->set_seconds(600); 443 EXPECT_EQ(full_hash, fhi.full_hash);
341 ThreatMatch* invalid = invalid_res.add_matches(); 444 const UpdateListIdentifier list_id(CHROME_PLATFORM, URL,
342 invalid->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION); 445 POTENTIALLY_HARMFUL_APPLICATION);
343 invalid->set_threat_entry_type(URL); 446 EXPECT_EQ(list_id, fhi.list_id);
344 invalid->set_platform_type(CHROME_PLATFORM); 447 EXPECT_EQ(ThreatPatternType::MALWARE_LANDING,
345 invalid->mutable_threat()->set_hash(SBFullHashToString(hash_string)); 448 fhi.metadata.threat_pattern_type);
346 ThreatEntryMetadata::MetadataEntry* invalid_meta = 449 }
347 invalid->mutable_threat_entry_metadata()->add_entries();
348 invalid_meta->set_key("pha_pattern_type");
349 invalid_meta->set_value("INVALIDE_VALUE");
350 450
351 std::string invalid_data; 451 {
352 invalid_res.SerializeToString(&invalid_data); 452 // Test invalid pattern type.
353 full_hashes.clear(); 453 FullHash full_hash("Not to fret.");
354 EXPECT_FALSE( 454 FindFullHashesResponse invalid_res;
355 pm->ParseHashResponse(invalid_data, &full_hashes, &cache_expire)); 455 invalid_res.mutable_negative_cache_duration()->set_seconds(600);
356 EXPECT_EQ(0ul, full_hashes.size()); 456 ThreatMatch* invalid = invalid_res.add_matches();
457 invalid->set_threat_type(POTENTIALLY_HARMFUL_APPLICATION);
458 invalid->set_threat_entry_type(URL);
459 invalid->set_platform_type(CHROME_PLATFORM);
460 invalid->mutable_threat()->set_hash(full_hash);
461 ThreatEntryMetadata::MetadataEntry* invalid_meta =
462 invalid->mutable_threat_entry_metadata()->add_entries();
463 invalid_meta->set_key("pha_pattern_type");
464 invalid_meta->set_value("INVALIDE_VALUE");
465
466 std::string invalid_data;
467 invalid_res.SerializeToString(&invalid_data);
468 std::vector<FullHashInfo> full_hash_infos;
469 base::Time cache_expire;
470 EXPECT_FALSE(
471 pm->ParseHashResponse(invalid_data, &full_hash_infos, &cache_expire));
472 EXPECT_EQ(0ul, full_hash_infos.size());
473 }
357 } 474 }
358 475
359 // Adds metadata with a key value that is not "permission". 476 // Adds metadata with a key value that is not "permission".
360 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, 477 TEST_F(V4GetHashProtocolManagerTest,
361 TestParseHashResponseNonPermissionMetadata) { 478 TestParseHashResponseNonPermissionMetadata) {
362 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 479 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
363 480
364 base::Time now = base::Time::UnixEpoch(); 481 base::Time now = base::Time::UnixEpoch();
365 SetTestClock(now, pm.get()); 482 SetTestClock(now, pm.get());
366 483
367 FindFullHashesResponse res; 484 FindFullHashesResponse res;
368 res.mutable_negative_cache_duration()->set_seconds(600); 485 res.mutable_negative_cache_duration()->set_seconds(600);
369 ThreatMatch* m = res.add_matches(); 486 ThreatMatch* m = res.add_matches();
370 m->set_threat_type(API_ABUSE); 487 m->set_threat_type(API_ABUSE);
371 m->set_platform_type(CHROME_PLATFORM); 488 m->set_platform_type(CHROME_PLATFORM);
372 m->set_threat_entry_type(URL); 489 m->set_threat_entry_type(URL);
373 m->mutable_threat()->set_hash( 490 m->mutable_threat()->set_hash(FullHash("Not to fret."));
374 SBFullHashToString(SBFullHashForString("Not to fret.")));
375 ThreatEntryMetadata::MetadataEntry* e = 491 ThreatEntryMetadata::MetadataEntry* e =
376 m->mutable_threat_entry_metadata()->add_entries(); 492 m->mutable_threat_entry_metadata()->add_entries();
377 e->set_key("notpermission"); 493 e->set_key("notpermission");
378 e->set_value("NOTGEOLOCATION"); 494 e->set_value("NOTGEOLOCATION");
379 495
380 // Serialize. 496 // Serialize.
381 std::string res_data; 497 std::string res_data;
382 res.SerializeToString(&res_data); 498 res.SerializeToString(&res_data);
383 499
384 std::vector<SBFullHashResult> full_hashes; 500 std::vector<FullHashInfo> full_hash_infos;
385 base::Time cache_expire; 501 base::Time cache_expire;
386 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); 502 EXPECT_FALSE(
503 pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire));
387 504
388 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire); 505 EXPECT_EQ(now + base::TimeDelta::FromSeconds(600), cache_expire);
389 EXPECT_EQ(0ul, full_hashes.size()); 506 EXPECT_EQ(0ul, full_hash_infos.size());
390 } 507 }
391 508
392 TEST_F(SafeBrowsingV4GetHashProtocolManagerTest, 509 TEST_F(V4GetHashProtocolManagerTest,
393 TestParseHashResponseInconsistentThreatTypes) { 510 TestParseHashResponseInconsistentThreatTypes) {
394 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); 511 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
395 512
396 FindFullHashesResponse res; 513 FindFullHashesResponse res;
397 res.mutable_negative_cache_duration()->set_seconds(600); 514 res.mutable_negative_cache_duration()->set_seconds(600);
398 ThreatMatch* m1 = res.add_matches(); 515 ThreatMatch* m1 = res.add_matches();
399 m1->set_threat_type(API_ABUSE); 516 m1->set_threat_type(API_ABUSE);
400 m1->set_platform_type(CHROME_PLATFORM); 517 m1->set_platform_type(CHROME_PLATFORM);
401 m1->set_threat_entry_type(URL); 518 m1->set_threat_entry_type(URL);
402 m1->mutable_threat()->set_hash( 519 m1->mutable_threat()->set_hash(FullHash("Everything's shiny, Cap'n."));
403 SBFullHashToString(SBFullHashForString("Everything's shiny, Cap'n.")));
404 m1->mutable_threat_entry_metadata()->add_entries(); 520 m1->mutable_threat_entry_metadata()->add_entries();
405 ThreatMatch* m2 = res.add_matches(); 521 ThreatMatch* m2 = res.add_matches();
406 m2->set_threat_type(MALWARE_THREAT); 522 m2->set_threat_type(MALWARE_THREAT);
407 m2->set_threat_entry_type(URL); 523 m2->set_threat_entry_type(URL);
408 m2->mutable_threat()->set_hash( 524 m2->mutable_threat()->set_hash(FullHash("Not to fret."));
409 SBFullHashToString(SBFullHashForString("Not to fret.")));
410 525
411 // Serialize. 526 // Serialize.
412 std::string res_data; 527 std::string res_data;
413 res.SerializeToString(&res_data); 528 res.SerializeToString(&res_data);
414 529
415 std::vector<SBFullHashResult> full_hashes; 530 std::vector<FullHashInfo> full_hash_infos;
416 base::Time cache_expire; 531 base::Time cache_expire;
417 EXPECT_FALSE(pm->ParseHashResponse(res_data, &full_hashes, &cache_expire)); 532 EXPECT_FALSE(
533 pm->ParseHashResponse(res_data, &full_hash_infos, &cache_expire));
534 }
535
536 // Checks that results are looked up correctly in the cache.
537 TEST_F(V4GetHashProtocolManagerTest, GetCachedResults) {
Nathan Parker 2016/09/09 21:26:22 An overall comment: I think it would be less fragi
538 base::Time now = base::Time::UnixEpoch();
539 FullHash full_hash("example.com/");
Nathan Parker 2016/09/09 21:26:22 nit: A url-as-hash is sortof confusing
vakh (use Gerrit instead) 2016/09/09 23:25:18 Done.
540 HashPrefix prefix("exam");
541 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes;
542 std::vector<HashPrefix> prefixes_to_request;
543 std::vector<FullHashInfo> cached_full_hash_infos;
544 full_hash_to_store_and_hash_prefixes[full_hash].push_back(
545 StoreAndHashPrefix(GetUrlMalwareId(), prefix));
546 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
547 FullHashCache* cache = pm->full_hash_cache_for_tests();
548
549 // Test with an empty cache. (Case: 2)
550 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now,
551 &prefixes_to_request, &cached_full_hash_infos);
552 EXPECT_TRUE(cache->empty());
553 ASSERT_EQ(1ul, prefixes_to_request.size());
554 EXPECT_EQ(prefix, prefixes_to_request[0]);
555 EXPECT_TRUE(cached_full_hash_infos.empty());
556
557 // Prefix has a cache entry but full hash is not there. (Case: 1-b-i)
558 CachedHashPrefixInfo* entry = &(*cache)[prefix];
Nathan Parker 2016/09/09 21:26:21 Do all these cases need to be in one test? Could y
vakh (use Gerrit instead) 2016/09/09 23:25:18 Scoped each of the cases, and clear the cache befo
559 entry->negative_ttl = now + base::TimeDelta::FromMinutes(5);
560 prefixes_to_request.clear();
561 cached_full_hash_infos.clear();
562 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now,
563 &prefixes_to_request, &cached_full_hash_infos);
564 EXPECT_TRUE(prefixes_to_request.empty());
565 EXPECT_TRUE(cached_full_hash_infos.empty());
566
567 // Expired negative cache entry. (Case: 1-b-ii)
568 entry->negative_ttl = now - base::TimeDelta::FromMinutes(5);
569 prefixes_to_request.clear();
570 cached_full_hash_infos.clear();
571 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now,
572 &prefixes_to_request, &cached_full_hash_infos);
573 ASSERT_EQ(1ul, prefixes_to_request.size());
574 EXPECT_EQ(prefix, prefixes_to_request[0]);
575 EXPECT_TRUE(cached_full_hash_infos.empty());
576
577 // Now put unexpired full hash in the cache. (Case: 1-a-i)
578 FullHashInfo fhi(full_hash, GetUrlMalwareId(),
579 now + base::TimeDelta::FromMinutes(3));
580 entry->full_hash_infos.push_back(fhi);
581 prefixes_to_request.clear();
582 cached_full_hash_infos.clear();
583 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now,
584 &prefixes_to_request, &cached_full_hash_infos);
585 EXPECT_TRUE(prefixes_to_request.empty());
586 ASSERT_EQ(1ul, cached_full_hash_infos.size());
587 EXPECT_EQ(full_hash, cached_full_hash_infos[0].full_hash);
588
589 // Expire the full hash in the cache. (Case: 1-a-ii)
590 entry->full_hash_infos[0].positive_ttl =
591 now - base::TimeDelta::FromMinutes(3);
592 prefixes_to_request.clear();
593 cached_full_hash_infos.clear();
594 pm->GetFullHashCachedResults(full_hash_to_store_and_hash_prefixes, now,
595 &prefixes_to_request, &cached_full_hash_infos);
596 ASSERT_EQ(1ul, prefixes_to_request.size());
597 EXPECT_EQ(prefix, prefixes_to_request[0]);
598 EXPECT_TRUE(cached_full_hash_infos.empty());
599 }
600
601 TEST_F(V4GetHashProtocolManagerTest, TestUpdatesAreMerged) {
602 // We'll add one of the requested FullHashInfo objects into the cache, and
603 // inject the other one as a response from the server. The result should
604 // include both FullHashInfo objects.
605
606 net::TestURLFetcherFactory factory;
607 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
608 HashPrefix prefix_1("exam");
609 FullHash full_hash_1("example.com/test");
Nathan Parker 2016/09/09 21:26:22 nit: url-as-hash is confusing
vakh (use Gerrit instead) 2016/09/09 23:25:18 Done.
610 HashPrefix prefix_2("Everything");
611 FullHash full_hash_2("Everything's shiny, Cap'n.");
612
613 base::Time now = Time::Now();
614 SetTestClock(now, pm.get());
615
616 FullHashCache* cache = pm->full_hash_cache_for_tests();
617 CachedHashPrefixInfo* entry = &(*cache)[prefix_1];
618 entry->negative_ttl = now + base::TimeDelta::FromMinutes(100);
619 // Put one unexpired full hash in the cache for a store we'll look in.
620 entry->full_hash_infos.emplace_back(full_hash_1, GetUrlMalwareId(),
621 now + base::TimeDelta::FromSeconds(200));
622 // Put one unexpired full hash in the cache for a store we'll not look in.
623 entry->full_hash_infos.emplace_back(full_hash_1, GetUrlSocEngId(),
624 now + base::TimeDelta::FromSeconds(200));
625
626 // Request full hash information from two stores.
627 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes;
628 full_hash_to_store_and_hash_prefixes[full_hash_1].push_back(
629 StoreAndHashPrefix(GetUrlMalwareId(), prefix_1));
630 full_hash_to_store_and_hash_prefixes[full_hash_2].push_back(
631 StoreAndHashPrefix(GetChromeUrlApiId(), prefix_2));
632
633 // Expect full hash information from both stores.
634 std::vector<FullHashInfo> expected_results;
635 expected_results.emplace_back(full_hash_1, GetUrlMalwareId(),
636 now + base::TimeDelta::FromSeconds(200));
637 expected_results.emplace_back(full_hash_2, GetChromeUrlApiId(),
638 now + base::TimeDelta::FromSeconds(300));
639 expected_results[1].metadata.api_permissions.insert("NOTIFICATIONS");
640
641 pm->GetFullHashes(
642 full_hash_to_store_and_hash_prefixes,
643 base::Bind(&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
644 base::Unretained(this), expected_results));
645
646 SetupFetcherToReturnOKResponse(factory, GetStockV4HashResponseInfos());
647
648 // No error, back off multiplier is unchanged.
649 EXPECT_EQ(0ul, pm->gethash_error_count_);
650 EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
651
652 // Verify the state of the cache.
653 ASSERT_EQ(2u, cache->size());
654 const CachedHashPrefixInfo& cached_result_1 = cache->at(prefix_1);
655 EXPECT_EQ(cached_result_1.negative_ttl,
656 now + base::TimeDelta::FromMinutes(100));
657 ASSERT_EQ(2u, cached_result_1.full_hash_infos.size());
658 EXPECT_EQ(full_hash_1, cached_result_1.full_hash_infos[0].full_hash);
659 EXPECT_EQ(GetUrlMalwareId(), cached_result_1.full_hash_infos[0].list_id);
660
661 const CachedHashPrefixInfo& cached_result_2 = cache->at(prefix_2);
662 EXPECT_EQ(cached_result_2.negative_ttl,
663 now + base::TimeDelta::FromSeconds(600));
664 ASSERT_EQ(1u, cached_result_2.full_hash_infos.size());
665 EXPECT_EQ(full_hash_2, cached_result_2.full_hash_infos[0].full_hash);
666 EXPECT_EQ(GetChromeUrlApiId(), cached_result_2.full_hash_infos[0].list_id);
667 EXPECT_TRUE(callback_called());
668 }
669
670 // The server responds back with full hash information containing metadata
671 // information for one of the full hashes for the URL in test.
672 TEST_F(V4GetHashProtocolManagerTest, TestGetFullHashesWithApisMergesMetadata) {
673 net::TestURLFetcherFactory factory;
674 const GURL url("https://www.example.com/more");
675 ThreatMetadata expected_md;
676 expected_md.api_permissions.insert("NOTIFICATIONS");
677 expected_md.api_permissions.insert("AUDIO_CAPTURE");
678 std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
679 pm->GetFullHashesWithApis(
680 url, base::Bind(&V4GetHashProtocolManagerTest::ValidateGetV4ApiResults,
681 base::Unretained(this), expected_md));
682
683 // The following two random looking strings value are two of the full hashes
684 // produced by UrlToFullHashes in v4_protocol_manager_util.h for the URL:
685 // "https://www.example.com/more"
686 std::vector<ResponseInfo> infos;
687 FullHash full_hash;
688 base::Base64Decode("1ZzJ0/7NjPkg6t0DAS8L5Jf7jA48Pn7opQcP4UXYeXc=",
689 &full_hash);
690 ResponseInfo info(full_hash, GetChromeUrlApiId());
691 info.key_values.emplace_back("permission", "NOTIFICATIONS");
692 infos.push_back(info);
693
694 base::Base64Decode("4rPDSdcei1BiCOPnj9kgsy2O6Ua6X3iFBakqphB3ZfA=",
695 &full_hash);
696 info = ResponseInfo(full_hash, GetChromeUrlApiId());
697 info.key_values.emplace_back("permission", "AUDIO_CAPTURE");
698 infos.push_back(info);
699
700 full_hash = FullHash("Everything's shiny, Cap'n.");
701 info = ResponseInfo(full_hash, GetChromeUrlApiId());
702 info.key_values.emplace_back("permission", "GEOLOCATION");
703 infos.push_back(info);
704 SetupFetcherToReturnOKResponse(factory, infos);
705
706 EXPECT_TRUE(callback_called());
418 } 707 }
419 708
420 } // namespace safe_browsing 709 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698