1 /*
2  * Copyright 2019 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 "common/bidi_queue.h"
18 
19 #include <future>
20 
21 #include "common/bind.h"
22 #include "gtest/gtest.h"
23 #include "os/handler.h"
24 #include "os/thread.h"
25 
26 using ::bluetooth::os::Handler;
27 using ::bluetooth::os::Thread;
28 
29 namespace bluetooth {
30 namespace common {
31 namespace {
32 
33 class BidiQueueTest : public ::testing::Test {
34 protected:
SetUp()35   void SetUp() override {
36     up_thread_ = new Thread("up_thread", Thread::Priority::NORMAL);
37     up_handler_ = new Handler(up_thread_);
38     down_thread_ = new Thread("down_thread", Thread::Priority::NORMAL);
39     down_handler_ = new Handler(down_thread_);
40   }
41 
TearDown()42   void TearDown() override {
43     delete up_handler_;
44     delete up_thread_;
45     delete down_handler_;
46     delete down_thread_;
47   }
48 
49   Thread* up_thread_;
50   Handler* up_handler_;
51   Thread* down_thread_;
52   Handler* down_handler_;
53 };
54 
55 class A {};
56 
57 class B {};
58 
59 template <typename TA, typename TB>
60 class TestBidiQueueEnd {
61 public:
TestBidiQueueEnd(BidiQueueEnd<TA,TB> * end,Handler * handler)62   explicit TestBidiQueueEnd(BidiQueueEnd<TA, TB>* end, Handler* handler)
63       : handler_(handler), end_(end) {}
64 
~TestBidiQueueEnd()65   ~TestBidiQueueEnd() { handler_->Clear(); }
66 
Send(TA * value)67   std::promise<void>* Send(TA* value) {
68     std::promise<void>* promise = new std::promise<void>();
69     handler_->Post(BindOnce(&TestBidiQueueEnd<TA, TB>::handle_send, common::Unretained(this),
70                             common::Unretained(value), common::Unretained(promise)));
71     return promise;
72   }
73 
Receive()74   std::promise<TB*>* Receive() {
75     std::promise<TB*>* promise = new std::promise<TB*>();
76     handler_->Post(BindOnce(&TestBidiQueueEnd<TA, TB>::handle_receive, common::Unretained(this),
77                             common::Unretained(promise)));
78 
79     return promise;
80   }
81 
handle_send(TA * value,std::promise<void> * promise)82   void handle_send(TA* value, std::promise<void>* promise) {
83     end_->RegisterEnqueue(handler_, Bind(&TestBidiQueueEnd<TA, TB>::handle_register_enqueue,
84                                          common::Unretained(this), common::Unretained(value),
85                                          common::Unretained(promise)));
86   }
87 
handle_register_enqueue(TA * value,std::promise<void> * promise)88   std::unique_ptr<TA> handle_register_enqueue(TA* value, std::promise<void>* promise) {
89     end_->UnregisterEnqueue();
90     promise->set_value();
91     return std::unique_ptr<TA>(value);
92   }
93 
handle_receive(std::promise<TB * > * promise)94   void handle_receive(std::promise<TB*>* promise) {
95     end_->RegisterDequeue(handler_, Bind(&TestBidiQueueEnd<TA, TB>::handle_register_dequeue,
96                                          common::Unretained(this), common::Unretained(promise)));
97   }
98 
handle_register_dequeue(std::promise<TB * > * promise)99   void handle_register_dequeue(std::promise<TB*>* promise) {
100     end_->UnregisterDequeue();
101     promise->set_value(end_->TryDequeue().get());
102   }
103 
104 private:
105   Handler* handler_;
106   BidiQueueEnd<TA, TB>* end_;
107 };
108 
TEST_F(BidiQueueTest,simple_test)109 TEST_F(BidiQueueTest, simple_test) {
110   BidiQueue<A, B> queue(100);
111   TestBidiQueueEnd<B, A> test_up(queue.GetUpEnd(), up_handler_);
112   TestBidiQueueEnd<A, B> test_down(queue.GetDownEnd(), down_handler_);
113 
114   auto sending_b = new B();
115   auto promise_sending_b = test_up.Send(sending_b);
116   promise_sending_b->get_future().wait();
117   auto promise_receive_b = test_down.Receive();
118   EXPECT_EQ(promise_receive_b->get_future().get(), sending_b);
119   delete promise_receive_b;
120   delete promise_sending_b;
121 
122   auto sending_a = new A();
123   auto promise_sending_a = test_down.Send(sending_a);
124   promise_sending_a->get_future().wait();
125   auto promise_receive_a = test_up.Receive();
126   EXPECT_EQ(promise_receive_a->get_future().get(), sending_a);
127   delete promise_receive_a;
128   delete promise_sending_a;
129 }
130 
131 }  // namespace
132 }  // namespace common
133 }  // namespace bluetooth
134