• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 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_proxy/internal/multibuf_writer.h"
16 
17 #include <array>
18 
19 #include "pw_containers/to_array.h"
20 #include "pw_multibuf/simple_allocator_for_test.h"
21 #include "pw_span/cast.h"
22 #include "pw_unit_test/framework.h"
23 
24 namespace pw::bluetooth::proxy {
25 namespace {
26 
27 using pw::containers::to_array;
28 
29 class MultiBufWriterTest : public testing::Test {
30  protected:
31   pw::multibuf::test::SimpleAllocatorForTest</*kDataSizeBytes=*/512,
32                                              /*kMetaSizeBytes=*/512>
33       allocator;
34 };
35 
TEST_F(MultiBufWriterTest,CanCreate)36 TEST_F(MultiBufWriterTest, CanCreate) {
37   pw::Result<MultiBufWriter> writer = MultiBufWriter::Create(allocator, 8u);
38   PW_TEST_ASSERT_OK(writer);
39   EXPECT_FALSE(writer->IsComplete());
40   EXPECT_EQ(writer->U8Span().size(), 0u);
41 }
42 
TEST_F(MultiBufWriterTest,CanWrite)43 TEST_F(MultiBufWriterTest, CanWrite) {
44   pw::Result<MultiBufWriter> writer = MultiBufWriter::Create(allocator, 8u);
45   PW_TEST_ASSERT_OK(writer);
46 
47   static constexpr auto kExpectedData =
48       to_array<uint8_t>({0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88});
49 
50   // Write first chunk
51   PW_TEST_EXPECT_OK(writer->Write(to_array<uint8_t>({0x11, 0x22, 0x33, 0x44})));
52   EXPECT_FALSE(writer->IsComplete());
53   EXPECT_EQ(writer->U8Span().size(), 4u);
54 
55   // Write second chunk
56   PW_TEST_EXPECT_OK(writer->Write(to_array<uint8_t>({0x55, 0x66, 0x77, 0x88})));
57   EXPECT_TRUE(writer->IsComplete());
58   EXPECT_EQ(writer->U8Span().size(), 8u);
59   EXPECT_TRUE(std::equal(writer->U8Span().begin(),
60                          writer->U8Span().end(),
61                          kExpectedData.begin(),
62                          kExpectedData.end()));
63 }
64 
TEST_F(MultiBufWriterTest,CannotWriteMoreThanRemains)65 TEST_F(MultiBufWriterTest, CannotWriteMoreThanRemains) {
66   pw::Result<MultiBufWriter> writer = MultiBufWriter::Create(allocator, 5u);
67   PW_TEST_ASSERT_OK(writer);
68 
69   // Write first chunk
70   PW_TEST_EXPECT_OK(writer->Write(to_array<uint8_t>({0x11, 0x22, 0x33, 0x44})));
71   EXPECT_FALSE(writer->IsComplete());
72   EXPECT_EQ(writer->U8Span().size(), 4u);
73 
74   // Cannot write second chunk (one byte too big)
75   EXPECT_EQ(writer->Write(to_array<uint8_t>({0x55, 0x66})),
76             Status::ResourceExhausted());
77   EXPECT_FALSE(writer->IsComplete());
78   EXPECT_EQ(writer->U8Span().size(), 4u);
79 }
80 
TEST_F(MultiBufWriterTest,CanTakeMultiBuf)81 TEST_F(MultiBufWriterTest, CanTakeMultiBuf) {
82   pw::Result<MultiBufWriter> writer = MultiBufWriter::Create(allocator, 8u);
83   PW_TEST_ASSERT_OK(writer);
84 
85   static constexpr auto kData =
86       to_array<uint8_t>({0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88});
87 
88   PW_TEST_EXPECT_OK(writer->Write(kData));
89   ASSERT_TRUE(writer->IsComplete());
90 
91   // Take the MultiBuf from the MultiBufWriter
92   multibuf::MultiBuf mbuf = std::move(writer->TakeMultiBuf());
93   EXPECT_EQ(mbuf.size(), 8u);
94 
95   std::optional<ByteSpan> mbuf_span = mbuf.ContiguousSpan();
96   ASSERT_TRUE(bool(mbuf_span));
97   pw::span<uint8_t> mbuf_u8_span = pw::span_cast<uint8_t>(*mbuf_span);
98   EXPECT_TRUE(std::equal(
99       mbuf_u8_span.begin(), mbuf_u8_span.end(), kData.begin(), kData.end()));
100 
101   // IsComplete() returns true
102   EXPECT_TRUE(writer->IsComplete());
103 
104   // Can no longer write
105   EXPECT_NE(writer->Write(kData), OkStatus());
106 
107   // Calling it again results in an empty multibuf.
108   multibuf::MultiBuf mbuf2 = std::move(writer->TakeMultiBuf());
109   EXPECT_EQ(mbuf2.size(), 0u);
110 }
111 
112 }  // namespace
113 }  // namespace pw::bluetooth::proxy
114