123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "device/gamepad/xbox_hid_controller.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/memory/raw_ptr.h"
- #include "base/memory/weak_ptr.h"
- #include "base/run_loop.h"
- #include "base/test/task_environment.h"
- #include "device/gamepad/hid_writer.h"
- #include "device/gamepad/public/mojom/gamepad.mojom.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace device {
- namespace {
- constexpr size_t kReportLength = 9;
- constexpr uint8_t kStopVibration[] = {0x03, // report ID
- 0x03, 0x00, 0x00,
- 0x00, // strong magnitude
- 0x00, // weak magnitude
- 0xff, 0x00, 0x01};
- static_assert(sizeof(kStopVibration) == kReportLength,
- "kStopVibration has incorrect size");
- constexpr uint8_t kStartVibration[] = {0x03, // report ID
- 0x03, 0x00, 0x00,
- 0xff, // strong magnitude
- 0x7f, // weak magnitude
- 0xff, 0x00, 0x01};
- static_assert(sizeof(kStartVibration) == kReportLength,
- "kStartVibration has incorrect size");
- // Use 1 ms for all non-zero effect durations. There is no reason to test longer
- // delays as they will be skipped anyway.
- constexpr double kDurationMillis = 1.0;
- // Setting |start_delay| to zero can cause additional reports to be sent.
- constexpr double kZeroStartDelayMillis = 0.0;
- // Vibration magnitudes for the strong and weak channels of a typical
- // dual-rumble vibration effect. kStartVibrationData describes a report with
- // these magnitudes.
- constexpr double kStrongMagnitude = 1.0; // 100% intensity
- constexpr double kWeakMagnitude = 0.5; // 50% intensity
- constexpr base::TimeDelta kPendingTaskDuration =
- base::Milliseconds(kDurationMillis);
- class FakeHidWriter : public HidWriter {
- public:
- FakeHidWriter() = default;
- ~FakeHidWriter() override = default;
- // HidWriter implementation.
- size_t WriteOutputReport(base::span<const uint8_t> report) override {
- output_reports.emplace_back(report.begin(), report.end());
- return report.size_bytes();
- }
- std::vector<std::vector<uint8_t>> output_reports;
- };
- // Main test fixture
- class XboxHidControllerTest : public testing::Test {
- public:
- XboxHidControllerTest()
- : start_vibration_report_(kStartVibration,
- kStartVibration + kReportLength),
- stop_vibration_report_(kStopVibration, kStopVibration + kReportLength),
- callback_count_(0),
- callback_result_(
- mojom::GamepadHapticsResult::GamepadHapticsResultError) {
- auto fake_hid_writer = std::make_unique<FakeHidWriter>();
- fake_hid_writer_ = fake_hid_writer.get();
- gamepad_ = std::make_unique<XboxHidController>(std::move(fake_hid_writer));
- }
- XboxHidControllerTest(const XboxHidControllerTest&) = delete;
- XboxHidControllerTest& operator=(const XboxHidControllerTest&) = delete;
- void TearDown() override { gamepad_->Shutdown(); }
- void PostPlayEffect(
- double start_delay,
- double strong_magnitude,
- double weak_magnitude,
- mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
- gamepad_->PlayEffect(
- mojom::GamepadHapticEffectType::GamepadHapticEffectTypeDualRumble,
- mojom::GamepadEffectParameters::New(
- kDurationMillis, start_delay, strong_magnitude, weak_magnitude,
- /*left_trigger=*/0, /*right_trigger=*/0),
- std::move(callback), base::ThreadTaskRunnerHandle::Get());
- }
- void PostResetVibration(
- mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
- gamepad_->ResetVibration(std::move(callback),
- base::ThreadTaskRunnerHandle::Get());
- }
- // Callback for PlayEffect or ResetVibration.
- void Callback(mojom::GamepadHapticsResult result) {
- callback_count_++;
- callback_result_ = result;
- }
- const std::vector<uint8_t> start_vibration_report_;
- const std::vector<uint8_t> stop_vibration_report_;
- int callback_count_;
- mojom::GamepadHapticsResult callback_result_;
- raw_ptr<FakeHidWriter> fake_hid_writer_;
- std::unique_ptr<XboxHidController> gamepad_;
- base::test::TaskEnvironment task_environment_{
- base::test::TaskEnvironment::TimeSource::MOCK_TIME};
- };
- TEST_F(XboxHidControllerTest, PlayEffect) {
- EXPECT_TRUE(fake_hid_writer_->output_reports.empty());
- EXPECT_EQ(0, callback_count_);
- PostPlayEffect(
- kZeroStartDelayMillis, kStrongMagnitude, kWeakMagnitude,
- base::BindOnce(&XboxHidControllerTest::Callback, base::Unretained(this)));
- // Run the queued task and start vibration.
- task_environment_.RunUntilIdle();
- EXPECT_THAT(fake_hid_writer_->output_reports,
- testing::ElementsAre(start_vibration_report_));
- EXPECT_EQ(0, callback_count_);
- EXPECT_LT(0U, task_environment_.GetPendingMainThreadTaskCount());
- // Finish the effect.
- task_environment_.FastForwardBy(kPendingTaskDuration);
- EXPECT_THAT(fake_hid_writer_->output_reports,
- testing::ElementsAre(start_vibration_report_));
- EXPECT_EQ(1, callback_count_);
- EXPECT_EQ(mojom::GamepadHapticsResult::GamepadHapticsResultComplete,
- callback_result_);
- EXPECT_EQ(0U, task_environment_.GetPendingMainThreadTaskCount());
- }
- TEST_F(XboxHidControllerTest, ResetVibration) {
- EXPECT_TRUE(fake_hid_writer_->output_reports.empty());
- EXPECT_EQ(0, callback_count_);
- PostResetVibration(
- base::BindOnce(&XboxHidControllerTest::Callback, base::Unretained(this)));
- // Run the queued task and reset vibration.
- task_environment_.RunUntilIdle();
- EXPECT_THAT(fake_hid_writer_->output_reports,
- testing::ElementsAre(stop_vibration_report_));
- EXPECT_EQ(1, callback_count_);
- EXPECT_EQ(mojom::GamepadHapticsResult::GamepadHapticsResultComplete,
- callback_result_);
- EXPECT_EQ(0U, task_environment_.GetPendingMainThreadTaskCount());
- }
- } // namespace
- } // namespace device
|