hid_device_info_unittest.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright 2021 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 "services/device/hid/hid_device_info.h"
  5. #include "base/containers/flat_map.h"
  6. #include "build/build_config.h"
  7. #include "services/device/hid/hid_report_type.h"
  8. #include "services/device/public/cpp/test/test_report_descriptors.h"
  9. #include "services/device/public/mojom/hid.mojom.h"
  10. #include "testing/gmock/include/gmock/gmock.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace device {
  13. namespace {
  14. using ::testing::ElementsAre;
  15. using ::testing::UnorderedElementsAre;
  16. scoped_refptr<HidDeviceInfo> CreateHidDeviceInfo(
  17. base::span<const uint8_t> report_descriptor) {
  18. #if BUILDFLAG(IS_MAC)
  19. const uint64_t kTestDeviceId = 0;
  20. #elif BUILDFLAG(IS_WIN)
  21. const wchar_t* const kTestDeviceId = L"0";
  22. #else
  23. const char* const kTestDeviceId = "0";
  24. #endif
  25. return base::MakeRefCounted<HidDeviceInfo>(
  26. kTestDeviceId, "physical-device-id",
  27. /*vendor_id=*/0x1234,
  28. /*product_id=*/0xabcd, "product-name", "serial-number",
  29. mojom::HidBusType::kHIDBusTypeUSB, report_descriptor);
  30. }
  31. TEST(HidDeviceInfoTest, FindCollectionWithReport_MultipleCollections) {
  32. // The device has 8 reports (4 input, 4 output) spread over 3 top-level
  33. // collections.
  34. auto device =
  35. CreateHidDeviceInfo(TestReportDescriptors::LogitechUnifyingReceiver());
  36. EXPECT_TRUE(device->has_report_id());
  37. EXPECT_EQ(3u, device->collections().size());
  38. base::flat_map<uint16_t, device::mojom::HidCollectionInfo*> collections;
  39. for (const auto& collection : device->collections()) {
  40. ASSERT_TRUE(collection->usage);
  41. EXPECT_EQ(mojom::kPageVendor, collection->usage->usage_page);
  42. collections[collection->usage->usage] = collection.get();
  43. }
  44. ASSERT_TRUE(collections.contains(1));
  45. ASSERT_TRUE(collections.contains(2));
  46. ASSERT_TRUE(collections.contains(4));
  47. EXPECT_THAT(collections[1]->report_ids, ElementsAre(0x10));
  48. ASSERT_EQ(1u, collections[1]->input_reports.size());
  49. EXPECT_EQ(0x10, collections[1]->input_reports[0]->report_id);
  50. ASSERT_EQ(1u, collections[1]->output_reports.size());
  51. EXPECT_EQ(0x10, collections[1]->output_reports[0]->report_id);
  52. EXPECT_EQ(0u, collections[1]->feature_reports.size());
  53. EXPECT_THAT(collections[2]->report_ids, ElementsAre(0x11));
  54. ASSERT_EQ(1u, collections[2]->input_reports.size());
  55. EXPECT_EQ(0x11, collections[2]->input_reports[0]->report_id);
  56. ASSERT_EQ(1u, collections[2]->output_reports.size());
  57. EXPECT_EQ(0x11, collections[2]->output_reports[0]->report_id);
  58. EXPECT_EQ(0u, collections[2]->feature_reports.size());
  59. EXPECT_THAT(collections[4]->report_ids, UnorderedElementsAre(0x20, 0x21));
  60. std::vector<uint8_t> input_report_ids;
  61. for (const auto& report : collections[4]->input_reports)
  62. input_report_ids.push_back(report->report_id);
  63. EXPECT_THAT(input_report_ids, UnorderedElementsAre(0x20, 0x21));
  64. std::vector<uint8_t> output_report_ids;
  65. for (const auto& report : collections[4]->output_reports)
  66. output_report_ids.push_back(report->report_id);
  67. EXPECT_THAT(output_report_ids, UnorderedElementsAre(0x20, 0x21));
  68. EXPECT_EQ(0u, collections[4]->feature_reports.size());
  69. // Ensure the correct collection is returned for each report.
  70. EXPECT_EQ(collections[1],
  71. device->FindCollectionWithReport(0x10, HidReportType::kInput));
  72. EXPECT_EQ(collections[1],
  73. device->FindCollectionWithReport(0x10, HidReportType::kOutput));
  74. EXPECT_EQ(collections[2],
  75. device->FindCollectionWithReport(0x11, HidReportType::kInput));
  76. EXPECT_EQ(collections[2],
  77. device->FindCollectionWithReport(0x11, HidReportType::kOutput));
  78. EXPECT_EQ(collections[4],
  79. device->FindCollectionWithReport(0x20, HidReportType::kInput));
  80. EXPECT_EQ(collections[4],
  81. device->FindCollectionWithReport(0x20, HidReportType::kOutput));
  82. EXPECT_EQ(collections[4],
  83. device->FindCollectionWithReport(0x21, HidReportType::kInput));
  84. EXPECT_EQ(collections[4],
  85. device->FindCollectionWithReport(0x21, HidReportType::kOutput));
  86. // Zero is not a valid report ID. Ensure no collection info is returned.
  87. EXPECT_EQ(nullptr,
  88. device->FindCollectionWithReport(0, HidReportType::kInput));
  89. EXPECT_EQ(nullptr,
  90. device->FindCollectionWithReport(0, HidReportType::kOutput));
  91. EXPECT_EQ(nullptr,
  92. device->FindCollectionWithReport(0, HidReportType::kFeature));
  93. // Ensure no collection is returned for reports not supported by the device.
  94. EXPECT_EQ(nullptr,
  95. device->FindCollectionWithReport(0x10, HidReportType::kFeature));
  96. EXPECT_EQ(nullptr,
  97. device->FindCollectionWithReport(0x11, HidReportType::kFeature));
  98. EXPECT_EQ(nullptr,
  99. device->FindCollectionWithReport(0x20, HidReportType::kFeature));
  100. EXPECT_EQ(nullptr,
  101. device->FindCollectionWithReport(0x21, HidReportType::kFeature));
  102. EXPECT_EQ(nullptr,
  103. device->FindCollectionWithReport(0x30, HidReportType::kInput));
  104. EXPECT_EQ(nullptr,
  105. device->FindCollectionWithReport(0x30, HidReportType::kOutput));
  106. EXPECT_EQ(nullptr,
  107. device->FindCollectionWithReport(0x30, HidReportType::kFeature));
  108. }
  109. TEST(HidDeviceInfoTest, FindCollectionWithReport_SameReportId) {
  110. // The device has 6 reports (1 input, 1 output, 4 feature). The input report,
  111. // output report, and first feature report share the same report ID.
  112. auto device = CreateHidDeviceInfo(TestReportDescriptors::SonyDualshock3Usb());
  113. EXPECT_TRUE(device->has_report_id());
  114. ASSERT_EQ(1u, device->collections().size());
  115. const auto* collection = device->collections()[0].get();
  116. EXPECT_FALSE(collection->report_ids.empty());
  117. ASSERT_EQ(1u, collection->input_reports.size());
  118. EXPECT_EQ(0x01, collection->input_reports[0]->report_id);
  119. ASSERT_EQ(1u, collection->output_reports.size());
  120. EXPECT_EQ(0x01, collection->output_reports[0]->report_id);
  121. ASSERT_EQ(4u, collection->feature_reports.size());
  122. std::vector<uint8_t> feature_report_ids;
  123. for (const auto& report : collection->feature_reports)
  124. feature_report_ids.push_back(report->report_id);
  125. EXPECT_THAT(feature_report_ids, UnorderedElementsAre(0x01, 0x02, 0xee, 0xef));
  126. // Ensure the correct collection is returned for each report.
  127. EXPECT_EQ(collection,
  128. device->FindCollectionWithReport(0x01, HidReportType::kInput));
  129. EXPECT_EQ(collection,
  130. device->FindCollectionWithReport(0x01, HidReportType::kOutput));
  131. EXPECT_EQ(collection,
  132. device->FindCollectionWithReport(0x01, HidReportType::kFeature));
  133. EXPECT_EQ(collection,
  134. device->FindCollectionWithReport(0x02, HidReportType::kFeature));
  135. EXPECT_EQ(collection,
  136. device->FindCollectionWithReport(0xee, HidReportType::kFeature));
  137. EXPECT_EQ(collection,
  138. device->FindCollectionWithReport(0xef, HidReportType::kFeature));
  139. // Zero is not a valid report ID. Ensure no collection info is returned.
  140. EXPECT_EQ(nullptr,
  141. device->FindCollectionWithReport(0, HidReportType::kInput));
  142. EXPECT_EQ(nullptr,
  143. device->FindCollectionWithReport(0, HidReportType::kOutput));
  144. EXPECT_EQ(nullptr,
  145. device->FindCollectionWithReport(0, HidReportType::kFeature));
  146. // Ensure no collection is returned for reports not supported by the device.
  147. EXPECT_EQ(nullptr,
  148. device->FindCollectionWithReport(0x02, HidReportType::kInput));
  149. EXPECT_EQ(nullptr,
  150. device->FindCollectionWithReport(0x02, HidReportType::kOutput));
  151. EXPECT_EQ(nullptr,
  152. device->FindCollectionWithReport(0x03, HidReportType::kFeature));
  153. }
  154. TEST(HidDeviceInfoTest, FindCollectionWithReport_NoReportIds) {
  155. // The device has 2 reports (1 input, 1 output) and does not use report IDs.
  156. auto device = CreateHidDeviceInfo(TestReportDescriptors::FidoU2fHid());
  157. EXPECT_FALSE(device->has_report_id());
  158. ASSERT_EQ(1u, device->collections().size());
  159. const auto* collection = device->collections()[0].get();
  160. EXPECT_TRUE(collection->report_ids.empty());
  161. ASSERT_EQ(1u, collection->input_reports.size());
  162. EXPECT_EQ(0u, collection->input_reports[0]->report_id);
  163. ASSERT_EQ(1u, collection->output_reports.size());
  164. EXPECT_EQ(0u, collection->output_reports[0]->report_id);
  165. EXPECT_TRUE(collection->feature_reports.empty());
  166. // Ensure the correct collection is returned for each report.
  167. EXPECT_EQ(collection,
  168. device->FindCollectionWithReport(0, HidReportType::kInput));
  169. EXPECT_EQ(collection,
  170. device->FindCollectionWithReport(0, HidReportType::kOutput));
  171. // Ensure no collection is found containing a feature report.
  172. EXPECT_EQ(nullptr,
  173. device->FindCollectionWithReport(0, HidReportType::kFeature));
  174. // No collections should be found for any non-zero report ID.
  175. for (uint32_t report_id = 0x01; report_id <= 0xff; ++report_id) {
  176. EXPECT_EQ(nullptr, device->FindCollectionWithReport(report_id,
  177. HidReportType::kInput));
  178. EXPECT_EQ(nullptr, device->FindCollectionWithReport(
  179. report_id, HidReportType::kOutput));
  180. EXPECT_EQ(nullptr, device->FindCollectionWithReport(
  181. report_id, HidReportType::kFeature));
  182. }
  183. }
  184. } // namespace
  185. } // namespace device