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) : handler_(handler), end_(end) {}
63 
~TestBidiQueueEnd()64   ~TestBidiQueueEnd() {
65     handler_->Clear();
66   }
67 
Send(TA * value)68   std::promise<void>* Send(TA* value) {
69     std::promise<void>* promise = new std::promise<void>();
70     handler_->Post(BindOnce(
71         &TestBidiQueueEnd<TA, TB>::handle_send,
72         common::Unretained(this),
73         common::Unretained(value),
74         common::Unretained(promise)));
75     return promise;
76   }
77 
Receive()78   std::promise<TB*>* Receive() {
79     std::promise<TB*>* promise = new std::promise<TB*>();
80     handler_->Post(
81         BindOnce(&TestBidiQueueEnd<TA, TB>::handle_receive, common::Unretained(this), common::Unretained(promise)));
82 
83     return promise;
84   }
85 
handle_send(TA * value,std::promise<void> * promise)86   void handle_send(TA* value, std::promise<void>* promise) {
87     end_->RegisterEnqueue(
88         handler_,
89         Bind(
90             &TestBidiQueueEnd<TA, TB>::handle_register_enqueue,
91             common::Unretained(this),
92             common::Unretained(value),
93             common::Unretained(promise)));
94   }
95 
handle_register_enqueue(TA * value,std::promise<void> * promise)96   std::unique_ptr<TA> handle_register_enqueue(TA* value, std::promise<void>* promise) {
97     end_->UnregisterEnqueue();
98     promise->set_value();
99     return std::unique_ptr<TA>(value);
100   }
101 
handle_receive(std::promise<TB * > * promise)102   void handle_receive(std::promise<TB*>* promise) {
103     end_->RegisterDequeue(
104         handler_,
105         Bind(
106             &TestBidiQueueEnd<TA, TB>::handle_register_dequeue, common::Unretained(this), common::Unretained(promise)));
107   }
108 
handle_register_dequeue(std::promise<TB * > * promise)109   void handle_register_dequeue(std::promise<TB*>* promise) {
110     end_->UnregisterDequeue();
111     promise->set_value(end_->TryDequeue().get());
112   }
113 
114  private:
115   Handler* handler_;
116   BidiQueueEnd<TA, TB>* end_;
117 };
118 
TEST_F(BidiQueueTest,simple_test)119 TEST_F(BidiQueueTest, simple_test) {
120   BidiQueue<A, B> queue(100);
121   TestBidiQueueEnd<B, A> test_up(queue.GetUpEnd(), up_handler_);
122   TestBidiQueueEnd<A, B> test_down(queue.GetDownEnd(), down_handler_);
123 
124   auto sending_b = new B();
125   auto promise_sending_b = test_up.Send(sending_b);
126   promise_sending_b->get_future().wait();
127   auto promise_receive_b = test_down.Receive();
128   EXPECT_EQ(promise_receive_b->get_future().get(), sending_b);
129   delete promise_receive_b;
130   delete promise_sending_b;
131 
132   auto sending_a = new A();
133   auto promise_sending_a = test_down.Send(sending_a);
134   promise_sending_a->get_future().wait();
135   auto promise_receive_a = test_up.Receive();
136   EXPECT_EQ(promise_receive_a->get_future().get(), sending_a);
137   delete promise_receive_a;
138   delete promise_sending_a;
139 }
140 
141 }  // namespace
142 }  // namespace common
143 }  // namespace bluetooth
144