1 /*
2 ** Copyright (C) 2003-2016 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 General Public License as published by
6 ** the Free Software Foundation; either version 2 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 General Public License for more details.
13 **
14 ** You should have received a copy of the GNU 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 #include <string.h>
24 #include <math.h>
25 #include <inttypes.h>
26
27 #if HAVE_UNISTD_H
28 #include <unistd.h>
29 #else
30 #include "sf_unistd.h"
31 #endif
32
33 #include <sndfile.h>
34
35 #include "utils.h"
36
37 #define BUFFER_LEN (1 << 10)
38 #define LOG_BUFFER_SIZE 1024
39
40 static void string_start_test (const char *filename, int typemajor) ;
41 static void string_start_end_test (const char *filename, int typemajor) ;
42 static void string_multi_set_test (const char *filename, int typemajor) ;
43 static void string_rdwr_test (const char *filename, int typemajor) ;
44 static void string_short_rdwr_test (const char *filename, int typemajor) ;
45 static void string_rdwr_grow_test (const char *filename, int typemajor) ;
46 static void string_header_update (const char *filename, int typemajor) ;
47
48 static void software_string_test (const char *filename) ;
49
50 static int str_count (const char * haystack, const char * needle) ;
51
52 int
main(int argc,char * argv[])53 main (int argc, char *argv [])
54 { int do_all = 0 ;
55 int test_count = 0 ;
56
57 if (argc != 2)
58 { printf ("Usage : %s <test>\n", argv [0]) ;
59 printf (" Where <test> is one of the following:\n") ;
60 printf (" wav - test adding strings to WAV files\n") ;
61 printf (" aiff - test adding strings to AIFF files\n") ;
62 printf (" flac - test adding strings to FLAC files\n") ;
63 printf (" ogg - test adding strings to OGG files\n") ;
64 printf (" opus - test adding strings to OPUS files\n") ;
65 printf (" all - perform all tests\n") ;
66 exit (1) ;
67 } ;
68
69 do_all = ! strcmp (argv [1], "all") ;
70
71 if (do_all || ! strcmp (argv [1], "wav"))
72 { string_start_end_test ("strings.wav", SF_FORMAT_WAV) ;
73 string_multi_set_test ("multi.wav", SF_FORMAT_WAV) ;
74 string_rdwr_test ("rdwr.wav", SF_FORMAT_WAV) ;
75 string_short_rdwr_test ("short_rdwr.wav", SF_FORMAT_WAV) ;
76 string_rdwr_grow_test ("rdwr_grow.wav", SF_FORMAT_WAV) ;
77 string_header_update ("header_update.wav", SF_FORMAT_WAV) ;
78
79 string_start_end_test ("strings.wavex", SF_FORMAT_WAVEX) ;
80 string_multi_set_test ("multi.wavex", SF_FORMAT_WAVEX) ;
81 string_rdwr_test ("rdwr.wavex", SF_FORMAT_WAVEX) ;
82 string_short_rdwr_test ("short_rdwr.wavex", SF_FORMAT_WAVEX) ;
83
84 string_start_end_test ("strings.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
85 string_multi_set_test ("multi.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
86 string_rdwr_test ("rdwr.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
87 string_short_rdwr_test ("short_rdwr.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
88
89 software_string_test ("software_string.wav") ;
90 test_count++ ;
91 } ;
92
93 if (do_all || ! strcmp (argv [1], "aiff"))
94 { string_start_test ("strings.aiff", SF_FORMAT_AIFF) ;
95 string_start_end_test ("strings.aiff", SF_FORMAT_AIFF) ;
96 /*
97 TODO : Fix src/aiff.c so these tests pass.
98 string_multi_set_test ("multi.aiff", SF_FORMAT_AIFF) ;
99 string_rdwr_test ("rdwr.aiff", SF_FORMAT_AIFF) ;
100 string_short_rdwr_test ("short_rdwr.aiff", SF_FORMAT_AIFF) ;
101 string_rdwr_grow_test ("rdwr_grow.aiff", SF_FORMAT_AIFF) ;
102 string_header_update ("header_update.aiff", SF_FORMAT_AIFF) ;
103 */
104
105 test_count++ ;
106 } ;
107
108 if (do_all || ! strcmp (argv [1], "flac"))
109 { if (HAVE_EXTERNAL_XIPH_LIBS)
110 string_start_test ("strings.flac", SF_FORMAT_FLAC) ;
111 else
112 puts (" No FLAC tests because FLAC support was not compiled in.") ;
113 test_count++ ;
114 } ;
115
116 if (do_all || ! strcmp (argv [1], "ogg"))
117 { if (HAVE_EXTERNAL_XIPH_LIBS)
118 string_start_test ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS) ;
119 else
120 puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
121 test_count++ ;
122 } ;
123
124 if (do_all || ! strcmp (argv [1], "opus"))
125 { if (HAVE_EXTERNAL_XIPH_LIBS)
126 string_start_test ("opus.opus", SF_FORMAT_OGG | SF_FORMAT_OPUS) ;
127 else
128 puts (" No Ogg/Opus tests because Ogg/Opus support was not compiled in.") ;
129 test_count++ ;
130 } ;
131
132 if (do_all || ! strcmp (argv [1], "caf"))
133 { string_start_test ("strings.caf", SF_FORMAT_CAF) ;
134 string_start_end_test ("strings.caf", SF_FORMAT_CAF) ;
135 string_multi_set_test ("multi.caf", SF_FORMAT_CAF) ;
136 /*
137 TODO : Fix src/caf.c so these tests pass.
138 string_rdwr_test ("rdwr.caf", SF_FORMAT_CAF) ;
139 string_short_rdwr_test ("short_rdwr.caf", SF_FORMAT_CAF) ;
140 string_header_update ("header_update.caf", SF_FORMAT_CAF) ;
141 */
142 test_count++ ;
143 } ;
144
145 if (do_all || ! strcmp (argv [1], "rf64"))
146 { string_start_test ("strings.rf64", SF_FORMAT_RF64) ;
147 string_start_end_test ("strings.rf64", SF_FORMAT_RF64) ;
148 string_multi_set_test ("multi.rf64", SF_FORMAT_RF64) ;
149 /*
150 TODO : Fix src/rf64.c so these tests pass.
151 string_rdwr_test ("rdwr.rf64", SF_FORMAT_RF64) ;
152 string_short_rdwr_test ("short_rdwr.rf64", SF_FORMAT_RF64) ;
153 string_header_update ("header_update.rf64", SF_FORMAT_RF64) ;
154 */
155 test_count++ ;
156 } ;
157
158 if (do_all || ! strcmp (argv [1], "w64"))
159 { puts ("\n\n **** String test not working yet for W64 format. ****\n") ;
160 /*
161 string_start_test ("strings.w64", SF_FORMAT_W64) ;
162 string_start_end_test ("strings.w64", SF_FORMAT_W64) ;
163 string_multi_set_test ("multi.w64", SF_FORMAT_W64) ;
164 string_rdwr_test ("rdwr.w64", SF_FORMAT_W64) ;
165 string_short_rdwr_test ("short_rdwr.w64", SF_FORMAT_W64) ;
166 string_header_update ("header_update.w64", SF_FORMAT_W64) ;
167 */
168 test_count++ ;
169 } ;
170
171 if (test_count == 0)
172 { printf ("Mono : ************************************\n") ;
173 printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
174 printf ("Mono : ************************************\n") ;
175 return 1 ;
176 } ;
177
178 return 0 ;
179 } /* main */
180
181
182 /*============================================================================================
183 ** Here are the test functions.
184 */
185
186 static const char
187 software [] = "software (libsndfile-X.Y.Z)",
188 artist [] = "The Artist",
189 copyright [] = "Copyright (c) 2001 Artist",
190 comment [] = "Comment goes here!!!",
191 date [] = "2001/01/27",
192 album [] = "The Album",
193 license [] = "The license",
194 title [] = "This is the title",
195 long_title [] = "This is a very long and very boring title for this file",
196 long_artist [] = "The artist who kept on changing its name",
197 genre [] = "The genre",
198 trackno [] = "Track three" ;
199
200
201 static short data_out [BUFFER_LEN] ;
202
203 static void
string_start_end_test(const char * filename,int typemajor)204 string_start_end_test (const char *filename, int typemajor)
205 { const char *cptr ;
206 SNDFILE *file ;
207 SF_INFO sfinfo ;
208 int errors = 0 ;
209
210 print_test_name ("string_start_end_test", filename) ;
211
212 memset (&sfinfo, 0, sizeof (sfinfo)) ;
213 sfinfo.samplerate = 44100 ;
214 sfinfo.channels = 1 ;
215 sfinfo.frames = 0 ;
216 sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
217
218 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
219
220 /* Write stuff at start of file. */
221 sf_set_string (file, SF_STR_TITLE, filename) ;
222 sf_set_string (file, SF_STR_SOFTWARE, software) ;
223 sf_set_string (file, SF_STR_ARTIST, artist) ;
224 sf_set_string (file, SF_STR_GENRE, genre) ;
225 sf_set_string (file, SF_STR_TRACKNUMBER, trackno) ;
226
227 /* Write data to file. */
228 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
229 test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
230
231 /* Write more stuff at end of file. */
232 sf_set_string (file, SF_STR_COPYRIGHT, copyright) ;
233 sf_set_string (file, SF_STR_COMMENT, comment) ;
234 sf_set_string (file, SF_STR_DATE, date) ;
235 sf_set_string (file, SF_STR_ALBUM, album) ;
236 sf_set_string (file, SF_STR_LICENSE, license) ;
237
238 sf_close (file) ;
239
240 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
241
242 check_log_buffer_or_die (file, __LINE__) ;
243
244 if (sfinfo.frames != BUFFER_LEN)
245 { printf ("***** Bad frame count %d (should be %d)\n\n", (int) sfinfo.frames, BUFFER_LEN) ;
246 errors ++ ;
247 } ;
248
249 cptr = sf_get_string (file, SF_STR_TITLE) ;
250 if (cptr == NULL || strcmp (filename, cptr) != 0)
251 { if (errors++ == 0)
252 puts ("\n") ;
253 printf (" Bad filename : %s\n", cptr) ;
254 } ;
255
256 cptr = sf_get_string (file, SF_STR_COPYRIGHT) ;
257 if (cptr == NULL || strcmp (copyright, cptr) != 0)
258 { if (errors++ == 0)
259 puts ("\n") ;
260 printf (" Bad copyright : %s\n", cptr) ;
261 } ;
262
263 cptr = sf_get_string (file, SF_STR_SOFTWARE) ;
264 if (cptr == NULL || strstr (cptr, software) != cptr)
265 { if (errors++ == 0)
266 puts ("\n") ;
267 printf (" Bad software : %s\n", cptr) ;
268 } ;
269
270 if (str_count (cptr, "libsndfile") != 1)
271 { if (errors++ == 0)
272 puts ("\n") ;
273 printf (" Bad software : %s\n", cptr) ;
274 } ;
275
276 cptr = sf_get_string (file, SF_STR_ARTIST) ;
277 if (cptr == NULL || strcmp (artist, cptr) != 0)
278 { if (errors++ == 0)
279 puts ("\n") ;
280 printf (" Bad artist : %s\n", cptr) ;
281 } ;
282
283 cptr = sf_get_string (file, SF_STR_COMMENT) ;
284 if (cptr == NULL || strcmp (comment, cptr) != 0)
285 { if (errors++ == 0)
286 puts ("\n") ;
287 printf (" Bad comment : %s\n", cptr) ;
288 } ;
289
290 if (typemajor != SF_FORMAT_AIFF)
291 { cptr = sf_get_string (file, SF_STR_DATE) ;
292 if (cptr == NULL || strcmp (date, cptr) != 0)
293 { if (errors++ == 0)
294 puts ("\n") ;
295 printf (" Bad date : %s\n", cptr) ;
296 } ;
297
298 cptr = sf_get_string (file, SF_STR_GENRE) ;
299 if (cptr == NULL || strcmp (genre, cptr) != 0)
300 { if (errors++ == 0)
301 puts ("\n") ;
302 printf (" Bad genre : %s\n", cptr) ;
303 } ;
304 } ;
305
306 switch (typemajor)
307 { case SF_FORMAT_AIFF :
308 case SF_FORMAT_WAV :
309 case SF_FORMAT_WAVEX :
310 case SF_ENDIAN_BIG | SF_FORMAT_WAV :
311 case SF_FORMAT_RF64 :
312 /* These formats do not support the following. */
313 break ;
314
315 default :
316 cptr = sf_get_string (file, SF_STR_ALBUM) ;
317 if (cptr == NULL || strcmp (album, cptr) != 0)
318 { if (errors++ == 0)
319 puts ("\n") ;
320 printf (" Bad album : %s\n", cptr) ;
321 } ;
322
323 cptr = sf_get_string (file, SF_STR_LICENSE) ;
324 if (cptr == NULL || strcmp (license, cptr) != 0)
325 { if (errors++ == 0)
326 puts ("\n") ;
327 printf (" Bad license : %s\n", cptr) ;
328 } ;
329
330 cptr = sf_get_string (file, SF_STR_TRACKNUMBER) ;
331 if (cptr == NULL || strcmp (trackno, cptr) != 0)
332 { if (errors++ == 0)
333 puts ("\n") ;
334 printf (" Bad track no. : %s\n", cptr) ;
335 } ;
336 break ;
337 } ;
338
339 if (errors > 0)
340 { printf ("\n*** Error count : %d ***\n\n", errors) ;
341 dump_log_buffer (file) ;
342 exit (1) ;
343 } ;
344
345 sf_close (file) ;
346 unlink (filename) ;
347
348 puts ("ok") ;
349 } /* string_start_end_test */
350
351 static void
string_start_test(const char * filename,int formattype)352 string_start_test (const char *filename, int formattype)
353 { const char *cptr ;
354 SNDFILE *file ;
355 SF_INFO sfinfo ;
356 int errors = 0 ;
357 int typemajor = SF_FORMAT_TYPEMASK & formattype ;
358
359 print_test_name ("string_start_test", filename) ;
360
361 memset (&sfinfo, 0, sizeof (sfinfo)) ;
362 sfinfo.samplerate = 44100 ;
363 sfinfo.channels = 1 ;
364 sfinfo.frames = 0 ;
365
366 switch (formattype)
367 { case SF_FORMAT_OGG | SF_FORMAT_OPUS :
368 /* Opus only supports some discrete sample rates. */
369 sfinfo.samplerate = 48000 ;
370 break ;
371
372 case SF_FORMAT_OGG | SF_FORMAT_VORBIS :
373 break ;
374
375 default :
376 formattype |= SF_FORMAT_PCM_16 ;
377 break ;
378 } ;
379 sfinfo.format = formattype ;
380
381 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
382
383 /* Write stuff at start of file. */
384 sf_set_string (file, SF_STR_TITLE, filename) ;
385 sf_set_string (file, SF_STR_SOFTWARE, software) ;
386 sf_set_string (file, SF_STR_ARTIST, artist) ;
387 sf_set_string (file, SF_STR_COPYRIGHT, copyright) ;
388 sf_set_string (file, SF_STR_COMMENT, comment) ;
389 sf_set_string (file, SF_STR_DATE, date) ;
390 sf_set_string (file, SF_STR_ALBUM, album) ;
391 sf_set_string (file, SF_STR_LICENSE, license) ;
392
393 /* Write data to file. */
394 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
395
396 sf_close (file) ;
397
398 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
399
400 check_log_buffer_or_die (file, __LINE__) ;
401
402 if (sfinfo.frames != BUFFER_LEN)
403 { printf ("***** Bad frame count %d (should be %d)\n\n", (int) sfinfo.frames, BUFFER_LEN) ;
404 errors ++ ;
405 } ;
406
407 cptr = sf_get_string (file, SF_STR_TITLE) ;
408 if (cptr == NULL || strcmp (filename, cptr) != 0)
409 { if (errors++ == 0)
410 puts ("\n") ;
411 printf (" Bad filename : %s\n", cptr) ;
412 } ;
413
414 cptr = sf_get_string (file, SF_STR_COPYRIGHT) ;
415 if (cptr == NULL || strcmp (copyright, cptr) != 0)
416 { if (errors++ == 0)
417 puts ("\n") ;
418 printf (" Bad copyright : %s\n", cptr) ;
419 } ;
420
421 cptr = sf_get_string (file, SF_STR_SOFTWARE) ;
422 if (cptr == NULL || strstr (cptr, software) != cptr)
423 { if (errors++ == 0)
424 puts ("\n") ;
425 printf (" Bad software : %s\n", cptr) ;
426 } ;
427
428 if (cptr && str_count (cptr, "libsndfile") != 1)
429 { if (errors++ == 0)
430 puts ("\n") ;
431 printf (" Bad software : %s\n", cptr) ;
432 } ;
433
434 cptr = sf_get_string (file, SF_STR_ARTIST) ;
435 if (cptr == NULL || strcmp (artist, cptr) != 0)
436 { if (errors++ == 0)
437 puts ("\n") ;
438 printf (" Bad artist : %s\n", cptr) ;
439 } ;
440
441 cptr = sf_get_string (file, SF_STR_COMMENT) ;
442 if (cptr == NULL || strcmp (comment, cptr) != 0)
443 { if (errors++ == 0)
444 puts ("\n") ;
445 printf (" Bad comment : %s\n", cptr) ;
446 } ;
447
448 if (typemajor != SF_FORMAT_AIFF)
449 { cptr = sf_get_string (file, SF_STR_DATE) ;
450 if (cptr == NULL || strcmp (date, cptr) != 0)
451 { if (errors++ == 0)
452 puts ("\n") ;
453 printf (" Bad date : %s\n", cptr) ;
454 } ;
455 } ;
456
457 if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF)
458 { cptr = sf_get_string (file, SF_STR_ALBUM) ;
459 if (cptr == NULL || strcmp (album, cptr) != 0)
460 { if (errors++ == 0)
461 puts ("\n") ;
462 printf (" Bad album : %s\n", cptr) ;
463 } ;
464 } ;
465
466 if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF && typemajor != SF_FORMAT_RF64)
467 { cptr = sf_get_string (file, SF_STR_LICENSE) ;
468 if (cptr == NULL || strcmp (license, cptr) != 0)
469 { if (errors++ == 0)
470 puts ("\n") ;
471 printf (" Bad license : %s\n", cptr) ;
472 } ;
473 } ;
474
475 if (errors > 0)
476 { printf ("\n*** Error count : %d ***\n\n", errors) ;
477 dump_log_buffer (file) ;
478 exit (1) ;
479 } ;
480
481 sf_close (file) ;
482 unlink (filename) ;
483
484 puts ("ok") ;
485 } /* string_start_test */
486
487 static void
string_multi_set_test(const char * filename,int typemajor)488 string_multi_set_test (const char *filename, int typemajor)
489 { static const char
490 new_software [] = "new software (libsndfile-X.Y.Z)",
491 new_copyright [] = "Copyright (c) 2001 New Artist",
492 new_artist [] = "The New Artist",
493 new_title [] = "This is the new title" ;
494
495 static char buffer [2048] ;
496 SNDFILE *file ;
497 SF_INFO sfinfo ;
498 int count ;
499
500 print_test_name (__func__, filename) ;
501
502 memset (&sfinfo, 0, sizeof (sfinfo)) ;
503 sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
504 sfinfo.samplerate = 44100 ;
505 sfinfo.channels = 1 ;
506 sfinfo.frames = 0 ;
507
508 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
509
510 /* Write stuff at start of file. */
511 sf_set_string (file, SF_STR_TITLE, title) ;
512 sf_set_string (file, SF_STR_SOFTWARE, software) ;
513 sf_set_string (file, SF_STR_ARTIST, artist) ;
514
515 /* Write data to file. */
516 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
517
518 /* Write it all again. */
519
520 sf_set_string (file, SF_STR_TITLE, new_title) ;
521 sf_set_string (file, SF_STR_SOFTWARE, new_software) ;
522 sf_set_string (file, SF_STR_ARTIST, new_artist) ;
523
524 sf_set_string (file, SF_STR_COPYRIGHT, copyright) ;
525 sf_set_string (file, SF_STR_COMMENT, comment) ;
526 sf_set_string (file, SF_STR_DATE, date) ;
527 sf_set_string (file, SF_STR_ALBUM, album) ;
528 sf_set_string (file, SF_STR_LICENSE, license) ;
529 sf_set_string (file, SF_STR_COPYRIGHT, new_copyright) ;
530 sf_set_string (file, SF_STR_COMMENT, comment) ;
531 sf_set_string (file, SF_STR_DATE, date) ;
532 sf_set_string (file, SF_STR_ALBUM, album) ;
533 sf_set_string (file, SF_STR_LICENSE, license) ;
534
535 sf_close (file) ;
536
537 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
538 sf_command (file, SFC_GET_LOG_INFO, buffer, sizeof (buffer)) ;
539 sf_close (file) ;
540
541 count = str_count (buffer, new_title) ;
542 exit_if_true (count < 1, "\n\nLine %d : Could not find new_title in :\n%s\n", __LINE__, buffer) ;
543 exit_if_true (count > 1, "\n\nLine %d : new_title appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
544
545 count = str_count (buffer, software) ;
546 exit_if_true (count < 1, "\n\nLine %d : Could not find new_software in :\n%s\n", __LINE__, buffer) ;
547 exit_if_true (count > 1, "\n\nLine %d : new_software appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
548
549 count = str_count (buffer, new_artist) ;
550 exit_if_true (count < 1, "\n\nLine %d : Could not find new_artist in :\n%s\n", __LINE__, buffer) ;
551 exit_if_true (count > 1, "\n\nLine %d : new_artist appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
552
553 count = str_count (buffer, new_copyright) ;
554 exit_if_true (count < 1, "\n\nLine %d : Could not find new_copyright in :\n%s\n", __LINE__, buffer) ;
555 exit_if_true (count > 1, "\n\nLine %d : new_copyright appears %d times in :\n\n%s\n", __LINE__, count, buffer) ;
556
557 unlink (filename) ;
558
559 puts ("ok") ;
560 } /* string_multi_set_test */
561
562 static void
string_rdwr_test(const char * filename,int typemajor)563 string_rdwr_test (const char *filename, int typemajor)
564 { SNDFILE *file ;
565 SF_INFO sfinfo ;
566 sf_count_t frames ;
567 const char * str ;
568
569 print_test_name (__func__, filename) ;
570 create_short_sndfile (filename, typemajor | SF_FORMAT_PCM_16, 2) ;
571
572 memset (&sfinfo, 0, sizeof (sfinfo)) ;
573 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
574 frames = sfinfo.frames ;
575 sf_set_string (file, SF_STR_TITLE, title) ;
576 sf_close (file) ;
577
578 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
579 exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
580 str = sf_get_string (file, SF_STR_TITLE) ;
581 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
582 exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
583 sf_close (file) ;
584
585 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
586 frames = sfinfo.frames ;
587 sf_set_string (file, SF_STR_TITLE, title) ;
588 sf_close (file) ;
589
590 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
591 str = sf_get_string (file, SF_STR_TITLE) ;
592 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
593 sf_set_string (file, SF_STR_ARTIST, artist) ;
594 sf_close (file) ;
595
596 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
597
598 str = sf_get_string (file, SF_STR_ARTIST) ;
599 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_ARTIST string is NULL.\n", __LINE__) ;
600 exit_if_true (strcmp (str, artist) != 0, "\n\nLine %d : SF_STR_ARTIST doesn't match what was written.\n", __LINE__) ;
601
602 str = sf_get_string (file, SF_STR_TITLE) ;
603 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
604 exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
605
606 exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
607
608 sf_close (file) ;
609 unlink (filename) ;
610
611 puts ("ok") ;
612 } /* string_rdwr_test */
613
614 static void
string_short_rdwr_test(const char * filename,int typemajor)615 string_short_rdwr_test (const char *filename, int typemajor)
616 { SNDFILE *file ;
617 SF_INFO sfinfo ;
618 sf_count_t frames = BUFFER_LEN ;
619 const char * str ;
620
621 print_test_name (__func__, filename) ;
622
623 memset (&sfinfo, 0, sizeof (sfinfo)) ;
624 sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
625 sfinfo.samplerate = 44100 ;
626 sfinfo.channels = 1 ;
627 sfinfo.frames = 0 ;
628
629 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
630
631 /* Write data to file. */
632 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
633
634 sf_set_string (file, SF_STR_TITLE, long_title) ;
635 sf_set_string (file, SF_STR_ARTIST, long_artist) ;
636 sf_close (file) ;
637
638 /* Open the file RDWR. */
639 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
640 exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
641 str = sf_get_string (file, SF_STR_TITLE) ;
642 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
643 exit_if_true (strcmp (str, long_title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
644 str = sf_get_string (file, SF_STR_ARTIST) ;
645 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
646 exit_if_true (strcmp (str, long_artist) != 0, "\n\nLine %d : SF_STR_ARTIST doesn't match what was written.\n", __LINE__) ;
647
648 /* Change title and artist. */
649 sf_set_string (file, SF_STR_TITLE, title) ;
650 sf_set_string (file, SF_STR_ARTIST, artist) ;
651
652 sf_close (file) ;
653
654 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
655
656 check_log_buffer_or_die (file, __LINE__) ;
657
658 str = sf_get_string (file, SF_STR_TITLE) ;
659 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
660 exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
661
662 str = sf_get_string (file, SF_STR_ARTIST) ;
663 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_ARTIST string is NULL.\n", __LINE__) ;
664 exit_if_true (strcmp (str, artist) != 0, "\n\nLine %d : SF_STR_ARTIST doesn't match what was written.\n", __LINE__) ;
665
666 sf_close (file) ;
667 unlink (filename) ;
668
669 puts ("ok") ;
670 } /* string_short_rdwr_test */
671
672 static int
str_count(const char * haystack,const char * needle)673 str_count (const char * haystack, const char * needle)
674 { int count = 0 ;
675
676 while ((haystack = strstr (haystack, needle)) != NULL)
677 { count ++ ;
678 haystack ++ ;
679 } ;
680
681 return count ;
682 } /* str_count */
683
684 #define MIN(a, b) ((a) < (b) ? (a) : (b))
685
686 static void
software_string_test(const char * filename)687 software_string_test (const char *filename)
688 { size_t k ;
689
690 print_test_name (__func__, filename) ;
691
692 for (k = 0 ; k < 50 ; k++)
693 { const char *result ;
694 char sfname [64] = "" ;
695 SNDFILE *file ;
696 SF_INFO info ;
697
698 sf_info_setup (&info, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 44100, 1) ;
699 file = test_open_file_or_die (filename, SFM_WRITE, &info, SF_TRUE, __LINE__) ;
700
701 snprintf (sfname, MIN (k, sizeof (sfname)), "%s", "abcdefghijklmnopqrestvwxyz0123456789abcdefghijklmnopqrestvwxyz") ;
702
703 exit_if_true (sf_set_string (file, SF_STR_SOFTWARE, sfname),
704 "\n\nLine %d : sf_set_string (f, SF_STR_SOFTWARE, '%s') failed : %s\n", __LINE__, sfname, sf_strerror (file)) ;
705
706 sf_close (file) ;
707
708 file = test_open_file_or_die (filename, SFM_READ, &info, SF_TRUE, __LINE__) ;
709 result = sf_get_string (file, SF_STR_SOFTWARE) ;
710
711 exit_if_true (result == NULL, "\n\nLine %d : sf_get_string (file, SF_STR_SOFTWARE) returned NULL.\n\n", __LINE__) ;
712
713 exit_if_true (strstr (result, sfname) != result,
714 "\n\nLine %d : Can't fine string '%s' in '%s'\n\n", __LINE__, sfname, result) ;
715 sf_close (file) ;
716 } ;
717
718 unlink (filename) ;
719 puts ("ok") ;
720 } /* software_string_test */
721
722
723 static void
string_rdwr_grow_test(const char * filename,int typemajor)724 string_rdwr_grow_test (const char *filename, int typemajor)
725 { SNDFILE *file ;
726 SF_INFO sfinfo ;
727 sf_count_t frames ;
728 const char * str ;
729
730 print_test_name (__func__, filename) ;
731
732 /* Create a file that contains some strings. Then open the file in RDWR mode and
733 grow the file by writing more audio data to it. Check that the audio data has
734 been added to the file, and that the strings are still there. */
735
736 /* Create a short file that contains a string. */
737 memset (&sfinfo, 0, sizeof (sfinfo)) ;
738 sfinfo.samplerate = 44100 ;
739 sfinfo.channels = 2 ;
740 sfinfo.frames = 0 ;
741 sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
742
743 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
744 /* Write data to file. */
745 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
746
747 /* Write some strings at end of file. */
748 sf_set_string (file, SF_STR_TITLE , title) ;
749 sf_set_string (file, SF_STR_COMMENT, comment) ;
750 sf_close (file) ;
751
752
753 /* Now open file again in SFM_RDWR mode and write more audio data to it. */
754 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
755 /* Write more data to file. */
756 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
757 sf_close (file) ;
758
759
760 /* Now open file again. It should now contain two BUFFER_LEN's worth of frames and the strings. */
761 frames = 2 * BUFFER_LEN / sfinfo.channels ;
762 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
763 exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
764
765 /* Check the strings */
766 str = sf_get_string (file, SF_STR_TITLE) ;
767 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
768 exit_if_true (strcmp (str, title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
769
770 str = sf_get_string (file, SF_STR_COMMENT) ;
771 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_COMMENT string is NULL.\n", __LINE__) ;
772 exit_if_true (strcmp (str, comment) != 0, "\n\nLine %d : SF_STR_COMMENT doesn't match what was written.\n", __LINE__) ;
773
774 sf_close (file) ;
775 unlink (filename) ;
776
777 puts ("ok") ;
778 } /* string_rdwr_grow_test */
779
780 static void
string_header_update(const char * filename,int typemajor)781 string_header_update (const char *filename, int typemajor)
782 { SNDFILE *file , *file1 ;
783 SF_INFO sfinfo , sfinfo1 ;
784 sf_count_t frames ;
785 const char * str ;
786 const int GROW_BUFFER_AMOUNT = 4 ; /* this should be less than half the size of the string header */
787
788 print_test_name (__func__, filename) ;
789
790 /* Create a short file. */
791 memset (&sfinfo, 0, sizeof (sfinfo)) ;
792 sfinfo.samplerate = 44100 ;
793 sfinfo.channels = 2 ;
794 sfinfo.frames = 0 ;
795 sfinfo.format = typemajor | SF_FORMAT_PCM_16 ;
796
797 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
798 test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ;
799 sf_set_string (file, SF_STR_TITLE, long_title) ;
800 sf_close (file) ;
801
802
803 /* Check that SFC_UPDATE_HEADER_NOW correctly calculates datalength. */
804 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
805 /* Write a very small amount of new audio data that doesn't completely overwrite the existing header. */
806 test_write_short_or_die (file, 0, data_out, GROW_BUFFER_AMOUNT, __LINE__) ;
807
808 /* Update the header without closing the file. */
809 sf_command (file, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
810
811 /* The file should now contain BUFFER_LEN + GROW_BUFFER_AMOUNT frames.
812 Open a second handle to the file and check the reported length. */
813 memset (&sfinfo1, 0, sizeof (sfinfo1)) ;
814 file1 = test_open_file_or_die (filename, SFM_READ, &sfinfo1, SF_TRUE, __LINE__) ;
815
816 frames = (BUFFER_LEN + GROW_BUFFER_AMOUNT) / sfinfo.channels ;
817 exit_if_true (frames != sfinfo1.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo1.frames, frames) ;
818
819 /* The strings are probably not readable by the second soundfile handle because write_tailer has not yet been called.
820 It's a design decision whether SFC_UPDATE_HEADER_NOW should write the tailer. I think it's fine that it doesn't. */
821
822 sf_close (file1) ;
823 sf_close (file) ;
824
825
826 /* Check that sf_close correctly calculates datalength. */
827 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
828 /* Write a very small amount of new audio data that doesn't completely overwrite the existing header. */
829 test_write_short_or_die (file, 0, data_out, GROW_BUFFER_AMOUNT, __LINE__) ;
830 sf_close (file) ;
831
832
833 /* Open file again and verify data and string. */
834 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
835 frames = (BUFFER_LEN + 2*GROW_BUFFER_AMOUNT) / sfinfo.channels ;
836 exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
837 str = sf_get_string (file, SF_STR_TITLE) ;
838 exit_if_true (str == NULL, "\n\nLine %d : SF_STR_TITLE string is NULL.\n", __LINE__) ;
839 exit_if_true (strcmp (str, long_title) != 0, "\n\nLine %d : SF_STR_TITLE doesn't match what was written.\n", __LINE__) ;
840 sf_close (file) ;
841 unlink (filename) ;
842 puts ("ok") ;
843 } /* string_header_update */
844