Home | History | Annotate | Download | only in gamepad
      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/memory/scoped_ptr.h"
      6 #include "base/memory/weak_ptr.h"
      7 #include "content/browser/gamepad/gamepad_data_fetcher.h"
      8 #include "content/browser/gamepad/gamepad_provider.h"
      9 #include "content/browser/gamepad/gamepad_test_helpers.h"
     10 #include "content/common/gamepad_hardware_buffer.h"
     11 #include "content/common/gamepad_messages.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace content {
     15 
     16 namespace {
     17 
     18 using WebKit::WebGamepads;
     19 
     20 // Helper class to generate and record user gesture callbacks.
     21 class UserGestureListener {
     22  public:
     23   UserGestureListener()
     24       : weak_factory_(this),
     25         has_user_gesture_(false) {
     26   }
     27 
     28   base::Closure GetClosure() {
     29     return base::Bind(&UserGestureListener::GotUserGesture,
     30                       weak_factory_.GetWeakPtr());
     31   }
     32 
     33   bool has_user_gesture() const { return has_user_gesture_; }
     34 
     35  private:
     36   void GotUserGesture() {
     37     has_user_gesture_ = true;
     38   }
     39 
     40   base::WeakPtrFactory<UserGestureListener> weak_factory_;
     41   bool has_user_gesture_;
     42 };
     43 
     44 // Main test fixture
     45 class GamepadProviderTest : public testing::Test, public GamepadTestHelper {
     46  public:
     47   GamepadProvider* CreateProvider(const WebGamepads& test_data) {
     48     mock_data_fetcher_ = new MockGamepadDataFetcher(test_data);
     49     provider_.reset(new GamepadProvider(
     50         scoped_ptr<GamepadDataFetcher>(mock_data_fetcher_)));
     51     return provider_.get();
     52   }
     53 
     54  protected:
     55   GamepadProviderTest() {
     56   }
     57 
     58   scoped_ptr<GamepadProvider> provider_;
     59 
     60   // Pointer owned by the provider.
     61   MockGamepadDataFetcher* mock_data_fetcher_;
     62 
     63   DISALLOW_COPY_AND_ASSIGN(GamepadProviderTest);
     64 };
     65 
     66 // Crashes. http://crbug.com/106163
     67 TEST_F(GamepadProviderTest, PollingAccess) {
     68   WebGamepads test_data;
     69   test_data.length = 1;
     70   test_data.items[0].connected = true;
     71   test_data.items[0].timestamp = 0;
     72   test_data.items[0].buttonsLength = 1;
     73   test_data.items[0].axesLength = 2;
     74   test_data.items[0].buttons[0] = 1.f;
     75   test_data.items[0].axes[0] = -1.f;
     76   test_data.items[0].axes[1] = .5f;
     77 
     78   GamepadProvider* provider = CreateProvider(test_data);
     79   provider->Resume();
     80 
     81   message_loop().RunUntilIdle();
     82 
     83   mock_data_fetcher_->WaitForDataRead();
     84 
     85   // Renderer-side, pull data out of poll buffer.
     86   base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
     87       base::GetCurrentProcessHandle());
     88   scoped_ptr<base::SharedMemory> shared_memory(
     89       new base::SharedMemory(handle, true));
     90   EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer)));
     91   void* mem = shared_memory->memory();
     92 
     93   GamepadHardwareBuffer* hwbuf = static_cast<GamepadHardwareBuffer*>(mem);
     94   // See gamepad_hardware_buffer.h for details on the read discipline.
     95   WebGamepads output;
     96 
     97   base::subtle::Atomic32 version;
     98   do {
     99     version = hwbuf->sequence.ReadBegin();
    100     memcpy(&output, &hwbuf->buffer, sizeof(output));
    101   } while (hwbuf->sequence.ReadRetry(version));
    102 
    103   EXPECT_EQ(1u, output.length);
    104   EXPECT_EQ(1u, output.items[0].buttonsLength);
    105   EXPECT_EQ(1.f, output.items[0].buttons[0]);
    106   EXPECT_EQ(2u, output.items[0].axesLength);
    107   EXPECT_EQ(-1.f, output.items[0].axes[0]);
    108   EXPECT_EQ(0.5f, output.items[0].axes[1]);
    109 }
    110 
    111 // Tests that waiting for a user gesture works properly.
    112 TEST_F(GamepadProviderTest, UserGesture) {
    113   WebGamepads no_button_data;
    114   no_button_data.length = 1;
    115   no_button_data.items[0].connected = true;
    116   no_button_data.items[0].timestamp = 0;
    117   no_button_data.items[0].buttonsLength = 1;
    118   no_button_data.items[0].axesLength = 2;
    119   no_button_data.items[0].buttons[0] = 0.f;
    120   no_button_data.items[0].axes[0] = -1.f;
    121   no_button_data.items[0].axes[1] = .5f;
    122 
    123   WebGamepads button_down_data = no_button_data;
    124   button_down_data.items[0].buttons[0] = 1.f;
    125 
    126   UserGestureListener listener;
    127   GamepadProvider* provider = CreateProvider(no_button_data);
    128   provider->Resume();
    129 
    130   // Register for a user gesture and make sure the provider reads it twice
    131   // see below for why).
    132   provider->RegisterForUserGesture(listener.GetClosure());
    133   mock_data_fetcher_->WaitForDataRead();
    134   mock_data_fetcher_->WaitForDataRead();
    135 
    136   // It should not have issued our callback.
    137   message_loop().RunUntilIdle();
    138   EXPECT_FALSE(listener.has_user_gesture());
    139 
    140   // Set a button down and wait for it to be read twice.
    141   //
    142   // We wait for two reads before calling RunAllPending because the provider
    143   // will read the data on the background thread (setting the event) and *then*
    144   // will issue the callback on our thread. Waiting for it to read twice
    145   // ensures that it was able to issue callbacks for the first read (if it
    146   // issued one) before we try to check for it.
    147   mock_data_fetcher_->SetTestData(button_down_data);
    148   mock_data_fetcher_->WaitForDataRead();
    149   mock_data_fetcher_->WaitForDataRead();
    150 
    151   // It should have issued our callback.
    152   message_loop().RunUntilIdle();
    153   EXPECT_TRUE(listener.has_user_gesture());
    154 }
    155 
    156 }  // namespace
    157 
    158 }  // namespace content
    159