usb_device_handle_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. // Copyright 2014 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/usb/usb_device_handle.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include "base/bind.h"
  8. #include "base/memory/ref_counted_memory.h"
  9. #include "base/run_loop.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "base/test/task_environment.h"
  12. #include "base/test/test_io_thread.h"
  13. #include "services/device/test/usb_test_gadget.h"
  14. #include "services/device/usb/usb_device.h"
  15. #include "services/device/usb/usb_service.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace device {
  18. using mojom::UsbControlTransferRecipient;
  19. using mojom::UsbControlTransferType;
  20. using mojom::UsbTransferDirection;
  21. using mojom::UsbTransferStatus;
  22. namespace {
  23. class UsbDeviceHandleTest : public ::testing::Test {
  24. public:
  25. UsbDeviceHandleTest()
  26. : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
  27. usb_service_(UsbService::Create()),
  28. io_thread_(base::TestIOThread::kAutoStart) {}
  29. protected:
  30. base::test::TaskEnvironment task_environment_;
  31. std::unique_ptr<UsbService> usb_service_;
  32. base::TestIOThread io_thread_;
  33. };
  34. class TestOpenCallback {
  35. public:
  36. TestOpenCallback() = default;
  37. scoped_refptr<UsbDeviceHandle> WaitForResult() {
  38. run_loop_.Run();
  39. return device_handle_;
  40. }
  41. UsbDevice::OpenCallback GetCallback() {
  42. return base::BindOnce(&TestOpenCallback::SetResult, base::Unretained(this));
  43. }
  44. private:
  45. void SetResult(scoped_refptr<UsbDeviceHandle> device_handle) {
  46. device_handle_ = device_handle;
  47. run_loop_.Quit();
  48. }
  49. base::RunLoop run_loop_;
  50. scoped_refptr<UsbDeviceHandle> device_handle_;
  51. };
  52. class TestResultCallback {
  53. public:
  54. TestResultCallback() = default;
  55. bool WaitForResult() {
  56. run_loop_.Run();
  57. return success_;
  58. }
  59. UsbDeviceHandle::ResultCallback GetCallback() {
  60. return base::BindOnce(&TestResultCallback::SetResult,
  61. base::Unretained(this));
  62. }
  63. private:
  64. void SetResult(bool success) {
  65. success_ = success;
  66. run_loop_.Quit();
  67. }
  68. base::RunLoop run_loop_;
  69. bool success_;
  70. };
  71. class TestCompletionCallback {
  72. public:
  73. TestCompletionCallback() = default;
  74. void WaitForResult() { run_loop_.Run(); }
  75. UsbDeviceHandle::TransferCallback GetCallback() {
  76. return base::BindOnce(&TestCompletionCallback::SetResult,
  77. base::Unretained(this));
  78. }
  79. UsbTransferStatus status() const { return status_; }
  80. size_t transferred() const { return transferred_; }
  81. private:
  82. void SetResult(UsbTransferStatus status,
  83. scoped_refptr<base::RefCountedBytes> buffer,
  84. size_t transferred) {
  85. status_ = status;
  86. transferred_ = transferred;
  87. run_loop_.Quit();
  88. }
  89. base::RunLoop run_loop_;
  90. UsbTransferStatus status_;
  91. size_t transferred_;
  92. };
  93. void ExpectTimeoutAndClose(scoped_refptr<UsbDeviceHandle> handle,
  94. base::OnceClosure quit_closure,
  95. UsbTransferStatus status,
  96. scoped_refptr<base::RefCountedBytes> buffer,
  97. size_t transferred) {
  98. EXPECT_EQ(UsbTransferStatus::TIMEOUT, status);
  99. handle->Close();
  100. std::move(quit_closure).Run();
  101. }
  102. TEST_F(UsbDeviceHandleTest, InterruptTransfer) {
  103. if (!UsbTestGadget::IsTestEnabled()) {
  104. return;
  105. }
  106. std::unique_ptr<UsbTestGadget> gadget =
  107. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  108. ASSERT_TRUE(gadget.get());
  109. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  110. TestOpenCallback open_device;
  111. gadget->GetDevice()->Open(open_device.GetCallback());
  112. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  113. ASSERT_TRUE(handle.get());
  114. TestResultCallback claim_interface;
  115. handle->ClaimInterface(0, claim_interface.GetCallback());
  116. ASSERT_TRUE(claim_interface.WaitForResult());
  117. const mojom::UsbInterfaceInfo* interface =
  118. handle->FindInterfaceByEndpoint(0x81);
  119. EXPECT_TRUE(interface);
  120. EXPECT_EQ(0, interface->interface_number);
  121. interface = handle->FindInterfaceByEndpoint(0x01);
  122. EXPECT_TRUE(interface);
  123. EXPECT_EQ(0, interface->interface_number);
  124. EXPECT_FALSE(handle->FindInterfaceByEndpoint(0x82));
  125. EXPECT_FALSE(handle->FindInterfaceByEndpoint(0x02));
  126. auto in_buffer = base::MakeRefCounted<base::RefCountedBytes>(64);
  127. TestCompletionCallback in_completion;
  128. handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x81, in_buffer,
  129. 5000, // 5 second timeout
  130. in_completion.GetCallback());
  131. auto out_buffer =
  132. base::MakeRefCounted<base::RefCountedBytes>(in_buffer->size());
  133. TestCompletionCallback out_completion;
  134. for (size_t i = 0; i < out_buffer->size(); ++i) {
  135. out_buffer->data()[i] = i;
  136. }
  137. handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x01, out_buffer,
  138. 5000, // 5 second timeout
  139. out_completion.GetCallback());
  140. out_completion.WaitForResult();
  141. ASSERT_EQ(UsbTransferStatus::COMPLETED, out_completion.status());
  142. EXPECT_EQ(static_cast<size_t>(out_buffer->size()),
  143. out_completion.transferred());
  144. in_completion.WaitForResult();
  145. ASSERT_EQ(UsbTransferStatus::COMPLETED, in_completion.status());
  146. EXPECT_EQ(static_cast<size_t>(in_buffer->size()),
  147. in_completion.transferred());
  148. for (size_t i = 0; i < in_completion.transferred(); ++i) {
  149. EXPECT_EQ(out_buffer->front()[i], in_buffer->front()[i])
  150. << "Mismatch at index " << i << ".";
  151. }
  152. TestResultCallback release_interface;
  153. handle->ReleaseInterface(0, release_interface.GetCallback());
  154. ASSERT_TRUE(release_interface.WaitForResult());
  155. handle->Close();
  156. }
  157. TEST_F(UsbDeviceHandleTest, BulkTransfer) {
  158. if (!UsbTestGadget::IsTestEnabled()) {
  159. return;
  160. }
  161. std::unique_ptr<UsbTestGadget> gadget =
  162. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  163. ASSERT_TRUE(gadget.get());
  164. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  165. TestOpenCallback open_device;
  166. gadget->GetDevice()->Open(open_device.GetCallback());
  167. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  168. ASSERT_TRUE(handle.get());
  169. TestResultCallback claim_interface;
  170. handle->ClaimInterface(1, claim_interface.GetCallback());
  171. ASSERT_TRUE(claim_interface.WaitForResult());
  172. EXPECT_FALSE(handle->FindInterfaceByEndpoint(0x81));
  173. EXPECT_FALSE(handle->FindInterfaceByEndpoint(0x01));
  174. const mojom::UsbInterfaceInfo* interface =
  175. handle->FindInterfaceByEndpoint(0x82);
  176. EXPECT_TRUE(interface);
  177. EXPECT_EQ(1, interface->interface_number);
  178. interface = handle->FindInterfaceByEndpoint(0x02);
  179. EXPECT_TRUE(interface);
  180. EXPECT_EQ(1, interface->interface_number);
  181. auto in_buffer = base::MakeRefCounted<base::RefCountedBytes>(512);
  182. TestCompletionCallback in_completion;
  183. handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, in_buffer,
  184. 5000, // 5 second timeout
  185. in_completion.GetCallback());
  186. auto out_buffer =
  187. base::MakeRefCounted<base::RefCountedBytes>(in_buffer->size());
  188. TestCompletionCallback out_completion;
  189. for (size_t i = 0; i < out_buffer->size(); ++i) {
  190. out_buffer->data()[i] = i;
  191. }
  192. handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x02, out_buffer,
  193. 5000, // 5 second timeout
  194. out_completion.GetCallback());
  195. out_completion.WaitForResult();
  196. ASSERT_EQ(UsbTransferStatus::COMPLETED, out_completion.status());
  197. EXPECT_EQ(static_cast<size_t>(out_buffer->size()),
  198. out_completion.transferred());
  199. in_completion.WaitForResult();
  200. ASSERT_EQ(UsbTransferStatus::COMPLETED, in_completion.status());
  201. EXPECT_EQ(static_cast<size_t>(in_buffer->size()),
  202. in_completion.transferred());
  203. for (size_t i = 0; i < in_completion.transferred(); ++i) {
  204. EXPECT_EQ(out_buffer->front()[i], in_buffer->front()[i])
  205. << "Mismatch at index " << i << ".";
  206. }
  207. TestResultCallback release_interface;
  208. handle->ReleaseInterface(1, release_interface.GetCallback());
  209. ASSERT_TRUE(release_interface.WaitForResult());
  210. handle->Close();
  211. }
  212. TEST_F(UsbDeviceHandleTest, ControlTransfer) {
  213. if (!UsbTestGadget::IsTestEnabled())
  214. return;
  215. std::unique_ptr<UsbTestGadget> gadget =
  216. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  217. ASSERT_TRUE(gadget.get());
  218. TestOpenCallback open_device;
  219. gadget->GetDevice()->Open(open_device.GetCallback());
  220. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  221. ASSERT_TRUE(handle.get());
  222. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(255);
  223. TestCompletionCallback completion;
  224. handle->ControlTransfer(UsbTransferDirection::INBOUND,
  225. UsbControlTransferType::STANDARD,
  226. UsbControlTransferRecipient::DEVICE, 0x06, 0x0301,
  227. 0x0409, buffer, 0, completion.GetCallback());
  228. completion.WaitForResult();
  229. ASSERT_EQ(UsbTransferStatus::COMPLETED, completion.status());
  230. const char expected_str[] = "\x18\x03G\0o\0o\0g\0l\0e\0 \0I\0n\0c\0.\0";
  231. EXPECT_EQ(sizeof(expected_str) - 1, completion.transferred());
  232. for (size_t i = 0; i < completion.transferred(); ++i) {
  233. EXPECT_EQ(expected_str[i], buffer->front()[i])
  234. << "Mismatch at index " << i << ".";
  235. }
  236. handle->Close();
  237. }
  238. TEST_F(UsbDeviceHandleTest, SetInterfaceAlternateSetting) {
  239. if (!UsbTestGadget::IsTestEnabled()) {
  240. return;
  241. }
  242. std::unique_ptr<UsbTestGadget> gadget =
  243. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  244. ASSERT_TRUE(gadget.get());
  245. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  246. TestOpenCallback open_device;
  247. gadget->GetDevice()->Open(open_device.GetCallback());
  248. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  249. ASSERT_TRUE(handle.get());
  250. TestResultCallback claim_interface;
  251. handle->ClaimInterface(2, claim_interface.GetCallback());
  252. ASSERT_TRUE(claim_interface.WaitForResult());
  253. TestResultCallback set_interface;
  254. handle->SetInterfaceAlternateSetting(2, 1, set_interface.GetCallback());
  255. ASSERT_TRUE(set_interface.WaitForResult());
  256. TestResultCallback release_interface;
  257. handle->ReleaseInterface(2, release_interface.GetCallback());
  258. ASSERT_TRUE(release_interface.WaitForResult());
  259. handle->Close();
  260. }
  261. TEST_F(UsbDeviceHandleTest, CancelOnClose) {
  262. if (!UsbTestGadget::IsTestEnabled()) {
  263. return;
  264. }
  265. std::unique_ptr<UsbTestGadget> gadget =
  266. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  267. ASSERT_TRUE(gadget.get());
  268. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  269. TestOpenCallback open_device;
  270. gadget->GetDevice()->Open(open_device.GetCallback());
  271. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  272. ASSERT_TRUE(handle.get());
  273. TestResultCallback claim_interface;
  274. handle->ClaimInterface(1, claim_interface.GetCallback());
  275. ASSERT_TRUE(claim_interface.WaitForResult());
  276. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(512);
  277. TestCompletionCallback completion;
  278. handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer,
  279. 5000, // 5 second timeout
  280. completion.GetCallback());
  281. handle->Close();
  282. completion.WaitForResult();
  283. ASSERT_EQ(UsbTransferStatus::CANCELLED, completion.status());
  284. }
  285. TEST_F(UsbDeviceHandleTest, ErrorOnDisconnect) {
  286. if (!UsbTestGadget::IsTestEnabled()) {
  287. return;
  288. }
  289. std::unique_ptr<UsbTestGadget> gadget =
  290. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  291. ASSERT_TRUE(gadget.get());
  292. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  293. TestOpenCallback open_device;
  294. gadget->GetDevice()->Open(open_device.GetCallback());
  295. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  296. ASSERT_TRUE(handle.get());
  297. TestResultCallback claim_interface;
  298. handle->ClaimInterface(1, claim_interface.GetCallback());
  299. ASSERT_TRUE(claim_interface.WaitForResult());
  300. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(512);
  301. TestCompletionCallback completion;
  302. handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer,
  303. 5000, // 5 second timeout
  304. completion.GetCallback());
  305. ASSERT_TRUE(gadget->Disconnect());
  306. completion.WaitForResult();
  307. // Depending on timing the transfer can be cancelled by the disconnection, be
  308. // rejected because the device is already missing or result in another generic
  309. // error as the device drops off the bus.
  310. EXPECT_TRUE(completion.status() == UsbTransferStatus::CANCELLED ||
  311. completion.status() == UsbTransferStatus::DISCONNECT ||
  312. completion.status() == UsbTransferStatus::TRANSFER_ERROR);
  313. handle->Close();
  314. }
  315. TEST_F(UsbDeviceHandleTest, Timeout) {
  316. if (!UsbTestGadget::IsTestEnabled()) {
  317. return;
  318. }
  319. std::unique_ptr<UsbTestGadget> gadget =
  320. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  321. ASSERT_TRUE(gadget.get());
  322. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  323. TestOpenCallback open_device;
  324. gadget->GetDevice()->Open(open_device.GetCallback());
  325. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  326. ASSERT_TRUE(handle.get());
  327. TestResultCallback claim_interface;
  328. handle->ClaimInterface(1, claim_interface.GetCallback());
  329. ASSERT_TRUE(claim_interface.WaitForResult());
  330. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(512);
  331. TestCompletionCallback completion;
  332. handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer,
  333. 10, // 10 millisecond timeout
  334. completion.GetCallback());
  335. completion.WaitForResult();
  336. ASSERT_EQ(UsbTransferStatus::TIMEOUT, completion.status());
  337. handle->Close();
  338. }
  339. TEST_F(UsbDeviceHandleTest, CloseReentrancy) {
  340. if (!UsbTestGadget::IsTestEnabled())
  341. return;
  342. std::unique_ptr<UsbTestGadget> gadget =
  343. UsbTestGadget::Claim(usb_service_.get(), io_thread_.task_runner());
  344. ASSERT_TRUE(gadget.get());
  345. ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
  346. TestOpenCallback open_device;
  347. gadget->GetDevice()->Open(open_device.GetCallback());
  348. scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
  349. ASSERT_TRUE(handle.get());
  350. TestResultCallback claim_interface;
  351. handle->ClaimInterface(1, claim_interface.GetCallback());
  352. ASSERT_TRUE(claim_interface.WaitForResult());
  353. base::RunLoop run_loop;
  354. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(512);
  355. handle->GenericTransfer(
  356. UsbTransferDirection::INBOUND, 0x82, buffer,
  357. 10, // 10 millisecond timeout
  358. base::BindOnce(&ExpectTimeoutAndClose, handle, run_loop.QuitClosure()));
  359. // Drop handle so that the completion callback holds the last reference.
  360. handle = nullptr;
  361. run_loop.Run();
  362. }
  363. } // namespace
  364. } // namespace device