Line data Source code
1 : // Copyright (c) 2018-2025 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : /** \file
20 : * \brief Verify that the vector_streambuf class works.
21 : *
22 : * This file implements tests for the vector_streambuf class to make
23 : * sure that the flags are indeed safe.
24 : */
25 :
26 : // self
27 : //
28 : #include <snapdev/vector_streambuf.h>
29 :
30 : #include "catch_main.h"
31 :
32 :
33 : // C++
34 : //
35 : #include <sstream>
36 :
37 :
38 : // last include
39 : //
40 : #include <snapdev/poison.h>
41 :
42 :
43 :
44 :
45 3 : CATCH_TEST_CASE("vector_streambuf", "[stream]")
46 : {
47 3 : CATCH_START_SECTION("vector_streambuf: verify read & seek capability")
48 : {
49 3 : std::vector<char> data{ 1, 2, 3, 4, 5, 6, 7 };
50 :
51 1 : snapdev::vector_streambuf buf(data);
52 :
53 1 : std::istream in(&buf);
54 :
55 1 : CATCH_REQUIRE(in.tellg() == 0);
56 1 : CATCH_REQUIRE(in.get() == 1);
57 1 : CATCH_REQUIRE(in.tellg() == 1);
58 1 : CATCH_REQUIRE(in.get() == 2);
59 1 : CATCH_REQUIRE(in.tellg() == 2);
60 1 : CATCH_REQUIRE(in.get() == 3);
61 1 : CATCH_REQUIRE(in.tellg() == 3);
62 1 : CATCH_REQUIRE(in.get() == 4);
63 1 : CATCH_REQUIRE(in.tellg() == 4);
64 1 : CATCH_REQUIRE(in.get() == 5);
65 1 : CATCH_REQUIRE(in.tellg() == 5);
66 1 : CATCH_REQUIRE(in.get() == 6);
67 1 : CATCH_REQUIRE(in.tellg() == 6);
68 1 : CATCH_REQUIRE(in.get() == 7);
69 1 : CATCH_REQUIRE(in.tellg() == 7);
70 :
71 1 : CATCH_REQUIRE(in.get() == EOF);
72 1 : CATCH_REQUIRE(in.tellg() == -1); // when eof() is true, the returned position is always -1
73 1 : CATCH_REQUIRE(in.get() == EOF);
74 1 : CATCH_REQUIRE(in.tellg() == -1);
75 1 : CATCH_REQUIRE(in.get() == EOF);
76 1 : CATCH_REQUIRE(in.tellg() == -1);
77 :
78 1 : in.clear(); // clear EOF
79 1 : in.seekg(4);
80 1 : CATCH_REQUIRE(in.get() == 5);
81 :
82 1 : in.seekg(-10);
83 1 : CATCH_REQUIRE(in.get() == 1);
84 :
85 1 : in.seekg(10);
86 1 : CATCH_REQUIRE(in.get() == EOF);
87 :
88 1 : in.clear(); // clear EOF
89 1 : in.seekg(-4, std::ios_base::end);
90 1 : CATCH_REQUIRE(in.get() == 4);
91 1 : CATCH_REQUIRE(in.get() == 5);
92 :
93 : // our exception gets swallowed by default, but the fail bit gets
94 : // set as expected
95 : //
96 1 : CATCH_REQUIRE_FALSE(in.fail());
97 1 : in.seekg(-4, static_cast<std::ios_base::seekdir>(100));
98 1 : CATCH_REQUIRE(in.fail());
99 1 : }
100 3 : CATCH_END_SECTION()
101 :
102 3 : CATCH_START_SECTION("vector_streambuf: verify read, write & seek capability")
103 : {
104 3 : std::vector<char> data{ 1, 2, 3, 4, 5, 6, 7 };
105 :
106 1 : snapdev::vector_streambuf buf(data);
107 :
108 1 : std::iostream s(&buf);
109 :
110 : // as above, we can read up to EOF
111 : //
112 1 : CATCH_REQUIRE(s.tellg() == 0);
113 1 : CATCH_REQUIRE(s.get() == 1);
114 1 : CATCH_REQUIRE(s.tellg() == 1);
115 1 : CATCH_REQUIRE(s.get() == 2);
116 1 : CATCH_REQUIRE(s.tellg() == 2);
117 1 : CATCH_REQUIRE(s.get() == 3);
118 1 : CATCH_REQUIRE(s.tellg() == 3);
119 1 : CATCH_REQUIRE(s.get() == 4);
120 1 : CATCH_REQUIRE(s.tellg() == 4);
121 1 : CATCH_REQUIRE(s.get() == 5);
122 1 : CATCH_REQUIRE(s.tellg() == 5);
123 1 : CATCH_REQUIRE(s.get() == 6);
124 1 : CATCH_REQUIRE(s.tellg() == 6);
125 1 : CATCH_REQUIRE(s.get() == 7);
126 1 : CATCH_REQUIRE(s.tellg() == 7);
127 :
128 1 : CATCH_REQUIRE(s.get() == EOF);
129 1 : s.clear(); // clear EOF
130 :
131 1 : s.seekp(4);
132 1 : CATCH_REQUIRE(s.tellp() == 4);
133 1 : s.put(10);
134 1 : CATCH_REQUIRE_FALSE(s.fail());
135 1 : CATCH_REQUIRE(s.tellp() == 5);
136 1 : s.put(11);
137 1 : CATCH_REQUIRE_FALSE(s.fail());
138 1 : CATCH_REQUIRE(s.tellp() == 6);
139 1 : s.put(12);
140 1 : CATCH_REQUIRE_FALSE(s.fail());
141 1 : CATCH_REQUIRE(s.tellp() == 7);
142 :
143 1 : s.seekg(4);
144 1 : CATCH_REQUIRE(s.get() == 10);
145 1 : CATCH_REQUIRE(s.get() == 11);
146 1 : CATCH_REQUIRE(s.get() == 12);
147 :
148 1 : CATCH_REQUIRE(s.get() == EOF);
149 :
150 1 : s.clear();
151 1 : s.seekp(-10);
152 1 : CATCH_REQUIRE(s.tellp() == 0);
153 1 : s.seekp(10);
154 1 : CATCH_REQUIRE(s.tellp() == 7);
155 1 : s.seekp(-4, std::ios_base::end);
156 1 : CATCH_REQUIRE(s.tellp() == 3);
157 1 : s.put(20);
158 1 : s.put(21);
159 1 : s.put(22);
160 1 : s.seekg(3);
161 1 : CATCH_REQUIRE(s.get() == 20);
162 1 : CATCH_REQUIRE(s.get() == 21);
163 1 : CATCH_REQUIRE(s.get() == 22);
164 1 : CATCH_REQUIRE(s.get() == 12);
165 :
166 1 : CATCH_REQUIRE_FALSE(s.fail());
167 3 : CATCH_REQUIRE_THROWS_MATCHES(
168 : s.seekp(10, static_cast<std::ios_base::seekdir>(100))
169 : , std::ios_base::failure
170 : , Catch::Matchers::ExceptionMessage(
171 : "unknown direction in seekpos() -- out: iostream error"));
172 : //CATCH_REQUIRE(s.fail()); -- that doesn't change, just the exception
173 1 : }
174 3 : CATCH_END_SECTION()
175 :
176 3 : CATCH_START_SECTION("vector_streambuf: verify read, write & seek capability with a read-only vector")
177 : {
178 3 : std::vector<char> const data{ 1, 2, 3, 4, 5, 6, 7 };
179 :
180 1 : snapdev::vector_streambuf buf(data);
181 :
182 1 : std::iostream s(&buf);
183 :
184 : // as above, we can read up to EOF
185 : //
186 1 : CATCH_REQUIRE(s.tellg() == 0);
187 1 : CATCH_REQUIRE(s.get() == 1);
188 1 : CATCH_REQUIRE(s.tellg() == 1);
189 1 : CATCH_REQUIRE(s.get() == 2);
190 1 : CATCH_REQUIRE(s.tellg() == 2);
191 1 : CATCH_REQUIRE(s.get() == 3);
192 1 : CATCH_REQUIRE(s.tellg() == 3);
193 1 : CATCH_REQUIRE(s.get() == 4);
194 1 : CATCH_REQUIRE(s.tellg() == 4);
195 1 : CATCH_REQUIRE(s.get() == 5);
196 1 : CATCH_REQUIRE(s.tellg() == 5);
197 1 : CATCH_REQUIRE(s.get() == 6);
198 1 : CATCH_REQUIRE(s.tellg() == 6);
199 1 : CATCH_REQUIRE(s.get() == 7);
200 1 : CATCH_REQUIRE(s.tellg() == 7);
201 :
202 1 : CATCH_REQUIRE(s.get() == EOF);
203 1 : s.clear(); // clear EOF
204 :
205 1 : s.seekp(4);
206 1 : CATCH_REQUIRE_FALSE(s.fail());
207 1 : s.put(10);
208 1 : CATCH_REQUIRE(s.fail());
209 1 : s.clear();
210 1 : s.put(11);
211 1 : CATCH_REQUIRE(s.fail());
212 1 : s.clear();
213 1 : s.put(12);
214 1 : CATCH_REQUIRE(s.fail());
215 1 : s.clear();
216 :
217 1 : s.seekg(4);
218 1 : CATCH_REQUIRE(s.get() == 5); // buffer not updated
219 1 : CATCH_REQUIRE(s.get() == 6);
220 1 : CATCH_REQUIRE(s.get() == 7);
221 :
222 1 : CATCH_REQUIRE(s.get() == EOF);
223 1 : }
224 3 : CATCH_END_SECTION()
225 3 : }
226 :
227 :
228 :
229 : // vim: ts=4 sw=4 et
230 :
|