xref: /aosp_15_r20/external/flac/src/test_libFLAC/decoders.c (revision 600f14f40d737144c998e2ec7a483122d3776fbc)
1 /* test_libFLAC - Unit tester for libFLAC
2  * Copyright (C) 2002-2009  Josh Coalson
3  * Copyright (C) 2011-2023  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. Also removes the seektable */
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_++] = &application1_;
678 		expected_metadata_sequence_[num_expected_++] = &application2_;
679 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
680 		expected_metadata_sequence_[num_expected_++] = &picture_;
681 		expected_metadata_sequence_[num_expected_++] = &unknown_;
682 	}
683 	else {
684 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
685 		expected_metadata_sequence_[num_expected_++] = &padding_;
686 		expected_metadata_sequence_[num_expected_++] = &seektable_;
687 		expected_metadata_sequence_[num_expected_++] = &application1_;
688 		expected_metadata_sequence_[num_expected_++] = &application2_;
689 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
690 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
691 		expected_metadata_sequence_[num_expected_++] = &picture_;
692 		expected_metadata_sequence_[num_expected_++] = &unknown_;
693 	}
694 
695 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
696 		return false;
697 
698 	/*
699 	 * ignore all
700 	 */
701 
702 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
703 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
704 		return die_s_("returned false", decoder);
705 	printf("OK\n");
706 
707 	num_expected_ = 0;
708 
709 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
710 		return false;
711 
712 	/*
713 	 * respond all, ignore VORBIS_COMMENT
714 	 */
715 
716 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
717 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
718 		return die_s_("returned false", decoder);
719 	printf("OK\n");
720 
721 	printf("testing FLAC__stream_decoder_set_metadata_ignore(VORBIS_COMMENT)... ");
722 	if(!FLAC__stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
723 		return die_s_("returned false", decoder);
724 	printf("OK\n");
725 
726 	num_expected_ = 0;
727 	expected_metadata_sequence_[num_expected_++] = &streaminfo_;
728 	expected_metadata_sequence_[num_expected_++] = &padding_;
729 	if(!is_ogg) /* encoder removes seektable for ogg */
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. Also removes the seektable */
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_++] = &cuesheet_;
760 		expected_metadata_sequence_[num_expected_++] = &picture_;
761 		expected_metadata_sequence_[num_expected_++] = &unknown_;
762 	}
763 	else {
764 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
765 		expected_metadata_sequence_[num_expected_++] = &padding_;
766 		expected_metadata_sequence_[num_expected_++] = &seektable_;
767 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
768 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
769 		expected_metadata_sequence_[num_expected_++] = &picture_;
770 		expected_metadata_sequence_[num_expected_++] = &unknown_;
771 	}
772 
773 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
774 		return false;
775 
776 	/*
777 	 * respond all, ignore APPLICATION id of app#1
778 	 */
779 
780 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
781 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
782 		return die_s_("returned false", decoder);
783 	printf("OK\n");
784 
785 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #1)... ");
786 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
787 		return die_s_("returned false", decoder);
788 	printf("OK\n");
789 
790 	num_expected_ = 0;
791 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping. Also removes the seektable */
792 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
793 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
794 		expected_metadata_sequence_[num_expected_++] = &padding_;
795 		expected_metadata_sequence_[num_expected_++] = &application2_;
796 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
797 		expected_metadata_sequence_[num_expected_++] = &picture_;
798 		expected_metadata_sequence_[num_expected_++] = &unknown_;
799 	}
800 	else {
801 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
802 		expected_metadata_sequence_[num_expected_++] = &padding_;
803 		expected_metadata_sequence_[num_expected_++] = &seektable_;
804 		expected_metadata_sequence_[num_expected_++] = &application2_;
805 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
806 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
807 		expected_metadata_sequence_[num_expected_++] = &picture_;
808 		expected_metadata_sequence_[num_expected_++] = &unknown_;
809 	}
810 
811 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
812 		return false;
813 
814 	/*
815 	 * respond all, ignore APPLICATION id of app#1 & app#2
816 	 */
817 
818 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
819 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
820 		return die_s_("returned false", decoder);
821 	printf("OK\n");
822 
823 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #1)... ");
824 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
825 		return die_s_("returned false", decoder);
826 	printf("OK\n");
827 
828 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #2)... ");
829 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application2_.data.application.id))
830 		return die_s_("returned false", decoder);
831 	printf("OK\n");
832 
833 	num_expected_ = 0;
834 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping. Also removes the seektable */
835 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
836 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
837 		expected_metadata_sequence_[num_expected_++] = &padding_;
838 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
839 		expected_metadata_sequence_[num_expected_++] = &picture_;
840 		expected_metadata_sequence_[num_expected_++] = &unknown_;
841 	}
842 	else {
843 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
844 		expected_metadata_sequence_[num_expected_++] = &padding_;
845 		expected_metadata_sequence_[num_expected_++] = &seektable_;
846 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
847 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
848 		expected_metadata_sequence_[num_expected_++] = &picture_;
849 		expected_metadata_sequence_[num_expected_++] = &unknown_;
850 	}
851 
852 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
853 		return false;
854 
855 	/*
856 	 * ignore all, respond VORBIS_COMMENT
857 	 */
858 
859 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
860 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
861 		return die_s_("returned false", decoder);
862 	printf("OK\n");
863 
864 	printf("testing FLAC__stream_decoder_set_metadata_respond(VORBIS_COMMENT)... ");
865 	if(!FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
866 		return die_s_("returned false", decoder);
867 	printf("OK\n");
868 
869 	num_expected_ = 0;
870 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
871 
872 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
873 		return false;
874 
875 	/*
876 	 * ignore all, respond APPLICATION
877 	 */
878 
879 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
880 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
881 		return die_s_("returned false", decoder);
882 	printf("OK\n");
883 
884 	printf("testing FLAC__stream_decoder_set_metadata_respond(APPLICATION)... ");
885 	if(!FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
886 		return die_s_("returned false", decoder);
887 	printf("OK\n");
888 
889 	num_expected_ = 0;
890 	expected_metadata_sequence_[num_expected_++] = &application1_;
891 	expected_metadata_sequence_[num_expected_++] = &application2_;
892 
893 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
894 		return false;
895 
896 	/*
897 	 * ignore all, respond APPLICATION id of app#1
898 	 */
899 
900 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
901 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
902 		return die_s_("returned false", decoder);
903 	printf("OK\n");
904 
905 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #1)... ");
906 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
907 		return die_s_("returned false", decoder);
908 	printf("OK\n");
909 
910 	num_expected_ = 0;
911 	expected_metadata_sequence_[num_expected_++] = &application1_;
912 
913 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
914 		return false;
915 
916 	/*
917 	 * ignore all, respond APPLICATION id of app#1 & app#2
918 	 */
919 
920 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
921 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
922 		return die_s_("returned false", decoder);
923 	printf("OK\n");
924 
925 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #1)... ");
926 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
927 		return die_s_("returned false", decoder);
928 	printf("OK\n");
929 
930 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #2)... ");
931 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application2_.data.application.id))
932 		return die_s_("returned false", decoder);
933 	printf("OK\n");
934 
935 	num_expected_ = 0;
936 	expected_metadata_sequence_[num_expected_++] = &application1_;
937 	expected_metadata_sequence_[num_expected_++] = &application2_;
938 
939 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
940 		return false;
941 
942 	/*
943 	 * respond all, ignore APPLICATION, respond APPLICATION id of app#1
944 	 */
945 
946 	printf("testing FLAC__stream_decoder_set_metadata_respond_all()... ");
947 	if(!FLAC__stream_decoder_set_metadata_respond_all(decoder))
948 		return die_s_("returned false", decoder);
949 	printf("OK\n");
950 
951 	printf("testing FLAC__stream_decoder_set_metadata_ignore(APPLICATION)... ");
952 	if(!FLAC__stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
953 		return die_s_("returned false", decoder);
954 	printf("OK\n");
955 
956 	printf("testing FLAC__stream_decoder_set_metadata_respond_application(of app block #1)... ");
957 	if(!FLAC__stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
958 		return die_s_("returned false", decoder);
959 	printf("OK\n");
960 
961 	num_expected_ = 0;
962 	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping. Also removes the seektable */
963 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
964 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
965 		expected_metadata_sequence_[num_expected_++] = &padding_;
966 		expected_metadata_sequence_[num_expected_++] = &application1_;
967 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
968 		expected_metadata_sequence_[num_expected_++] = &picture_;
969 		expected_metadata_sequence_[num_expected_++] = &unknown_;
970 	}
971 	else {
972 		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
973 		expected_metadata_sequence_[num_expected_++] = &padding_;
974 		expected_metadata_sequence_[num_expected_++] = &seektable_;
975 		expected_metadata_sequence_[num_expected_++] = &application1_;
976 		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
977 		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
978 		expected_metadata_sequence_[num_expected_++] = &picture_;
979 		expected_metadata_sequence_[num_expected_++] = &unknown_;
980 	}
981 
982 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
983 		return false;
984 
985 	/*
986 	 * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
987 	 */
988 
989 	printf("testing FLAC__stream_decoder_set_metadata_ignore_all()... ");
990 	if(!FLAC__stream_decoder_set_metadata_ignore_all(decoder))
991 		return die_s_("returned false", decoder);
992 	printf("OK\n");
993 
994 	printf("testing FLAC__stream_decoder_set_metadata_respond(APPLICATION)... ");
995 	if(!FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
996 		return die_s_("returned false", decoder);
997 	printf("OK\n");
998 
999 	printf("testing FLAC__stream_decoder_set_metadata_ignore_application(of app block #1)... ");
1000 	if(!FLAC__stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
1001 		return die_s_("returned false", decoder);
1002 	printf("OK\n");
1003 
1004 	num_expected_ = 0;
1005 	expected_metadata_sequence_[num_expected_++] = &application2_;
1006 
1007 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data, is_ogg))
1008 		return false;
1009 
1010 	if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
1011 		fclose(decoder_client_data.file);
1012 
1013 	printf("testing FLAC__stream_decoder_delete()... ");
1014 	FLAC__stream_decoder_delete(decoder);
1015 	printf("OK\n");
1016 
1017 	printf("\nPASSED!\n");
1018 
1019 	return true;
1020 }
1021 
test_decoders(void)1022 FLAC__bool test_decoders(void)
1023 {
1024 	FLAC__bool is_ogg = false;
1025 
1026 	while(1) {
1027 		init_metadata_blocks_();
1028 
1029 		if(!generate_file_(is_ogg))
1030 			return false;
1031 
1032 		if(!test_stream_decoder(LAYER_STREAM, is_ogg))
1033 			return false;
1034 
1035 		if(!test_stream_decoder(LAYER_SEEKABLE_STREAM, is_ogg))
1036 			return false;
1037 
1038 		if(!test_stream_decoder(LAYER_FILE, is_ogg))
1039 			return false;
1040 
1041 		if(!test_stream_decoder(LAYER_FILENAME, is_ogg))
1042 			return false;
1043 
1044 		(void) grabbag__file_remove_file(flacfilename(is_ogg));
1045 
1046 		free_metadata_blocks_();
1047 
1048 		if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
1049 			break;
1050 		is_ogg = true;
1051 	}
1052 
1053 	return true;
1054 }
1055