| // Copyright (c) 2013 The Chromium OS 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 "mist/usb_transfer.h" |
| |
| #include <libusb.h> |
| |
| #include <gtest/gtest.h> |
| |
| namespace mist { |
| |
| class UsbTransferTest : public testing::Test { |
| protected: |
| UsbTransferTest() : original_transfer_state_(UsbTransfer::kIdle) {} |
| |
| void TearDown() { |
| // Take out the injected libusb_transfer to bypass the invocation of |
| // libusb_free_transfer() in UsbTransfer. |
| if (transfer_.transfer_ == &test_transfer_) |
| transfer_.transfer_ = nullptr; |
| |
| transfer_.state_ = original_transfer_state_; |
| } |
| |
| // Temporarily injects a hand crafted libusb_transfer struct into |transfer_| |
| // for testing. The injected libusb_transfer struct is removed in TearDown(). |
| void InjectTestLibUsbTransfer() { |
| transfer_.transfer_ = &test_transfer_; |
| } |
| |
| // Pretends the transfer has been submitted and is still in progress. |
| void PretendTransferInProgress() { |
| original_transfer_state_ = transfer_.state_; |
| transfer_.state_ = UsbTransfer::kInProgress; |
| } |
| |
| // Pretends the transfer is being cancelled. |
| void PretendTransferBeingCancelled() { |
| original_transfer_state_ = transfer_.state_; |
| transfer_.state_ = UsbTransfer::kCancelling; |
| } |
| |
| UsbTransfer transfer_; |
| UsbTransfer::State original_transfer_state_; |
| libusb_transfer test_transfer_; |
| }; |
| |
| TEST_F(UsbTransferTest, DefaultConstructor) { |
| EXPECT_EQ(nullptr, transfer_.buffer()); |
| EXPECT_EQ(0, transfer_.buffer_length()); |
| EXPECT_EQ(UsbTransfer::kIdle, transfer_.state()); |
| EXPECT_TRUE(transfer_.error().IsSuccess()); |
| } |
| |
| TEST_F(UsbTransferTest, GetType) { |
| EXPECT_EQ(kUsbTransferTypeUnknown, transfer_.GetType()); |
| |
| InjectTestLibUsbTransfer(); |
| |
| test_transfer_.type = LIBUSB_TRANSFER_TYPE_CONTROL; |
| EXPECT_EQ(kUsbTransferTypeControl, transfer_.GetType()); |
| |
| test_transfer_.type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; |
| EXPECT_EQ(kUsbTransferTypeIsochronous, transfer_.GetType()); |
| |
| test_transfer_.type = LIBUSB_TRANSFER_TYPE_BULK; |
| EXPECT_EQ(kUsbTransferTypeBulk, transfer_.GetType()); |
| |
| test_transfer_.type = LIBUSB_TRANSFER_TYPE_INTERRUPT; |
| EXPECT_EQ(kUsbTransferTypeInterrupt, transfer_.GetType()); |
| } |
| |
| TEST_F(UsbTransferTest, GetStatus) { |
| EXPECT_EQ(kUsbTransferStatusUnknown, transfer_.GetStatus()); |
| |
| InjectTestLibUsbTransfer(); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_COMPLETED; |
| EXPECT_EQ(kUsbTransferStatusCompleted, transfer_.GetStatus()); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_ERROR; |
| EXPECT_EQ(kUsbTransferStatusError, transfer_.GetStatus()); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_TIMED_OUT; |
| EXPECT_EQ(kUsbTransferStatusTimedOut, transfer_.GetStatus()); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_CANCELLED; |
| EXPECT_EQ(kUsbTransferStatusCancelled, transfer_.GetStatus()); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_STALL; |
| EXPECT_EQ(kUsbTransferStatusStall, transfer_.GetStatus()); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_NO_DEVICE; |
| EXPECT_EQ(kUsbTransferStatusNoDevice, transfer_.GetStatus()); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_OVERFLOW; |
| EXPECT_EQ(kUsbTransferStatusOverflow, transfer_.GetStatus()); |
| } |
| |
| TEST_F(UsbTransferTest, GetLength) { |
| EXPECT_EQ(0, transfer_.GetLength()); |
| |
| InjectTestLibUsbTransfer(); |
| |
| test_transfer_.length = 20; |
| EXPECT_EQ(test_transfer_.length, transfer_.GetLength()); |
| } |
| |
| TEST_F(UsbTransferTest, GetActualLength) { |
| EXPECT_EQ(0, transfer_.GetLength()); |
| |
| InjectTestLibUsbTransfer(); |
| |
| test_transfer_.actual_length = 10; |
| EXPECT_EQ(test_transfer_.actual_length, transfer_.GetActualLength()); |
| } |
| |
| TEST_F(UsbTransferTest, IsCompletedWithExpectedLength) { |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(0)); |
| |
| InjectTestLibUsbTransfer(); |
| |
| test_transfer_.actual_length = 5; |
| test_transfer_.status = LIBUSB_TRANSFER_COMPLETED; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.actual_length = 10; |
| EXPECT_TRUE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_ERROR; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_TIMED_OUT; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_CANCELLED; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_STALL; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_NO_DEVICE; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| |
| test_transfer_.status = LIBUSB_TRANSFER_OVERFLOW; |
| EXPECT_FALSE(transfer_.IsCompletedWithExpectedLength(10)); |
| } |
| |
| TEST_F(UsbTransferTest, VerifyAllocated) { |
| EXPECT_FALSE(transfer_.VerifyAllocated()); |
| EXPECT_EQ(UsbError::kErrorTransferNotAllocated, transfer_.error().type()); |
| } |
| |
| TEST_F(UsbTransferTest, AllocateAfterAllocate) { |
| InjectTestLibUsbTransfer(); |
| EXPECT_FALSE(transfer_.Allocate(0)); |
| EXPECT_EQ(UsbError::kErrorTransferAlreadyAllocated, transfer_.error().type()); |
| } |
| |
| TEST_F(UsbTransferTest, FreeBeforeAllocate) { |
| // Free() without calling Allocate() should be ok. |
| transfer_.Free(); |
| } |
| |
| TEST_F(UsbTransferTest, AllocateBuffer) { |
| // Allocate a zero-size buffer should be ok. |
| EXPECT_TRUE(transfer_.AllocateBuffer(0)); |
| EXPECT_NE(nullptr, transfer_.buffer()); |
| EXPECT_EQ(0, transfer_.buffer_length()); |
| |
| // Re-allocate the buffer should be ok. |
| const uint8_t kTestData[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| EXPECT_TRUE(transfer_.AllocateBuffer(arraysize(kTestData))); |
| EXPECT_NE(nullptr, transfer_.buffer()); |
| EXPECT_EQ(arraysize(kTestData), transfer_.buffer_length()); |
| // Write to the allocated buffer and then read from it to ensure the buffer |
| // is properly allocated. |
| memcpy(transfer_.buffer(), kTestData, arraysize(kTestData)); |
| EXPECT_EQ(0, memcmp(transfer_.buffer(), kTestData, arraysize(kTestData))); |
| } |
| |
| TEST_F(UsbTransferTest, AllocateBufferAfterSubmit) { |
| PretendTransferInProgress(); |
| EXPECT_FALSE(transfer_.AllocateBuffer(0)); |
| EXPECT_EQ(UsbTransfer::kInProgress, transfer_.state()); |
| EXPECT_EQ(UsbError::kErrorTransferAlreadySubmitted, transfer_.error().type()); |
| } |
| |
| TEST_F(UsbTransferTest, SubmitBeforeAllocate) { |
| EXPECT_FALSE(transfer_.Submit(UsbTransfer::CompletionCallback())); |
| EXPECT_EQ(UsbTransfer::kIdle, transfer_.state()); |
| EXPECT_EQ(UsbError::kErrorTransferNotAllocated, transfer_.error().type()); |
| } |
| |
| TEST_F(UsbTransferTest, SubmitBeforeComplete) { |
| InjectTestLibUsbTransfer(); |
| PretendTransferInProgress(); |
| EXPECT_FALSE(transfer_.Submit(UsbTransfer::CompletionCallback())); |
| EXPECT_EQ(UsbTransfer::kInProgress, transfer_.state()); |
| EXPECT_EQ(UsbError::kErrorTransferAlreadySubmitted, transfer_.error().type()); |
| } |
| |
| TEST_F(UsbTransferTest, CancelBeforeSubmit) { |
| EXPECT_FALSE(transfer_.Cancel()); |
| EXPECT_EQ(UsbTransfer::kIdle, transfer_.state()); |
| EXPECT_EQ(UsbError::kErrorTransferNotSubmitted, transfer_.error().type()); |
| } |
| |
| TEST_F(UsbTransferTest, CancelWhileBeingCancelled) { |
| PretendTransferBeingCancelled(); |
| EXPECT_FALSE(transfer_.Cancel()); |
| EXPECT_EQ(UsbTransfer::kCancelling, transfer_.state()); |
| EXPECT_EQ(UsbError::kErrorTransferBeingCancelled, transfer_.error().type()); |
| } |
| |
| } // namespace mist |