libsndfile source files.
[Faustine.git] / interpretor / libsndfile-1.0.25 / src / test_file_io.c
1 /*
2 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ** GNU Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "sfconfig.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #include <string.h>
29 #include <errno.h>
30 #include <inttypes.h>
31
32 #include "common.h"
33
34 #include "test_main.h"
35
36 static void make_data (int *data, int len, int seed) ;
37
38 static void file_open_test (const char *filename) ;
39 static void file_read_write_test (const char *filename) ;
40 static void file_truncate_test (const char *filename) ;
41
42 static void test_open_or_die (SF_PRIVATE *psf, int linenum) ;
43 static void test_close_or_die (SF_PRIVATE *psf, int linenum) ;
44
45 static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
46 static void test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
47 static void test_equal_or_die (int *array1, int *array2, int len, int linenum) ;
48 static void test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) ;
49
50
51
52 /*==============================================================================
53 ** Actual test functions.
54 */
55
56 static void
57 file_open_test (const char *filename)
58 { SF_PRIVATE sf_data, *psf ;
59 int error ;
60
61 print_test_name ("Testing file open") ;
62
63 memset (&sf_data, 0, sizeof (sf_data)) ;
64 psf = &sf_data ;
65
66 /* Ensure that the file doesn't already exist. */
67 if (unlink (filename) != 0 && errno != ENOENT)
68 { printf ("\n\nLine %d: unlink failed (%d) : %s\n\n", __LINE__, errno, strerror (errno)) ;
69 exit (1) ;
70 } ;
71
72 psf->file.mode = SFM_READ ;
73 snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
74
75 /* Test that open for read fails if the file doesn't exist. */
76 error = psf_fopen (psf) ;
77 if (error == 0)
78 { printf ("\n\nLine %d: psf_fopen() should have failed.\n\n", __LINE__) ;
79 exit (1) ;
80 } ;
81
82 /* Reset error to zero. */
83 psf->error = SFE_NO_ERROR ;
84
85 /* Test file open in write mode. */
86 psf->file.mode = SFM_WRITE ;
87 test_open_or_die (psf, __LINE__) ;
88
89 test_close_or_die (psf, __LINE__) ;
90
91 unlink (psf->file.path.c) ;
92
93 /* Test file open in read/write mode for a non-existant file. */
94 psf->file.mode = SFM_RDWR ;
95 test_open_or_die (psf, __LINE__) ;
96
97 test_close_or_die (psf, __LINE__) ;
98
99 /* Test file open in read/write mode for an existing file. */
100 psf->file.mode = SFM_RDWR ;
101 test_open_or_die (psf, __LINE__) ;
102
103 test_close_or_die (psf, __LINE__) ;
104
105 unlink (psf->file.path.c) ;
106 puts ("ok") ;
107 } /* file_open_test */
108
109 static void
110 file_read_write_test (const char *filename)
111 { static int data_out [512] ;
112 static int data_in [512] ;
113
114 SF_PRIVATE sf_data, *psf ;
115 sf_count_t retval ;
116
117 /*
118 ** Open a new file and write two blocks of data to the file. After each
119 ** write, test that psf_get_filelen() returns the new length.
120 */
121
122 print_test_name ("Testing file write") ;
123
124 memset (&sf_data, 0, sizeof (sf_data)) ;
125 psf = &sf_data ;
126 snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
127
128 /* Test file open in write mode. */
129 psf->file.mode = SFM_WRITE ;
130 test_open_or_die (psf, __LINE__) ;
131
132 make_data (data_out, ARRAY_LEN (data_out), 1) ;
133 test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), sizeof (data_out), __LINE__) ;
134
135 if ((retval = psf_get_filelen (psf)) != sizeof (data_out))
136 { printf ("\n\nLine %d: file length after write is not correct (%" PRId64 " should be %zd).\n\n", __LINE__, retval, sizeof (data_out)) ;
137 if (retval == 0)
138 printf ("An fsync() may be necessary before fstat() in psf_get_filelen().\n\n") ;
139 exit (1) ;
140 } ;
141
142 make_data (data_out, ARRAY_LEN (data_out), 2) ;
143 test_write_or_die (psf, data_out, ARRAY_LEN (data_out), sizeof (data_out [0]), 2 * sizeof (data_out), __LINE__) ;
144
145 if ((retval = psf_get_filelen (psf)) != 2 * sizeof (data_out))
146 { printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %zd)\n\n", __LINE__, retval, 2 * sizeof (data_out)) ;
147 exit (1) ;
148 } ;
149
150 test_close_or_die (psf, __LINE__) ;
151 puts ("ok") ;
152
153 /*
154 ** Now open the file in read mode, check the file length and check
155 ** that the data is correct.
156 */
157
158 print_test_name ("Testing file read") ;
159
160 /* Test file open in write mode. */
161 psf->file.mode = SFM_READ ;
162 test_open_or_die (psf, __LINE__) ;
163
164 make_data (data_out, ARRAY_LEN (data_out), 1) ;
165 test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
166 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
167
168 make_data (data_out, ARRAY_LEN (data_out), 2) ;
169 test_read_or_die (psf, data_in, sizeof (data_in [0]), ARRAY_LEN (data_in), 2 * sizeof (data_in), __LINE__) ;
170 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
171
172 test_close_or_die (psf, __LINE__) ;
173
174 puts ("ok") ;
175
176 /*
177 ** Open the file in read/write mode, seek around a bit and then seek to
178 ** the end of the file and write another block of data (3rd block). Then
179 ** go back and check that all three blocks are correct.
180 */
181
182 print_test_name ("Testing file seek") ;
183
184 /* Test file open in read/write mode. */
185 psf->file.mode = SFM_RDWR ;
186 test_open_or_die (psf, __LINE__) ;
187
188 test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
189 test_seek_or_die (psf, 0, SEEK_END, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
190 test_seek_or_die (psf, -1 * SIGNED_SIZEOF (data_out), SEEK_CUR, (sf_count_t) sizeof (data_out), __LINE__) ;
191
192 test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_CUR, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
193 make_data (data_out, ARRAY_LEN (data_out), 3) ;
194 test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 3 * sizeof (data_out), __LINE__) ;
195
196 test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
197 make_data (data_out, ARRAY_LEN (data_out), 1) ;
198 test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
199 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
200
201 test_seek_or_die (psf, 2 * SIGNED_SIZEOF (data_out), SEEK_SET, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
202 make_data (data_out, ARRAY_LEN (data_out), 3) ;
203 test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
204 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
205
206 test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
207 make_data (data_out, ARRAY_LEN (data_out), 2) ;
208 test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
209 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
210
211 test_close_or_die (psf, __LINE__) ;
212 puts ("ok") ;
213
214 /*
215 ** Now test operations with a non-zero psf->fileoffset field. This field
216 ** sets an artificial file start positions so that a seek to the start of
217 ** the file will actually be a seek to the value given by psf->fileoffset.
218 */
219
220 print_test_name ("Testing file offset") ;
221
222 /* Test file open in read/write mode. */
223 psf->file.mode = SFM_RDWR ;
224 psf->fileoffset = sizeof (data_out [0]) * ARRAY_LEN (data_out) ;
225 test_open_or_die (psf, __LINE__) ;
226
227 if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
228 { printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %zd)\n\n", __LINE__, retval, 3 * sizeof (data_out)) ;
229 exit (1) ;
230 } ;
231
232 test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
233 make_data (data_out, ARRAY_LEN (data_out), 5) ;
234 test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 2 * sizeof (data_out), __LINE__) ;
235 test_close_or_die (psf, __LINE__) ;
236
237 /* final test with psf->fileoffset == 0. */
238
239 psf->file.mode = SFM_RDWR ;
240 psf->fileoffset = 0 ;
241 test_open_or_die (psf, __LINE__) ;
242
243 if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
244 { printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %zd)\n\n", __LINE__, retval, 3 * sizeof (data_out)) ;
245 exit (1) ;
246 } ;
247
248 make_data (data_out, ARRAY_LEN (data_out), 1) ;
249 test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
250 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
251
252 make_data (data_out, ARRAY_LEN (data_out), 2) ;
253 test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
254 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
255
256 make_data (data_out, ARRAY_LEN (data_out), 5) ;
257 test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
258 test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
259
260 test_close_or_die (psf, __LINE__) ;
261
262 puts ("ok") ;
263 } /* file_read_write_test */
264
265 static void
266 file_truncate_test (const char *filename)
267 { SF_PRIVATE sf_data, *psf ;
268 unsigned char buffer [256] ;
269 int k ;
270
271 /*
272 ** Open a new file and write two blocks of data to the file. After each
273 ** write, test that psf_get_filelen() returns the new length.
274 */
275
276 print_test_name ("Testing file truncate") ;
277
278 memset (&sf_data, 0, sizeof (sf_data)) ;
279 memset (buffer, 0xEE, sizeof (buffer)) ;
280
281 psf = &sf_data ;
282 snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
283
284 /*
285 ** Open the file write mode, write 0xEE data and then extend the file
286 ** using truncate (the extended data should be 0x00).
287 */
288 psf->file.mode = SFM_WRITE ;
289 test_open_or_die (psf, __LINE__) ;
290 test_write_or_die (psf, buffer, sizeof (buffer) / 2, 1, sizeof (buffer) / 2, __LINE__) ;
291 psf_ftruncate (psf, sizeof (buffer)) ;
292 test_close_or_die (psf, __LINE__) ;
293
294 /* Open the file in read mode and check the data. */
295 psf->file.mode = SFM_READ ;
296 test_open_or_die (psf, __LINE__) ;
297 test_read_or_die (psf, buffer, sizeof (buffer), 1, sizeof (buffer), __LINE__) ;
298 test_close_or_die (psf, __LINE__) ;
299
300 for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++)
301 if (buffer [k] != 0xEE)
302 { printf ("\n\nLine %d : buffer [%d] = %d (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ;
303 exit (1) ;
304 } ;
305
306 for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++)
307 if (buffer [k] != 0)
308 { printf ("\n\nLine %d : buffer [%d] = %d (should be 0)\n\n", __LINE__, k, buffer [k]) ;
309 exit (1) ;
310 } ;
311
312 /* Open the file in read/write and shorten the file using truncate. */
313 psf->file.mode = SFM_RDWR ;
314 test_open_or_die (psf, __LINE__) ;
315 psf_ftruncate (psf, sizeof (buffer) / 4) ;
316 test_close_or_die (psf, __LINE__) ;
317
318 /* Check the file length. */
319 psf->file.mode = SFM_READ ;
320 test_open_or_die (psf, __LINE__) ;
321 test_seek_or_die (psf, 0, SEEK_END, SIGNED_SIZEOF (buffer) / 4, __LINE__) ;
322 test_close_or_die (psf, __LINE__) ;
323
324 puts ("ok") ;
325 } /* file_truncate_test */
326
327 /*==============================================================================
328 ** Testing helper functions.
329 */
330
331 static void
332 test_open_or_die (SF_PRIVATE *psf, int linenum)
333 { int error ;
334
335 /* Test that open for read fails if the file doesn't exist. */
336 error = psf_fopen (psf) ;
337 if (error)
338 { printf ("\n\nLine %d: psf_fopen() failed : %s\n\n", linenum, strerror (errno)) ;
339 exit (1) ;
340 } ;
341
342 } /* test_open_or_die */
343
344 static void
345 test_close_or_die (SF_PRIVATE *psf, int linenum)
346 {
347 psf_fclose (psf) ;
348 if (psf_file_valid (psf))
349 { printf ("\n\nLine %d: psf->file.filedes should not be valid.\n\n", linenum) ;
350 exit (1) ;
351 } ;
352
353 } /* test_close_or_die */
354
355 static void
356 test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
357 { sf_count_t retval ;
358
359 retval = psf_fwrite (data, bytes, items, psf) ;
360 if (retval != items)
361 { printf ("\n\nLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")\n\n", linenum, retval, items) ;
362 exit (1) ;
363 } ;
364
365 if ((retval = psf_ftell (psf)) != new_position)
366 { printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")\n\n", linenum, retval, new_position) ;
367 exit (1) ;
368 } ;
369
370 return ;
371 } /* test_write_or_die */
372
373 static void
374 test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
375 { sf_count_t retval ;
376
377 retval = psf_fread (data, bytes, items, psf) ;
378 if (retval != items)
379 { printf ("\n\nLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")\n\n", linenum, retval, items) ;
380 exit (1) ;
381 } ;
382
383 if ((retval = psf_ftell (psf)) != new_position)
384 { printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")\n\n", linenum, retval, new_position) ;
385 exit (1) ;
386 } ;
387
388 return ;
389 } /* test_write_or_die */
390
391 static void
392 test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum)
393 { sf_count_t retval ;
394
395 retval = psf_fseek (psf, offset, whence) ;
396
397 if (retval != new_position)
398 { printf ("\n\nLine %d: psf_fseek() failed. New position is %" PRId64 " (should be %" PRId64 ").\n\n",
399 linenum, retval, new_position) ;
400 exit (1) ;
401 } ;
402
403 } /* test_seek_or_die */
404
405 static void
406 test_equal_or_die (int *array1, int *array2, int len, int linenum)
407 { int k ;
408
409 for (k = 0 ; k < len ; k++)
410 if (array1 [k] != array2 [k])
411 printf ("\n\nLine %d: error at index %d (%d != %d).\n\n",
412 linenum, k, array1 [k], array2 [k]) ;
413
414 return ;
415 } /* test_equal_or_die */
416
417 static void
418 make_data (int *data, int len, int seed)
419 { int k ;
420
421 srand (seed * 3333333 + 14756123) ;
422
423 for (k = 0 ; k < len ; k++)
424 data [k] = rand () ;
425
426 } /* make_data */
427
428 void
429 test_file_io (void)
430 { const char *filename = "file_io.dat" ;
431
432 file_open_test (filename) ;
433 file_read_write_test (filename) ;
434 file_truncate_test (filename) ;
435
436 unlink (filename) ;
437 } /* main */
438