xbox_hid_controller_unittest.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright 2019 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. #include "device/gamepad/xbox_hid_controller.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/memory/weak_ptr.h"
  9. #include "base/run_loop.h"
  10. #include "base/test/task_environment.h"
  11. #include "device/gamepad/hid_writer.h"
  12. #include "device/gamepad/public/mojom/gamepad.mojom.h"
  13. #include "testing/gmock/include/gmock/gmock.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. namespace device {
  16. namespace {
  17. constexpr size_t kReportLength = 9;
  18. constexpr uint8_t kStopVibration[] = {0x03, // report ID
  19. 0x03, 0x00, 0x00,
  20. 0x00, // strong magnitude
  21. 0x00, // weak magnitude
  22. 0xff, 0x00, 0x01};
  23. static_assert(sizeof(kStopVibration) == kReportLength,
  24. "kStopVibration has incorrect size");
  25. constexpr uint8_t kStartVibration[] = {0x03, // report ID
  26. 0x03, 0x00, 0x00,
  27. 0xff, // strong magnitude
  28. 0x7f, // weak magnitude
  29. 0xff, 0x00, 0x01};
  30. static_assert(sizeof(kStartVibration) == kReportLength,
  31. "kStartVibration has incorrect size");
  32. // Use 1 ms for all non-zero effect durations. There is no reason to test longer
  33. // delays as they will be skipped anyway.
  34. constexpr double kDurationMillis = 1.0;
  35. // Setting |start_delay| to zero can cause additional reports to be sent.
  36. constexpr double kZeroStartDelayMillis = 0.0;
  37. // Vibration magnitudes for the strong and weak channels of a typical
  38. // dual-rumble vibration effect. kStartVibrationData describes a report with
  39. // these magnitudes.
  40. constexpr double kStrongMagnitude = 1.0; // 100% intensity
  41. constexpr double kWeakMagnitude = 0.5; // 50% intensity
  42. constexpr base::TimeDelta kPendingTaskDuration =
  43. base::Milliseconds(kDurationMillis);
  44. class FakeHidWriter : public HidWriter {
  45. public:
  46. FakeHidWriter() = default;
  47. ~FakeHidWriter() override = default;
  48. // HidWriter implementation.
  49. size_t WriteOutputReport(base::span<const uint8_t> report) override {
  50. output_reports.emplace_back(report.begin(), report.end());
  51. return report.size_bytes();
  52. }
  53. std::vector<std::vector<uint8_t>> output_reports;
  54. };
  55. // Main test fixture
  56. class XboxHidControllerTest : public testing::Test {
  57. public:
  58. XboxHidControllerTest()
  59. : start_vibration_report_(kStartVibration,
  60. kStartVibration + kReportLength),
  61. stop_vibration_report_(kStopVibration, kStopVibration + kReportLength),
  62. callback_count_(0),
  63. callback_result_(
  64. mojom::GamepadHapticsResult::GamepadHapticsResultError) {
  65. auto fake_hid_writer = std::make_unique<FakeHidWriter>();
  66. fake_hid_writer_ = fake_hid_writer.get();
  67. gamepad_ = std::make_unique<XboxHidController>(std::move(fake_hid_writer));
  68. }
  69. XboxHidControllerTest(const XboxHidControllerTest&) = delete;
  70. XboxHidControllerTest& operator=(const XboxHidControllerTest&) = delete;
  71. void TearDown() override { gamepad_->Shutdown(); }
  72. void PostPlayEffect(
  73. double start_delay,
  74. double strong_magnitude,
  75. double weak_magnitude,
  76. mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
  77. gamepad_->PlayEffect(
  78. mojom::GamepadHapticEffectType::GamepadHapticEffectTypeDualRumble,
  79. mojom::GamepadEffectParameters::New(
  80. kDurationMillis, start_delay, strong_magnitude, weak_magnitude,
  81. /*left_trigger=*/0, /*right_trigger=*/0),
  82. std::move(callback), base::ThreadTaskRunnerHandle::Get());
  83. }
  84. void PostResetVibration(
  85. mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
  86. gamepad_->ResetVibration(std::move(callback),
  87. base::ThreadTaskRunnerHandle::Get());
  88. }
  89. // Callback for PlayEffect or ResetVibration.
  90. void Callback(mojom::GamepadHapticsResult result) {
  91. callback_count_++;
  92. callback_result_ = result;
  93. }
  94. const std::vector<uint8_t> start_vibration_report_;
  95. const std::vector<uint8_t> stop_vibration_report_;
  96. int callback_count_;
  97. mojom::GamepadHapticsResult callback_result_;
  98. raw_ptr<FakeHidWriter> fake_hid_writer_;
  99. std::unique_ptr<XboxHidController> gamepad_;
  100. base::test::TaskEnvironment task_environment_{
  101. base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  102. };
  103. TEST_F(XboxHidControllerTest, PlayEffect) {
  104. EXPECT_TRUE(fake_hid_writer_->output_reports.empty());
  105. EXPECT_EQ(0, callback_count_);
  106. PostPlayEffect(
  107. kZeroStartDelayMillis, kStrongMagnitude, kWeakMagnitude,
  108. base::BindOnce(&XboxHidControllerTest::Callback, base::Unretained(this)));
  109. // Run the queued task and start vibration.
  110. task_environment_.RunUntilIdle();
  111. EXPECT_THAT(fake_hid_writer_->output_reports,
  112. testing::ElementsAre(start_vibration_report_));
  113. EXPECT_EQ(0, callback_count_);
  114. EXPECT_LT(0U, task_environment_.GetPendingMainThreadTaskCount());
  115. // Finish the effect.
  116. task_environment_.FastForwardBy(kPendingTaskDuration);
  117. EXPECT_THAT(fake_hid_writer_->output_reports,
  118. testing::ElementsAre(start_vibration_report_));
  119. EXPECT_EQ(1, callback_count_);
  120. EXPECT_EQ(mojom::GamepadHapticsResult::GamepadHapticsResultComplete,
  121. callback_result_);
  122. EXPECT_EQ(0U, task_environment_.GetPendingMainThreadTaskCount());
  123. }
  124. TEST_F(XboxHidControllerTest, ResetVibration) {
  125. EXPECT_TRUE(fake_hid_writer_->output_reports.empty());
  126. EXPECT_EQ(0, callback_count_);
  127. PostResetVibration(
  128. base::BindOnce(&XboxHidControllerTest::Callback, base::Unretained(this)));
  129. // Run the queued task and reset vibration.
  130. task_environment_.RunUntilIdle();
  131. EXPECT_THAT(fake_hid_writer_->output_reports,
  132. testing::ElementsAre(stop_vibration_report_));
  133. EXPECT_EQ(1, callback_count_);
  134. EXPECT_EQ(mojom::GamepadHapticsResult::GamepadHapticsResultComplete,
  135. callback_result_);
  136. EXPECT_EQ(0U, task_environment_.GetPendingMainThreadTaskCount());
  137. }
  138. } // namespace
  139. } // namespace device