xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/testing/controller_test_double_base.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test_double_base.h"
16 
17 namespace bt::testing {
18 
ControllerTestDoubleBase(pw::async::Dispatcher & pw_dispatcher)19 ControllerTestDoubleBase::ControllerTestDoubleBase(
20     pw::async::Dispatcher& pw_dispatcher)
21     : pw_dispatcher_(pw_dispatcher), heap_dispatcher_(pw_dispatcher) {}
22 
~ControllerTestDoubleBase()23 ControllerTestDoubleBase::~ControllerTestDoubleBase() {
24   // When this destructor gets called any subclass state will be undefined. If
25   // Stop() has not been called before reaching this point this can cause
26   // runtime errors when our event loop handlers attempt to invoke the pure
27   // virtual methods of this class.
28 }
29 
SendCommandChannelPacket(const ByteBuffer & packet)30 bool ControllerTestDoubleBase::SendCommandChannelPacket(
31     const ByteBuffer& packet) {
32   if (!event_cb_) {
33     return false;
34   }
35 
36   // Post packet to simulate async behavior that many tests expect.
37   DynamicByteBuffer buffer(packet);
38   auto self = weak_self_.GetWeakPtr();
39   (void)heap_dispatcher().Post(
40       [self, buffer = std::move(buffer)](pw::async::Context /*ctx*/,
41                                          pw::Status status) {
42         if (self.is_alive() && status.ok()) {
43           self->event_cb_({reinterpret_cast<const std::byte*>(buffer.data()),
44                            buffer.size()});
45         }
46       });
47   return true;
48 }
49 
SendACLDataChannelPacket(const ByteBuffer & packet)50 bool ControllerTestDoubleBase::SendACLDataChannelPacket(
51     const ByteBuffer& packet) {
52   if (!acl_cb_) {
53     return false;
54   }
55 
56   // Post packet to simulate async behavior that some tests expect.
57   DynamicByteBuffer buffer(packet);
58   auto self = weak_self_.GetWeakPtr();
59   (void)heap_dispatcher().Post(
60       [self, buffer = std::move(buffer)](pw::async::Context /*ctx*/,
61                                          pw::Status status) {
62         if (self.is_alive() && status.ok()) {
63           self->acl_cb_({reinterpret_cast<const std::byte*>(buffer.data()),
64                          buffer.size()});
65         }
66       });
67   return true;
68 }
69 
SendScoDataChannelPacket(const ByteBuffer & packet)70 bool ControllerTestDoubleBase::SendScoDataChannelPacket(
71     const ByteBuffer& packet) {
72   if (!sco_cb_) {
73     return false;
74   }
75 
76   sco_cb_({reinterpret_cast<const std::byte*>(packet.data()), packet.size()});
77   return true;
78 }
79 
SendIsoDataChannelPacket(const pw::span<const std::byte> & packet)80 bool ControllerTestDoubleBase::SendIsoDataChannelPacket(
81     const pw::span<const std::byte>& packet) {
82   if (!iso_cb_) {
83     return false;
84   }
85 
86   iso_cb_(packet);
87   return true;
88 }
89 
Initialize(PwStatusCallback complete_callback,PwStatusCallback error_callback)90 void ControllerTestDoubleBase::Initialize(PwStatusCallback complete_callback,
91                                           PwStatusCallback error_callback) {
92   error_cb_ = std::move(error_callback);
93   complete_callback(PW_STATUS_OK);
94 }
95 
Close(PwStatusCallback callback)96 void ControllerTestDoubleBase::Close(PwStatusCallback callback) {
97   event_cb_ = nullptr;
98   acl_cb_ = nullptr;
99   sco_cb_ = nullptr;
100   callback(PW_STATUS_OK);
101 }
102 
ConfigureSco(ScoCodingFormat coding_format,ScoEncoding encoding,ScoSampleRate sample_rate,pw::Callback<void (pw::Status)> callback)103 void ControllerTestDoubleBase::ConfigureSco(
104     ScoCodingFormat coding_format,
105     ScoEncoding encoding,
106     ScoSampleRate sample_rate,
107     pw::Callback<void(pw::Status)> callback) {
108   if (!configure_sco_cb_) {
109     return;
110   }
111 
112   // Post the callback to simulate async behavior with a real controller.
113   auto callback_wrapper =
114       [dispatcher = &pw_dispatcher_,
115        cb = std::move(callback)](pw::Status cb_status) mutable {
116         (void)pw::async::HeapDispatcher(*dispatcher)
117             .Post([cb_status, cb = std::move(cb)](pw::async::Context /*ctx*/,
118                                                   pw::Status status) mutable {
119               if (status.ok()) {
120                 cb(cb_status);
121               }
122             });
123       };
124   configure_sco_cb_(
125       coding_format, encoding, sample_rate, std::move(callback_wrapper));
126 }
127 
ResetSco(pw::Callback<void (pw::Status)> callback)128 void ControllerTestDoubleBase::ResetSco(
129     pw::Callback<void(pw::Status)> callback) {
130   if (!reset_sco_cb_) {
131     return;
132   }
133 
134   // Post the callback to simulate async behavior with a real controller.
135   auto callback_wrapper =
136       [dispatcher = &pw_dispatcher_,
137        cb = std::move(callback)](pw::Status cb_status) mutable {
138         (void)pw::async::HeapDispatcher(*dispatcher)
139             .Post([cb_status, cb = std::move(cb)](pw::async::Context /*ctx*/,
140                                                   pw::Status status) mutable {
141               if (status.ok()) {
142                 cb(cb_status);
143               }
144             });
145       };
146   reset_sco_cb_(std::move(callback_wrapper));
147 }
148 
149 }  // namespace bt::testing
150