1 /*
2 ** Copyright (C) 1999-2018 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 <errno.h>
25
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #else
29 #include "sf_unistd.h"
30 #endif
31
32 #include <sndfile.h>
33
34 #include "utils.h"
35
36 #define BUFFER_SIZE (1 << 15)
37 #define SHORT_BUFFER (256)
38
39 static void
error_number_test(void)40 error_number_test (void)
41 { const char *noerror, *errstr ;
42 int k ;
43
44 print_test_name ("error_number_test", "") ;
45
46 noerror = sf_error_number (0) ;
47
48 for (k = 1 ; k < 300 ; k++)
49 { errstr = sf_error_number (k) ;
50
51 /* Test for termination condition. */
52 if (errstr == noerror)
53 break ;
54
55 /* Test for error. */
56 if (strstr (errstr, "This is a bug in libsndfile."))
57 { printf ("\n\nError : error number %d : %s\n\n\n", k, errstr) ;
58 exit (1) ;
59 } ;
60 } ;
61
62
63 puts ("ok") ;
64 return ;
65 } /* error_number_test */
66
67 static void
error_value_test(void)68 error_value_test (void)
69 { static unsigned char aiff_data [0x1b0] =
70 { 'F' , 'O' , 'R' , 'M' ,
71 0x00, 0x00, 0x01, 0xA8, /* FORM length */
72
73 'A' , 'I' , 'F' , 'C' ,
74 } ;
75
76 const char *filename = "error.aiff" ;
77 SNDFILE *file ;
78 SF_INFO sfinfo ;
79 int error_num ;
80
81 print_test_name ("error_value_test", filename) ;
82
83 dump_data_to_file (filename, aiff_data, sizeof (aiff_data)) ;
84
85 memset (&sfinfo, 0, sizeof (sfinfo)) ;
86
87 file = sf_open (filename, SFM_READ, &sfinfo) ;
88 if (file != NULL)
89 { printf ("\n\nLine %d : Should not have been able to open this file.\n\n", __LINE__) ;
90 exit (1) ;
91 } ;
92
93 if ((error_num = sf_error (NULL)) <= 1 || error_num > 300)
94 { printf ("\n\nLine %d : Should not have had an error number of %d.\n\n", __LINE__, error_num) ;
95 exit (1) ;
96 } ;
97
98 remove (filename) ;
99 puts ("ok") ;
100 return ;
101 } /* error_value_test */
102
103 static void
no_file_test(const char * filename)104 no_file_test (const char * filename)
105 { SNDFILE *sndfile ;
106 SF_INFO sfinfo ;
107
108 print_test_name (__func__, filename) ;
109
110 unlink (filename) ;
111
112 memset (&sfinfo, 0, sizeof (sfinfo)) ;
113 sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
114
115 exit_if_true (sndfile != NULL, "\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ;
116
117 unlink (filename) ;
118 puts ("ok") ;
119 } /* no_file_test */
120
121 static void
zero_length_test(const char * filename)122 zero_length_test (const char *filename)
123 { SNDFILE *sndfile ;
124 SF_INFO sfinfo ;
125 FILE *file ;
126
127 print_test_name (__func__, filename) ;
128
129 /* Create a zero length file. */
130 file = fopen (filename, "w") ;
131 exit_if_true (file == NULL, "\n\nLine %d : fopen ('%s') failed.\n", __LINE__, filename) ;
132 fclose (file) ;
133
134 memset (&sfinfo, 0, sizeof (sfinfo)) ;
135 sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
136
137 exit_if_true (sndfile != NULL, "\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ;
138
139 exit_if_true (0 && sf_error (NULL) != SF_ERR_UNRECOGNISED_FORMAT,
140 "\n\nLine %3d : Error : %s\n should be : %s\n", __LINE__,
141 sf_strerror (NULL), sf_error_number (SF_ERR_UNRECOGNISED_FORMAT)) ;
142
143 unlink (filename) ;
144 puts ("ok") ;
145 } /* zero_length_test */
146
147 static void
bad_wav_test(const char * filename)148 bad_wav_test (const char * filename)
149 { SNDFILE *sndfile ;
150 SF_INFO sfinfo ;
151
152 FILE *file ;
153 const char data [] = "RIFF WAVEfmt " ;
154
155 print_test_name (__func__, filename) ;
156
157 if ((file = fopen (filename, "w")) == NULL)
158 { printf ("\n\nLine %d : fopen returned NULL.\n", __LINE__) ;
159 exit (1) ;
160 } ;
161
162 exit_if_true (fwrite (data, sizeof (data), 1, file) != 1, "\n\nLine %d : fwrite failed.\n", __LINE__) ;
163 fclose (file) ;
164
165 memset (&sfinfo, 0, sizeof (sfinfo)) ;
166 sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
167
168 if (sndfile)
169 { printf ("\n\nLine %d : should not have received a valid SNDFILE* pointer.\n", __LINE__) ;
170 exit (1) ;
171 } ;
172
173 unlink (filename) ;
174 puts ("ok") ;
175 } /* bad_wav_test */
176
177 static void
wav_list_recover_test(const char * filename)178 wav_list_recover_test (const char * filename)
179 { SNDFILE *sndfile ;
180 SF_INFO sfinfo ;
181
182 FILE *file ;
183 const char data [] =
184 "RIFF" "J\000\000\000"
185 "WAVE" "fmt " "\020\000\000\000" "\001\000\001\000D\254\000\000\210X\001\000\002\000\020\000"
186 "LIST" "\014\000\000\000" "test" "\010\000\000\000" "1234" /* test is 4 bytes short inside LIST container */
187 "data" "\004\000\000\000" "abcd" ;
188
189 print_test_name (__func__, filename) ;
190
191 if ((file = fopen (filename, "w")) == NULL)
192 { printf ("\n\nLine %d : fopen returned NULL.\n", __LINE__) ;
193 exit (1) ;
194 } ;
195
196 exit_if_true (fwrite (data, sizeof (data) - 1, 1, file) != 1, "\n\nLine %d : fwrite failed.\n", __LINE__) ;
197 fclose (file) ;
198
199 memset (&sfinfo, 0, sizeof (sfinfo)) ;
200 sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
201
202 if (!sndfile)
203 { printf ("\n\nLine %d : expected recovery from bogus LIST content.\n", __LINE__) ;
204 exit (1) ;
205 } ;
206
207 if (sfinfo.frames != 2)
208 { printf ("\n\nLine %d : Should have read data chunk with 2 stereo frames, got %ld.\n\n", __LINE__, (long)sfinfo.frames) ;
209 exit (1) ;
210 } ;
211
212 unlink (filename) ;
213 puts ("ok") ;
214 } /* wav_list_recover_test */
215
216 static void
error_close_test(void)217 error_close_test (void)
218 { static short buffer [SHORT_BUFFER] ;
219 const char *filename = "error_close.wav" ;
220 SNDFILE *sndfile ;
221 SF_INFO sfinfo ;
222 FILE *file ;
223
224 print_test_name (__func__, filename) ;
225
226 /* Open a FILE* from which we will extract a file descriptor. */
227 if ((file = fopen (filename, "w")) == NULL)
228 { printf ("\n\nLine %d : fopen returned NULL.\n", __LINE__) ;
229 exit (1) ;
230 } ;
231
232 /* Set parameters for writing the file. */
233 memset (&sfinfo, 0, sizeof (sfinfo)) ;
234 sfinfo.channels = 1 ;
235 sfinfo.samplerate = 44100 ;
236 sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
237
238 sndfile = sf_open_fd (fileno (file), SFM_WRITE, &sfinfo, SF_TRUE) ;
239 if (sndfile == NULL)
240 { printf ("\n\nLine %d : sf_open_fd failed : %s\n", __LINE__, sf_strerror (NULL)) ;
241 exit (1) ;
242 } ;
243
244 test_write_short_or_die (sndfile, 0, buffer, ARRAY_LEN (buffer), __LINE__) ;
245
246 /* Now close the fd associated with file before calling sf_close. */
247 fclose (file) ;
248
249 if (sf_close (sndfile) == 0)
250 {
251 printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ;
252 #if OS_IS_WIN32
253 printf ("\nHowever, this is a known bug on windows platform so we'll ignore it.\n\n") ;
254 #else
255 exit (1) ;
256 #endif
257 } ;
258
259 unlink (filename) ;
260 puts ("ok") ;
261 } /* error_close_test */
262
263 static void
unrecognised_test(void)264 unrecognised_test (void)
265 { const char *filename = "unrecognised.bin" ;
266 SNDFILE *sndfile ;
267 SF_INFO sfinfo ;
268 FILE *file ;
269 int k ;
270
271 print_test_name (__func__, filename) ;
272
273 file = fopen (filename, "wb") ;
274 exit_if_true (file == NULL,
275 "\n\nLine %d : fopen ('%s') failed : %s\n", __LINE__, filename, strerror (errno)
276 ) ;
277 fputs ("Unrecognised file", file) ;
278 fclose (file) ;
279
280 memset (&sfinfo, 0, sizeof (sfinfo)) ;
281 sndfile = sf_open (filename, SFM_READ, &sfinfo) ;
282
283 exit_if_true (sndfile != NULL,
284 "\n\nLine %d : SNDFILE* pointer (%p) should be NULL.\n", __LINE__, (void *) sndfile
285 ) ;
286
287 k = sf_error (sndfile) ;
288 exit_if_true (k != SF_ERR_UNRECOGNISED_FORMAT,
289 "\n\nLine %d : error (%d) should have been SF_ERR_UNRECOGNISED_FORMAT (%d).\n",
290 __LINE__, k, SF_ERR_UNRECOGNISED_FORMAT
291 ) ;
292
293 unlink (filename) ;
294 puts ("ok") ;
295 } /* unrecognised_test */
296
297 int
main(void)298 main (void)
299 {
300 error_number_test () ;
301 error_value_test () ;
302
303 error_close_test () ;
304
305 no_file_test ("no_file.wav") ;
306 zero_length_test ("zero_length.wav") ;
307 bad_wav_test ("bad_wav.wav") ;
308 wav_list_recover_test ("list_recover.wav") ;
309
310 unrecognised_test () ;
311
312 return 0 ;
313 } /* main */
314
315