comparison src/libsndfile-1.0.27/tests/chunk_test.c @ 125:cd6cdf86811e

Current libsndfile source
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 18 Oct 2016 13:22:47 +0100
parents
children
comparison
equal deleted inserted replaced
124:e3d5853d5918 125:cd6cdf86811e
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
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 #include <sndfile.h>
31
32 #include "utils.h"
33
34 #define BUFFER_LEN (1 << 10)
35 #define LOG_BUFFER_SIZE 1024
36
37 static void chunk_test (const char *filename, int format) ;
38
39 static void
40 chunk_test_helper (const char *filename, int format, const char * testdata) ;
41
42 int
43 main (int argc, char *argv [])
44 { int do_all = 0 ;
45 int test_count = 0 ;
46
47 if (argc != 2)
48 { printf ("Usage : %s <test>\n", argv [0]) ;
49 printf (" Where <test> is one of the following:\n") ;
50 printf (" wav - test adding chunks to WAV files\n") ;
51 printf (" aiff - test adding chunks to AIFF files\n") ;
52 printf (" caf - test adding chunks to CAF files\n") ;
53 printf (" rf64 - test adding chunks to RF64 files\n") ;
54 printf (" all - perform all tests\n") ;
55 exit (1) ;
56 } ;
57
58 do_all = ! strcmp (argv [1], "all") ;
59
60 if (do_all || ! strcmp (argv [1], "wav"))
61 { chunk_test ("chunks_pcm16.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
62 chunk_test ("chunks_pcm16.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
63 chunk_test ("chunks_pcm16.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
64 test_count++ ;
65 } ;
66
67 if (do_all || ! strcmp (argv [1], "aiff"))
68 { chunk_test ("chunks_pcm16.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
69 test_count++ ;
70 } ;
71
72 if (do_all || ! strcmp (argv [1], "caf"))
73 { chunk_test ("chunks_pcm16.caf", SF_FORMAT_CAF | SF_FORMAT_PCM_16) ;
74 chunk_test ("chunks_alac.caf", SF_FORMAT_CAF | SF_FORMAT_ALAC_16) ;
75 test_count++ ;
76 } ;
77
78 if (do_all || ! strcmp (argv [1], "rf64"))
79 { chunk_test ("chunks_pcm16.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
80 test_count++ ;
81 } ;
82
83 if (test_count == 0)
84 { printf ("Mono : ************************************\n") ;
85 printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
86 printf ("Mono : ************************************\n") ;
87 return 1 ;
88 } ;
89
90 return 0 ;
91 } /* main */
92
93
94 /*============================================================================================
95 ** Here are the test functions.
96 */
97
98 static void
99 chunk_test_helper (const char *filename, int format, const char * testdata)
100 { SNDFILE *file ;
101 SF_INFO sfinfo ;
102 SF_CHUNK_INFO chunk_info ;
103 SF_CHUNK_ITERATOR * iterator ;
104 uint32_t length_before ;
105 int err, allow_fd ;
106
107 switch (format & SF_FORMAT_SUBMASK)
108 { case SF_FORMAT_ALAC_16 :
109 allow_fd = SF_FALSE ;
110 break ;
111 default :
112 allow_fd = SF_TRUE ;
113 break ;
114 } ;
115
116 sfinfo.samplerate = 44100 ;
117 sfinfo.channels = 1 ;
118 sfinfo.frames = 0 ;
119 sfinfo.format = format ;
120
121 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
122
123 /* Set up the chunk to write. */
124 memset (&chunk_info, 0, sizeof (chunk_info)) ;
125 snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
126 chunk_info.id_size = 4 ;
127 chunk_info.data = strdup (testdata) ;
128 chunk_info.datalen = strlen (chunk_info.data) ;
129
130 length_before = chunk_info.datalen ;
131
132 err = sf_set_chunk (file, &chunk_info) ;
133 exit_if_true (
134 err != SF_ERR_NO_ERROR,
135 "\n\nLine %d : sf_set_chunk returned for testdata '%s' : %s\n\n", __LINE__, testdata, sf_error_number (err)
136 ) ;
137
138 memset (chunk_info.data, 0, chunk_info.datalen) ;
139 free (chunk_info.data) ;
140
141 sf_close (file) ;
142
143 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
144
145 memset (&chunk_info, 0, sizeof (chunk_info)) ;
146 snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
147 chunk_info.id_size = 4 ;
148
149 iterator = sf_get_chunk_iterator (file, &chunk_info) ;
150 err = sf_get_chunk_size (iterator, &chunk_info) ;
151 exit_if_true (
152 err != SF_ERR_NO_ERROR,
153 "\n\nLine %d : sf_get_chunk_size returned for testdata '%s' : %s\n\n", __LINE__, testdata, sf_error_number (err)
154 ) ;
155
156 exit_if_true (
157 length_before > chunk_info.datalen || chunk_info.datalen - length_before > 4,
158 "\n\nLine %d : testdata '%s' : Bad chunk length %u (previous length %u)\n\n", __LINE__, testdata, chunk_info.datalen, length_before
159 ) ;
160
161 chunk_info.data = malloc (chunk_info.datalen) ;
162 err = sf_get_chunk_data (iterator, &chunk_info) ;
163 exit_if_true (
164 err != SF_ERR_NO_ERROR,
165 "\n\nLine %d : sf_get_chunk_size returned for testdata '%s' : %s\n\n", __LINE__, testdata, sf_error_number (err)
166 ) ;
167
168 exit_if_true (
169 memcmp (testdata, chunk_info.data, length_before),
170 "\n\nLine %d : Data compare failed.\n %s\n %s\n\n", __LINE__, testdata, (char*) chunk_info.data
171 ) ;
172
173 free (chunk_info.data) ;
174
175 sf_close (file) ;
176 unlink (filename) ;
177 } /* chunk_test_helper */
178
179 static void
180 multichunk_test_helper (const char *filename, int format, const char * testdata [], size_t testdata_len)
181 { SNDFILE *file ;
182 SF_INFO sfinfo ;
183 SF_CHUNK_INFO chunk_info ;
184 SF_CHUNK_ITERATOR * iterator ;
185 uint32_t length_before [testdata_len] ;
186 int err, allow_fd ;
187 size_t i ;
188
189 sfinfo.samplerate = 44100 ;
190 sfinfo.channels = 1 ;
191 sfinfo.frames = 0 ;
192 sfinfo.format = format ;
193
194 switch (format & SF_FORMAT_SUBMASK)
195 { case SF_FORMAT_ALAC_16 :
196 allow_fd = SF_FALSE ;
197 break ;
198 default :
199 allow_fd = SF_TRUE ;
200 break ;
201 } ;
202
203 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
204
205 /* Set up the chunk to write. */
206 for (i = 0 ; i < testdata_len ; i++)
207 { memset (&chunk_info, 0, sizeof (chunk_info)) ;
208 snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
209 chunk_info.id_size = 4 ;
210
211 chunk_info.data = strdup (testdata [i]) ;
212 chunk_info.datalen = strlen (chunk_info.data) ;
213
214 length_before [i] = chunk_info.datalen ;
215
216 err = sf_set_chunk (file, &chunk_info) ;
217 exit_if_true (
218 err != SF_ERR_NO_ERROR,
219 "\n\nLine %d : sf_set_chunk returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err)
220 ) ;
221
222 memset (chunk_info.data, 0, chunk_info.datalen) ;
223 free (chunk_info.data) ;
224 }
225
226 sf_close (file) ;
227
228 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
229
230 memset (&chunk_info, 0, sizeof (chunk_info)) ;
231 snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
232 chunk_info.id_size = 4 ;
233
234 iterator = sf_get_chunk_iterator (file, &chunk_info) ;
235
236 i = 0 ;
237 while (iterator)
238 { memset (&chunk_info, 0, sizeof (chunk_info)) ;
239 err = sf_get_chunk_size (iterator, &chunk_info) ;
240 exit_if_true (
241 i > testdata_len,
242 "\n\nLine %d : iterated to chunk #%d, but only %d chunks have been written\n\n", __LINE__, (int) i, (int) testdata_len
243 ) ;
244
245 exit_if_true (
246 err != SF_ERR_NO_ERROR,
247 "\n\nLine %d : sf_get_chunk_size returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err)
248 ) ;
249
250 exit_if_true (
251 length_before [i] > chunk_info.datalen || chunk_info.datalen - length_before [i] > 4,
252 "\n\nLine %d : testdata[%d] '%s' : Bad chunk length %u (previous length %u)\n\n", __LINE__, (int) i, testdata [i], chunk_info.datalen, length_before [i]
253 ) ;
254
255 chunk_info.data = malloc (chunk_info.datalen) ;
256 err = sf_get_chunk_data (iterator, &chunk_info) ;
257 exit_if_true (
258 err != SF_ERR_NO_ERROR,
259 "\n\nLine %d : sf_get_chunk_size returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err)
260 ) ;
261
262 exit_if_true (
263 4 != chunk_info.id_size,
264 "\n\nLine %d : testdata[%d] : Bad ID length %u (previous length %u)\n\n", __LINE__, (int) i, chunk_info.id_size, 4
265 ) ;
266 exit_if_true (
267 memcmp ("Test", chunk_info.id, 4),
268 "\n\nLine %d : ID compare failed at %d.\n %s\n %s\n\n", __LINE__, (int) i, "Test", (char*) chunk_info.id
269 ) ;
270
271 exit_if_true (
272 memcmp (testdata [i], chunk_info.data, length_before [i]),
273 "\n\nLine %d : Data compare failed at %d.\n %s\n %s\n\n", __LINE__, (int) i, testdata [i], (char*) chunk_info.data
274 ) ;
275
276 free (chunk_info.data) ;
277 iterator = sf_next_chunk_iterator (iterator) ;
278 i++ ;
279 }
280
281 sf_close (file) ;
282 unlink (filename) ;
283 } /* multichunk_test_helper */
284
285
286 static void
287 chunk_test (const char *filename, int format)
288 { const char* testdata [] =
289 { "There can be only one.", "", "A", "AB", "ABC", "ABCD", "ABCDE" } ;
290 uint32_t k ;
291
292 print_test_name (__func__, filename) ;
293
294 for (k = 0 ; k < ARRAY_LEN (testdata) ; k++)
295 chunk_test_helper (filename, format, testdata [k]) ;
296
297 multichunk_test_helper (filename, format, testdata, ARRAY_LEN (testdata)) ;
298
299 puts ("ok") ;
300 } /* chunk_test */