1 // 2 // Copyright 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "vendor_libs/test_vendor_lib/include/command_packet.h" 18 #include "vendor_libs/test_vendor_lib/include/hci_transport.h" 19 20 #include "base/bind.h" 21 #include "base/message_loop/message_loop.h" 22 #include "base/threading/thread.h" 23 24 #include <gtest/gtest.h> 25 #include <functional> 26 #include <mutex> 27 28 extern "C" { 29 #include "stack/include/hcidefs.h" 30 } // extern "C" 31 32 namespace { 33 const std::vector<uint8_t> stub_command({DATA_TYPE_COMMAND, 34 static_cast<uint8_t>(HCI_RESET), 35 static_cast<uint8_t>(HCI_RESET >> 8), 36 0}); 37 38 const int kMultiIterations = 10000; 39 40 void WriteStubCommand(int fd) { 41 write(fd, &stub_command[0], stub_command.size()); 42 } 43 44 } // namespace 45 46 namespace test_vendor_lib { 47 48 class HciTransportTest : public ::testing::Test { 49 public: 50 HciTransportTest() 51 : command_callback_count_(0), 52 thread_("HciTransportTest"), 53 weak_ptr_factory_(this) { 54 SetUpTransport(); 55 StartThread(); 56 PostStartWatchingOnThread(); 57 } 58 59 ~HciTransportTest() { 60 transport_.CloseHciFd(); 61 } 62 63 void CommandCallback(std::unique_ptr<CommandPacket> command) { 64 ++command_callback_count_; 65 // Ensure that the received packet matches the stub command. 66 EXPECT_EQ(DATA_TYPE_COMMAND, command->GetType()); 67 EXPECT_EQ(HCI_RESET, command->GetOpcode()); 68 EXPECT_EQ(0, command->GetPayloadSize()); 69 transport_.CloseVendorFd(); 70 } 71 72 void MultiCommandCallback(std::unique_ptr<CommandPacket> command) { 73 ++command_callback_count_; 74 // Ensure that the received packet matches the stub command. 75 EXPECT_EQ(DATA_TYPE_COMMAND, command->GetType()); 76 EXPECT_EQ(HCI_RESET, command->GetOpcode()); 77 EXPECT_EQ(0, command->GetPayloadSize()); 78 if (command_callback_count_ == kMultiIterations) 79 transport_.CloseVendorFd(); 80 } 81 82 protected: 83 // Tracks the number of commands received. 84 int command_callback_count_; 85 base::Thread thread_; 86 HciTransport transport_; 87 base::MessageLoopForIO::FileDescriptorWatcher watcher_; 88 base::WeakPtrFactory<HciTransportTest> weak_ptr_factory_; 89 90 private: 91 // Workaround because ASSERT cannot be used directly in a constructor 92 void SetUpTransport() { 93 ASSERT_TRUE(transport_.SetUp()); 94 } 95 96 void StartThread() { 97 ASSERT_TRUE(thread_.StartWithOptions( 98 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 99 } 100 101 void PostStartWatchingOnThread() { 102 thread_.task_runner()->PostTask( 103 FROM_HERE, base::Bind(&HciTransportTest::StartWatchingOnThread, 104 weak_ptr_factory_.GetWeakPtr())); 105 } 106 107 void StartWatchingOnThread() { 108 base::MessageLoopForIO* loop = 109 static_cast<base::MessageLoopForIO*>(thread_.message_loop()); 110 ASSERT_TRUE(loop); 111 ASSERT_TRUE(loop->WatchFileDescriptor( 112 transport_.GetVendorFd(), true, 113 base::MessageLoopForIO::WATCH_READ_WRITE, &watcher_, &transport_)); 114 } 115 }; 116 117 TEST_F(HciTransportTest, SingleCommandCallback) { 118 transport_.RegisterCommandHandler(std::bind( 119 &HciTransportTest::CommandCallback, this, std::placeholders::_1)); 120 EXPECT_EQ(0, command_callback_count_); 121 WriteStubCommand(transport_.GetHciFd()); 122 thread_.Stop(); // Wait for the command handler to finish. 123 EXPECT_EQ(1, command_callback_count_); 124 } 125 126 TEST_F(HciTransportTest, MultiCommandCallback) { 127 transport_.RegisterCommandHandler(std::bind( 128 &HciTransportTest::MultiCommandCallback, this, std::placeholders::_1)); 129 EXPECT_EQ(0, command_callback_count_); 130 WriteStubCommand(transport_.GetHciFd()); 131 for (int i = 1; i < kMultiIterations; ++i) 132 WriteStubCommand(transport_.GetHciFd()); 133 thread_.Stop(); // Wait for the command handler to finish. 134 EXPECT_EQ(kMultiIterations, command_callback_count_); 135 } 136 137 // TODO(dennischeng): Add tests for PostEventResponse and 138 // PostDelayedEventResponse. 139 140 } // namespace test_vendor_lib 141