1 /* test_libFLAC - Unit tester for libFLAC
2  * Copyright (C) 2002-2009  Josh Coalson
3  * Copyright (C) 2011-2016  Xiph.Org Foundation
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23 
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "decoders.h"
29 #include "FLAC/assert.h"
30 #include "FLAC/stream_decoder.h"
31 #include "share/grabbag.h"
32 #include "share/compat.h"
33 #include "share/safe_str.h"
34 #include "test_libs_common/file_utils_flac.h"
35 #include "test_libs_common/metadata_utils.h"
36 
37 typedef enum {
38 	LAYER_STREAM = 0, /* FLAC__stream_decoder_init_[ogg_]stream() without seeking */
39 	LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_[ogg_]stream() with seeking */
40 	LAYER_FILE, /* FLAC__stream_decoder_init_[ogg_]FILE() */
41 	LAYER_FILENAME /* FLAC__stream_decoder_init_[ogg_]file() */
42 } Layer;
43 
44 static const char * const LayerString[] = {
45 	"Stream",
46 	"Seekable Stream",
47 	"FILE*",
48 	"Filename"
49 };
50 
51 typedef struct {
52 	Layer layer;
53 	FILE *file;
54 	char filename[512];
55 	uint32_t current_metadata_number;
56 	FLAC__bool ignore_errors;
57 	FLAC__bool error_occurred;
58 } StreamDecoderClientData;
59 
60 static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
61 static FLAC__StreamMetadata *expected_metadata_sequence_[9];
62 static uint32_t num_expected_;
63 static FLAC__off_t flacfilesize_;
64 
flacfilename(FLAC__bool is_ogg)65 static const char *flacfilename(FLAC__bool is_ogg)
66 {
67 	return is_ogg? "metadata.oga" : "metadata.flac";
68 }
69 
die_(const char * msg)70 static FLAC__bool die_(const char *msg)
71 {
72 	printf("ERROR: %s\n", msg);
73 	return false;
74 }
75 
die_s_(const char * msg,const FLAC__StreamDecoder * decoder)76 static FLAC__bool die_s_(const char *msg, const FLAC__StreamDecoder *decoder)
77 {
78 	FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(decoder);
79 
80 	if(msg)
81 		printf("FAILED, %s", msg);
82 	else
83 		printf("FAILED");
84 
85 	printf(", state = %u (%s)\n", (uint32_t)state, FLAC__StreamDecoderStateString[state]);
86 
87 	return false;
88 }
89 
open_test_file(StreamDecoderClientData * pdcd,int is_ogg,const char * mode)90 static void open_test_file(StreamDecoderClientData * pdcd, int is_ogg, const char * mode)
91 {
92 	pdcd->file = flac_fopen(flacfilename(is_ogg), mode);
93 	safe_strncpy(pdcd->filename, flacfilename(is_ogg), sizeof (pdcd->filename));
94 }
95 
init_metadata_blocks_(void)96 static void init_metadata_blocks_(void)
97 {
98 	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
99 }
100 
free_metadata_blocks_(void)101 static void free_metadata_blocks_(void)
102 {
103 	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
104 }
105 
generate_file_(FLAC__bool is_ogg)106 static FLAC__bool generate_file_(FLAC__bool is_ogg)
107 {
108 	printf("\n\ngenerating %sFLAC file for decoder tests...\n", is_ogg? "Ogg ":"");
109 
110 	num_expected_ = 0;
111 	expected_metadata_sequence_[num_expected_++] = &padding_;
112 	expected_metadata_sequence_[num_expected_++] = &seektable_;
113 	expected_metadata_sequence_[num_expected_++] = &application1_;
114 	expected_metadata_sequence_[num_expected_++] = &application2_;
115 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
116 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
117 	expected_metadata_sequence_[num_expected_++] = &picture_;
118 	expected_metadata_sequence_[num_expected_++] = &unknown_;
119 	/* WATCHOUT: for Ogg FLAC the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
120 
121 	if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
122 		return die_("creating the encoded file");
123 
124 	return true;
125 }
126 
stream_decoder_read_callback_(const FLAC__StreamDecoder * decoder,FLAC__byte buffer[],size_t * bytes,void * client_data)127 static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
128 {
129 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
130 	const size_t requested_bytes = *bytes;
131 
132 	(void)decoder;
133 
134 	if(0 == dcd) {
135 		printf("ERROR: client_data in read callback is NULL\n");
136 		return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
137 	}
138 
139 	if(dcd->error_occurred)
140 		return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
141 
142 	if(feof(dcd->file)) {
143 		*bytes = 0;
144 		return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
145 	}
146 	else if(requested_bytes > 0) {
147 		*bytes = fread(buffer, 1, requested_bytes, dcd->file);
148 		if(*bytes == 0) {
149 			if(feof(dcd->file))
150 				return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
151 			else
152 				return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
153 		}
154 		else {
155 			return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
156 		}
157 	}
158 	else
159 		return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
160 }
161 
stream_decoder_seek_callback_(const FLAC__StreamDecoder * decoder,FLAC__uint64 absolute_byte_offset,void * client_data)162 static FLAC__StreamDecoderSeekStatus stream_decoder_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
163 {
164 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
165 
166 	(void)decoder;
167 
168 	if(0 == dcd) {
169 		printf("ERROR: client_data in seek callback is NULL\n");
170 		return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
171 	}
172 
173 	if(dcd->error_occurred)
174 		return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
175 
176 	if(fseeko(dcd->file, (FLAC__off_t)absolute_byte_offset, SEEK_SET) < 0) {
177 		dcd->error_occurred = true;
178 		return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
179 	}
180 
181 	return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
182 }
183 
stream_decoder_tell_callback_(const FLAC__StreamDecoder * decoder,FLAC__uint64 * absolute_byte_offset,void * client_data)184 static FLAC__StreamDecoderTellStatus stream_decoder_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
185 {
186 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
187 	FLAC__off_t offset;
188 
189 	(void)decoder;
190 
191 	if(0 == dcd) {
192 		printf("ERROR: client_data in tell callback is NULL\n");
193 		return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
194 	}
195 
196 	if(dcd->error_occurred)
197 		return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
198 
199 	offset = ftello(dcd->file);
200 	*absolute_byte_offset = (FLAC__uint64)offset;
201 
202 	if(offset < 0) {
203 		dcd->error_occurred = true;
204 		return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
205 	}
206 
207 	return FLAC__STREAM_DECODER_TELL_STATUS_OK;
208 }
209 
stream_decoder_length_callback_(const FLAC__StreamDecoder * decoder,FLAC__uint64 * stream_length,void * client_data)210 static FLAC__StreamDecoderLengthStatus stream_decoder_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
211 {
212 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
213 
214 	(void)decoder;
215 
216 	if(0 == dcd) {
217 		printf("ERROR: client_data in length callback is NULL\n");
218 		return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
219 	}
220 
221 	if(dcd->error_occurred)
222 		return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
223 
224 	*stream_length = (FLAC__uint64)flacfilesize_;
225 	return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
226 }
227 
stream_decoder_eof_callback_(const FLAC__StreamDecoder * decoder,void * client_data)228 static FLAC__bool stream_decoder_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data)
229 {
230 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
231 
232 	(void)decoder;
233 
234 	if(0 == dcd) {
235 		printf("ERROR: client_data in eof callback is NULL\n");
236 		return true;
237 	}
238 
239 	if(dcd->error_occurred)
240 		return true;
241 
242 	return feof(dcd->file);
243 }
244 
stream_decoder_write_callback_(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)245 static FLAC__StreamDecoderWriteStatus stream_decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
246 {
247 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
248 
249 	(void)decoder, (void)buffer;
250 
251 	if(0 == dcd) {
252 		printf("ERROR: client_data in write callback is NULL\n");
253 		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
254 	}
255 
256 	if(dcd->error_occurred)
257 		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
258 
259 	if(
260 		(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
261 		(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
262 	) {
263 		printf("content... ");
264 		fflush(stdout);
265 	}
266 
267 	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
268 }
269 
stream_decoder_metadata_callback_(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)270 static void stream_decoder_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
271 {
272 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
273 
274 	(void)decoder;
275 
276 	if(0 == dcd) {
277 		printf("ERROR: client_data in metadata callback is NULL\n");
278 		return;
279 	}
280 
281 	if(dcd->error_occurred)
282 		return;
283 
284 	if (metadata->type == FLAC__METADATA_TYPE_APPLICATION) {
285 		printf ("%u ('%c%c%c%c')... ", dcd->current_metadata_number, metadata->data.application.id [0], metadata->data.application.id [1], metadata->data.application.id [2], metadata->data.application.id [3]);
286 	}
287 	else {
288 		printf("%u... ", dcd->current_metadata_number);
289 	}
290 	fflush(stdout);
291 
292 
293 	if(dcd->current_metadata_number >= num_expected_) {
294 		(void)die_("got more metadata blocks than expected");
295 		dcd->error_occurred = true;
296 	}
297 	else {
298 		if(!mutils__compare_block(expected_metadata_sequence_[dcd->current_metadata_number], metadata)) {
299 			(void)die_("metadata block mismatch");
300 			dcd->error_occurred = true;
301 		}
302 	}
303 	dcd->current_metadata_number++;
304 }
305 
stream_decoder_error_callback_(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)306 static void stream_decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
307 {
308 	StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
309 
310 	(void)decoder;
311 
312 	if(0 == dcd) {
313 		printf("ERROR: client_data in error callback is NULL\n");
314 		return;
315 	}
316 
317 	if(!dcd->ignore_errors) {
318 		printf("ERROR: got error callback: err = %u (%s)\n", (uint32_t)status, FLAC__StreamDecoderErrorStatusString[status]);
319 		dcd->error_occurred = true;
320 	}
321 }
322 
stream_decoder_test_respond_(FLAC__StreamDecoder * decoder,StreamDecoderClientData * dcd,FLAC__bool is_ogg)323 static FLAC__bool stream_decoder_test_respond_(FLAC__StreamDecoder *decoder, StreamDecoderClientData *dcd, FLAC__bool is_ogg)
324 {
325 	FLAC__StreamDecoderInitStatus init_status;
326 
327 	if(!FLAC__stream_decoder_set_md5_checking(decoder, true))
328 		return die_s_("at FLAC__stream_decoder_set_md5_checking(), returned false", decoder);
329 
330 	/* for FLAC__stream_encoder_init_FILE(), the FLAC__stream_encoder_finish() closes the file so we have to keep re-opening: */
331 	if(dcd->layer == LAYER_FILE) {
332 		printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
333 		open_test_file(dcd, is_ogg, "rb");
334 		if(0 == dcd->file) {
335 			printf("ERROR (%s)\n", strerror(errno));
336 			return false;
337 		}
338 		printf("OK\n");
339 	}
340 
341 	switch(dcd->layer) {
342 		case LAYER_STREAM:
343 			printf("testing FLAC__stream_decoder_init_%sstream()... ", is_ogg? "ogg_":"");
344 			init_status = is_ogg?
345 				FLAC__stream_decoder_init_ogg_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd) :
346 				FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd)
347 			;
348 			break;
349 		case LAYER_SEEKABLE_STREAM:
350 			printf("testing FLAC__stream_decoder_init_%sstream()... ", is_ogg? "ogg_":"");
351 			init_status = is_ogg?
352 				FLAC__stream_decoder_init_ogg_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd) :
353 				FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
354 			break;
355 		case LAYER_FILE:
356 			printf("testing FLAC__stream_decoder_init_%sFILE()... ", is_ogg? "ogg_":"");
357 			init_status = is_ogg?
358 				FLAC__stream_decoder_init_ogg_FILE(decoder, dcd->file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd) :
359 				FLAC__stream_decoder_init_FILE(decoder, dcd->file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
360 			break;
361 		case LAYER_FILENAME:
362 			printf("testing FLAC__stream_decoder_init_%sfile()... ", is_ogg? "ogg_":"");
363 			init_status = is_ogg?
364 				FLAC__stream_decoder_init_ogg_file(decoder, flacfilename(is_ogg), stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd) :
365 				FLAC__stream_decoder_init_file(decoder, flacfilename(is_ogg), stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
366 			break;
367 		default:
368 			die_("internal error 000");
369 			return false;
370 	}
371 	if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
372 		return die_s_(0, decoder);
373 	printf("OK\n");
374 
375 	dcd->current_metadata_number = 0;
376 
377 	if(dcd->layer < LAYER_FILE && fseeko(dcd->file, 0, SEEK_SET) < 0) {
378 		printf("FAILED rewinding input, errno = %d\n", errno);
379 		return false;
380 	}
381 
382 	printf("testing FLAC__stream_decoder_process_until_end_of_stream()... ");
383 	if(!FLAC__stream_decoder_process_until_end_of_stream(decoder))
384 		return die_s_("returned false", decoder);
385 	printf("OK\n");
386 
387 	printf("testing FLAC__stream_decoder_finish()... ");
388 	if(!FLAC__stream_decoder_finish(decoder))
389 		return die_s_("returned false", decoder);
390 	printf("OK\n");
391 
392 	return true;
393 }
394 
test_stream_decoder(Layer layer,FLAC__bool is_ogg)395 static FLAC__bool test_stream_decoder(Layer layer, FLAC__bool is_ogg)
396 {
397 	FLAC__StreamDecoder *decoder;
398 	FLAC__StreamDecoderInitStatus init_status;
399 	FLAC__StreamDecoderState state;
400 	StreamDecoderClientData decoder_client_data;
401 	FLAC__bool expect;
402 
403 	decoder_client_data.layer = layer;
404 
405 	printf("\n+++ libFLAC unit test: FLAC__StreamDecoder (layer: %s, format: %s)\n\n", LayerString[layer], is_ogg? "Ogg FLAC" : "FLAC");
406 
407 	printf("testing FLAC__stream_decoder_new()... ");
408 	decoder = FLAC__stream_decoder_new();
409 	if(0 == decoder) {
410 		printf("FAILED, returned NULL\n");
411 		return false;
412 	}
413 	printf("OK\n");
414 
415 	printf("testing FLAC__stream_decoder_delete()... ");
416 	FLAC__stream_decoder_delete(decoder);
417 	printf("OK\n");
418 
419 	printf("testing FLAC__stream_decoder_new()... ");
420 	decoder = FLAC__stream_decoder_new();
421 	if(0 == decoder) {
422 		printf("FAILED, returned NULL\n");
423 		return false;
424 	}
425 	printf("OK\n");
426 
427 	switch(layer) {
428 		case LAYER_STREAM:
429 		case LAYER_SEEKABLE_STREAM:
430 			printf("testing FLAC__stream_decoder_init_%sstream()... ", is_ogg? "ogg_":"");
431 			init_status = is_ogg?
432 				FLAC__stream_decoder_init_ogg_stream(decoder, 0, 0, 0, 0, 0, 0, 0, 0, 0) :
433 				FLAC__stream_decoder_init_stream(decoder, 0, 0, 0, 0, 0, 0, 0, 0, 0);
434 			break;
435 		case LAYER_FILE:
436 			printf("testing FLAC__stream_decoder_init_%sFILE()... ", is_ogg? "ogg_":"");
437 			init_status = is_ogg?
438 				FLAC__stream_decoder_init_ogg_FILE(decoder, stdin, 0, 0, 0, 0) :
439 				FLAC__stream_decoder_init_FILE(decoder, stdin, 0, 0, 0, 0);
440 			break;
441 		case LAYER_FILENAME:
442 			printf("testing FLAC__stream_decoder_init_%sfile()... ", is_ogg? "ogg_":"");
443 			init_status = is_ogg?
444 				FLAC__stream_decoder_init_ogg_file(decoder, flacfilename(is_ogg), 0, 0, 0, 0) :
445 				FLAC__stream_decoder_init_file(decoder, flacfilename(is_ogg), 0, 0, 0, 0);
446 			break;
447 		default:
448 			die_("internal error 003");
449 			return false;
450 	}
451 	if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
452 		return die_s_(0, decoder);
453 	printf("OK\n");
454 
455 	printf("testing FLAC__stream_decoder_delete()... ");
456 	FLAC__stream_decoder_delete(decoder);
457 	printf("OK\n");
458 
459 	num_expected_ = 0;
460 	expected_metadata_sequence_[num_expected_++] = &streaminfo_;
461 
462 	printf("testing FLAC__stream_decoder_new()... ");
463 	decoder = FLAC__stream_decoder_new();
464 	if(0 == decoder) {
465 		printf("FAILED, returned NULL\n");
466 		return false;
467 	}
468 	printf("OK\n");
469 
470 	if(is_ogg) {
471 		printf("testing FLAC__stream_decoder_set_ogg_serial_number()... ");
472 		if(!FLAC__stream_decoder_set_ogg_serial_number(decoder, file_utils__ogg_serial_number))
473 			return die_s_("returned false", decoder);
474 		printf("OK\n");
475 	}
476 
477 	printf("testing FLAC__stream_decoder_set_md5_checking()... ");
478 	if(!FLAC__stream_decoder_set_md5_checking(decoder, true))
479 		return die_s_("returned false", decoder);
480 	printf("OK\n");
481 
482 	if(layer < LAYER_FILENAME) {
483 		printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
484 		open_test_file(&decoder_client_data, is_ogg, "rb");
485 		if(0 == decoder_client_data.file) {
486 			printf("ERROR (%s)\n", strerror(errno));
487 			return false;
488 		}
489 		printf("OK\n");
490 	}
491 
492 	switch(layer) {
493 		case LAYER_STREAM:
494 			printf("testing FLAC__stream_decoder_init_%sstream()... ", is_ogg? "ogg_":"");
495 			init_status = is_ogg?
496 				FLAC__stream_decoder_init_ogg_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) :
497 				FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data);
498 			break;
499 		case LAYER_SEEKABLE_STREAM:
500 			printf("testing FLAC__stream_decoder_init_%sstream()... ", is_ogg? "ogg_":"");
501 			init_status = is_ogg?
502 				FLAC__stream_decoder_init_ogg_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) :
503 				FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data);
504 			break;
505 		case LAYER_FILE:
506 			printf("testing FLAC__stream_decoder_init_%sFILE()... ", is_ogg? "ogg_":"");
507 			init_status = is_ogg?
508 				FLAC__stream_decoder_init_ogg_FILE(decoder, decoder_client_data.file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) :
509 				FLAC__stream_decoder_init_FILE(decoder, decoder_client_data.file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data);
510 			break;
511 		case LAYER_FILENAME:
512 			printf("testing FLAC__stream_decoder_init_%sfile()... ", is_ogg? "ogg_":"");
513 			init_status = is_ogg?
514 				FLAC__stream_decoder_init_ogg_file(decoder, flacfilename(is_ogg), stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) :
515 				FLAC__stream_decoder_init_file(decoder, flacfilename(is_ogg), stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data);
516 			break;
517 		default:
518 			die_("internal error 009");
519 			return false;
520 	}
521 	if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
522 		return die_s_(0, decoder);
523 	printf("OK\n");
524 
525 	printf("testing FLAC__stream_decoder_get_state()... ");
526 	state = FLAC__stream_decoder_get_state(decoder);
527 	printf("returned state = %u (%s)... OK\n", state, FLAC__StreamDecoderStateString[state]);
528 
529 	decoder_client_data.current_metadata_number = 0;
530 	decoder_client_data.ignore_errors = false;
531 	decoder_client_data.error_occurred = false;
532 
533 	printf("testing FLAC__stream_decoder_get_md5_checking()... ");
534 	if(!FLAC__stream_decoder_get_md5_checking(decoder)) {
535 		printf("FAILED, returned false, expected true\n");
536 		return false;
537 	}
538 	printf("OK\n");
539 
540 	printf("testing FLAC__stream_decoder_process_until_end_of_metadata()... ");
541 	if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
542 		return die_s_("returned false", decoder);
543 	printf("OK\n");
544 
545 	printf("testing FLAC__stream_decoder_process_single()... ");
546 	if(!FLAC__stream_decoder_process_single(decoder))
547 		return die_s_("returned false", decoder);
548 	printf("OK\n");
549 
550 	printf("testing FLAC__stream_decoder_skip_single_frame()... ");
551 	if(!FLAC__stream_decoder_skip_single_frame(decoder))
552 		return die_s_("returned false", decoder);
553 	printf("OK\n");
554 
555 	if(layer < LAYER_FILE) {
556 		printf("testing FLAC__stream_decoder_flush()... ");
557 		if(!FLAC__stream_decoder_flush(decoder))
558 			return die_s_("returned false", decoder);
559 		printf("OK\n");
560 
561 		decoder_client_data.ignore_errors = true;
562 		printf("testing FLAC__stream_decoder_process_single()... ");
563 		if(!FLAC__stream_decoder_process_single(decoder))
564 			return die_s_("returned false", decoder);
565 		printf("OK\n");
566 		decoder_client_data.ignore_errors = false;
567 	}
568 
569 	expect = (layer != LAYER_STREAM);
570 	printf("testing FLAC__stream_decoder_seek_absolute()... ");
571 	if(FLAC__stream_decoder_seek_absolute(decoder, 0) != expect)
572 		return die_s_(expect? "returned false" : "returned true", decoder);
573 	printf("OK\n");
574 
575 	printf("testing FLAC__stream_decoder_process_until_end_of_stream()... ");
576 	if(!FLAC__stream_decoder_process_until_end_of_stream(decoder))
577 		return die_s_("returned false", decoder);
578 	printf("OK\n");
579 
580 	expect = (layer != LAYER_STREAM);
581 	printf("testing FLAC__stream_decoder_seek_absolute()... ");
582 	if(FLAC__stream_decoder_seek_absolute(decoder, 0) != expect)
583 		return die_s_(expect? "returned false" : "returned true", decoder);
584 	printf("OK\n");
585 
586 	printf("testing FLAC__stream_decoder_get_channels()... ");
587 	{
588 		uint32_t channels = FLAC__stream_decoder_get_channels(decoder);
589 		if(channels != streaminfo_.data.stream_info.channels) {
590 			printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
591 			return false;
592 		}
593 	}
594 	printf("OK\n");
595 
596 	printf("testing FLAC__stream_decoder_get_bits_per_sample()... ");
597 	{
598 		uint32_t bits_per_sample = FLAC__stream_decoder_get_bits_per_sample(decoder);
599 		if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
600 			printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
601 			return false;
602 		}
603 	}
604 	printf("OK\n");
605 
606 	printf("testing FLAC__stream_decoder_get_sample_rate()... ");
607 	{
608 		uint32_t sample_rate = FLAC__stream_decoder_get_sample_rate(decoder);
609 		if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
610 			printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
611 			return false;
612 		}
613 	}
614 	printf("OK\n");
615 
616 	printf("testing FLAC__stream_decoder_get_blocksize()... ");
617 	{
618 		uint32_t blocksize = FLAC__stream_decoder_get_blocksize(decoder);
619 		/* value could be anything since we're at the last block, so accept any reasonable answer */
620 		printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
621 		if(blocksize == 0)
622 			return false;
623 	}
624 
625 	printf("testing FLAC__stream_decoder_get_channel_assignment()... ");
626 	{
627 		FLAC__ChannelAssignment ca = FLAC__stream_decoder_get_channel_assignment(decoder);
628 		printf("returned %u (%s)... OK\n", (uint32_t)ca, FLAC__ChannelAssignmentString[ca]);
629 	}
630 
631 	if(layer < LAYER_FILE) {
632 		printf("testing FLAC__stream_decoder_reset()... ");
633 		if(!FLAC__stream_decoder_reset(decoder)) {
634 			state = FLAC__stream_decoder_get_state(decoder);
635 			printf("FAILED, returned false, state = %u (%s)\n", state, FLAC__StreamDecoderStateString[state]);
636 			return false;
637 		}
638 		printf("OK\n");
639 
640 		if(layer == LAYER_STREAM) {
641 			/* after a reset() we have to rewind the input ourselves */
642 			printf("rewinding input... ");
643 			if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
644 				printf("FAILED, errno = %d\n", errno);
645 				return false;
646 			}
647 			printf("OK\n");
648 		}
649 
650 		decoder_client_data.current_metadata_number = 0;
651 
652 		printf("testing FLAC__stream_decoder_process_until_end_of_stream()... ");
653 		if(!FLAC__stream_decoder_process_until_end_of_stream(decoder))
654 			return die_s_("returned false", decoder);
655 		printf("OK\n");
656 	}
657 
658 	printf("testing FLAC__stream_decoder_finish()... ");
659 	if(!FLAC__stream_decoder_finish(decoder))
660 		return die_s_("returned false", decoder);
661 	printf("OK\n");
662 
663 	/*
664 	 * respond all
665 	 */
666 
667 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
668 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
669 		return die_s_("returned false", decoder);
670 	printf("OK\n");
671 
672 	num_expected_ = 0;
673 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
674 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
675 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
676 		expected_metadata_sequence_[num_expected_++] = &padding_;
677 		expected_metadata_sequence_[num_expected_++] = &seektable_;
678 		expected_metadata_sequence_[num_expected_++] = &application1_;
679 		expected_metadata_sequence_[num_expected_++] = &application2_;
680 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
681 		expected_metadata_sequence_[num_expected_++] = &picture_;
682 		expected_metadata_sequence_[num_expected_++] = &unknown_;
683 	}
684 	else {
685 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
686 		expected_metadata_sequence_[num_expected_++] = &padding_;
687 		expected_metadata_sequence_[num_expected_++] = &seektable_;
688 		expected_metadata_sequence_[num_expected_++] = &application1_;
689 		expected_metadata_sequence_[num_expected_++] = &application2_;
690 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
691 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
692 		expected_metadata_sequence_[num_expected_++] = &picture_;
693 		expected_metadata_sequence_[num_expected_++] = &unknown_;
694 	}
695 
696 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
697 		return false;
698 
699 	/*
700 	 * ignore all
701 	 */
702 
703 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
704 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
705 		return die_s_("returned false", decoder);
706 	printf("OK\n");
707 
708 	num_expected_ = 0;
709 
710 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
711 		return false;
712 
713 	/*
714 	 * respond all, ignore VORBIS_COMMENT
715 	 */
716 
717 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
718 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
719 		return die_s_("returned false", decoder);
720 	printf("OK\n");
721 
722 	printf("testing FLAC__stream_decoder_set_metadata_ignore(VORBIS_COMMENT)... ");
723 	if(!FLAC__stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
724 		return die_s_("returned false", decoder);
725 	printf("OK\n");
726 
727 	num_expected_ = 0;
728 	expected_metadata_sequence_[num_expected_++] = &streaminfo_;
729 	expected_metadata_sequence_[num_expected_++] = &padding_;
730 	expected_metadata_sequence_[num_expected_++] = &seektable_;
731 	expected_metadata_sequence_[num_expected_++] = &application1_;
732 	expected_metadata_sequence_[num_expected_++] = &application2_;
733 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
734 	expected_metadata_sequence_[num_expected_++] = &picture_;
735 	expected_metadata_sequence_[num_expected_++] = &unknown_;
736 
737 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
738 		return false;
739 
740 	/*
741 	 * respond all, ignore APPLICATION
742 	 */
743 
744 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
745 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
746 		return die_s_("returned false", decoder);
747 	printf("OK\n");
748 
749 	printf("testing FLAC__stream_decoder_set_metadata_ignore(APPLICATION)... ");
750 	if(!FLAC__stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
751 		return die_s_("returned false", decoder);
752 	printf("OK\n");
753 
754 	num_expected_ = 0;
755 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
756 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
757 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
758 		expected_metadata_sequence_[num_expected_++] = &padding_;
759 		expected_metadata_sequence_[num_expected_++] = &seektable_;
760 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
761 		expected_metadata_sequence_[num_expected_++] = &picture_;
762 		expected_metadata_sequence_[num_expected_++] = &unknown_;
763 	}
764 	else {
765 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
766 		expected_metadata_sequence_[num_expected_++] = &padding_;
767 		expected_metadata_sequence_[num_expected_++] = &seektable_;
768 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
769 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
770 		expected_metadata_sequence_[num_expected_++] = &picture_;
771 		expected_metadata_sequence_[num_expected_++] = &unknown_;
772 	}
773 
774 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
775 		return false;
776 
777 	/*
778 	 * respond all, ignore APPLICATION id of app#1
779 	 */
780 
781 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
782 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
783 		return die_s_("returned false", decoder);
784 	printf("OK\n");
785 
786 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #1)... ");
787 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
788 		return die_s_("returned false", decoder);
789 	printf("OK\n");
790 
791 	num_expected_ = 0;
792 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
793 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
794 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
795 		expected_metadata_sequence_[num_expected_++] = &padding_;
796 		expected_metadata_sequence_[num_expected_++] = &seektable_;
797 		expected_metadata_sequence_[num_expected_++] = &application2_;
798 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
799 		expected_metadata_sequence_[num_expected_++] = &picture_;
800 		expected_metadata_sequence_[num_expected_++] = &unknown_;
801 	}
802 	else {
803 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
804 		expected_metadata_sequence_[num_expected_++] = &padding_;
805 		expected_metadata_sequence_[num_expected_++] = &seektable_;
806 		expected_metadata_sequence_[num_expected_++] = &application2_;
807 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
808 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
809 		expected_metadata_sequence_[num_expected_++] = &picture_;
810 		expected_metadata_sequence_[num_expected_++] = &unknown_;
811 	}
812 
813 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
814 		return false;
815 
816 	/*
817 	 * respond all, ignore APPLICATION id of app#1 & app#2
818 	 */
819 
820 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
821 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
822 		return die_s_("returned false", decoder);
823 	printf("OK\n");
824 
825 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #1)... ");
826 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
827 		return die_s_("returned false", decoder);
828 	printf("OK\n");
829 
830 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #2)... ");
831 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application2_.data.application.id))
832 		return die_s_("returned false", decoder);
833 	printf("OK\n");
834 
835 	num_expected_ = 0;
836 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
837 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
838 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
839 		expected_metadata_sequence_[num_expected_++] = &padding_;
840 		expected_metadata_sequence_[num_expected_++] = &seektable_;
841 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
842 		expected_metadata_sequence_[num_expected_++] = &picture_;
843 		expected_metadata_sequence_[num_expected_++] = &unknown_;
844 	}
845 	else {
846 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
847 		expected_metadata_sequence_[num_expected_++] = &padding_;
848 		expected_metadata_sequence_[num_expected_++] = &seektable_;
849 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
850 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
851 		expected_metadata_sequence_[num_expected_++] = &picture_;
852 		expected_metadata_sequence_[num_expected_++] = &unknown_;
853 	}
854 
855 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
856 		return false;
857 
858 	/*
859 	 * ignore all, respond VORBIS_COMMENT
860 	 */
861 
862 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
863 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
864 		return die_s_("returned false", decoder);
865 	printf("OK\n");
866 
867 	printf("testing FLAC__stream_decoder_set_metadata_respond(VORBIS_COMMENT)... ");
868 	if(!FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
869 		return die_s_("returned false", decoder);
870 	printf("OK\n");
871 
872 	num_expected_ = 0;
873 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
874 
875 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
876 		return false;
877 
878 	/*
879 	 * ignore all, respond APPLICATION
880 	 */
881 
882 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
883 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
884 		return die_s_("returned false", decoder);
885 	printf("OK\n");
886 
887 	printf("testing FLAC__stream_decoder_set_metadata_respond(APPLICATION)... ");
888 	if(!FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
889 		return die_s_("returned false", decoder);
890 	printf("OK\n");
891 
892 	num_expected_ = 0;
893 	expected_metadata_sequence_[num_expected_++] = &application1_;
894 	expected_metadata_sequence_[num_expected_++] = &application2_;
895 
896 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
897 		return false;
898 
899 	/*
900 	 * ignore all, respond APPLICATION id of app#1
901 	 */
902 
903 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
904 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
905 		return die_s_("returned false", decoder);
906 	printf("OK\n");
907 
908 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #1)... ");
909 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
910 		return die_s_("returned false", decoder);
911 	printf("OK\n");
912 
913 	num_expected_ = 0;
914 	expected_metadata_sequence_[num_expected_++] = &application1_;
915 
916 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
917 		return false;
918 
919 	/*
920 	 * ignore all, respond APPLICATION id of app#1 & app#2
921 	 */
922 
923 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
924 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
925 		return die_s_("returned false", decoder);
926 	printf("OK\n");
927 
928 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #1)... ");
929 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
930 		return die_s_("returned false", decoder);
931 	printf("OK\n");
932 
933 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #2)... ");
934 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application2_.data.application.id))
935 		return die_s_("returned false", decoder);
936 	printf("OK\n");
937 
938 	num_expected_ = 0;
939 	expected_metadata_sequence_[num_expected_++] = &application1_;
940 	expected_metadata_sequence_[num_expected_++] = &application2_;
941 
942 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
943 		return false;
944 
945 	/*
946 	 * respond all, ignore APPLICATION, respond APPLICATION id of app#1
947 	 */
948 
949 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
950 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
951 		return die_s_("returned false", decoder);
952 	printf("OK\n");
953 
954 	printf("testing FLAC__stream_decoder_set_metadata_ignore(APPLICATION)... ");
955 	if(!FLAC__stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
956 		return die_s_("returned false", decoder);
957 	printf("OK\n");
958 
959 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #1)... ");
960 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
961 		return die_s_("returned false", decoder);
962 	printf("OK\n");
963 
964 	num_expected_ = 0;
965 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
966 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
967 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
968 		expected_metadata_sequence_[num_expected_++] = &padding_;
969 		expected_metadata_sequence_[num_expected_++] = &seektable_;
970 		expected_metadata_sequence_[num_expected_++] = &application1_;
971 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
972 		expected_metadata_sequence_[num_expected_++] = &picture_;
973 		expected_metadata_sequence_[num_expected_++] = &unknown_;
974 	}
975 	else {
976 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
977 		expected_metadata_sequence_[num_expected_++] = &padding_;
978 		expected_metadata_sequence_[num_expected_++] = &seektable_;
979 		expected_metadata_sequence_[num_expected_++] = &application1_;
980 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
981 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
982 		expected_metadata_sequence_[num_expected_++] = &picture_;
983 		expected_metadata_sequence_[num_expected_++] = &unknown_;
984 	}
985 
986 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
987 		return false;
988 
989 	/*
990 	 * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
991 	 */
992 
993 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
994 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
995 		return die_s_("returned false", decoder);
996 	printf("OK\n");
997 
998 	printf("testing FLAC__stream_decoder_set_metadata_respond(APPLICATION)... ");
999 	if(!FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
1000 		return die_s_("returned false", decoder);
1001 	printf("OK\n");
1002 
1003 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #1)... ");
1004 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
1005 		return die_s_("returned false", decoder);
1006 	printf("OK\n");
1007 
1008 	num_expected_ = 0;
1009 	expected_metadata_sequence_[num_expected_++] = &application2_;
1010 
1011 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
1012 		return false;
1013 
1014 	if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
1015 		fclose(decoder_client_data.file);
1016 
1017 	printf("testing FLAC__stream_decoder_delete()... ");
1018 	FLAC__stream_decoder_delete(decoder);
1019 	printf("OK\n");
1020 
1021 	printf("\nPASSED!\n");
1022 
1023 	return true;
1024 }
1025 
test_decoders(void)1026 FLAC__bool test_decoders(void)
1027 {
1028 	FLAC__bool is_ogg = false;
1029 
1030 	while(1) {
1031 		init_metadata_blocks_();
1032 
1033 		if(!generate_file_(is_ogg))
1034 			return false;
1035 
1036 		if(!test_stream_decoder(LAYER_STREAM, is_ogg))
1037 			return false;
1038 
1039 		if(!test_stream_decoder(LAYER_SEEKABLE_STREAM, is_ogg))
1040 			return false;
1041 
1042 		if(!test_stream_decoder(LAYER_FILE, is_ogg))
1043 			return false;
1044 
1045 		if(!test_stream_decoder(LAYER_FILENAME, is_ogg))
1046 			return false;
1047 
1048 		(void) grabbag__file_remove_file(flacfilename(is_ogg));
1049 
1050 		free_metadata_blocks_();
1051 
1052 		if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
1053 			break;
1054 		is_ogg = true;
1055 	}
1056 
1057 	return true;
1058 }
1059