1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util/file/string_file.h"
16 
17 #include <stdint.h>
18 #include <string.h>
19 
20 #include <algorithm>
21 #include <limits>
22 
23 #include "gtest/gtest.h"
24 #include "util/misc/implicit_cast.h"
25 
26 namespace crashpad {
27 namespace test {
28 namespace {
29 
TEST(StringFile,EmptyFile)30 TEST(StringFile, EmptyFile) {
31   StringFile string_file;
32   EXPECT_TRUE(string_file.string().empty());
33   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
34   EXPECT_TRUE(string_file.Write("", 0));
35   EXPECT_TRUE(string_file.string().empty());
36   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
37 
38   char c = '6';
39   EXPECT_EQ(string_file.Read(&c, 1), 0);
40   EXPECT_EQ(c, '6');
41   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
42 
43   EXPECT_TRUE(string_file.string().empty());
44 }
45 
TEST(StringFile,OneByteFile)46 TEST(StringFile, OneByteFile) {
47   StringFile string_file;
48 
49   EXPECT_TRUE(string_file.Write("a", 1));
50   EXPECT_EQ(string_file.string().size(), 1u);
51   EXPECT_EQ(string_file.string(), "a");
52   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
53   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
54   char c = '6';
55   EXPECT_EQ(string_file.Read(&c, 1), 1);
56   EXPECT_EQ(c, 'a');
57   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
58   EXPECT_EQ(string_file.Read(&c, 1), 0);
59   EXPECT_EQ(c, 'a');
60   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
61   EXPECT_EQ(string_file.string(), "a");
62 
63   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
64   EXPECT_TRUE(string_file.Write("b", 1));
65   EXPECT_EQ(string_file.string().size(), 1u);
66   EXPECT_EQ(string_file.string(), "b");
67   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
68   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
69   EXPECT_EQ(string_file.Read(&c, 1), 1);
70   EXPECT_EQ(c, 'b');
71   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
72   EXPECT_EQ(string_file.Read(&c, 1), 0);
73   EXPECT_EQ(c, 'b');
74   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
75   EXPECT_EQ(string_file.string(), "b");
76 
77   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
78   EXPECT_TRUE(string_file.Write("\0", 1));
79   EXPECT_EQ(string_file.string().size(), 1u);
80   EXPECT_EQ(string_file.string()[0], '\0');
81   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
82   EXPECT_EQ(string_file.string().size(), 1u);
83   EXPECT_EQ(string_file.string()[0], '\0');
84 }
85 
TEST(StringFile,SetString)86 TEST(StringFile, SetString) {
87   char kString1[] = "Four score";
88   StringFile string_file;
89   string_file.SetString(kString1);
90   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
91   char buf[5] = "****";
92   EXPECT_EQ(string_file.Read(buf, 4), 4);
93   EXPECT_STREQ("Four", buf);
94   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
95   EXPECT_EQ(string_file.Seek(0, SEEK_END),
96             static_cast<FileOffset>(strlen(kString1)));
97   EXPECT_EQ(string_file.string(), kString1);
98 
99   char kString2[] = "and seven years ago";
100   EXPECT_EQ(string_file.Seek(4, SEEK_SET), 4);
101   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
102   string_file.SetString(kString2);
103   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
104   EXPECT_EQ(string_file.Read(buf, 4), 4);
105   EXPECT_STREQ("and ", buf);
106   EXPECT_EQ(string_file.Seek(0, SEEK_END),
107             static_cast<FileOffset>(strlen(kString2)));
108   EXPECT_EQ(string_file.string(), kString2);
109 
110   char kString3[] = "our fathers";
111   EXPECT_EQ(string_file.Seek(4, SEEK_SET), 4);
112   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
113   string_file.SetString(kString3);
114   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
115   EXPECT_EQ(string_file.Read(buf, 4), 4);
116   EXPECT_STREQ("our ", buf);
117   EXPECT_EQ(string_file.Seek(0, SEEK_END),
118             static_cast<FileOffset>(strlen(kString3)));
119   EXPECT_EQ(string_file.string(), kString3);
120 }
121 
TEST(StringFile,ReadExactly)122 TEST(StringFile, ReadExactly) {
123   StringFile string_file;
124   string_file.SetString("1234567");
125   char buf[4] = "***";
126   EXPECT_TRUE(string_file.ReadExactly(buf, 3));
127   EXPECT_STREQ("123", buf);
128   EXPECT_TRUE(string_file.ReadExactly(buf, 3));
129   EXPECT_STREQ("456", buf);
130   EXPECT_FALSE(string_file.ReadExactly(buf, 3));
131 }
132 
TEST(StringFile,Reset)133 TEST(StringFile, Reset) {
134   StringFile string_file;
135 
136   EXPECT_TRUE(string_file.Write("abc", 3));
137   EXPECT_EQ(string_file.string().size(), 3u);
138   EXPECT_EQ(string_file.string(), "abc");
139   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 3);
140   char buf[10] = "*********";
141   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
142   EXPECT_EQ(string_file.Read(&buf, 10), 3);
143   EXPECT_STREQ("abc******", buf);
144   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 3);
145   EXPECT_FALSE(string_file.string().empty());
146 
147   string_file.Reset();
148   EXPECT_TRUE(string_file.string().empty());
149   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
150 
151   EXPECT_TRUE(string_file.Write("de", 2));
152   EXPECT_EQ(string_file.string().size(), 2u);
153   EXPECT_EQ(string_file.string(), "de");
154   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
155   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
156   EXPECT_EQ(string_file.Read(&buf, 10), 2);
157   EXPECT_STREQ("dec******", buf);
158   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
159   EXPECT_FALSE(string_file.string().empty());
160 
161   string_file.Reset();
162   EXPECT_TRUE(string_file.string().empty());
163   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
164 
165   EXPECT_TRUE(string_file.Write("fghi", 4));
166   EXPECT_EQ(string_file.string().size(), 4u);
167   EXPECT_EQ(string_file.string(), "fghi");
168   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
169   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
170   EXPECT_EQ(string_file.Read(&buf, 2), 2);
171   EXPECT_STREQ("fgc******", buf);
172   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
173   EXPECT_EQ(string_file.Read(&buf, 2), 2);
174   EXPECT_STREQ("hic******", buf);
175   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
176   EXPECT_FALSE(string_file.string().empty());
177 
178   string_file.Reset();
179   EXPECT_TRUE(string_file.string().empty());
180   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
181 
182   // Test resetting after a sparse write.
183   EXPECT_EQ(string_file.Seek(1, SEEK_SET), 1);
184   EXPECT_TRUE(string_file.Write("j", 1));
185   EXPECT_EQ(string_file.string().size(), 2u);
186   EXPECT_EQ(string_file.string(), std::string("\0j", 2));
187   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
188   EXPECT_FALSE(string_file.string().empty());
189 
190   string_file.Reset();
191   EXPECT_TRUE(string_file.string().empty());
192   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
193 }
194 
TEST(StringFile,WriteInvalid)195 TEST(StringFile, WriteInvalid) {
196   StringFile string_file;
197 
198   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
199 
200   EXPECT_FALSE(string_file.Write(
201       "",
202       implicit_cast<size_t>(std::numeric_limits<FileOperationResult>::max()) +
203           1));
204   EXPECT_TRUE(string_file.string().empty());
205   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
206 
207   EXPECT_TRUE(string_file.Write("a", 1));
208   EXPECT_FALSE(string_file.Write(
209       "",
210       implicit_cast<size_t>(std::numeric_limits<FileOperationResult>::max())));
211   EXPECT_EQ(string_file.string().size(), 1u);
212   EXPECT_EQ(string_file.string(), "a");
213   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
214 }
215 
TEST(StringFile,WriteIoVec)216 TEST(StringFile, WriteIoVec) {
217   StringFile string_file;
218 
219   std::vector<WritableIoVec> iovecs;
220   WritableIoVec iov;
221   iov.iov_base = "";
222   iov.iov_len = 0;
223   iovecs.push_back(iov);
224   EXPECT_TRUE(string_file.WriteIoVec(&iovecs));
225   EXPECT_TRUE(string_file.string().empty());
226   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
227 
228   iovecs.clear();
229   iov.iov_base = "a";
230   iov.iov_len = 1;
231   iovecs.push_back(iov);
232   EXPECT_TRUE(string_file.WriteIoVec(&iovecs));
233   EXPECT_EQ(string_file.string().size(), 1u);
234   EXPECT_EQ(string_file.string(), "a");
235   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
236 
237   iovecs.clear();
238   iovecs.push_back(iov);
239   EXPECT_TRUE(string_file.WriteIoVec(&iovecs));
240   EXPECT_EQ(string_file.string().size(), 2u);
241   EXPECT_EQ(string_file.string(), "aa");
242   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
243 
244   iovecs.clear();
245   iovecs.push_back(iov);
246   iov.iov_base = "bc";
247   iov.iov_len = 2;
248   iovecs.push_back(iov);
249   EXPECT_TRUE(string_file.WriteIoVec(&iovecs));
250   EXPECT_EQ(string_file.string().size(), 5u);
251   EXPECT_EQ(string_file.string(), "aaabc");
252   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 5);
253 
254   EXPECT_TRUE(string_file.Write("def", 3));
255   EXPECT_EQ(string_file.string().size(), 8u);
256   EXPECT_EQ(string_file.string(), "aaabcdef");
257   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 8);
258 
259   iovecs.clear();
260   iov.iov_base = "ghij";
261   iov.iov_len = 4;
262   iovecs.push_back(iov);
263   iov.iov_base = "klmno";
264   iov.iov_len = 5;
265   iovecs.push_back(iov);
266   EXPECT_TRUE(string_file.WriteIoVec(&iovecs));
267   EXPECT_EQ(string_file.string().size(), 17u);
268   EXPECT_EQ(string_file.string(), "aaabcdefghijklmno");
269   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 17);
270 
271   string_file.Reset();
272   EXPECT_TRUE(string_file.string().empty());
273   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
274 
275   iovecs.clear();
276   iov.iov_base = "abcd";
277   iov.iov_len = 4;
278   iovecs.resize(16, iov);
279   EXPECT_TRUE(string_file.WriteIoVec(&iovecs));
280   EXPECT_EQ(string_file.string().size(), 64u);
281   EXPECT_EQ(string_file.string(),
282             "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd");
283   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 64);
284 }
285 
TEST(StringFile,WriteIoVecInvalid)286 TEST(StringFile, WriteIoVecInvalid) {
287   StringFile string_file;
288 
289   std::vector<WritableIoVec> iovecs;
290   EXPECT_FALSE(string_file.WriteIoVec(&iovecs));
291   EXPECT_TRUE(string_file.string().empty());
292   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
293 
294   WritableIoVec iov;
295   EXPECT_EQ(string_file.Seek(1, SEEK_CUR), 1);
296   iov.iov_base = "a";
297   iov.iov_len = std::numeric_limits<FileOperationResult>::max();
298   iovecs.push_back(iov);
299   EXPECT_FALSE(string_file.WriteIoVec(&iovecs));
300   EXPECT_TRUE(string_file.string().empty());
301   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
302 
303   iovecs.clear();
304   iov.iov_base = "a";
305   iov.iov_len = 1;
306   iovecs.push_back(iov);
307   iov.iov_len = std::numeric_limits<FileOperationResult>::max() - 1;
308   iovecs.push_back(iov);
309   EXPECT_FALSE(string_file.WriteIoVec(&iovecs));
310   EXPECT_TRUE(string_file.string().empty());
311   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
312 }
313 
TEST(StringFile,Seek)314 TEST(StringFile, Seek) {
315   StringFile string_file;
316 
317   EXPECT_TRUE(string_file.Write("abcd", 4));
318   EXPECT_EQ(string_file.string().size(), 4u);
319   EXPECT_EQ(string_file.string(), "abcd");
320   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
321 
322   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
323   EXPECT_TRUE(string_file.Write("efgh", 4));
324   EXPECT_EQ(string_file.string().size(), 4u);
325   EXPECT_EQ(string_file.string(), "efgh");
326   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 4);
327 
328   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
329   EXPECT_TRUE(string_file.Write("ijk", 3));
330   EXPECT_EQ(string_file.string().size(), 4u);
331   EXPECT_EQ(string_file.string(), "ijkh");
332   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 3);
333 
334   EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0);
335   EXPECT_TRUE(string_file.Write("lmnop", 5));
336   EXPECT_EQ(string_file.string().size(), 5u);
337   EXPECT_EQ(string_file.string(), "lmnop");
338   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 5);
339 
340   EXPECT_EQ(string_file.Seek(1, SEEK_SET), 1);
341   EXPECT_TRUE(string_file.Write("q", 1));
342   EXPECT_EQ(string_file.string().size(), 5u);
343   EXPECT_EQ(string_file.string(), "lqnop");
344   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
345 
346   EXPECT_EQ(string_file.Seek(-1, SEEK_CUR), 1);
347   EXPECT_TRUE(string_file.Write("r", 1));
348   EXPECT_EQ(string_file.string().size(), 5u);
349   EXPECT_EQ(string_file.string(), "lrnop");
350   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
351 
352   EXPECT_TRUE(string_file.Write("s", 1));
353   EXPECT_EQ(string_file.string().size(), 5u);
354   EXPECT_EQ(string_file.string(), "lrsop");
355   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 3);
356 
357   EXPECT_EQ(string_file.Seek(-1, SEEK_CUR), 2);
358   EXPECT_TRUE(string_file.Write("t", 1));
359   EXPECT_EQ(string_file.string().size(), 5u);
360   EXPECT_EQ(string_file.string(), "lrtop");
361   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 3);
362 
363   EXPECT_EQ(string_file.Seek(-1, SEEK_END), 4);
364   EXPECT_TRUE(string_file.Write("u", 1));
365   EXPECT_EQ(string_file.string().size(), 5u);
366   EXPECT_EQ(string_file.string(), "lrtou");
367   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 5);
368 
369   EXPECT_EQ(string_file.Seek(-5, SEEK_END), 0);
370   EXPECT_TRUE(string_file.Write("v", 1));
371   EXPECT_EQ(string_file.string().size(), 5u);
372   EXPECT_EQ(string_file.string(), "vrtou");
373   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
374 
375   EXPECT_EQ(string_file.Seek(0, SEEK_END), 5);
376   EXPECT_TRUE(string_file.Write("w", 1));
377   EXPECT_EQ(string_file.string().size(), 6u);
378   EXPECT_EQ(string_file.string(), "vrtouw");
379   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 6);
380 
381   EXPECT_EQ(string_file.Seek(2, SEEK_END), 8);
382   EXPECT_EQ(string_file.string().size(), 6u);
383   EXPECT_EQ(string_file.string(), "vrtouw");
384 
385   EXPECT_EQ(string_file.Seek(0, SEEK_END), 6);
386   EXPECT_TRUE(string_file.Write("x", 1));
387   EXPECT_EQ(string_file.string().size(), 7u);
388   EXPECT_EQ(string_file.string(), "vrtouwx");
389   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 7);
390 }
391 
TEST(StringFile,SeekSparse)392 TEST(StringFile, SeekSparse) {
393   StringFile string_file;
394 
395   EXPECT_EQ(string_file.Seek(3, SEEK_SET), 3);
396   EXPECT_TRUE(string_file.string().empty());
397   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 3);
398 
399   EXPECT_TRUE(string_file.Write("abc", 3));
400   EXPECT_EQ(string_file.string().size(), 6u);
401   EXPECT_EQ(string_file.string(), std::string("\0\0\0abc", 6));
402   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 6);
403 
404   EXPECT_EQ(string_file.Seek(3, SEEK_END), 9);
405   EXPECT_EQ(string_file.string().size(), 6u);
406   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 9);
407   char c;
408   EXPECT_EQ(string_file.Read(&c, 1), 0);
409   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 9);
410   EXPECT_EQ(string_file.string().size(), 6u);
411   EXPECT_TRUE(string_file.Write("def", 3));
412   EXPECT_EQ(string_file.string().size(), 12u);
413   EXPECT_EQ(string_file.string(), std::string("\0\0\0abc\0\0\0def", 12));
414   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 12);
415 
416   EXPECT_EQ(string_file.Seek(-5, SEEK_END), 7);
417   EXPECT_EQ(string_file.string().size(), 12u);
418   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 7);
419   EXPECT_TRUE(string_file.Write("g", 1));
420   EXPECT_EQ(string_file.string().size(), 12u);
421   EXPECT_EQ(string_file.string(), std::string("\0\0\0abc\0g\0def", 12));
422   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 8);
423 
424   EXPECT_EQ(string_file.Seek(7, SEEK_CUR), 15);
425   EXPECT_EQ(string_file.string().size(), 12u);
426   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 15);
427   EXPECT_TRUE(string_file.Write("hij", 3));
428   EXPECT_EQ(string_file.string().size(), 18u);
429   EXPECT_EQ(string_file.string(),
430             std::string("\0\0\0abc\0g\0def\0\0\0hij", 18));
431   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 18);
432 
433   EXPECT_EQ(string_file.Seek(-17, SEEK_CUR), 1);
434   EXPECT_EQ(string_file.string().size(), 18u);
435   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
436   EXPECT_TRUE(string_file.Write("k", 1));
437   EXPECT_EQ(string_file.string().size(), 18u);
438   EXPECT_EQ(string_file.string(), std::string("\0k\0abc\0g\0def\0\0\0hij", 18));
439   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 2);
440 
441   EXPECT_TRUE(string_file.Write("l", 1));
442   EXPECT_TRUE(string_file.Write("mnop", 4));
443   EXPECT_EQ(string_file.string().size(), 18u);
444   EXPECT_EQ(string_file.string(), std::string("\0klmnopg\0def\0\0\0hij", 18));
445   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 7);
446 }
447 
TEST(StringFile,SeekInvalid)448 TEST(StringFile, SeekInvalid) {
449   StringFile string_file;
450 
451   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
452   EXPECT_EQ(string_file.Seek(1, SEEK_SET), 1);
453   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
454   EXPECT_LT(string_file.Seek(-1, SEEK_SET), 0);
455   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
456   EXPECT_LT(string_file.Seek(std::numeric_limits<FileOperationResult>::min(),
457                              SEEK_SET),
458             0);
459   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
460   EXPECT_LT(string_file.Seek(std::numeric_limits<FileOffset>::min(), SEEK_SET),
461             0);
462   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
463   EXPECT_TRUE(string_file.string().empty());
464 
465   static_assert(SEEK_SET != 3 && SEEK_CUR != 3 && SEEK_END != 3,
466                 "3 must be invalid for whence");
467   EXPECT_LT(string_file.Seek(0, 3), 0);
468 
469   string_file.Reset();
470   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
471   EXPECT_TRUE(string_file.string().empty());
472 
473   const FileOffset kMaxOffset = static_cast<FileOffset>(
474       std::min(implicit_cast<uint64_t>(std::numeric_limits<FileOffset>::max()),
475                implicit_cast<uint64_t>(std::numeric_limits<size_t>::max())));
476 
477   EXPECT_EQ(string_file.Seek(kMaxOffset, SEEK_SET), kMaxOffset);
478   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), kMaxOffset);
479   EXPECT_LT(string_file.Seek(1, SEEK_CUR), 0);
480 
481   EXPECT_EQ(string_file.Seek(1, SEEK_SET), 1);
482   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
483   EXPECT_LT(string_file.Seek(kMaxOffset, SEEK_CUR), 0);
484 }
485 
TEST(StringFile,SeekSet)486 TEST(StringFile, SeekSet) {
487   StringFile string_file;
488   EXPECT_TRUE(string_file.SeekSet(1));
489   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 1);
490   EXPECT_TRUE(string_file.SeekSet(0));
491   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 0);
492   EXPECT_TRUE(string_file.SeekSet(10));
493   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 10);
494   EXPECT_FALSE(string_file.SeekSet(-1));
495   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 10);
496   EXPECT_FALSE(
497       string_file.SeekSet(std::numeric_limits<FileOperationResult>::min()));
498   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 10);
499   EXPECT_FALSE(string_file.SeekSet(std::numeric_limits<FileOffset>::min()));
500   EXPECT_EQ(string_file.Seek(0, SEEK_CUR), 10);
501 }
502 
503 }  // namespace
504 }  // namespace test
505 }  // namespace crashpad
506