blob: 1471cdedfbc7fd6f31090583559f44b52301fddc [file] [log] [blame]
Wyatt Hepler7b62e932021-08-10 23:57:10 -07001// Copyright 2021 The Pigweed Authors
Wyatt Heplerecb85ed2020-12-04 15:45:24 -08002//
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_stream/stream.h"
16
17#include <limits>
18
19#include "gtest/gtest.h"
20#include "pw_stream/null_stream.h"
21
22namespace pw::stream {
23namespace {
24
Wyatt Hepler7b62e932021-08-10 23:57:10 -070025static_assert(sizeof(Stream) <= 2 * sizeof(void*),
26 "Stream should be no larger than two pointers (vtable pointer & "
27 "packed members)");
28
29class TestNonSeekableReader : public NonSeekableReader {
30 private:
31 StatusWithSize DoRead(ByteSpan) override { return StatusWithSize(0); }
32};
33
34class TestRelativeSeekableReader : public RelativeSeekableReader {
35 private:
36 StatusWithSize DoRead(ByteSpan) override { return StatusWithSize(0); }
37 Status DoSeek(ssize_t, Whence) override { return Status(); }
38};
39
40class TestSeekableReader : public SeekableReader {
41 private:
42 StatusWithSize DoRead(ByteSpan) override { return StatusWithSize(0); }
43 Status DoSeek(ssize_t, Whence) override { return Status(); }
44};
45
46class TestNonSeekableWriter : public NonSeekableWriter {
47 private:
48 Status DoWrite(ConstByteSpan) override { return OkStatus(); }
49};
50
51class TestRelativeSeekableWriter : public RelativeSeekableWriter {
52 private:
53 Status DoWrite(ConstByteSpan) override { return OkStatus(); }
54 Status DoSeek(ssize_t, Whence) override { return OkStatus(); }
55};
56
57class TestSeekableWriter : public SeekableWriter {
58 private:
59 Status DoWrite(ConstByteSpan) override { return OkStatus(); }
60 Status DoSeek(ssize_t, Whence) override { return OkStatus(); }
61};
62
63class TestNonSeekableReaderWriter : public NonSeekableReaderWriter {
64 private:
65 StatusWithSize DoRead(ByteSpan) override { return StatusWithSize(0); }
66 Status DoWrite(ConstByteSpan) override { return OkStatus(); }
67};
68
69class TestRelativeSeekableReaderWriter : public RelativeSeekableReaderWriter {
70 private:
71 StatusWithSize DoRead(ByteSpan) override { return StatusWithSize(0); }
72 Status DoWrite(ConstByteSpan) override { return OkStatus(); }
73 Status DoSeek(ssize_t, Whence) override { return OkStatus(); }
74};
75
76class TestSeekableReaderWriter : public SeekableReaderWriter {
77 private:
78 StatusWithSize DoRead(ByteSpan) override { return StatusWithSize(0); }
79 Status DoWrite(ConstByteSpan) override { return OkStatus(); }
80 Status DoSeek(ssize_t, Whence) override { return OkStatus(); }
81};
82
83// Test ReaderWriter conversions to Reader/Writer.
84// clang-format off
85static_assert(std::is_convertible<TestNonSeekableReaderWriter, Reader&>());
86static_assert(std::is_convertible<TestNonSeekableReaderWriter, Writer&>());
87static_assert(!std::is_convertible<TestNonSeekableReaderWriter, RelativeSeekableReader&>());
88static_assert(!std::is_convertible<TestNonSeekableReaderWriter, RelativeSeekableWriter&>());
89static_assert(!std::is_convertible<TestNonSeekableReaderWriter, SeekableWriter&>());
90static_assert(!std::is_convertible<TestNonSeekableReaderWriter, SeekableReader&>());
91
92static_assert(std::is_convertible<TestRelativeSeekableReaderWriter, Reader&>());
93static_assert(std::is_convertible<TestRelativeSeekableReaderWriter, Writer&>());
94static_assert(std::is_convertible<TestRelativeSeekableReaderWriter, RelativeSeekableReader&>());
95static_assert(std::is_convertible<TestRelativeSeekableReaderWriter, RelativeSeekableWriter&>());
96static_assert(!std::is_convertible<TestRelativeSeekableReaderWriter, SeekableWriter&>());
97static_assert(!std::is_convertible<TestRelativeSeekableReaderWriter, SeekableReader&>());
98
99static_assert(std::is_convertible<TestSeekableReaderWriter, Reader&>());
100static_assert(std::is_convertible<TestSeekableReaderWriter, Writer&>());
101static_assert(std::is_convertible<TestSeekableReaderWriter, RelativeSeekableReader&>());
102static_assert(std::is_convertible<TestSeekableReaderWriter, RelativeSeekableWriter&>());
103static_assert(std::is_convertible<TestSeekableReaderWriter, SeekableWriter&>());
104static_assert(std::is_convertible<TestSeekableReaderWriter, SeekableReader&>());
105// clang-format on
106
107constexpr uint8_t kSeekable =
108 Stream::kBeginning | Stream::kCurrent | Stream::kEnd;
109constexpr uint8_t kRelativeSeekable = Stream::kCurrent;
110constexpr uint8_t kNonSeekable = 0;
111
112enum Readable : bool { kNonReadable = false, kReadable = true };
113enum Writable : bool { kNonWritable = false, kWritable = true };
114
115template <typename T, Readable readable, Writable writable, uint8_t seekable>
116void TestStreamImpl() {
117 T derived_stream;
118 Stream& stream = derived_stream;
119
120 // Check stream properties
121 ASSERT_EQ(writable, stream.writable());
122 ASSERT_EQ(readable, stream.readable());
123
124 ASSERT_EQ((seekable & Stream::kBeginning) != 0,
125 stream.seekable(Stream::kBeginning));
126 ASSERT_EQ((seekable & Stream::kCurrent) != 0,
127 stream.seekable(Stream::kCurrent));
128 ASSERT_EQ((seekable & Stream::kEnd) != 0, stream.seekable(Stream::kEnd));
129
130 ASSERT_EQ(seekable != kNonSeekable, stream.seekable());
131
132 // Check Read()/Write()/Seek()
133 ASSERT_EQ(readable ? OkStatus() : Status::Unimplemented(),
134 stream.Read({}).status());
135 ASSERT_EQ(writable ? OkStatus() : Status::Unimplemented(), stream.Write({}));
136 ASSERT_EQ(seekable ? OkStatus() : Status::Unimplemented(), stream.Seek(0));
137
138 // Check ConservativeLimits()
139 ASSERT_EQ(readable ? Stream::kUnlimited : 0, stream.ConservativeReadLimit());
140 ASSERT_EQ(writable ? Stream::kUnlimited : 0, stream.ConservativeWriteLimit());
Wyatt Heplerecb85ed2020-12-04 15:45:24 -0800141}
142
Wyatt Hepler7b62e932021-08-10 23:57:10 -0700143TEST(Stream, NonSeekableReader) {
144 TestStreamImpl<TestNonSeekableReader,
145 kReadable,
146 kNonWritable,
147 kNonSeekable>();
Wyatt Heplerecb85ed2020-12-04 15:45:24 -0800148}
149
Wyatt Hepler7b62e932021-08-10 23:57:10 -0700150TEST(Stream, RelativeSeekableReader) {
151 TestStreamImpl<TestRelativeSeekableReader,
152 kReadable,
153 kNonWritable,
154 kRelativeSeekable>();
155}
156
157TEST(Stream, SeekableReader) {
158 TestStreamImpl<TestSeekableReader, kReadable, kNonWritable, kSeekable>();
159}
160
161TEST(Stream, NonSeekableWriter) {
162 TestStreamImpl<TestNonSeekableWriter,
163 kNonReadable,
164 kWritable,
165 kNonSeekable>();
166}
167
168TEST(Stream, RelativeSeekableWriter) {
169 TestStreamImpl<TestRelativeSeekableWriter,
170 kNonReadable,
171 kWritable,
172 kRelativeSeekable>();
173}
174
175TEST(Stream, SeekableWriter) {
176 TestStreamImpl<TestSeekableWriter, kNonReadable, kWritable, kSeekable>();
177}
178
179TEST(Stream, NonSeekableReaderWriter) {
180 TestStreamImpl<TestNonSeekableReaderWriter,
181 kReadable,
182 kWritable,
183 kNonSeekable>();
184}
185
186TEST(Stream, RelativeSeekableReaderWriter) {
187 TestStreamImpl<TestRelativeSeekableReaderWriter,
188 kReadable,
189 kWritable,
190 kRelativeSeekable>();
191}
192
193TEST(Stream, SeekableReaderWriter) {
194 TestStreamImpl<TestSeekableReaderWriter, kReadable, kWritable, kSeekable>();
195}
196
197TEST(NullStream, DefaultConservativeWriteLimit) {
198 NullStream stream;
199 EXPECT_EQ(stream.ConservativeWriteLimit(), Stream::kUnlimited);
200}
201
202TEST(NullStream, DefaultConservativeReadLimit) {
203 NullStream stream;
204 EXPECT_EQ(stream.ConservativeReadLimit(), Stream::kUnlimited);
205}
206
207TEST(NullStream, DefaultConservativeReadWriteLimit) {
208 NullStream stream;
209 EXPECT_EQ(stream.ConservativeWriteLimit(), Stream::kUnlimited);
210 EXPECT_EQ(stream.ConservativeReadLimit(), Stream::kUnlimited);
211}
212
213TEST(NullStream, DefaultTell) {
214 NullStream stream;
215 EXPECT_EQ(stream.Tell(), Stream::kUnknownPosition);
Yecheng Zhao78d07302021-06-09 11:10:07 -0700216}
217
Wyatt Heplerecb85ed2020-12-04 15:45:24 -0800218} // namespace
219} // namespace pw::stream