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