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 "content/browser/browser_thread_impl.h"
      6 #include "content/browser/geolocation/gps_location_provider_linux.h"
      7 #include "testing/gtest/include/gtest/gtest.h"
      8 
      9 #include "base/bind.h"
     10 
     11 namespace content {
     12 
     13 class MockLibGps : public LibGps {
     14  public:
     15   MockLibGps();
     16   virtual ~MockLibGps();
     17 
     18   virtual bool GetPositionIfFixed(Geoposition* position) OVERRIDE {
     19     CHECK(position);
     20     ++get_position_calls_;
     21     *position = get_position_;
     22     return get_position_ret_;
     23   }
     24 
     25   static int gps_open_stub(const char*, const char*, struct gps_data_t*) {
     26     CHECK(g_instance_);
     27     g_instance_->gps_open_calls_++;
     28     return g_instance_->gps_open_ret_;
     29   }
     30 
     31   static int gps_close_stub(struct gps_data_t*) {
     32     return 0;
     33   }
     34 
     35   static int gps_read_stub(struct gps_data_t*) {
     36     CHECK(g_instance_);
     37     g_instance_->gps_read_calls_++;
     38     return g_instance_->gps_read_ret_;
     39   }
     40 
     41   int get_position_calls_;
     42   bool get_position_ret_;
     43   int gps_open_calls_;
     44   int gps_open_ret_;
     45   int gps_read_calls_;
     46   int gps_read_ret_;
     47   Geoposition get_position_;
     48   static MockLibGps* g_instance_;
     49 };
     50 
     51 class GeolocationGpsProviderLinuxTests : public testing::Test {
     52  public:
     53   GeolocationGpsProviderLinuxTests();
     54   virtual ~GeolocationGpsProviderLinuxTests();
     55 
     56   static LibGps* NewMockLibGps() {
     57     return new MockLibGps();
     58   }
     59   static LibGps* NoLibGpsFactory() {
     60     return NULL;
     61   }
     62 
     63  protected:
     64   base::MessageLoop message_loop_;
     65   BrowserThreadImpl ui_thread_;
     66   scoped_ptr<LocationProvider> provider_;
     67 };
     68 
     69 void CheckValidPosition(const Geoposition& expected,
     70                         const Geoposition& actual) {
     71   EXPECT_TRUE(actual.Validate());
     72   EXPECT_DOUBLE_EQ(expected.latitude, actual.latitude);
     73   EXPECT_DOUBLE_EQ(expected.longitude, actual.longitude);
     74   EXPECT_DOUBLE_EQ(expected.accuracy, actual.accuracy);
     75 }
     76 
     77 void QuitMessageLoopAfterUpdate(const LocationProvider* provider,
     78                                 const Geoposition& position) {
     79   base::MessageLoop::current()->Quit();
     80 }
     81 
     82 MockLibGps* MockLibGps::g_instance_ = NULL;
     83 
     84 MockLibGps::MockLibGps()
     85     : get_position_calls_(0),
     86       get_position_ret_(true),
     87       gps_open_calls_(0),
     88       gps_open_ret_(0),
     89       gps_read_calls_(0),
     90       gps_read_ret_(0) {
     91   get_position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
     92   EXPECT_FALSE(g_instance_);
     93   g_instance_ = this;
     94 #if defined(USE_LIBGPS)
     95   libgps_loader_.gps_open = gps_open_stub;
     96   libgps_loader_.gps_close = gps_close_stub;
     97   libgps_loader_.gps_read = gps_read_stub;
     98 #endif  // defined(USE_LIBGPS)
     99 }
    100 
    101 MockLibGps::~MockLibGps() {
    102   EXPECT_EQ(this, g_instance_);
    103   g_instance_ = NULL;
    104 }
    105 
    106 GeolocationGpsProviderLinuxTests::GeolocationGpsProviderLinuxTests()
    107     : ui_thread_(BrowserThread::IO, &message_loop_),
    108       provider_(new GpsLocationProviderLinux(NewMockLibGps)) {
    109   provider_->SetUpdateCallback(base::Bind(&QuitMessageLoopAfterUpdate));
    110 }
    111 
    112 GeolocationGpsProviderLinuxTests::~GeolocationGpsProviderLinuxTests() {
    113 }
    114 
    115 TEST_F(GeolocationGpsProviderLinuxTests, NoLibGpsInstalled) {
    116   provider_.reset(new GpsLocationProviderLinux(NoLibGpsFactory));
    117   ASSERT_TRUE(provider_.get());
    118   const bool ok = provider_->StartProvider(true);
    119   EXPECT_FALSE(ok);
    120   Geoposition position;
    121   provider_->GetPosition(&position);
    122   EXPECT_FALSE(position.Validate());
    123   EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code);
    124 }
    125 
    126 #if defined(OS_CHROMEOS)
    127 
    128 TEST_F(GeolocationGpsProviderLinuxTests, GetPosition) {
    129   ASSERT_TRUE(provider_.get());
    130   const bool ok = provider_->StartProvider(true);
    131   EXPECT_TRUE(ok);
    132   ASSERT_TRUE(MockLibGps::g_instance_);
    133   EXPECT_EQ(0, MockLibGps::g_instance_->get_position_calls_);
    134   EXPECT_EQ(0, MockLibGps::g_instance_->gps_open_calls_);
    135   EXPECT_EQ(0, MockLibGps::g_instance_->gps_read_calls_);
    136   Geoposition position;
    137   provider_->GetPosition(&position);
    138   EXPECT_FALSE(position.Validate());
    139   EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code);
    140   MockLibGps::g_instance_->get_position_.error_code =
    141       Geoposition::ERROR_CODE_NONE;
    142   MockLibGps::g_instance_->get_position_.latitude = 4.5;
    143   MockLibGps::g_instance_->get_position_.longitude = -34.1;
    144   MockLibGps::g_instance_->get_position_.accuracy = 345;
    145   MockLibGps::g_instance_->get_position_.timestamp =
    146       base::Time::FromDoubleT(200);
    147   EXPECT_TRUE(MockLibGps::g_instance_->get_position_.Validate());
    148   base::MessageLoop::current()->Run();
    149   EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_);
    150   EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_);
    151   EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_);
    152   provider_->GetPosition(&position);
    153   CheckValidPosition(MockLibGps::g_instance_->get_position_, position);
    154 
    155   // Movement. This will block for up to half a second.
    156   MockLibGps::g_instance_->get_position_.latitude += 0.01;
    157   base::MessageLoop::current()->Run();
    158   provider_->GetPosition(&position);
    159   EXPECT_EQ(2, MockLibGps::g_instance_->get_position_calls_);
    160   EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_);
    161   EXPECT_EQ(2, MockLibGps::g_instance_->gps_read_calls_);
    162   CheckValidPosition(MockLibGps::g_instance_->get_position_, position);
    163 }
    164 
    165 void EnableGpsOpenCallback() {
    166   CHECK(MockLibGps::g_instance_);
    167   MockLibGps::g_instance_->gps_open_ret_ = 0;
    168 }
    169 
    170 TEST_F(GeolocationGpsProviderLinuxTests, LibGpsReconnect) {
    171   // Setup gpsd reconnect interval to be 1000ms to speed up test.
    172   GpsLocationProviderLinux* gps_provider =
    173       static_cast<GpsLocationProviderLinux*>(provider_.get());
    174   gps_provider->SetGpsdReconnectIntervalMillis(1000);
    175   gps_provider->SetPollPeriodMovingMillis(200);
    176   const bool ok = provider_->StartProvider(true);
    177   EXPECT_TRUE(ok);
    178   ASSERT_TRUE(MockLibGps::g_instance_);
    179   // Let gps_open() fails, and so will LibGps::Start().
    180   // Reconnect will happen in 1000ms.
    181   MockLibGps::g_instance_->gps_open_ret_ = 1;
    182   Geoposition position;
    183   MockLibGps::g_instance_->get_position_.error_code =
    184       Geoposition::ERROR_CODE_NONE;
    185   MockLibGps::g_instance_->get_position_.latitude = 4.5;
    186   MockLibGps::g_instance_->get_position_.longitude = -34.1;
    187   MockLibGps::g_instance_->get_position_.accuracy = 345;
    188   MockLibGps::g_instance_->get_position_.timestamp =
    189       base::Time::FromDoubleT(200);
    190   EXPECT_TRUE(MockLibGps::g_instance_->get_position_.Validate());
    191   // This task makes gps_open() and LibGps::Start() to succeed after
    192   // 1500ms.
    193   base::MessageLoop::current()->PostDelayedTask(
    194       FROM_HERE,
    195       base::Bind(&EnableGpsOpenCallback),
    196       base::TimeDelta::FromMilliseconds(1500));
    197   base::MessageLoop::current()->Run();
    198   provider_->GetPosition(&position);
    199   EXPECT_TRUE(position.Validate());
    200   // 3 gps_open() calls are expected (2 failures and 1 success)
    201   EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_);
    202   EXPECT_EQ(3, MockLibGps::g_instance_->gps_open_calls_);
    203   EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_);
    204 }
    205 
    206 #endif  // #if defined(OS_CHROMEOS)
    207 
    208 }  // namespace content
    209