Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 1 | // Copyright (c) 2013 The Chromium OS 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 | |
| 5 | #include "mist/usb_transfer.h" |
| 6 | |
| 7 | #include <libusb.h> |
| 8 | |
| 9 | #include <gtest/gtest.h> |
| 10 | |
| 11 | namespace mist { |
| 12 | |
| 13 | class UsbTransferTest : public testing::Test { |
| 14 | protected: |
| 15 | UsbTransferTest() : original_transfer_state_(UsbTransfer::kIdle) {} |
| 16 | |
| 17 | void TearDown() { |
| 18 | // Take out the injected libusb_transfer to bypass the invocation of |
| 19 | // libusb_free_transfer() in UsbTransfer. |
| 20 | if (transfer_.transfer_ == &test_transfer_) |
Ben Chan | 61ac5ba | 2014-08-29 18:06:43 -0700 | [diff] [blame] | 21 | transfer_.transfer_ = nullptr; |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 22 | |
| 23 | transfer_.state_ = original_transfer_state_; |
| 24 | } |
| 25 | |
| 26 | // Temporarily injects a hand crafted libusb_transfer struct into |transfer_| |
| 27 | // for testing. The injected libusb_transfer struct is removed in TearDown(). |
Ben Chan | c440db5 | 2017-09-26 06:30:47 -0700 | [diff] [blame] | 28 | void InjectTestLibUsbTransfer() { transfer_.transfer_ = &test_transfer_; } |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 29 | |
| 30 | // Pretends the transfer has been submitted and is still in progress. |
| 31 | void PretendTransferInProgress() { |
| 32 | original_transfer_state_ = transfer_.state_; |
| 33 | transfer_.state_ = UsbTransfer::kInProgress; |
| 34 | } |
| 35 | |
| 36 | // Pretends the transfer is being cancelled. |
| 37 | void PretendTransferBeingCancelled() { |
| 38 | original_transfer_state_ = transfer_.state_; |
| 39 | transfer_.state_ = UsbTransfer::kCancelling; |
| 40 | } |
| 41 | |
| 42 | UsbTransfer transfer_; |
| 43 | UsbTransfer::State original_transfer_state_; |
| 44 | libusb_transfer test_transfer_; |
| 45 | }; |
| 46 | |
| 47 | TEST_F(UsbTransferTest, DefaultConstructor) { |
Ben Chan | 61ac5ba | 2014-08-29 18:06:43 -0700 | [diff] [blame] | 48 | EXPECT_EQ(nullptr, transfer_.buffer()); |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 49 | EXPECT_EQ(0, transfer_.buffer_length()); |
| 50 | EXPECT_EQ(UsbTransfer::kIdle, transfer_.state()); |
| 51 | EXPECT_TRUE(transfer_.error().IsSuccess()); |
| 52 | } |
| 53 | |
| 54 | TEST_F(UsbTransferTest, GetType) { |
| 55 | EXPECT_EQ(kUsbTransferTypeUnknown, transfer_.GetType()); |
| 56 | |
| 57 | InjectTestLibUsbTransfer(); |
| 58 | |
| 59 | test_transfer_.type = LIBUSB_TRANSFER_TYPE_CONTROL; |
| 60 | EXPECT_EQ(kUsbTransferTypeControl, transfer_.GetType()); |
| 61 | |
| 62 | test_transfer_.type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; |
| 63 | EXPECT_EQ(kUsbTransferTypeIsochronous, transfer_.GetType()); |
| 64 | |
| 65 | test_transfer_.type = LIBUSB_TRANSFER_TYPE_BULK; |
| 66 | EXPECT_EQ(kUsbTransferTypeBulk, transfer_.GetType()); |
| 67 | |
| 68 | test_transfer_.type = LIBUSB_TRANSFER_TYPE_INTERRUPT; |
| 69 | EXPECT_EQ(kUsbTransferTypeInterrupt, transfer_.GetType()); |
| 70 | } |
| 71 | |
| 72 | TEST_F(UsbTransferTest, GetStatus) { |
| 73 | EXPECT_EQ(kUsbTransferStatusUnknown, transfer_.GetStatus()); |
| 74 | |
| 75 | InjectTestLibUsbTransfer(); |
| 76 | |
| 77 | test_transfer_.status = LIBUSB_TRANSFER_COMPLETED; |
| 78 | EXPECT_EQ(kUsbTransferStatusCompleted, transfer_.GetStatus()); |
| 79 | |
| 80 | test_transfer_.status = LIBUSB_TRANSFER_ERROR; |
| 81 | EXPECT_EQ(kUsbTransferStatusError, transfer_.GetStatus()); |
| 82 | |
| 83 | test_transfer_.status = LIBUSB_TRANSFER_TIMED_OUT; |
| 84 | EXPECT_EQ(kUsbTransferStatusTimedOut, transfer_.GetStatus()); |
| 85 | |
| 86 | test_transfer_.status = LIBUSB_TRANSFER_CANCELLED; |
| 87 | EXPECT_EQ(kUsbTransferStatusCancelled, transfer_.GetStatus()); |
| 88 | |
| 89 | test_transfer_.status = LIBUSB_TRANSFER_STALL; |
| 90 | EXPECT_EQ(kUsbTransferStatusStall, transfer_.GetStatus()); |
| 91 | |
| 92 | test_transfer_.status = LIBUSB_TRANSFER_NO_DEVICE; |
| 93 | EXPECT_EQ(kUsbTransferStatusNoDevice, transfer_.GetStatus()); |
| 94 | |
| 95 | test_transfer_.status = LIBUSB_TRANSFER_OVERFLOW; |
| 96 | EXPECT_EQ(kUsbTransferStatusOverflow, transfer_.GetStatus()); |
| 97 | } |
| 98 | |
| 99 | TEST_F(UsbTransferTest, GetLength) { |
| 100 | EXPECT_EQ(0, transfer_.GetLength()); |
| 101 | |
| 102 | InjectTestLibUsbTransfer(); |
| 103 | |
| 104 | test_transfer_.length = 20; |
| 105 | EXPECT_EQ(test_transfer_.length, transfer_.GetLength()); |
| 106 | } |
| 107 | |
| 108 | TEST_F(UsbTransferTest, GetActualLength) { |
| 109 | EXPECT_EQ(0, transfer_.GetLength()); |
| 110 | |
| 111 | InjectTestLibUsbTransfer(); |
| 112 | |
| 113 | test_transfer_.actual_length = 10; |
| 114 | EXPECT_EQ(test_transfer_.actual_length, transfer_.GetActualLength()); |
| 115 | } |
| 116 | |
Ben Chan | 7264392 | 2013-09-17 00:36:25 -0700 | [diff] [blame] | 117 | TEST_F(UsbTransferTest, IsCompletedWithExpectedLength) { |
| 118 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(0)); |
| 119 | |
| 120 | InjectTestLibUsbTransfer(); |
| 121 | |
| 122 | test_transfer_.actual_length = 5; |
| 123 | test_transfer_.status = LIBUSB_TRANSFER_COMPLETED; |
| 124 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 125 | |
| 126 | test_transfer_.actual_length = 10; |
| 127 | EXPECT_TRUE(transfer_.IsCompletedWithExpectedLength(10)); |
| 128 | |
| 129 | test_transfer_.status = LIBUSB_TRANSFER_ERROR; |
| 130 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 131 | |
| 132 | test_transfer_.status = LIBUSB_TRANSFER_TIMED_OUT; |
| 133 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 134 | |
| 135 | test_transfer_.status = LIBUSB_TRANSFER_CANCELLED; |
| 136 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 137 | |
| 138 | test_transfer_.status = LIBUSB_TRANSFER_STALL; |
| 139 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 140 | |
| 141 | test_transfer_.status = LIBUSB_TRANSFER_NO_DEVICE; |
| 142 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 143 | |
| 144 | test_transfer_.status = LIBUSB_TRANSFER_OVERFLOW; |
| 145 | EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| 146 | } |
| 147 | |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 148 | TEST_F(UsbTransferTest, VerifyAllocated) { |
| 149 | EXPECT_FALSE(transfer_.VerifyAllocated()); |
| 150 | EXPECT_EQ(UsbError::kErrorTransferNotAllocated, transfer_.error().type()); |
| 151 | } |
| 152 | |
| 153 | TEST_F(UsbTransferTest, AllocateAfterAllocate) { |
| 154 | InjectTestLibUsbTransfer(); |
| 155 | EXPECT_FALSE(transfer_.Allocate(0)); |
| 156 | EXPECT_EQ(UsbError::kErrorTransferAlreadyAllocated, transfer_.error().type()); |
| 157 | } |
| 158 | |
| 159 | TEST_F(UsbTransferTest, FreeBeforeAllocate) { |
| 160 | // Free() without calling Allocate() should be ok. |
| 161 | transfer_.Free(); |
| 162 | } |
| 163 | |
| 164 | TEST_F(UsbTransferTest, AllocateBuffer) { |
| 165 | // Allocate a zero-size buffer should be ok. |
| 166 | EXPECT_TRUE(transfer_.AllocateBuffer(0)); |
Ben Chan | 61ac5ba | 2014-08-29 18:06:43 -0700 | [diff] [blame] | 167 | EXPECT_NE(nullptr, transfer_.buffer()); |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 168 | EXPECT_EQ(0, transfer_.buffer_length()); |
| 169 | |
| 170 | // Re-allocate the buffer should be ok. |
Ben Chan | 956f79b | 2014-08-06 17:11:01 -0700 | [diff] [blame] | 171 | const uint8_t kTestData[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 172 | EXPECT_TRUE(transfer_.AllocateBuffer(arraysize(kTestData))); |
Ben Chan | 61ac5ba | 2014-08-29 18:06:43 -0700 | [diff] [blame] | 173 | EXPECT_NE(nullptr, transfer_.buffer()); |
Ben Chan | de49015 | 2013-05-29 17:05:49 -0700 | [diff] [blame] | 174 | EXPECT_EQ(arraysize(kTestData), transfer_.buffer_length()); |
| 175 | // Write to the allocated buffer and then read from it to ensure the buffer |
| 176 | // is properly allocated. |
| 177 | memcpy(transfer_.buffer(), kTestData, arraysize(kTestData)); |
| 178 | EXPECT_EQ(0, memcmp(transfer_.buffer(), kTestData, arraysize(kTestData))); |
| 179 | } |
| 180 | |
| 181 | TEST_F(UsbTransferTest, AllocateBufferAfterSubmit) { |
| 182 | PretendTransferInProgress(); |
| 183 | EXPECT_FALSE(transfer_.AllocateBuffer(0)); |
| 184 | EXPECT_EQ(UsbTransfer::kInProgress, transfer_.state()); |
| 185 | EXPECT_EQ(UsbError::kErrorTransferAlreadySubmitted, transfer_.error().type()); |
| 186 | } |
| 187 | |
| 188 | TEST_F(UsbTransferTest, SubmitBeforeAllocate) { |
| 189 | EXPECT_FALSE(transfer_.Submit(UsbTransfer::CompletionCallback())); |
| 190 | EXPECT_EQ(UsbTransfer::kIdle, transfer_.state()); |
| 191 | EXPECT_EQ(UsbError::kErrorTransferNotAllocated, transfer_.error().type()); |
| 192 | } |
| 193 | |
| 194 | TEST_F(UsbTransferTest, SubmitBeforeComplete) { |
| 195 | InjectTestLibUsbTransfer(); |
| 196 | PretendTransferInProgress(); |
| 197 | EXPECT_FALSE(transfer_.Submit(UsbTransfer::CompletionCallback())); |
| 198 | EXPECT_EQ(UsbTransfer::kInProgress, transfer_.state()); |
| 199 | EXPECT_EQ(UsbError::kErrorTransferAlreadySubmitted, transfer_.error().type()); |
| 200 | } |
| 201 | |
| 202 | TEST_F(UsbTransferTest, CancelBeforeSubmit) { |
| 203 | EXPECT_FALSE(transfer_.Cancel()); |
| 204 | EXPECT_EQ(UsbTransfer::kIdle, transfer_.state()); |
| 205 | EXPECT_EQ(UsbError::kErrorTransferNotSubmitted, transfer_.error().type()); |
| 206 | } |
| 207 | |
| 208 | TEST_F(UsbTransferTest, CancelWhileBeingCancelled) { |
| 209 | PretendTransferBeingCancelled(); |
| 210 | EXPECT_FALSE(transfer_.Cancel()); |
| 211 | EXPECT_EQ(UsbTransfer::kCancelling, transfer_.state()); |
| 212 | EXPECT_EQ(UsbError::kErrorTransferBeingCancelled, transfer_.error().type()); |
| 213 | } |
| 214 | |
| 215 | } // namespace mist |