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