102
}
103
104
105
+#ifdef CONFIG_PREADV
106
+static void test_io_channel_pread_all(void)
107
+{
108
+ QIOChannel *ioc;
109
+ char write_buf[] = "Hello World, pread_all";
110
+ char read_buf[sizeof(write_buf)] = {0};
111
+ int ret;
112
+
113
+ unlink(TEST_FILE);
114
+ ioc = QIO_CHANNEL(qio_channel_file_new_path(
115
+ TEST_FILE,
116
+ O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
117
+ TEST_MASK,
118
+ &error_abort));
119
+
120
+ ret = qio_channel_pwrite_all(ioc, write_buf, sizeof(write_buf),
121
+ 0, &error_abort);
122
+ g_assert_cmpint(ret, ==, 0);
123
+
124
+ /* Read back at offset 0 */
125
+ ret = qio_channel_pread_all(ioc, read_buf, sizeof(read_buf),
126
+ 0, &error_abort);
127
+ g_assert_cmpint(ret, ==, 0);
128
+ g_assert_cmpmem(write_buf, sizeof(write_buf),
129
+ read_buf, sizeof(read_buf));
130
+
131
+ /* Read at a non-zero offset */
132
+ memset(read_buf, 0, sizeof(read_buf));
133
+ ret = qio_channel_pread_all(ioc, read_buf, sizeof(write_buf) - 7,
134
+ 7, &error_abort);
135
+ g_assert_cmpint(ret, ==, 0);
136
+ g_assert_cmpmem(write_buf + 7, sizeof(write_buf) - 7,
137
+ read_buf, sizeof(write_buf) - 7);
138
+
139
+ unlink(TEST_FILE);
140
+ object_unref(OBJECT(ioc));
141
+}
142
+
143
+static void test_io_channel_preadv_all(void)
144
+{
145
+ QIOChannel *ioc;
146
+ char write_buf[256];
147
+ char read_buf[256] = {0};
148
+ struct iovec write_iov[2];
149
+ struct iovec read_iov[2];
150
+ int ret;
151
+ size_t i;
152
+
153
+ for (i = 0; i < sizeof(write_buf); i++) {
154
+ write_buf[i] = i & 0xff;
155
+ }
156
+
157
+ unlink(TEST_FILE);
158
+ ioc = QIO_CHANNEL(qio_channel_file_new_path(
159
+ TEST_FILE,
160
+ O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
161
+ TEST_MASK,
162
+ &error_abort));
163
+
164
+ /* Write using pwritev_all with 2 iovecs */
165
+ write_iov[0].iov_base = write_buf;
166
+ write_iov[0].iov_len = 128;
167
+ write_iov[1].iov_base = write_buf + 128;
168
+ write_iov[1].iov_len = 128;
169
+ ret = qio_channel_pwritev_all(ioc, write_iov, 2, 0, &error_abort);
170
+ g_assert_cmpint(ret, ==, 0);
171
+
172
+ /* Read back using preadv_all with 2 iovecs */
173
+ read_iov[0].iov_base = read_buf;
174
+ read_iov[0].iov_len = 128;
175
+ read_iov[1].iov_base = read_buf + 128;
176
+ read_iov[1].iov_len = 128;
177
+ ret = qio_channel_preadv_all(ioc, read_iov, 2, 0, &error_abort);
178
+ g_assert_cmpint(ret, ==, 0);
179
+
180
+ g_assert_cmpmem(write_buf, sizeof(write_buf),
181
+ read_buf, sizeof(read_buf));
182
+
183
+ /* Read at non-zero offset with preadv_all */
184
+ memset(read_buf, 0, sizeof(read_buf));
185
+ read_iov[0].iov_base = read_buf;
186
+ read_iov[0].iov_len = 64;
187
+ read_iov[1].iov_base = read_buf + 64;
188
+ read_iov[1].iov_len = 64;
189
+ ret = qio_channel_preadv_all(ioc, read_iov, 2, 128, &error_abort);
190
+ g_assert_cmpint(ret, ==, 0);
191
+
192
+ g_assert_cmpmem(write_buf + 128, 128,
193
+ read_buf, 128);
194
+
195
+ unlink(TEST_FILE);
196
+ object_unref(OBJECT(ioc));
197
+}
198
+
199
+static void test_io_channel_preadv_all_eof(void)
200
+{
201
+ QIOChannel *ioc;
202
+ char write_buf[] = "Hello World, preadv_all_eof";
203
+ char read_buf[sizeof(write_buf)] = {0};
204
+ struct iovec iov;
205
+ int ret;
206
+ Error *err = NULL;
207
+
208
+ unlink(TEST_FILE);
209
+ ioc = QIO_CHANNEL(qio_channel_file_new_path(
210
+ TEST_FILE,
211
+ O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
212
+ TEST_MASK,
213
+ &error_abort));
214
+
215
+ ret = qio_channel_pwrite_all(ioc, write_buf, sizeof(write_buf),
216
+ 0, &error_abort);
217
+ g_assert_cmpint(ret, ==, 0);
218
+
219
+ /* Full read succeeds: should return 1 */
220
+ iov.iov_base = read_buf;
221
+ iov.iov_len = sizeof(read_buf);
222
+ ret = qio_channel_preadv_all_eof(ioc, &iov, 1, 0, &error_abort);
223
+ g_assert_cmpint(ret, ==, 1);
224
+ g_assert_cmpmem(write_buf, sizeof(write_buf),
225
+ read_buf, sizeof(read_buf));
226
+
227
+ /* Clean EOF: offset at file end, should return 0 */
228
+ iov.iov_base = read_buf;
229
+ iov.iov_len = 1;
230
+ ret = qio_channel_preadv_all_eof(ioc, &iov, 1,
231
+ sizeof(write_buf), &err);
232
+ g_assert_cmpint(ret, ==, 0);
233
+ g_assert_null(err);
234
+
235
+ /* Partial EOF: start before end, request extends past */
236
+ iov.iov_base = read_buf;
237
+ iov.iov_len = 8;
238
+ ret = qio_channel_preadv_all_eof(ioc, &iov, 1,
239
+ sizeof(write_buf) - 4, &err);
240
+ g_assert_cmpint(ret, ==, -1);
241
+ g_assert_nonnull(err);
242
+ error_free(err);
243
+ err = NULL;
244
+
245
+ /* Strict wrapper (preadv_all) treats clean EOF as error */
246
+ iov.iov_base = read_buf;
247
+ iov.iov_len = 1;
248
+ ret = qio_channel_preadv_all(ioc, &iov, 1,
249
+ sizeof(write_buf), &err);
250
+ g_assert_cmpint(ret, ==, -1);
251
+ g_assert_nonnull(err);
252
+ error_free(err);
253
+
254
+ unlink(TEST_FILE);
255
+ object_unref(OBJECT(ioc));
256
+}
257
+
258
+static void test_io_channel_pread_all_eof(void)
259
+{
260
+ QIOChannel *ioc;
261
+ char write_buf[] = "Hello World, pread_all_eof";
262
+ char read_buf[sizeof(write_buf)] = {0};
263
+ int ret;
264
+ Error *err = NULL;
265
+
266
+ unlink(TEST_FILE);
267
+ ioc = QIO_CHANNEL(qio_channel_file_new_path(
268
+ TEST_FILE,
269
+ O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
270
+ TEST_MASK,
271
+ &error_abort));
272
+
273
+ ret = qio_channel_pwrite_all(ioc, write_buf, sizeof(write_buf),
274
+ 0, &error_abort);
275
+ g_assert_cmpint(ret, ==, 0);
276
+
277
+ /* Full read succeeds: should return 1 */
278
+ ret = qio_channel_pread_all_eof(ioc, read_buf, sizeof(read_buf),
279
+ 0, &error_abort);
280
+ g_assert_cmpint(ret, ==, 1);
281
+ g_assert_cmpmem(write_buf, sizeof(write_buf),
282
+ read_buf, sizeof(read_buf));
283
+
284
+ /* Clean EOF: should return 0 */
285
+ ret = qio_channel_pread_all_eof(ioc, read_buf, 1,
286
+ sizeof(write_buf), &err);
287
+ g_assert_cmpint(ret, ==, 0);
288
+ g_assert_null(err);
289
+
290
+ /* Partial EOF: should return -1 */
291
+ ret = qio_channel_pread_all_eof(ioc, read_buf, 8,
292
+ sizeof(write_buf) - 4, &err);
293
+ g_assert_cmpint(ret, ==, -1);
294
+ g_assert_nonnull(err);
295
+ error_free(err);
296
+
297
+ unlink(TEST_FILE);
298
+ object_unref(OBJECT(ioc));
299
+}
300
+#endif /* CONFIG_PREADV */
301
+
302
#ifndef _WIN32
303
static void test_io_channel_pipe(bool async)
304
{
344
g_test_add_func("/io/channel/file", test_io_channel_file);
345
g_test_add_func("/io/channel/file/rdwr", test_io_channel_file_rdwr);
346
g_test_add_func("/io/channel/file/fd", test_io_channel_fd);
347
+#ifdef CONFIG_PREADV
348
+ g_test_add_func("/io/channel/file/pread-all",
349
+ test_io_channel_pread_all);
350
+ g_test_add_func("/io/channel/file/preadv-all",
351
+ test_io_channel_preadv_all);
352
+ g_test_add_func("/io/channel/file/preadv-all-eof",
353
+ test_io_channel_preadv_all_eof);
354
+ g_test_add_func("/io/channel/file/pread-all-eof",
355
+ test_io_channel_pread_all_eof);
356
+#endif
357
#ifndef _WIN32
358
g_test_add_func("/io/channel/pipe/sync", test_io_channel_pipe_sync);
359
g_test_add_func("/io/channel/pipe/async", test_io_channel_pipe_async);