1 // Copyright (c) 2012 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 "base/json/json_reader.h" 6 #include "base/json/json_writer.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/values.h" 13 #include "content/browser/geolocation/fake_access_token_store.h" 14 #include "content/browser/geolocation/location_arbitrator_impl.h" 15 #include "content/browser/geolocation/network_location_provider.h" 16 #include "net/url_request/test_url_fetcher_factory.h" 17 #include "net/url_request/url_request_status.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 namespace content { 21 22 // Constants used in multiple tests. 23 const char kTestServerUrl[] = "https://www.geolocation.test/service"; 24 const char kAccessTokenString[] = "accessToken"; 25 26 // Using #define so we can easily paste this into various other strings. 27 #define REFERENCE_ACCESS_TOKEN "2:k7j3G6LaL6u_lafw:4iXOeOpTh1glSXe" 28 29 // Stops the specified (nested) message loop when the listener is called back. 30 class MessageLoopQuitListener { 31 public: 32 MessageLoopQuitListener() 33 : client_message_loop_(base::MessageLoop::current()), 34 updated_provider_(NULL) { 35 CHECK(client_message_loop_); 36 } 37 38 void LocationUpdateAvailable(const LocationProvider* provider, 39 const Geoposition& position) { 40 EXPECT_EQ(client_message_loop_, base::MessageLoop::current()); 41 updated_provider_ = provider; 42 client_message_loop_->Quit(); 43 } 44 45 base::MessageLoop* client_message_loop_; 46 const LocationProvider* updated_provider_; 47 }; 48 49 // A mock implementation of DeviceDataProviderImplBase for testing. Adapted from 50 // http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation_test.cc 51 template<typename DataType> 52 class MockDeviceDataProviderImpl 53 : public DeviceDataProviderImplBase<DataType> { 54 public: 55 // Factory method for use with DeviceDataProvider::SetFactory. 56 static DeviceDataProviderImplBase<DataType>* GetInstance() { 57 CHECK(instance_); 58 return instance_; 59 } 60 61 static MockDeviceDataProviderImpl<DataType>* CreateInstance() { 62 CHECK(!instance_); 63 instance_ = new MockDeviceDataProviderImpl<DataType>; 64 return instance_; 65 } 66 67 MockDeviceDataProviderImpl() 68 : start_calls_(0), 69 stop_calls_(0), 70 got_data_(true) { 71 } 72 73 virtual ~MockDeviceDataProviderImpl() { 74 CHECK(this == instance_); 75 instance_ = NULL; 76 } 77 78 // DeviceDataProviderImplBase implementation. 79 virtual bool StartDataProvider() { 80 ++start_calls_; 81 return true; 82 } 83 virtual void StopDataProvider() { 84 ++stop_calls_; 85 } 86 virtual bool GetData(DataType* data_out) { 87 CHECK(data_out); 88 *data_out = data_; 89 return got_data_; 90 } 91 92 void SetData(const DataType& new_data) { 93 got_data_ = true; 94 const bool differs = data_.DiffersSignificantly(new_data); 95 data_ = new_data; 96 if (differs) 97 this->NotifyListeners(); 98 } 99 100 void set_got_data(bool got_data) { got_data_ = got_data; } 101 int start_calls_; 102 int stop_calls_; 103 104 private: 105 static MockDeviceDataProviderImpl<DataType>* instance_; 106 107 DataType data_; 108 bool got_data_; 109 110 DISALLOW_COPY_AND_ASSIGN(MockDeviceDataProviderImpl); 111 }; 112 113 template<typename DataType> 114 MockDeviceDataProviderImpl<DataType>* 115 MockDeviceDataProviderImpl<DataType>::instance_ = NULL; 116 117 // Main test fixture 118 class GeolocationNetworkProviderTest : public testing::Test { 119 public: 120 virtual void SetUp() { 121 test_server_url_ = GURL(kTestServerUrl); 122 access_token_store_ = new FakeAccessTokenStore; 123 wifi_data_provider_ = 124 MockDeviceDataProviderImpl<WifiData>::CreateInstance(); 125 } 126 127 virtual void TearDown() { 128 WifiDataProvider::ResetFactory(); 129 } 130 131 LocationProvider* CreateProvider(bool set_permission_granted) { 132 LocationProvider* provider = NewNetworkLocationProvider( 133 access_token_store_.get(), 134 NULL, // No URLContextGetter needed, as using test urlfecther factory. 135 test_server_url_, 136 access_token_store_->access_token_set_[test_server_url_]); 137 if (set_permission_granted) 138 provider->OnPermissionGranted(); 139 return provider; 140 } 141 142 protected: 143 GeolocationNetworkProviderTest() { 144 // TODO(joth): Really these should be in SetUp, not here, but they take no 145 // effect on Mac OS Release builds if done there. I kid not. Figure out why. 146 WifiDataProvider::SetFactory( 147 MockDeviceDataProviderImpl<WifiData>::GetInstance); 148 } 149 150 // Returns the current url fetcher (if any) and advances the id ready for the 151 // next test step. 152 net::TestURLFetcher* get_url_fetcher_and_advance_id() { 153 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID( 154 NetworkLocationRequest::url_fetcher_id_for_tests); 155 if (fetcher) 156 ++NetworkLocationRequest::url_fetcher_id_for_tests; 157 return fetcher; 158 } 159 160 static int IndexToChannel(int index) { return index + 4; } 161 162 // Creates wifi data containing the specified number of access points, with 163 // some differentiating charactistics in each. 164 static WifiData CreateReferenceWifiScanData(int ap_count) { 165 WifiData data; 166 for (int i = 0; i < ap_count; ++i) { 167 AccessPointData ap; 168 ap.mac_address = 169 ASCIIToUTF16(base::StringPrintf("%02d-34-56-78-54-32", i)); 170 ap.radio_signal_strength = ap_count - i; 171 ap.channel = IndexToChannel(i); 172 ap.signal_to_noise = i + 42; 173 ap.ssid = ASCIIToUTF16("Some nice+network|name\\"); 174 data.access_point_data.insert(ap); 175 } 176 return data; 177 } 178 179 static void CreateReferenceWifiScanDataJson( 180 int ap_count, int start_index, base::ListValue* wifi_access_point_list) { 181 std::vector<std::string> wifi_data; 182 for (int i = 0; i < ap_count; ++i) { 183 base::DictionaryValue* ap = new base::DictionaryValue(); 184 ap->SetString("macAddress", base::StringPrintf("%02d-34-56-78-54-32", i)); 185 ap->SetInteger("signalStrength", start_index + ap_count - i); 186 ap->SetInteger("age", 0); 187 ap->SetInteger("channel", IndexToChannel(i)); 188 ap->SetInteger("signalToNoiseRatio", i + 42); 189 wifi_access_point_list->Append(ap); 190 } 191 } 192 193 static Geoposition CreateReferencePosition(int id) { 194 Geoposition pos; 195 pos.latitude = id; 196 pos.longitude = -(id + 1); 197 pos.altitude = 2 * id; 198 pos.timestamp = base::Time::Now(); 199 return pos; 200 } 201 202 static std::string PrettyJson(const base::Value& value) { 203 std::string pretty; 204 base::JSONWriter::WriteWithOptions( 205 &value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &pretty); 206 return pretty; 207 } 208 209 static testing::AssertionResult JsonGetList( 210 const std::string& field, 211 const base::DictionaryValue& dict, 212 const base::ListValue** output_list) { 213 if (!dict.GetList(field, output_list)) 214 return testing::AssertionFailure() << "Dictionary " << PrettyJson(dict) 215 << " is missing list field " << field; 216 return testing::AssertionSuccess(); 217 } 218 219 static testing::AssertionResult JsonFieldEquals( 220 const std::string& field, 221 const base::DictionaryValue& expected, 222 const base::DictionaryValue& actual) { 223 const base::Value* expected_value; 224 const base::Value* actual_value; 225 if (!expected.Get(field, &expected_value)) 226 return testing::AssertionFailure() 227 << "Expected dictionary " << PrettyJson(expected) 228 << " is missing field " << field; 229 if (!expected.Get(field, &actual_value)) 230 return testing::AssertionFailure() 231 << "Actual dictionary " << PrettyJson(actual) 232 << " is missing field " << field; 233 if (!expected_value->Equals(actual_value)) 234 return testing::AssertionFailure() 235 << "Field " << field << " mismatch: " << PrettyJson(*expected_value) 236 << " != " << PrettyJson(*actual_value); 237 return testing::AssertionSuccess(); 238 } 239 240 static GURL UrlWithoutQuery(const GURL& url) { 241 url_canon::Replacements<char> replacements; 242 replacements.ClearQuery(); 243 return url.ReplaceComponents(replacements); 244 } 245 246 testing::AssertionResult IsTestServerUrl(const GURL& request_url) { 247 const GURL a(UrlWithoutQuery(test_server_url_)); 248 const GURL b(UrlWithoutQuery(request_url)); 249 if (a == b) 250 return testing::AssertionSuccess(); 251 return testing::AssertionFailure() << a << " != " << b; 252 } 253 254 void CheckRequestIsValid(const net::TestURLFetcher& request, 255 int expected_routers, 256 int expected_wifi_aps, 257 int wifi_start_index, 258 const std::string& expected_access_token) { 259 const GURL& request_url = request.GetOriginalURL(); 260 261 EXPECT_TRUE(IsTestServerUrl(request_url)); 262 263 // Check to see that the api key is being appended for the default 264 // network provider url. 265 bool is_default_url = UrlWithoutQuery(request_url) == 266 UrlWithoutQuery(GeolocationArbitratorImpl::DefaultNetworkProviderURL()); 267 EXPECT_EQ(is_default_url, !request_url.query().empty()); 268 269 const std::string& upload_data = request.upload_data(); 270 ASSERT_FALSE(upload_data.empty()); 271 std::string json_parse_error_msg; 272 scoped_ptr<base::Value> parsed_json( 273 base::JSONReader::ReadAndReturnError( 274 upload_data, 275 base::JSON_PARSE_RFC, 276 NULL, 277 &json_parse_error_msg)); 278 EXPECT_TRUE(json_parse_error_msg.empty()); 279 ASSERT_TRUE(parsed_json.get() != NULL); 280 281 const base::DictionaryValue* request_json; 282 ASSERT_TRUE(parsed_json->GetAsDictionary(&request_json)); 283 284 if (!is_default_url) { 285 if (expected_access_token.empty()) 286 ASSERT_FALSE(request_json->HasKey(kAccessTokenString)); 287 else { 288 std::string access_token; 289 EXPECT_TRUE(request_json->GetString(kAccessTokenString, &access_token)); 290 EXPECT_EQ(expected_access_token, access_token); 291 } 292 } 293 294 if (expected_wifi_aps) { 295 base::ListValue expected_wifi_aps_json; 296 CreateReferenceWifiScanDataJson( 297 expected_wifi_aps, 298 wifi_start_index, 299 &expected_wifi_aps_json); 300 EXPECT_EQ(size_t(expected_wifi_aps), expected_wifi_aps_json.GetSize()); 301 302 const base::ListValue* wifi_aps_json; 303 ASSERT_TRUE(JsonGetList("wifiAccessPoints", *request_json, 304 &wifi_aps_json)); 305 for (size_t i = 0; i < expected_wifi_aps_json.GetSize(); ++i ) { 306 const base::DictionaryValue* expected_json; 307 ASSERT_TRUE(expected_wifi_aps_json.GetDictionary(i, &expected_json)); 308 const base::DictionaryValue* actual_json; 309 ASSERT_TRUE(wifi_aps_json->GetDictionary(i, &actual_json)); 310 ASSERT_TRUE(JsonFieldEquals("macAddress", *expected_json, 311 *actual_json)); 312 ASSERT_TRUE(JsonFieldEquals("signalStrength", *expected_json, 313 *actual_json)); 314 ASSERT_TRUE(JsonFieldEquals("channel", *expected_json, *actual_json)); 315 ASSERT_TRUE(JsonFieldEquals("signalToNoiseRatio", *expected_json, 316 *actual_json)); 317 } 318 } else { 319 ASSERT_FALSE(request_json->HasKey("wifiAccessPoints")); 320 } 321 EXPECT_TRUE(request_url.is_valid()); 322 } 323 324 GURL test_server_url_; 325 base::MessageLoop main_message_loop_; 326 scoped_refptr<FakeAccessTokenStore> access_token_store_; 327 net::TestURLFetcherFactory url_fetcher_factory_; 328 scoped_refptr<MockDeviceDataProviderImpl<WifiData> > wifi_data_provider_; 329 }; 330 331 TEST_F(GeolocationNetworkProviderTest, CreateDestroy) { 332 // Test fixture members were SetUp correctly. 333 EXPECT_EQ(&main_message_loop_, base::MessageLoop::current()); 334 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 335 EXPECT_TRUE(NULL != provider.get()); 336 provider.reset(); 337 SUCCEED(); 338 } 339 340 TEST_F(GeolocationNetworkProviderTest, StartProvider) { 341 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 342 EXPECT_TRUE(provider->StartProvider(false)); 343 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 344 ASSERT_TRUE(fetcher != NULL); 345 CheckRequestIsValid(*fetcher, 0, 0, 0, std::string()); 346 } 347 348 TEST_F(GeolocationNetworkProviderTest, StartProviderDefaultUrl) { 349 test_server_url_ = GeolocationArbitratorImpl::DefaultNetworkProviderURL(); 350 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 351 EXPECT_TRUE(provider->StartProvider(false)); 352 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 353 ASSERT_TRUE(fetcher != NULL); 354 CheckRequestIsValid(*fetcher, 0, 0, 0, std::string()); 355 } 356 357 TEST_F(GeolocationNetworkProviderTest, StartProviderLongRequest) { 358 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 359 EXPECT_TRUE(provider->StartProvider(false)); 360 const int kFirstScanAps = 20; 361 wifi_data_provider_->SetData(CreateReferenceWifiScanData(kFirstScanAps)); 362 main_message_loop_.RunUntilIdle(); 363 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 364 ASSERT_TRUE(fetcher != NULL); 365 // The request url should have been shortened to less than 2048 characters 366 // in length by not including access points with the lowest signal strength 367 // in the request. 368 EXPECT_LT(fetcher->GetOriginalURL().spec().size(), size_t(2048)); 369 CheckRequestIsValid(*fetcher, 0, 16, 4, std::string()); 370 } 371 372 TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { 373 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 374 EXPECT_TRUE(provider->StartProvider(false)); 375 376 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 377 ASSERT_TRUE(fetcher != NULL); 378 EXPECT_TRUE(IsTestServerUrl(fetcher->GetOriginalURL())); 379 380 // Complete the network request with bad position fix. 381 const char* kNoFixNetworkResponse = 382 "{" 383 " \"status\": \"ZERO_RESULTS\"" 384 "}"; 385 fetcher->set_url(test_server_url_); 386 fetcher->set_status(net::URLRequestStatus()); 387 fetcher->set_response_code(200); // OK 388 fetcher->SetResponseString(kNoFixNetworkResponse); 389 fetcher->delegate()->OnURLFetchComplete(fetcher); 390 391 Geoposition position; 392 provider->GetPosition(&position); 393 EXPECT_FALSE(position.Validate()); 394 395 // Now wifi data arrives -- SetData will notify listeners. 396 const int kFirstScanAps = 6; 397 wifi_data_provider_->SetData(CreateReferenceWifiScanData(kFirstScanAps)); 398 main_message_loop_.RunUntilIdle(); 399 fetcher = get_url_fetcher_and_advance_id(); 400 ASSERT_TRUE(fetcher != NULL); 401 // The request should have the wifi data. 402 CheckRequestIsValid(*fetcher, 0, kFirstScanAps, 0, std::string()); 403 404 // Send a reply with good position fix. 405 const char* kReferenceNetworkResponse = 406 "{" 407 " \"accessToken\": \"" REFERENCE_ACCESS_TOKEN "\"," 408 " \"accuracy\": 1200.4," 409 " \"location\": {" 410 " \"lat\": 51.0," 411 " \"lng\": -0.1" 412 " }" 413 "}"; 414 fetcher->set_url(test_server_url_); 415 fetcher->set_status(net::URLRequestStatus()); 416 fetcher->set_response_code(200); // OK 417 fetcher->SetResponseString(kReferenceNetworkResponse); 418 fetcher->delegate()->OnURLFetchComplete(fetcher); 419 420 provider->GetPosition(&position); 421 EXPECT_EQ(51.0, position.latitude); 422 EXPECT_EQ(-0.1, position.longitude); 423 EXPECT_EQ(1200.4, position.accuracy); 424 EXPECT_FALSE(position.timestamp.is_null()); 425 EXPECT_TRUE(position.Validate()); 426 427 // Token should be in the store. 428 EXPECT_EQ(UTF8ToUTF16(REFERENCE_ACCESS_TOKEN), 429 access_token_store_->access_token_set_[test_server_url_]); 430 431 // Wifi updated again, with one less AP. This is 'close enough' to the 432 // previous scan, so no new request made. 433 const int kSecondScanAps = kFirstScanAps - 1; 434 wifi_data_provider_->SetData(CreateReferenceWifiScanData(kSecondScanAps)); 435 main_message_loop_.RunUntilIdle(); 436 fetcher = get_url_fetcher_and_advance_id(); 437 EXPECT_FALSE(fetcher); 438 439 provider->GetPosition(&position); 440 EXPECT_EQ(51.0, position.latitude); 441 EXPECT_EQ(-0.1, position.longitude); 442 EXPECT_TRUE(position.Validate()); 443 444 // Now a third scan with more than twice the original amount -> new request. 445 const int kThirdScanAps = kFirstScanAps * 2 + 1; 446 wifi_data_provider_->SetData(CreateReferenceWifiScanData(kThirdScanAps)); 447 main_message_loop_.RunUntilIdle(); 448 fetcher = get_url_fetcher_and_advance_id(); 449 EXPECT_TRUE(fetcher); 450 CheckRequestIsValid(*fetcher, 0, kThirdScanAps, 0, REFERENCE_ACCESS_TOKEN); 451 // ...reply with a network error. 452 453 fetcher->set_url(test_server_url_); 454 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1)); 455 fetcher->set_response_code(200); // should be ignored 456 fetcher->SetResponseString(std::string()); 457 fetcher->delegate()->OnURLFetchComplete(fetcher); 458 459 // Error means we now no longer have a fix. 460 provider->GetPosition(&position); 461 EXPECT_FALSE(position.Validate()); 462 463 // Wifi scan returns to original set: should be serviced from cache. 464 wifi_data_provider_->SetData(CreateReferenceWifiScanData(kFirstScanAps)); 465 main_message_loop_.RunUntilIdle(); 466 EXPECT_FALSE(get_url_fetcher_and_advance_id()); // No new request created. 467 468 provider->GetPosition(&position); 469 EXPECT_EQ(51.0, position.latitude); 470 EXPECT_EQ(-0.1, position.longitude); 471 EXPECT_TRUE(position.Validate()); 472 } 473 474 TEST_F(GeolocationNetworkProviderTest, NoRequestOnStartupUntilWifiData) { 475 MessageLoopQuitListener listener; 476 wifi_data_provider_->set_got_data(false); 477 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 478 EXPECT_TRUE(provider->StartProvider(false)); 479 480 provider->SetUpdateCallback( 481 base::Bind(&MessageLoopQuitListener::LocationUpdateAvailable, 482 base::Unretained(&listener))); 483 484 main_message_loop_.RunUntilIdle(); 485 EXPECT_FALSE(get_url_fetcher_and_advance_id()) 486 << "Network request should not be created right away on startup when " 487 "wifi data has not yet arrived"; 488 489 wifi_data_provider_->SetData(CreateReferenceWifiScanData(1)); 490 main_message_loop_.RunUntilIdle(); 491 EXPECT_TRUE(get_url_fetcher_and_advance_id()); 492 } 493 494 TEST_F(GeolocationNetworkProviderTest, NewDataReplacesExistingNetworkRequest) { 495 // Send initial request with empty device data 496 scoped_ptr<LocationProvider> provider(CreateProvider(true)); 497 EXPECT_TRUE(provider->StartProvider(false)); 498 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 499 EXPECT_TRUE(fetcher); 500 501 // Now wifi data arrives; new request should be sent. 502 wifi_data_provider_->SetData(CreateReferenceWifiScanData(4)); 503 main_message_loop_.RunUntilIdle(); 504 fetcher = get_url_fetcher_and_advance_id(); 505 EXPECT_TRUE(fetcher); 506 } 507 508 TEST_F(GeolocationNetworkProviderTest, NetworkRequestDeferredForPermission) { 509 scoped_ptr<LocationProvider> provider(CreateProvider(false)); 510 EXPECT_TRUE(provider->StartProvider(false)); 511 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 512 EXPECT_FALSE(fetcher); 513 provider->OnPermissionGranted(); 514 515 fetcher = get_url_fetcher_and_advance_id(); 516 ASSERT_TRUE(fetcher != NULL); 517 518 EXPECT_TRUE(IsTestServerUrl(fetcher->GetOriginalURL())); 519 } 520 521 TEST_F(GeolocationNetworkProviderTest, 522 NetworkRequestWithWifiDataDeferredForPermission) { 523 access_token_store_->access_token_set_[test_server_url_] = 524 UTF8ToUTF16(REFERENCE_ACCESS_TOKEN); 525 scoped_ptr<LocationProvider> provider(CreateProvider(false)); 526 EXPECT_TRUE(provider->StartProvider(false)); 527 net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id(); 528 EXPECT_FALSE(fetcher); 529 530 static const int kScanCount = 4; 531 wifi_data_provider_->SetData(CreateReferenceWifiScanData(kScanCount)); 532 main_message_loop_.RunUntilIdle(); 533 534 fetcher = get_url_fetcher_and_advance_id(); 535 EXPECT_FALSE(fetcher); 536 537 provider->OnPermissionGranted(); 538 539 fetcher = get_url_fetcher_and_advance_id(); 540 ASSERT_TRUE(fetcher != NULL); 541 542 CheckRequestIsValid(*fetcher, 0, kScanCount, 0, REFERENCE_ACCESS_TOKEN); 543 } 544 545 TEST_F(GeolocationNetworkProviderTest, NetworkPositionCache) { 546 NetworkLocationProvider::PositionCache cache; 547 548 const int kCacheSize = NetworkLocationProvider::PositionCache::kMaximumSize; 549 for (int i = 1; i < kCacheSize * 2 + 1; ++i) { 550 Geoposition pos = CreateReferencePosition(i); 551 bool ret = cache.CachePosition(CreateReferenceWifiScanData(i), pos); 552 EXPECT_TRUE(ret) << i; 553 const Geoposition* item = 554 cache.FindPosition(CreateReferenceWifiScanData(i)); 555 ASSERT_TRUE(item) << i; 556 EXPECT_EQ(pos.latitude, item->latitude) << i; 557 EXPECT_EQ(pos.longitude, item->longitude) << i; 558 if (i <= kCacheSize) { 559 // Nothing should have spilled yet; check oldest item is still there. 560 EXPECT_TRUE(cache.FindPosition(CreateReferenceWifiScanData(1))); 561 } else { 562 const int evicted = i - kCacheSize; 563 EXPECT_FALSE(cache.FindPosition(CreateReferenceWifiScanData(evicted))); 564 EXPECT_TRUE(cache.FindPosition(CreateReferenceWifiScanData(evicted + 1))); 565 } 566 } 567 } 568 569 } // namespace content 570