1 // Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include <algorithm>
6
7 #include "include/cef_stream.h"
8 #include "tests/gtest/include/gtest/gtest.h"
9
VerifyStreamReadBehavior(CefRefPtr<CefStreamReader> stream,const std::string & contents)10 static void VerifyStreamReadBehavior(CefRefPtr<CefStreamReader> stream,
11 const std::string& contents) {
12 int contentSize = static_cast<int>(contents.size());
13 const char* contentStr = contents.c_str();
14
15 // Move to the beginning of the stream
16 ASSERT_EQ(0, stream->Seek(0, SEEK_SET));
17 ASSERT_EQ(0, stream->Tell());
18
19 // Move to the end of the stream
20 ASSERT_EQ(0, stream->Seek(0, SEEK_END));
21 ASSERT_EQ(contentSize, stream->Tell());
22
23 // Move to the beginning of the stream
24 ASSERT_EQ(0, stream->Seek(-contentSize, SEEK_CUR));
25 ASSERT_EQ(0, stream->Tell());
26
27 // Read 10 characters at a time and verify the result
28 char buff[10];
29 int res, read, offset = 0;
30 do {
31 read = std::min(static_cast<int>(sizeof(buff)), contentSize - offset);
32 res = static_cast<int>(stream->Read(buff, 1, read));
33 ASSERT_EQ(read, res);
34 ASSERT_TRUE(!memcmp(contentStr + offset, buff, res));
35 offset += res;
36 } while (offset < contentSize);
37
38 // Read past the end of the file
39 stream->Read(buff, 1, 1);
40 ASSERT_TRUE(stream->Eof());
41 }
42
VerifyStreamWriteBehavior(CefRefPtr<CefStreamWriter> stream,const std::string & contents)43 static void VerifyStreamWriteBehavior(CefRefPtr<CefStreamWriter> stream,
44 const std::string& contents) {
45 int contentSize = static_cast<int>(contents.size());
46 const char* contentStr = contents.c_str();
47
48 // Write 10 characters at a time and verify the result
49 int res, write, offset = 0;
50 do {
51 write = std::min(10, contentSize - offset);
52 res = static_cast<int>(stream->Write(contentStr + offset, 1, write));
53 ASSERT_EQ(write, res);
54 offset += res;
55 ASSERT_EQ(offset, stream->Tell());
56 } while (offset < contentSize);
57
58 // Move to the beginning of the stream
59 ASSERT_EQ(0, stream->Seek(-contentSize, SEEK_CUR));
60 ASSERT_EQ(0, stream->Tell());
61
62 // Move to the end of the stream
63 ASSERT_EQ(0, stream->Seek(0, SEEK_END));
64 ASSERT_EQ(contentSize, stream->Tell());
65
66 // Move to the beginning of the stream
67 ASSERT_EQ(0, stream->Seek(0, SEEK_SET));
68 ASSERT_EQ(0, stream->Tell());
69 }
70
TEST(StreamTest,ReadFile)71 TEST(StreamTest, ReadFile) {
72 const char* fileName = "StreamTest.VerifyReadFile.txt";
73 CefString fileNameStr = "StreamTest.VerifyReadFile.txt";
74 std::string contents = "This is my test\ncontents for the file";
75
76 // Create the file
77 FILE* f = nullptr;
78 #ifdef _WIN32
79 fopen_s(&f, fileName, "wb");
80 #else
81 f = fopen(fileName, "wb");
82 #endif
83 ASSERT_TRUE(f != nullptr);
84 ASSERT_EQ((size_t)1, fwrite(contents.c_str(), contents.size(), 1, f));
85 fclose(f);
86
87 // Test the stream
88 CefRefPtr<CefStreamReader> stream(
89 CefStreamReader::CreateForFile(fileNameStr));
90 ASSERT_TRUE(stream.get() != nullptr);
91 ASSERT_TRUE(stream->MayBlock());
92 VerifyStreamReadBehavior(stream, contents);
93
94 // Release the file pointer
95 stream = nullptr;
96
97 // Delete the file
98 #ifdef _WIN32
99 ASSERT_EQ(0, _unlink(fileName));
100 #else
101 ASSERT_EQ(0, unlink(fileName));
102 #endif
103 }
104
TEST(StreamTest,ReadData)105 TEST(StreamTest, ReadData) {
106 std::string contents = "This is my test\ncontents for the file";
107
108 // Test the stream
109 CefRefPtr<CefStreamReader> stream(CefStreamReader::CreateForData(
110 static_cast<void*>(const_cast<char*>(contents.c_str())),
111 contents.size()));
112 ASSERT_TRUE(stream.get() != nullptr);
113 ASSERT_FALSE(stream->MayBlock());
114 VerifyStreamReadBehavior(stream, contents);
115 }
116
TEST(StreamTest,WriteFile)117 TEST(StreamTest, WriteFile) {
118 const char* fileName = "StreamTest.VerifyWriteFile.txt";
119 CefString fileNameStr = "StreamTest.VerifyWriteFile.txt";
120 std::string contents = "This is my test\ncontents for the file";
121
122 // Test the stream
123 CefRefPtr<CefStreamWriter> stream(
124 CefStreamWriter::CreateForFile(fileNameStr));
125 ASSERT_TRUE(stream.get() != nullptr);
126 ASSERT_TRUE(stream->MayBlock());
127 VerifyStreamWriteBehavior(stream, contents);
128
129 // Release the file pointer
130 stream = nullptr;
131
132 // Read the file that was written
133 FILE* f = nullptr;
134 char* buff = new char[contents.size()];
135 #ifdef _WIN32
136 fopen_s(&f, fileName, "rb");
137 #else
138 f = fopen(fileName, "rb");
139 #endif
140 ASSERT_TRUE(f != nullptr);
141 ASSERT_EQ((size_t)1, fread(buff, contents.size(), 1, f));
142
143 // Read past the end of the file
144 fgetc(f);
145 ASSERT_TRUE(feof(f));
146 fclose(f);
147
148 // Verify the file contents
149 ASSERT_TRUE(!memcmp(contents.c_str(), buff, contents.size()));
150 delete[] buff;
151
152 // Delete the file
153 #ifdef _WIN32
154 ASSERT_EQ(0, _unlink(fileName));
155 #else
156 ASSERT_EQ(0, unlink(fileName));
157 #endif
158 }
159
160 bool g_ReadHandlerTesterDeleted = false;
161
162 class ReadHandlerTester : public CefReadHandler {
163 public:
ReadHandlerTester()164 ReadHandlerTester()
165 : read_called_(false),
166 read_ptr_(nullptr),
167 read_size_(0),
168 read_n_(0),
169 seek_called_(false),
170 seek_offset_(0),
171 seek_whence_(0),
172 tell_called_(false),
173 eof_called_(false) {}
~ReadHandlerTester()174 ~ReadHandlerTester() override { g_ReadHandlerTesterDeleted = true; }
175
Read(void * ptr,size_t size,size_t n)176 size_t Read(void* ptr, size_t size, size_t n) override {
177 read_called_ = true;
178 read_ptr_ = ptr;
179 read_size_ = size;
180 read_n_ = n;
181 return 10;
182 }
183
Seek(int64 offset,int whence)184 int Seek(int64 offset, int whence) override {
185 seek_called_ = true;
186 seek_offset_ = offset;
187 seek_whence_ = whence;
188 return 10;
189 }
190
Tell()191 int64 Tell() override {
192 tell_called_ = true;
193 return 10;
194 }
195
Eof()196 int Eof() override {
197 eof_called_ = true;
198 return 10;
199 }
200
MayBlock()201 bool MayBlock() override { return false; }
202
203 bool read_called_;
204 const void* read_ptr_;
205 size_t read_size_;
206 size_t read_n_;
207
208 bool seek_called_;
209 int64 seek_offset_;
210 int seek_whence_;
211
212 bool tell_called_;
213
214 bool eof_called_;
215
216 IMPLEMENT_REFCOUNTING(ReadHandlerTester);
217 };
218
TEST(StreamTest,ReadHandler)219 TEST(StreamTest, ReadHandler) {
220 ReadHandlerTester* handler = new ReadHandlerTester();
221 ASSERT_TRUE(handler != nullptr);
222
223 CefRefPtr<CefStreamReader> stream(CefStreamReader::CreateForHandler(handler));
224 ASSERT_TRUE(stream.get() != nullptr);
225 ASSERT_FALSE(stream->MayBlock());
226
227 // CefReadHandler Read
228 const char* read_ptr = "My data";
229 size_t read_size = sizeof(read_ptr);
230 size_t read_n = 1;
231 size_t read_res = stream->Read(
232 static_cast<void*>(const_cast<char*>(read_ptr)), read_size, read_n);
233 ASSERT_TRUE(handler->read_called_);
234 ASSERT_EQ((size_t)10, read_res);
235 ASSERT_EQ(read_ptr, handler->read_ptr_);
236 ASSERT_EQ(read_size, handler->read_size_);
237 ASSERT_EQ(read_n, handler->read_n_);
238
239 // CefReadHandler Seek
240 int64 seek_offset = 10;
241 int seek_whence = SEEK_CUR;
242 int seek_res = stream->Seek(seek_offset, seek_whence);
243 ASSERT_TRUE(handler->seek_called_);
244 ASSERT_EQ(10, seek_res);
245 ASSERT_EQ(seek_offset, handler->seek_offset_);
246 ASSERT_EQ(seek_whence, handler->seek_whence_);
247
248 // CefReadHandler Tell
249 int64 tell_res = stream->Tell();
250 ASSERT_TRUE(handler->tell_called_);
251 ASSERT_EQ(10, tell_res);
252
253 // CefReadHandler Eof
254 int eof_res = stream->Eof();
255 ASSERT_TRUE(handler->eof_called_);
256 ASSERT_EQ(10, eof_res);
257
258 // Delete the stream
259 stream = nullptr;
260
261 // Verify that the handler object was deleted
262 ASSERT_TRUE(g_ReadHandlerTesterDeleted);
263 }
264
265 bool g_WriteHandlerTesterDeleted = false;
266
267 class WriteHandlerTester : public CefWriteHandler {
268 public:
WriteHandlerTester()269 WriteHandlerTester()
270 : write_called_(false),
271 write_ptr_(nullptr),
272 write_size_(0),
273 write_n_(0),
274 seek_called_(false),
275 seek_offset_(0),
276 seek_whence_(0),
277 tell_called_(false),
278 flush_called_(false) {}
~WriteHandlerTester()279 ~WriteHandlerTester() override { g_WriteHandlerTesterDeleted = true; }
280
Write(const void * ptr,size_t size,size_t n)281 size_t Write(const void* ptr, size_t size, size_t n) override {
282 write_called_ = true;
283 write_ptr_ = ptr;
284 write_size_ = size;
285 write_n_ = n;
286 return 10;
287 }
288
Seek(int64 offset,int whence)289 int Seek(int64 offset, int whence) override {
290 seek_called_ = true;
291 seek_offset_ = offset;
292 seek_whence_ = whence;
293 return 10;
294 }
295
Tell()296 int64 Tell() override {
297 tell_called_ = true;
298 return 10;
299 }
300
Flush()301 int Flush() override {
302 flush_called_ = true;
303 return 10;
304 }
305
MayBlock()306 bool MayBlock() override { return false; }
307
308 bool write_called_;
309 const void* write_ptr_;
310 size_t write_size_;
311 size_t write_n_;
312
313 bool seek_called_;
314 int64 seek_offset_;
315 int seek_whence_;
316
317 bool tell_called_;
318
319 bool flush_called_;
320
321 IMPLEMENT_REFCOUNTING(WriteHandlerTester);
322 };
323
TEST(StreamTest,WriteHandler)324 TEST(StreamTest, WriteHandler) {
325 WriteHandlerTester* handler = new WriteHandlerTester();
326 ASSERT_TRUE(handler != nullptr);
327
328 CefRefPtr<CefStreamWriter> stream(CefStreamWriter::CreateForHandler(handler));
329 ASSERT_TRUE(stream.get() != nullptr);
330 ASSERT_FALSE(stream->MayBlock());
331
332 // CefWriteHandler Write
333 const char* write_ptr = "My data";
334 size_t write_size = sizeof(write_ptr);
335 size_t write_n = 1;
336 size_t write_res = stream->Write(write_ptr, write_size, write_n);
337 ASSERT_TRUE(handler->write_called_);
338 ASSERT_EQ((size_t)10, write_res);
339 ASSERT_EQ(write_ptr, handler->write_ptr_);
340 ASSERT_EQ(write_size, handler->write_size_);
341 ASSERT_EQ(write_n, handler->write_n_);
342
343 // CefWriteHandler Seek
344 int64 seek_offset = 10;
345 int seek_whence = SEEK_CUR;
346 int seek_res = stream->Seek(seek_offset, seek_whence);
347 ASSERT_TRUE(handler->seek_called_);
348 ASSERT_EQ(10, seek_res);
349 ASSERT_EQ(seek_offset, handler->seek_offset_);
350 ASSERT_EQ(seek_whence, handler->seek_whence_);
351
352 // CefWriteHandler Tell
353 int64 tell_res = stream->Tell();
354 ASSERT_TRUE(handler->tell_called_);
355 ASSERT_EQ(10, tell_res);
356
357 // CefWriteHandler Flush
358 int flush_res = stream->Flush();
359 ASSERT_TRUE(handler->flush_called_);
360 ASSERT_EQ(10, flush_res);
361
362 // Delete the stream
363 stream = nullptr;
364
365 // Verify that the handler object was deleted
366 ASSERT_TRUE(g_WriteHandlerTesterDeleted);
367 }
368