Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
|
reveman
2017/05/31 22:42:23
why would we just be testing the joydev version? d
jkwang
2017/06/01 19:43:15
I have added test for device connect/disconnect.
M
| |
| 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 "components/exo/gaming_seat_joydev.h" | |
| 6 #include "ash/shell.h" | |
| 7 #include "base/command_line.h" | |
| 8 #include "base/run_loop.h" | |
| 9 #include "base/test/test_simple_task_runner.h" | |
| 10 #include "components/exo/buffer.h" | |
| 11 #include "components/exo/gamepad_delegate.h" | |
| 12 #include "components/exo/gaming_seat_delegate.h" | |
| 13 #include "components/exo/shell_surface.h" | |
| 14 #include "components/exo/surface.h" | |
| 15 #include "components/exo/test/exo_test_base.h" | |
| 16 #include "components/exo/test/exo_test_helper.h" | |
| 17 #include "device/gamepad/gamepad_test_helpers.h" | |
| 18 #include "testing/gmock/include/gmock/gmock.h" | |
| 19 #include "testing/gtest/include/gtest/gtest.h" | |
| 20 #include "ui/aura/client/focus_client.h" | |
| 21 | |
| 22 namespace exo { | |
| 23 namespace { | |
| 24 | |
| 25 class MockGamingSeatDelegate : public GamingSeatDelegate { | |
| 26 public: | |
| 27 MOCK_CONST_METHOD1(CanAcceptGamepadEventsForSurface, bool(Surface*)); | |
| 28 MOCK_METHOD0(GamepadAdded, GamepadDelegate*()); | |
| 29 MOCK_METHOD0(Die, void()); | |
| 30 void OnGamingSeatDestroying(GamingSeat*) override { delete this; }; | |
| 31 ~MockGamingSeatDelegate() { Die(); }; | |
| 32 }; | |
| 33 | |
| 34 class MockGamepadDelegate : public GamepadDelegate { | |
| 35 public: | |
| 36 MockGamepadDelegate() {} | |
| 37 | |
| 38 // Overridden from GamepadDelegate: | |
| 39 MOCK_METHOD0(OnRemoved, void()); | |
| 40 MOCK_METHOD2(OnAxis, void(int, double)); | |
| 41 MOCK_METHOD3(OnButton, void(int, bool, double)); | |
| 42 MOCK_METHOD0(OnFrame, void()); | |
| 43 }; | |
| 44 | |
| 45 class GamingSeatJoydevTest : public test::ExoTestBase { | |
| 46 public: | |
| 47 GamingSeatJoydevTest() {} | |
| 48 | |
| 49 std::unique_ptr<device::GamepadDataFetcher> MockDataFetcherFactory() { | |
| 50 device::Gamepads initial_data; | |
| 51 std::unique_ptr<device::MockGamepadDataFetcher> fetcher( | |
| 52 new device::MockGamepadDataFetcher(initial_data)); | |
| 53 mock_data_fetcher_ = fetcher.get(); | |
| 54 return std::move(fetcher); | |
| 55 } | |
| 56 | |
| 57 void InitializeGamingSeat(MockGamingSeatDelegate* delegate) { | |
| 58 polling_task_runner_ = new base::TestSimpleTaskRunner(); | |
| 59 gaming_seat_.reset(new GamingSeatJoydev( | |
| 60 delegate, polling_task_runner_.get(), | |
| 61 base::Bind(&GamingSeatJoydevTest::MockDataFetcherFactory, | |
| 62 base::Unretained(this)))); | |
| 63 // Run the polling task runner to have it create the data fetcher. | |
| 64 polling_task_runner_->RunPendingTasks(); | |
| 65 } | |
| 66 | |
| 67 void DestroyGamingSeat(MockGamingSeatDelegate* delegate) { | |
| 68 EXPECT_CALL(*delegate, Die()).Times(1); | |
| 69 mock_data_fetcher_ = nullptr; | |
| 70 gaming_seat_.reset(); | |
| 71 // Process tasks until polling is shut down. | |
| 72 polling_task_runner_->RunPendingTasks(); | |
| 73 polling_task_runner_ = nullptr; | |
| 74 } | |
| 75 | |
| 76 void SetDataAndPostToDelegate(const device::Gamepads& new_data) { | |
| 77 ASSERT_TRUE(mock_data_fetcher_ != nullptr); | |
| 78 mock_data_fetcher_->SetTestData(new_data); | |
| 79 // Run one polling cycle, which will post a task to the origin task runner. | |
| 80 polling_task_runner_->RunPendingTasks(); | |
| 81 // Run origin task runner to invoke delegate. | |
| 82 base::RunLoop().RunUntilIdle(); | |
| 83 } | |
| 84 | |
| 85 protected: | |
| 86 std::unique_ptr<GamingSeatJoydev> gaming_seat_; | |
| 87 | |
| 88 // Task runner to simulate the polling thread. | |
| 89 scoped_refptr<base::TestSimpleTaskRunner> polling_task_runner_; | |
| 90 | |
| 91 // Weak reference to the mock data fetcher provided by MockDataFetcherFactory. | |
| 92 // This instance is valid until both gamepad_ and polling_task_runner_ are | |
| 93 // shut down. | |
| 94 device::MockGamepadDataFetcher* mock_data_fetcher_; | |
| 95 | |
| 96 DISALLOW_COPY_AND_ASSIGN(GamingSeatJoydevTest); | |
| 97 }; | |
| 98 | |
| 99 TEST_F(GamingSeatJoydevTest, ConnectionChange) { | |
| 100 std::unique_ptr<Surface> surface(new Surface); | |
| 101 std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); | |
| 102 gfx::Size buffer_size(10, 10); | |
| 103 std::unique_ptr<Buffer> buffer( | |
| 104 new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); | |
| 105 surface->Attach(buffer.get()); | |
| 106 surface->Commit(); | |
| 107 | |
| 108 testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = | |
| 109 new testing::StrictMock<MockGamingSeatDelegate>(); | |
| 110 EXPECT_CALL(*gaming_seat_delegate, | |
| 111 CanAcceptGamepadEventsForSurface(testing::_)) | |
| 112 .WillOnce(testing::Return(true)); | |
| 113 | |
| 114 InitializeGamingSeat(gaming_seat_delegate); | |
| 115 testing::StrictMock<MockGamepadDelegate> gamepad_delegate0; | |
| 116 testing::StrictMock<MockGamepadDelegate> gamepad_delegate1; | |
| 117 testing::StrictMock<MockGamepadDelegate> gamepad_delegate2; | |
| 118 | |
| 119 { // Test sequence | |
| 120 testing::InSequence s; | |
| 121 // connect gamepad 0 | |
| 122 // connect gamepad 2 | |
| 123 // connect gamepad 1 | |
| 124 EXPECT_CALL(*gaming_seat_delegate, GamepadAdded()) | |
| 125 .WillOnce(testing::Return(&gamepad_delegate0)) | |
| 126 .WillOnce(testing::Return(&gamepad_delegate2)) | |
| 127 .WillOnce(testing::Return(&gamepad_delegate1)); | |
| 128 // disconnect gamepad 1 | |
| 129 EXPECT_CALL(gamepad_delegate1, OnRemoved()).Times(1); | |
| 130 // disconnect other gamepads | |
| 131 EXPECT_CALL(gamepad_delegate0, OnRemoved()).Times(1); | |
| 132 EXPECT_CALL(gamepad_delegate2, OnRemoved()).Times(1); | |
| 133 } | |
| 134 // Gamepad connected. | |
| 135 device::Gamepads gamepad_connected; | |
| 136 gamepad_connected.items[0].connected = true; | |
| 137 gamepad_connected.items[0].timestamp = 1; | |
| 138 SetDataAndPostToDelegate(gamepad_connected); | |
| 139 | |
| 140 gamepad_connected.items[2].connected = true; | |
| 141 gamepad_connected.items[2].timestamp = 1; | |
| 142 SetDataAndPostToDelegate(gamepad_connected); | |
| 143 | |
| 144 gamepad_connected.items[1].connected = true; | |
| 145 gamepad_connected.items[1].timestamp = 1; | |
| 146 SetDataAndPostToDelegate(gamepad_connected); | |
| 147 | |
| 148 // Gamepad 1 is dis connected | |
| 149 gamepad_connected.items[1].connected = false; | |
| 150 gamepad_connected.items[1].timestamp = 2; | |
| 151 | |
| 152 SetDataAndPostToDelegate(gamepad_connected); | |
| 153 | |
| 154 // Gamepad disconnected. | |
| 155 device::Gamepads all_disconnected; | |
| 156 SetDataAndPostToDelegate(all_disconnected); | |
| 157 | |
| 158 DestroyGamingSeat(gaming_seat_delegate); | |
| 159 } | |
| 160 | |
| 161 TEST_F(GamingSeatJoydevTest, OnAxis) { | |
| 162 std::unique_ptr<Surface> surface(new Surface); | |
| 163 std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); | |
| 164 gfx::Size buffer_size(10, 10); | |
| 165 std::unique_ptr<Buffer> buffer( | |
| 166 new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); | |
| 167 surface->Attach(buffer.get()); | |
| 168 surface->Commit(); | |
| 169 | |
| 170 testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = | |
| 171 new testing::StrictMock<MockGamingSeatDelegate>(); | |
| 172 EXPECT_CALL(*gaming_seat_delegate, | |
| 173 CanAcceptGamepadEventsForSurface(testing::_)) | |
| 174 .WillOnce(testing::Return(true)); | |
| 175 | |
| 176 InitializeGamingSeat(gaming_seat_delegate); | |
| 177 testing::StrictMock<MockGamepadDelegate> gamepad_delegate0; | |
| 178 testing::StrictMock<MockGamepadDelegate> gamepad_delegate2; | |
| 179 | |
| 180 // connect gamepad 0 and 2 | |
| 181 EXPECT_CALL(*gaming_seat_delegate, GamepadAdded()) | |
| 182 .WillOnce(testing::Return(&gamepad_delegate0)) | |
| 183 .WillOnce(testing::Return(&gamepad_delegate2)); | |
| 184 | |
| 185 device::Gamepads gamepad_connected; | |
| 186 gamepad_connected.items[0].connected = true; | |
| 187 gamepad_connected.items[0].timestamp = 1; | |
| 188 SetDataAndPostToDelegate(gamepad_connected); | |
| 189 | |
| 190 gamepad_connected.items[2].connected = true; | |
| 191 gamepad_connected.items[2].timestamp = 1; | |
| 192 SetDataAndPostToDelegate(gamepad_connected); | |
| 193 | |
| 194 // send axis event to 2 and then 0 | |
| 195 device::Gamepads axis_moved; | |
| 196 axis_moved.items[0].connected = true; | |
| 197 axis_moved.items[0].timestamp = 1; | |
| 198 axis_moved.items[2].connected = true; | |
| 199 axis_moved.items[2].timestamp = 2; | |
| 200 axis_moved.items[2].axes_length = 1; | |
| 201 axis_moved.items[2].axes[0] = 1.0; | |
| 202 | |
| 203 EXPECT_CALL(gamepad_delegate2, OnAxis(0, 1.0)).Times(1); | |
| 204 EXPECT_CALL(gamepad_delegate2, OnFrame()).Times(1); | |
| 205 SetDataAndPostToDelegate(axis_moved); | |
| 206 | |
| 207 axis_moved.items[0].timestamp = 2; | |
| 208 axis_moved.items[0].axes_length = 1; | |
| 209 axis_moved.items[0].axes[0] = 2.0; | |
| 210 | |
| 211 EXPECT_CALL(gamepad_delegate0, OnAxis(0, 2.0)).Times(1); | |
| 212 EXPECT_CALL(gamepad_delegate0, OnFrame()).Times(1); | |
| 213 SetDataAndPostToDelegate(axis_moved); | |
| 214 | |
| 215 EXPECT_CALL(gamepad_delegate0, OnRemoved()).Times(1); | |
| 216 EXPECT_CALL(gamepad_delegate2, OnRemoved()).Times(1); | |
| 217 DestroyGamingSeat(gaming_seat_delegate); | |
| 218 } | |
| 219 | |
| 220 TEST_F(GamingSeatJoydevTest, OnButton) { | |
| 221 std::unique_ptr<Surface> surface(new Surface); | |
| 222 std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); | |
| 223 gfx::Size buffer_size(10, 10); | |
| 224 std::unique_ptr<Buffer> buffer( | |
| 225 new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); | |
| 226 surface->Attach(buffer.get()); | |
| 227 surface->Commit(); | |
| 228 | |
| 229 testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = | |
| 230 new testing::StrictMock<MockGamingSeatDelegate>(); | |
| 231 EXPECT_CALL(*gaming_seat_delegate, | |
| 232 CanAcceptGamepadEventsForSurface(testing::_)) | |
| 233 .WillOnce(testing::Return(true)); | |
| 234 | |
| 235 InitializeGamingSeat(gaming_seat_delegate); | |
| 236 testing::StrictMock<MockGamepadDelegate> gamepad_delegate0; | |
| 237 testing::StrictMock<MockGamepadDelegate> gamepad_delegate2; | |
| 238 | |
| 239 // connect gamepad 0 and 2 | |
| 240 EXPECT_CALL(*gaming_seat_delegate, GamepadAdded()) | |
| 241 .WillOnce(testing::Return(&gamepad_delegate0)) | |
| 242 .WillOnce(testing::Return(&gamepad_delegate2)); | |
| 243 | |
| 244 device::Gamepads gamepad_connected; | |
| 245 gamepad_connected.items[0].connected = true; | |
| 246 gamepad_connected.items[0].timestamp = 1; | |
| 247 SetDataAndPostToDelegate(gamepad_connected); | |
| 248 | |
| 249 gamepad_connected.items[2].connected = true; | |
| 250 gamepad_connected.items[2].timestamp = 1; | |
| 251 SetDataAndPostToDelegate(gamepad_connected); | |
| 252 | |
| 253 // send axis event to 2 and then 0 | |
| 254 device::Gamepads axis_moved; | |
| 255 axis_moved.items[0].connected = true; | |
| 256 axis_moved.items[0].timestamp = 1; | |
| 257 axis_moved.items[2].connected = true; | |
| 258 axis_moved.items[2].timestamp = 2; | |
| 259 | |
| 260 axis_moved.items[2].buttons_length = 1; | |
| 261 axis_moved.items[2].buttons[0].pressed = true; | |
| 262 axis_moved.items[2].buttons[0].value = 1.0; | |
| 263 | |
| 264 EXPECT_CALL(gamepad_delegate2, OnButton(0, true, 1.0)).Times(1); | |
| 265 EXPECT_CALL(gamepad_delegate2, OnFrame()).Times(1); | |
| 266 SetDataAndPostToDelegate(axis_moved); | |
| 267 | |
| 268 axis_moved.items[0].timestamp = 2; | |
| 269 axis_moved.items[0].buttons_length = 1; | |
| 270 axis_moved.items[0].buttons[0].pressed = true; | |
| 271 axis_moved.items[0].buttons[0].value = 2.0; | |
| 272 | |
| 273 EXPECT_CALL(gamepad_delegate0, OnButton(0, true, 2.0)).Times(1); | |
| 274 EXPECT_CALL(gamepad_delegate0, OnFrame()).Times(1); | |
| 275 SetDataAndPostToDelegate(axis_moved); | |
| 276 | |
| 277 EXPECT_CALL(gamepad_delegate0, OnRemoved()).Times(1); | |
| 278 EXPECT_CALL(gamepad_delegate2, OnRemoved()).Times(1); | |
| 279 | |
| 280 DestroyGamingSeat(gaming_seat_delegate); | |
| 281 } | |
| 282 | |
| 283 TEST_F(GamingSeatJoydevTest, OnWindowFocused) { | |
| 284 // Create surface and move focus to it. | |
| 285 std::unique_ptr<Surface> surface(new Surface); | |
| 286 std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); | |
| 287 gfx::Size buffer_size(10, 10); | |
| 288 std::unique_ptr<Buffer> buffer( | |
| 289 new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); | |
| 290 surface->Attach(buffer.get()); | |
| 291 surface->Commit(); | |
| 292 | |
| 293 testing::StrictMock<MockGamingSeatDelegate>* gaming_seat_delegate = | |
| 294 new testing::StrictMock<MockGamingSeatDelegate>(); | |
| 295 EXPECT_CALL(*gaming_seat_delegate, | |
| 296 CanAcceptGamepadEventsForSurface(testing::_)) | |
| 297 .WillOnce(testing::Return(true)); | |
| 298 | |
| 299 InitializeGamingSeat(gaming_seat_delegate); | |
| 300 | |
| 301 // In focus. Should be polling indefinitely, check a couple of time that the | |
| 302 // poll task is re-posted. | |
| 303 for (size_t i = 0; i < 5; ++i) { | |
| 304 polling_task_runner_->RunPendingTasks(); | |
| 305 ASSERT_TRUE(polling_task_runner_->HasPendingTask()); | |
| 306 } | |
| 307 | |
| 308 // Remove focus from window. | |
| 309 aura::client::FocusClient* focus_client = | |
| 310 aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); | |
| 311 focus_client->FocusWindow(nullptr); | |
| 312 | |
| 313 // Run EnablePolling and OnPoll task, no more polls should be scheduled. | |
| 314 // In the first round of RunPendingTasks we will execute | |
| 315 // EnablePollingOnPollingThread, which will cause the polling to stop being | |
| 316 // scheduled in the next round. | |
| 317 polling_task_runner_->RunPendingTasks(); | |
| 318 polling_task_runner_->RunPendingTasks(); | |
| 319 ASSERT_FALSE(polling_task_runner_->HasPendingTask()); | |
| 320 | |
| 321 DestroyGamingSeat(gaming_seat_delegate); | |
| 322 } | |
| 323 | |
| 324 } // namespace | |
| 325 } // namespace exo | |
| OLD | NEW |