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 blink::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].value = 1.f;
     75   test_data.items[0].buttons[0].pressed = true;
     76   test_data.items[0].axes[0] = -1.f;
     77   test_data.items[0].axes[1] = .5f;
     78 
     79   GamepadProvider* provider = CreateProvider(test_data);
     80   provider->Resume();
     81 
     82   message_loop().RunUntilIdle();
     83 
     84   mock_data_fetcher_->WaitForDataRead();
     85 
     86   // Renderer-side, pull data out of poll buffer.
     87   base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
     88       base::GetCurrentProcessHandle());
     89   scoped_ptr<base::SharedMemory> shared_memory(
     90       new base::SharedMemory(handle, true));
     91   EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer)));
     92   void* mem = shared_memory->memory();
     93 
     94   GamepadHardwareBuffer* hwbuf = static_cast<GamepadHardwareBuffer*>(mem);
     95   // See gamepad_hardware_buffer.h for details on the read discipline.
     96   WebGamepads output;
     97 
     98   base::subtle::Atomic32 version;
     99   do {
    100     version = hwbuf->sequence.ReadBegin();
    101     memcpy(&output, &hwbuf->buffer, sizeof(output));
    102   } while (hwbuf->sequence.ReadRetry(version));
    103 
    104   EXPECT_EQ(1u, output.length);
    105   EXPECT_EQ(1u, output.items[0].buttonsLength);
    106   EXPECT_EQ(1.f, output.items[0].buttons[0].value);
    107   EXPECT_EQ(true, output.items[0].buttons[0].pressed);
    108   EXPECT_EQ(2u, output.items[0].axesLength);
    109   EXPECT_EQ(-1.f, output.items[0].axes[0]);
    110   EXPECT_EQ(0.5f, output.items[0].axes[1]);
    111 }
    112 
    113 // Tests that waiting for a user gesture works properly.
    114 TEST_F(GamepadProviderTest, UserGesture) {
    115   WebGamepads no_button_data;
    116   no_button_data.length = 1;
    117   no_button_data.items[0].connected = true;
    118   no_button_data.items[0].timestamp = 0;
    119   no_button_data.items[0].buttonsLength = 1;
    120   no_button_data.items[0].axesLength = 2;
    121   no_button_data.items[0].buttons[0].value = 0.f;
    122   no_button_data.items[0].buttons[0].pressed = false;
    123   no_button_data.items[0].axes[0] = -1.f;
    124   no_button_data.items[0].axes[1] = .5f;
    125 
    126   WebGamepads button_down_data = no_button_data;
    127   button_down_data.items[0].buttons[0].value = 1.f;
    128   button_down_data.items[0].buttons[0].pressed = true;
    129 
    130   UserGestureListener listener;
    131   GamepadProvider* provider = CreateProvider(no_button_data);
    132   provider->Resume();
    133 
    134   // Register for a user gesture and make sure the provider reads it twice
    135   // see below for why).
    136   provider->RegisterForUserGesture(listener.GetClosure());
    137   mock_data_fetcher_->WaitForDataRead();
    138   mock_data_fetcher_->WaitForDataRead();
    139 
    140   // It should not have issued our callback.
    141   message_loop().RunUntilIdle();
    142   EXPECT_FALSE(listener.has_user_gesture());
    143 
    144   // Set a button down and wait for it to be read twice.
    145   //
    146   // We wait for two reads before calling RunAllPending because the provider
    147   // will read the data on the background thread (setting the event) and *then*
    148   // will issue the callback on our thread. Waiting for it to read twice
    149   // ensures that it was able to issue callbacks for the first read (if it
    150   // issued one) before we try to check for it.
    151   mock_data_fetcher_->SetTestData(button_down_data);
    152   mock_data_fetcher_->WaitForDataRead();
    153   mock_data_fetcher_->WaitForDataRead();
    154 
    155   // It should have issued our callback.
    156   message_loop().RunUntilIdle();
    157   EXPECT_TRUE(listener.has_user_gesture());
    158 }
    159 
    160 }  // namespace
    161 
    162 }  // namespace content
    163