Home | History | Annotate | Download | only in test
      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