• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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