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