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