1 : /*
2 : * Copyright 2010 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include <stdio.h>
8 : #include "native_client/src/shared/gio/gio_test_base.h"
9 : #include "gtest/gtest.h"
10 :
11 : #define EXPECT_RETCODE(_E_, _R_) \
12 : EXPECT_EQ(_E_, _R_);
13 :
14 : /* Uncomment and connect to above macro for debugging.
15 : if (0 > _R_) { \
16 : perror("Bad return code"); \
17 : }
18 : */
19 :
20 1 : char GioExpectedCharAt(char initial_char, int file_pos) {
21 1 : return static_cast<char>(initial_char + file_pos);
22 1 : }
23 :
24 : void GioReadTestWithOffset(struct Gio* my_file,
25 1 : char initial_char) {
26 : char* out_buffer;
27 1 : int out_size = 16;
28 : ssize_t ret_code;
29 :
30 1 : out_buffer = reinterpret_cast<char*>(malloc(out_size));
31 :
32 : // mf_curpos = 0, 32 left, read 16
33 1 : ret_code = my_file->vtbl->Read(my_file, out_buffer, 16);
34 1 : EXPECT_RETCODE(16, ret_code);
35 1 : for (int i = 0; i < 16; ++i)
36 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, i), out_buffer[i]);
37 :
38 : // mf_curpos = 16, 16 left, read 10
39 1 : ret_code = my_file->vtbl->Read(my_file, out_buffer, 10);
40 1 : EXPECT_RETCODE(10, ret_code);
41 1 : for (int i = 0; i < 10; ++i)
42 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, i + 16), out_buffer[i]);
43 : // residual value after idx 10
44 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 10), out_buffer[10]);
45 :
46 : // mf_curpos = 26, 6 left, read 8
47 1 : ret_code = my_file->vtbl->Read(my_file, out_buffer, 8);
48 1 : EXPECT_RETCODE(6, ret_code);
49 1 : for (int i = 0; i < 6; ++i)
50 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, i + 26), out_buffer[i]);
51 : // residual value after idx 6
52 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 16 + 6), out_buffer[6]);
53 :
54 : // mf_curpos = 32, 0 left, read 16
55 1 : ret_code = my_file->vtbl->Read(my_file, out_buffer, 16);
56 1 : EXPECT_EQ(0, ret_code);
57 :
58 1 : free(out_buffer);
59 1 : }
60 :
61 : /** Should be given a scratch file that can be written to without worry. */
62 : void GioWriteTest(struct Gio* my_file,
63 1 : bool fixed_length) {
64 : char* in_buffer;
65 1 : int in_size = 44;
66 1 : char initial_char = 'A';
67 : char out_char;
68 : ssize_t ret_code;
69 :
70 1 : in_buffer = reinterpret_cast<char*>(malloc(in_size));
71 1 : for (int i = 0; i < in_size; ++i)
72 1 : in_buffer[i] = GioExpectedCharAt(initial_char, i);
73 :
74 : // mf_curpos = 0, 64 left, write 44
75 1 : ret_code = my_file->vtbl->Write(my_file, in_buffer, in_size);
76 1 : EXPECT_RETCODE(in_size, ret_code);
77 1 : EXPECT_EQ(0, my_file->vtbl->Flush(my_file));
78 :
79 1 : ret_code = my_file->vtbl->Seek(my_file, -1, SEEK_CUR);
80 1 : EXPECT_RETCODE(in_size - 1, ret_code);
81 1 : ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
82 1 : EXPECT_EQ(1, ret_code);
83 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, in_size - 1), out_char);
84 :
85 : // Windows *requires* hitting EOF before writing more.
86 : // See _flsbuf in _flsbuf.c.
87 1 : if (!fixed_length) {
88 1 : ret_code = my_file->vtbl->Seek(my_file, 0, SEEK_END);
89 1 : EXPECT_EQ(in_size, ret_code);
90 : }
91 :
92 : // mf_curpos = 44, 20 left, write 10
93 1 : ret_code = my_file->vtbl->Write(my_file, in_buffer, 10);
94 1 : EXPECT_RETCODE(10, ret_code);
95 1 : EXPECT_EQ(0, my_file->vtbl->Flush(my_file));
96 :
97 : // Sample a couple of other spots
98 :
99 : // seek mf_curpos = 40
100 1 : ret_code = my_file->vtbl->Seek(my_file, in_size - 4, SEEK_SET);
101 1 : EXPECT_RETCODE(in_size - 4, ret_code);
102 1 : ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
103 1 : EXPECT_EQ(1, ret_code);
104 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, in_size - 4), out_char);
105 :
106 : // mf_curpose = 41, advance by 12 and read to get back to 54
107 1 : ret_code = my_file->vtbl->Seek(my_file, 12, SEEK_CUR);
108 1 : EXPECT_RETCODE(in_size - 3 + 12, ret_code);
109 1 : ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
110 1 : EXPECT_EQ(1, ret_code);
111 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 9), out_char);
112 :
113 : // Back at the mf_curpos = 54
114 :
115 1 : if (fixed_length) {
116 : // mf_curpos = 54, 10 left, write 20
117 0 : ret_code = my_file->vtbl->Write(my_file, in_buffer, 20);
118 0 : EXPECT_RETCODE(10, ret_code);
119 :
120 0 : my_file->vtbl->Seek(my_file, -1, SEEK_CUR);
121 0 : my_file->vtbl->Read(my_file, &out_char, 1);
122 0 : EXPECT_EQ(GioExpectedCharAt(initial_char, 9), out_char);
123 :
124 : // mf_curpos = 64, 0 left, write 20
125 0 : ret_code = my_file->vtbl->Write(my_file, in_buffer, 20);
126 0 : EXPECT_RETCODE(0, ret_code);
127 : }
128 :
129 1 : free(in_buffer);
130 1 : }
131 :
132 : void GioSeekTestWithOffset(struct Gio* my_file,
133 : char initial_char,
134 1 : bool wrap_err) {
135 : char out_char;
136 : ssize_t ret_code;
137 :
138 : // mf_curpos = 0
139 1 : ret_code = my_file->vtbl->Seek(my_file, 15, SEEK_SET);
140 1 : EXPECT_RETCODE(15, ret_code);
141 :
142 1 : ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
143 1 : EXPECT_RETCODE(1, ret_code);
144 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 15), out_char);
145 :
146 : // mf_curpos = 16
147 1 : ret_code = my_file->vtbl->Seek(my_file, 4, SEEK_CUR);
148 1 : EXPECT_RETCODE(20, ret_code);
149 :
150 1 : ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
151 1 : EXPECT_RETCODE(1, ret_code);
152 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 20), out_char);
153 :
154 : // mf_curpos = 21
155 1 : ret_code = my_file->vtbl->Seek(my_file, -4, SEEK_CUR);
156 1 : EXPECT_RETCODE(17, ret_code);
157 :
158 1 : ret_code = my_file->vtbl->Read(my_file, &out_char, 1);
159 1 : EXPECT_RETCODE(1, ret_code);
160 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 17), out_char);
161 :
162 : // mf_curpos = 17
163 1 : ret_code = my_file->vtbl->Seek(my_file, -4, SEEK_END);
164 1 : EXPECT_RETCODE(28, ret_code);
165 :
166 1 : my_file->vtbl->Read(my_file, &out_char, 1);
167 1 : EXPECT_EQ(GioExpectedCharAt(initial_char, 28), out_char);
168 :
169 :
170 : // At this point we try to seek out of bounds in various ways.
171 1 : if (wrap_err) {
172 0 : const int BAD_SEEK_WHENCE = SEEK_END + 3;
173 :
174 : // mf_curpos = 29
175 0 : ret_code = my_file->vtbl->Seek(my_file, 4, SEEK_END);
176 0 : EXPECT_RETCODE(-1, ret_code);
177 :
178 0 : my_file->vtbl->Read(my_file, &out_char, 1);
179 0 : EXPECT_EQ(GioExpectedCharAt(initial_char, 29), out_char);
180 :
181 : // mf_curpos = 30
182 0 : ret_code = my_file->vtbl->Seek(my_file, 4, BAD_SEEK_WHENCE);
183 0 : EXPECT_RETCODE(-1, ret_code);
184 :
185 0 : my_file->vtbl->Read(my_file, &out_char, 1);
186 0 : EXPECT_EQ(GioExpectedCharAt(initial_char, 30), out_char);
187 :
188 : // mf_curpos = 31
189 0 : ret_code = my_file->vtbl->Seek(my_file, -5, SEEK_SET);
190 0 : EXPECT_RETCODE(-1, ret_code);
191 :
192 0 : my_file->vtbl->Read(my_file, &out_char, 1);
193 0 : EXPECT_EQ(GioExpectedCharAt(initial_char, 31), out_char);
194 0 : } else {
195 : // Not testing seek past end and then READING.
196 :
197 : // mf_curpos = 29
198 1 : ret_code = my_file->vtbl->Seek(my_file, -5, SEEK_SET);
199 1 : EXPECT_RETCODE(-1, ret_code);
200 :
201 : /* Different behavior on Windows vs Posix.
202 : It appears that file_pos after a bad seek is undefined.
203 : TODO(jvoung): Once gio library makes seek behavior standard,
204 : we can re-enable this test. See:
205 : http://code.google.com/p/nativeclient/issues/detail?id=850
206 : my_file->vtbl->Read(my_file, &out_char, 1);
207 : EXPECT_EQ(GioExpectedCharAt(initial_char, 29), out_char);
208 : */
209 : }
210 1 : }
211 :
212 1 : void GioCloseTest(struct Gio* my_file) {
213 : int ret_code;
214 1 : ret_code = my_file->vtbl->Close(my_file);
215 1 : EXPECT_RETCODE(0, ret_code);
216 1 : my_file->vtbl->Dtor(my_file);
217 1 : }
|