1/* test_libFLAC++ - Unit tester for libFLAC++
2 * Copyright (C) 2002,2003,2004,2005,2006,2007  Josh Coalson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (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#if HAVE_CONFIG_H
20#  include <config.h>
21#endif
22
23#include <errno.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#if defined _MSC_VER || defined __MINGW32__
28#if _MSC_VER <= 1600 /* @@@ [2G limit] */
29#define fseeko fseek
30#define ftello ftell
31#endif
32#endif
33#include "decoders.h"
34#include "FLAC/assert.h"
35#include "FLAC/metadata.h" // for ::FLAC__metadata_object_is_equal()
36#include "FLAC++/decoder.h"
37#include "share/grabbag.h"
38extern "C" {
39#include "test_libs_common/file_utils_flac.h"
40#include "test_libs_common/metadata_utils.h"
41}
42
43#ifdef _MSC_VER
44// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
45#pragma warning ( disable : 4800 )
46#endif
47
48typedef enum {
49	LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
50	LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
51	LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
52	LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
53} Layer;
54
55static const char * const LayerString[] = {
56	"Stream",
57	"Seekable Stream",
58	"FILE*",
59	"Filename"
60};
61
62static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
63static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
64static unsigned num_expected_;
65static off_t flacfilesize_;
66
67static const char *flacfilename(bool is_ogg)
68{
69	return is_ogg? "metadata.oga" : "metadata.flac";
70}
71
72static bool die_(const char *msg)
73{
74	printf("ERROR: %s\n", msg);
75	return false;
76}
77
78static FLAC__bool die_s_(const char *msg, const FLAC::Decoder::Stream *decoder)
79{
80	FLAC::Decoder::Stream::State state = decoder->get_state();
81
82	if(msg)
83		printf("FAILED, %s", msg);
84	else
85		printf("FAILED");
86
87	printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
88
89	return false;
90}
91
92static void init_metadata_blocks_()
93{
94	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
95}
96
97static void free_metadata_blocks_()
98{
99	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
100}
101
102static bool generate_file_(FLAC__bool is_ogg)
103{
104	printf("\n\ngenerating %sFLAC file for decoder tests...\n", is_ogg? "Ogg ":"");
105
106	num_expected_ = 0;
107	expected_metadata_sequence_[num_expected_++] = &padding_;
108	expected_metadata_sequence_[num_expected_++] = &seektable_;
109	expected_metadata_sequence_[num_expected_++] = &application1_;
110	expected_metadata_sequence_[num_expected_++] = &application2_;
111	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
112	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
113	expected_metadata_sequence_[num_expected_++] = &picture_;
114	expected_metadata_sequence_[num_expected_++] = &unknown_;
115	/* WATCHOUT: for Ogg FLAC the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
116
117	if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
118		return die_("creating the encoded file");
119
120	return true;
121}
122
123
124class DecoderCommon {
125public:
126	Layer layer_;
127	unsigned current_metadata_number_;
128	bool ignore_errors_;
129	bool error_occurred_;
130
131	DecoderCommon(Layer layer): layer_(layer), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
132	::FLAC__StreamDecoderWriteStatus common_write_callback_(const ::FLAC__Frame *frame);
133	void common_metadata_callback_(const ::FLAC__StreamMetadata *metadata);
134	void common_error_callback_(::FLAC__StreamDecoderErrorStatus status);
135};
136
137::FLAC__StreamDecoderWriteStatus DecoderCommon::common_write_callback_(const ::FLAC__Frame *frame)
138{
139	if(error_occurred_)
140		return ::FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
141
142	if(
143		(frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
144		(frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
145	) {
146		printf("content... ");
147		fflush(stdout);
148	}
149
150	return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
151}
152
153void DecoderCommon::common_metadata_callback_(const ::FLAC__StreamMetadata *metadata)
154{
155	if(error_occurred_)
156		return;
157
158	printf("%d... ", current_metadata_number_);
159	fflush(stdout);
160
161	if(current_metadata_number_ >= num_expected_) {
162		(void)die_("got more metadata blocks than expected");
163		error_occurred_ = true;
164	}
165	else {
166		if(!::FLAC__metadata_object_is_equal(expected_metadata_sequence_[current_metadata_number_], metadata)) {
167			(void)die_("metadata block mismatch");
168			error_occurred_ = true;
169		}
170	}
171	current_metadata_number_++;
172}
173
174void DecoderCommon::common_error_callback_(::FLAC__StreamDecoderErrorStatus status)
175{
176	if(!ignore_errors_) {
177		printf("ERROR: got error callback: err = %u (%s)\n", (unsigned)status, ::FLAC__StreamDecoderErrorStatusString[status]);
178		error_occurred_ = true;
179	}
180}
181
182class StreamDecoder : public FLAC::Decoder::Stream, public DecoderCommon {
183public:
184	FILE *file_;
185
186	StreamDecoder(Layer layer): FLAC::Decoder::Stream(), DecoderCommon(layer), file_(0) { }
187	~StreamDecoder() { }
188
189	// from FLAC::Decoder::Stream
190	::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
191	::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
192	::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
193	::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
194	bool eof_callback();
195	::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
196	void metadata_callback(const ::FLAC__StreamMetadata *metadata);
197	void error_callback(::FLAC__StreamDecoderErrorStatus status);
198
199	bool test_respond(bool is_ogg);
200};
201
202::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], size_t *bytes)
203{
204	const size_t requested_bytes = *bytes;
205
206	if(error_occurred_)
207		return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
208
209	if(feof(file_)) {
210		*bytes = 0;
211		return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
212	}
213	else if(requested_bytes > 0) {
214		*bytes = ::fread(buffer, 1, requested_bytes, file_);
215		if(*bytes == 0) {
216			if(feof(file_))
217				return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
218			else
219				return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
220		}
221		else {
222			return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
223		}
224	}
225	else
226		return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
227}
228
229::FLAC__StreamDecoderSeekStatus StreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
230{
231	if(layer_ == LAYER_STREAM)
232		return ::FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
233
234	if(error_occurred_)
235		return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
236
237	if(fseeko(file_, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
238		error_occurred_ = true;
239		return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
240	}
241
242	return ::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
243}
244
245::FLAC__StreamDecoderTellStatus StreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
246{
247	if(layer_ == LAYER_STREAM)
248		return ::FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
249
250	if(error_occurred_)
251		return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
252
253	off_t offset = ftello(file_);
254	*absolute_byte_offset = (FLAC__uint64)offset;
255
256	if(offset < 0) {
257		error_occurred_ = true;
258		return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
259	}
260
261	return ::FLAC__STREAM_DECODER_TELL_STATUS_OK;
262}
263
264::FLAC__StreamDecoderLengthStatus StreamDecoder::length_callback(FLAC__uint64 *stream_length)
265{
266	if(layer_ == LAYER_STREAM)
267		return ::FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
268
269	if(error_occurred_)
270		return ::FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
271
272	*stream_length = (FLAC__uint64)flacfilesize_;
273	return ::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
274}
275
276bool StreamDecoder::eof_callback()
277{
278	if(layer_ == LAYER_STREAM)
279		return false;
280
281	if(error_occurred_)
282		return true;
283
284	return (bool)feof(file_);
285}
286
287::FLAC__StreamDecoderWriteStatus StreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
288{
289	(void)buffer;
290
291	return common_write_callback_(frame);
292}
293
294void StreamDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
295{
296	common_metadata_callback_(metadata);
297}
298
299void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
300{
301	common_error_callback_(status);
302}
303
304bool StreamDecoder::test_respond(bool is_ogg)
305{
306	::FLAC__StreamDecoderInitStatus init_status;
307
308	if(!set_md5_checking(true)) {
309		printf("FAILED at set_md5_checking(), returned false\n");
310		return false;
311	}
312
313	printf("testing init%s()... ", is_ogg? "_ogg":"");
314	init_status = is_ogg? init_ogg() : init();
315	if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
316		return die_s_(0, this);
317	printf("OK\n");
318
319	current_metadata_number_ = 0;
320
321	if(fseeko(file_, 0, SEEK_SET) < 0) {
322		printf("FAILED rewinding input, errno = %d\n", errno);
323		return false;
324	}
325
326	printf("testing process_until_end_of_stream()... ");
327	if(!process_until_end_of_stream()) {
328		State state = get_state();
329		printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
330		return false;
331	}
332	printf("OK\n");
333
334	printf("testing finish()... ");
335	if(!finish()) {
336		State state = get_state();
337		printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
338		return false;
339	}
340	printf("OK\n");
341
342	return true;
343}
344
345class FileDecoder : public FLAC::Decoder::File, public DecoderCommon {
346public:
347	FileDecoder(Layer layer): FLAC::Decoder::File(), DecoderCommon(layer) { }
348	~FileDecoder() { }
349
350	// from FLAC::Decoder::Stream
351	::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
352	void metadata_callback(const ::FLAC__StreamMetadata *metadata);
353	void error_callback(::FLAC__StreamDecoderErrorStatus status);
354
355	bool test_respond(bool is_ogg);
356};
357
358::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
359{
360	(void)buffer;
361	return common_write_callback_(frame);
362}
363
364void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
365{
366	common_metadata_callback_(metadata);
367}
368
369void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
370{
371	common_error_callback_(status);
372}
373
374bool FileDecoder::test_respond(bool is_ogg)
375{
376	::FLAC__StreamDecoderInitStatus init_status;
377
378	if(!set_md5_checking(true)) {
379		printf("FAILED at set_md5_checking(), returned false\n");
380		return false;
381	}
382
383	switch(layer_) {
384		case LAYER_FILE:
385			{
386				printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
387				FILE *file = ::fopen(flacfilename(is_ogg), "rb");
388				if(0 == file) {
389					printf("ERROR (%s)\n", strerror(errno));
390					return false;
391				}
392				printf("OK\n");
393
394				printf("testing init%s()... ", is_ogg? "_ogg":"");
395				init_status = is_ogg? init_ogg(file) : init(file);
396			}
397			break;
398		case LAYER_FILENAME:
399			printf("testing init%s()... ", is_ogg? "_ogg":"");
400			init_status = is_ogg? init_ogg(flacfilename(is_ogg)) : init(flacfilename(is_ogg));
401			break;
402		default:
403			die_("internal error 001");
404			return false;
405	}
406	if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
407		return die_s_(0, this);
408	printf("OK\n");
409
410	current_metadata_number_ = 0;
411
412	printf("testing process_until_end_of_stream()... ");
413	if(!process_until_end_of_stream()) {
414		State state = get_state();
415		printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
416		return false;
417	}
418	printf("OK\n");
419
420	printf("testing finish()... ");
421	if(!finish()) {
422		State state = get_state();
423		printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
424		return false;
425	}
426	printf("OK\n");
427
428	return true;
429}
430
431
432static FLAC::Decoder::Stream *new_by_layer(Layer layer)
433{
434	if(layer < LAYER_FILE)
435		return new StreamDecoder(layer);
436	else
437		return new FileDecoder(layer);
438}
439
440static bool test_stream_decoder(Layer layer, bool is_ogg)
441{
442	FLAC::Decoder::Stream *decoder;
443	::FLAC__StreamDecoderInitStatus init_status;
444	bool expect;
445
446	printf("\n+++ libFLAC++ unit test: FLAC::Decoder::%s (layer: %s, format: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer], is_ogg? "Ogg FLAC" : "FLAC");
447
448	//
449	// test new -> delete
450	//
451	printf("allocating decoder instance... ");
452	decoder = new_by_layer(layer);
453	if(0 == decoder) {
454		printf("FAILED, new returned NULL\n");
455		return false;
456	}
457	printf("OK\n");
458
459	printf("testing is_valid()... ");
460	if(!decoder->is_valid()) {
461		printf("FAILED, returned false\n");
462		return false;
463	}
464	printf("OK\n");
465
466	printf("freeing decoder instance... ");
467	delete decoder;
468	printf("OK\n");
469
470	//
471	// test new -> init -> delete
472	//
473	printf("allocating decoder instance... ");
474	decoder = new_by_layer(layer);
475	if(0 == decoder) {
476		printf("FAILED, new returned NULL\n");
477		return false;
478	}
479	printf("OK\n");
480
481	printf("testing is_valid()... ");
482	if(!decoder->is_valid()) {
483		printf("FAILED, returned false\n");
484		return false;
485	}
486	printf("OK\n");
487
488	printf("testing init%s()... ", is_ogg? "_ogg":"");
489	switch(layer) {
490		case LAYER_STREAM:
491		case LAYER_SEEKABLE_STREAM:
492			dynamic_cast<StreamDecoder*>(decoder)->file_ = stdin;
493			init_status = is_ogg? decoder->init_ogg() : decoder->init();
494			break;
495		case LAYER_FILE:
496			init_status = is_ogg?
497				dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(stdin) :
498				dynamic_cast<FLAC::Decoder::File*>(decoder)->init(stdin);
499			break;
500		case LAYER_FILENAME:
501			init_status = is_ogg?
502				dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
503				dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
504			break;
505		default:
506			die_("internal error 006");
507			return false;
508	}
509	if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
510		return die_s_(0, decoder);
511	printf("OK\n");
512
513	printf("freeing decoder instance... ");
514	delete decoder;
515	printf("OK\n");
516
517	//
518	// test normal usage
519	//
520	num_expected_ = 0;
521	expected_metadata_sequence_[num_expected_++] = &streaminfo_;
522
523	printf("allocating decoder instance... ");
524	decoder = new_by_layer(layer);
525	if(0 == decoder) {
526		printf("FAILED, new returned NULL\n");
527		return false;
528	}
529	printf("OK\n");
530
531	printf("testing is_valid()... ");
532	if(!decoder->is_valid()) {
533		printf("FAILED, returned false\n");
534		return false;
535	}
536	printf("OK\n");
537
538	if(is_ogg) {
539		printf("testing set_ogg_serial_number()... ");
540		if(!decoder->set_ogg_serial_number(file_utils__ogg_serial_number))
541			return die_s_("returned false", decoder);
542		printf("OK\n");
543	}
544
545	if(!decoder->set_md5_checking(true)) {
546		printf("FAILED at set_md5_checking(), returned false\n");
547		return false;
548	}
549
550	switch(layer) {
551		case LAYER_STREAM:
552		case LAYER_SEEKABLE_STREAM:
553			printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
554			dynamic_cast<StreamDecoder*>(decoder)->file_ = ::fopen(flacfilename(is_ogg), "rb");
555			if(0 == dynamic_cast<StreamDecoder*>(decoder)->file_) {
556				printf("ERROR (%s)\n", strerror(errno));
557				return false;
558			}
559			printf("OK\n");
560
561			printf("testing init%s()... ", is_ogg? "_ogg":"");
562			init_status = is_ogg? decoder->init_ogg() : decoder->init();
563			break;
564		case LAYER_FILE:
565			{
566				printf("opening FLAC file... ");
567				FILE *file = ::fopen(flacfilename(is_ogg), "rb");
568				if(0 == file) {
569					printf("ERROR (%s)\n", strerror(errno));
570					return false;
571				}
572				printf("OK\n");
573
574				printf("testing init%s()... ", is_ogg? "_ogg":"");
575				init_status = is_ogg?
576					dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(file) :
577					dynamic_cast<FLAC::Decoder::File*>(decoder)->init(file);
578			}
579			break;
580		case LAYER_FILENAME:
581			printf("testing init%s()... ", is_ogg? "_ogg":"");
582			init_status = is_ogg?
583				dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
584				dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
585			break;
586		default:
587			die_("internal error 009");
588			return false;
589	}
590	if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
591		return die_s_(0, decoder);
592	printf("OK\n");
593
594	printf("testing get_state()... ");
595	FLAC::Decoder::Stream::State state = decoder->get_state();
596	printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
597
598	dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
599	dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
600	dynamic_cast<DecoderCommon*>(decoder)->error_occurred_ = false;
601
602	printf("testing get_md5_checking()... ");
603	if(!decoder->get_md5_checking()) {
604		printf("FAILED, returned false, expected true\n");
605		return false;
606	}
607	printf("OK\n");
608
609	printf("testing process_until_end_of_metadata()... ");
610	if(!decoder->process_until_end_of_metadata())
611		return die_s_("returned false", decoder);
612	printf("OK\n");
613
614	printf("testing process_single()... ");
615	if(!decoder->process_single())
616		return die_s_("returned false", decoder);
617	printf("OK\n");
618
619	printf("testing skip_single_frame()... ");
620	if(!decoder->skip_single_frame())
621		return die_s_("returned false", decoder);
622	printf("OK\n");
623
624	if(layer < LAYER_FILE) {
625		printf("testing flush()... ");
626		if(!decoder->flush())
627			return die_s_("returned false", decoder);
628		printf("OK\n");
629
630		dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = true;
631		printf("testing process_single()... ");
632		if(!decoder->process_single())
633			return die_s_("returned false", decoder);
634		printf("OK\n");
635		dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
636	}
637
638	expect = (layer != LAYER_STREAM);
639	printf("testing seek_absolute()... ");
640	if(decoder->seek_absolute(0) != expect)
641		return die_s_(expect? "returned false" : "returned true", decoder);
642	printf("OK\n");
643
644	printf("testing process_until_end_of_stream()... ");
645	if(!decoder->process_until_end_of_stream())
646		return die_s_("returned false", decoder);
647	printf("OK\n");
648
649	expect = (layer != LAYER_STREAM);
650	printf("testing seek_absolute()... ");
651	if(decoder->seek_absolute(0) != expect)
652		return die_s_(expect? "returned false" : "returned true", decoder);
653	printf("OK\n");
654
655	printf("testing get_channels()... ");
656	{
657		unsigned channels = decoder->get_channels();
658		if(channels != streaminfo_.data.stream_info.channels) {
659			printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
660			return false;
661		}
662	}
663	printf("OK\n");
664
665	printf("testing get_bits_per_sample()... ");
666	{
667		unsigned bits_per_sample = decoder->get_bits_per_sample();
668		if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
669			printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
670			return false;
671		}
672	}
673	printf("OK\n");
674
675	printf("testing get_sample_rate()... ");
676	{
677		unsigned sample_rate = decoder->get_sample_rate();
678		if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
679			printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
680			return false;
681		}
682	}
683	printf("OK\n");
684
685	printf("testing get_blocksize()... ");
686	{
687		unsigned blocksize = decoder->get_blocksize();
688		/* value could be anything since we're at the last block, so accept any reasonable answer */
689		printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
690		if(blocksize == 0)
691			return false;
692	}
693
694	printf("testing get_channel_assignment()... ");
695	{
696		::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
697		printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
698	}
699
700	if(layer < LAYER_FILE) {
701		printf("testing reset()... ");
702		if(!decoder->reset())
703			return die_s_("returned false", decoder);
704		printf("OK\n");
705
706		if(layer == LAYER_STREAM) {
707			/* after a reset() we have to rewind the input ourselves */
708			printf("rewinding input... ");
709			if(fseeko(dynamic_cast<StreamDecoder*>(decoder)->file_, 0, SEEK_SET) < 0) {
710				printf("FAILED, errno = %d\n", errno);
711				return false;
712			}
713			printf("OK\n");
714		}
715
716		dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
717
718		printf("testing process_until_end_of_stream()... ");
719		if(!decoder->process_until_end_of_stream())
720			return die_s_("returned false", decoder);
721		printf("OK\n");
722	}
723
724	printf("testing finish()... ");
725	if(!decoder->finish()) {
726		FLAC::Decoder::Stream::State state = decoder->get_state();
727		printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
728		return false;
729	}
730	printf("OK\n");
731
732	/*
733	 * respond all
734	 */
735
736	printf("testing set_metadata_respond_all()... ");
737	if(!decoder->set_metadata_respond_all()) {
738		printf("FAILED, returned false\n");
739		return false;
740	}
741	printf("OK\n");
742
743	num_expected_ = 0;
744	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
745		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
746		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
747		expected_metadata_sequence_[num_expected_++] = &padding_;
748		expected_metadata_sequence_[num_expected_++] = &seektable_;
749		expected_metadata_sequence_[num_expected_++] = &application1_;
750		expected_metadata_sequence_[num_expected_++] = &application2_;
751		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
752		expected_metadata_sequence_[num_expected_++] = &picture_;
753		expected_metadata_sequence_[num_expected_++] = &unknown_;
754	}
755	else {
756		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
757		expected_metadata_sequence_[num_expected_++] = &padding_;
758		expected_metadata_sequence_[num_expected_++] = &seektable_;
759		expected_metadata_sequence_[num_expected_++] = &application1_;
760		expected_metadata_sequence_[num_expected_++] = &application2_;
761		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
762		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
763		expected_metadata_sequence_[num_expected_++] = &picture_;
764		expected_metadata_sequence_[num_expected_++] = &unknown_;
765	}
766
767	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
768		return false;
769
770	/*
771	 * ignore all
772	 */
773
774	printf("testing set_metadata_ignore_all()... ");
775	if(!decoder->set_metadata_ignore_all()) {
776		printf("FAILED, returned false\n");
777		return false;
778	}
779	printf("OK\n");
780
781	num_expected_ = 0;
782
783	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
784		return false;
785
786	/*
787	 * respond all, ignore VORBIS_COMMENT
788	 */
789
790	printf("testing set_metadata_respond_all()... ");
791	if(!decoder->set_metadata_respond_all()) {
792		printf("FAILED, returned false\n");
793		return false;
794	}
795	printf("OK\n");
796
797	printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
798	if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
799		printf("FAILED, returned false\n");
800		return false;
801	}
802	printf("OK\n");
803
804	num_expected_ = 0;
805	expected_metadata_sequence_[num_expected_++] = &streaminfo_;
806	expected_metadata_sequence_[num_expected_++] = &padding_;
807	expected_metadata_sequence_[num_expected_++] = &seektable_;
808	expected_metadata_sequence_[num_expected_++] = &application1_;
809	expected_metadata_sequence_[num_expected_++] = &application2_;
810	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
811	expected_metadata_sequence_[num_expected_++] = &picture_;
812	expected_metadata_sequence_[num_expected_++] = &unknown_;
813
814	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
815		return false;
816
817	/*
818	 * respond all, ignore APPLICATION
819	 */
820
821	printf("testing set_metadata_respond_all()... ");
822	if(!decoder->set_metadata_respond_all()) {
823		printf("FAILED, returned false\n");
824		return false;
825	}
826	printf("OK\n");
827
828	printf("testing set_metadata_ignore(APPLICATION)... ");
829	if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
830		printf("FAILED, returned false\n");
831		return false;
832	}
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(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
856		return false;
857
858	/*
859	 * respond all, ignore APPLICATION id of app#1
860	 */
861
862	printf("testing set_metadata_respond_all()... ");
863	if(!decoder->set_metadata_respond_all()) {
864		printf("FAILED, returned false\n");
865		return false;
866	}
867	printf("OK\n");
868
869	printf("testing set_metadata_ignore_application(of app block #1)... ");
870	if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
871		printf("FAILED, returned false\n");
872		return false;
873	}
874	printf("OK\n");
875
876	num_expected_ = 0;
877	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
878		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
879		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
880		expected_metadata_sequence_[num_expected_++] = &padding_;
881		expected_metadata_sequence_[num_expected_++] = &seektable_;
882		expected_metadata_sequence_[num_expected_++] = &application2_;
883		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
884		expected_metadata_sequence_[num_expected_++] = &picture_;
885		expected_metadata_sequence_[num_expected_++] = &unknown_;
886	}
887	else {
888		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
889		expected_metadata_sequence_[num_expected_++] = &padding_;
890		expected_metadata_sequence_[num_expected_++] = &seektable_;
891		expected_metadata_sequence_[num_expected_++] = &application2_;
892		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
893		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
894		expected_metadata_sequence_[num_expected_++] = &picture_;
895		expected_metadata_sequence_[num_expected_++] = &unknown_;
896	}
897
898	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
899		return false;
900
901	/*
902	 * respond all, ignore APPLICATION id of app#1 & app#2
903	 */
904
905	printf("testing set_metadata_respond_all()... ");
906	if(!decoder->set_metadata_respond_all()) {
907		printf("FAILED, returned false\n");
908		return false;
909	}
910	printf("OK\n");
911
912	printf("testing set_metadata_ignore_application(of app block #1)... ");
913	if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
914		printf("FAILED, returned false\n");
915		return false;
916	}
917	printf("OK\n");
918
919	printf("testing set_metadata_ignore_application(of app block #2)... ");
920	if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
921		printf("FAILED, returned false\n");
922		return false;
923	}
924	printf("OK\n");
925
926	num_expected_ = 0;
927	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
928		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
929		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
930		expected_metadata_sequence_[num_expected_++] = &padding_;
931		expected_metadata_sequence_[num_expected_++] = &seektable_;
932		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
933		expected_metadata_sequence_[num_expected_++] = &picture_;
934		expected_metadata_sequence_[num_expected_++] = &unknown_;
935	}
936	else {
937		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
938		expected_metadata_sequence_[num_expected_++] = &padding_;
939		expected_metadata_sequence_[num_expected_++] = &seektable_;
940		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
941		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
942		expected_metadata_sequence_[num_expected_++] = &picture_;
943		expected_metadata_sequence_[num_expected_++] = &unknown_;
944	}
945
946	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
947		return false;
948
949	/*
950	 * ignore all, respond VORBIS_COMMENT
951	 */
952
953	printf("testing set_metadata_ignore_all()... ");
954	if(!decoder->set_metadata_ignore_all()) {
955		printf("FAILED, returned false\n");
956		return false;
957	}
958	printf("OK\n");
959
960	printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
961	if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
962		printf("FAILED, returned false\n");
963		return false;
964	}
965	printf("OK\n");
966
967	num_expected_ = 0;
968	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
969
970	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
971		return false;
972
973	/*
974	 * ignore all, respond APPLICATION
975	 */
976
977	printf("testing set_metadata_ignore_all()... ");
978	if(!decoder->set_metadata_ignore_all()) {
979		printf("FAILED, returned false\n");
980		return false;
981	}
982	printf("OK\n");
983
984	printf("testing set_metadata_respond(APPLICATION)... ");
985	if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
986		printf("FAILED, returned false\n");
987		return false;
988	}
989	printf("OK\n");
990
991	num_expected_ = 0;
992	expected_metadata_sequence_[num_expected_++] = &application1_;
993	expected_metadata_sequence_[num_expected_++] = &application2_;
994
995	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
996		return false;
997
998	/*
999	 * ignore all, respond APPLICATION id of app#1
1000	 */
1001
1002	printf("testing set_metadata_ignore_all()... ");
1003	if(!decoder->set_metadata_ignore_all()) {
1004		printf("FAILED, returned false\n");
1005		return false;
1006	}
1007	printf("OK\n");
1008
1009	printf("testing set_metadata_respond_application(of app block #1)... ");
1010	if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1011		printf("FAILED, returned false\n");
1012		return false;
1013	}
1014	printf("OK\n");
1015
1016	num_expected_ = 0;
1017	expected_metadata_sequence_[num_expected_++] = &application1_;
1018
1019	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1020		return false;
1021
1022	/*
1023	 * ignore all, respond APPLICATION id of app#1 & app#2
1024	 */
1025
1026	printf("testing set_metadata_ignore_all()... ");
1027	if(!decoder->set_metadata_ignore_all()) {
1028		printf("FAILED, returned false\n");
1029		return false;
1030	}
1031	printf("OK\n");
1032
1033	printf("testing set_metadata_respond_application(of app block #1)... ");
1034	if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1035		printf("FAILED, returned false\n");
1036		return false;
1037	}
1038	printf("OK\n");
1039
1040	printf("testing set_metadata_respond_application(of app block #2)... ");
1041	if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
1042		printf("FAILED, returned false\n");
1043		return false;
1044	}
1045	printf("OK\n");
1046
1047	num_expected_ = 0;
1048	expected_metadata_sequence_[num_expected_++] = &application1_;
1049	expected_metadata_sequence_[num_expected_++] = &application2_;
1050
1051	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1052		return false;
1053
1054	/*
1055	 * respond all, ignore APPLICATION, respond APPLICATION id of app#1
1056	 */
1057
1058	printf("testing set_metadata_respond_all()... ");
1059	if(!decoder->set_metadata_respond_all()) {
1060		printf("FAILED, returned false\n");
1061		return false;
1062	}
1063	printf("OK\n");
1064
1065	printf("testing set_metadata_ignore(APPLICATION)... ");
1066	if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
1067		printf("FAILED, returned false\n");
1068		return false;
1069	}
1070	printf("OK\n");
1071
1072	printf("testing set_metadata_respond_application(of app block #1)... ");
1073	if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1074		printf("FAILED, returned false\n");
1075		return false;
1076	}
1077	printf("OK\n");
1078
1079	num_expected_ = 0;
1080	if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
1081		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
1082		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
1083		expected_metadata_sequence_[num_expected_++] = &padding_;
1084		expected_metadata_sequence_[num_expected_++] = &seektable_;
1085		expected_metadata_sequence_[num_expected_++] = &application1_;
1086		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
1087		expected_metadata_sequence_[num_expected_++] = &picture_;
1088		expected_metadata_sequence_[num_expected_++] = &unknown_;
1089	}
1090	else {
1091		expected_metadata_sequence_[num_expected_++] = &streaminfo_;
1092		expected_metadata_sequence_[num_expected_++] = &padding_;
1093		expected_metadata_sequence_[num_expected_++] = &seektable_;
1094		expected_metadata_sequence_[num_expected_++] = &application1_;
1095		expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
1096		expected_metadata_sequence_[num_expected_++] = &cuesheet_;
1097		expected_metadata_sequence_[num_expected_++] = &picture_;
1098		expected_metadata_sequence_[num_expected_++] = &unknown_;
1099	}
1100
1101	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1102		return false;
1103
1104	/*
1105	 * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
1106	 */
1107
1108	printf("testing set_metadata_ignore_all()... ");
1109	if(!decoder->set_metadata_ignore_all()) {
1110		printf("FAILED, returned false\n");
1111		return false;
1112	}
1113	printf("OK\n");
1114
1115	printf("testing set_metadata_respond(APPLICATION)... ");
1116	if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
1117		printf("FAILED, returned false\n");
1118		return false;
1119	}
1120	printf("OK\n");
1121
1122	printf("testing set_metadata_ignore_application(of app block #1)... ");
1123	if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
1124		printf("FAILED, returned false\n");
1125		return false;
1126	}
1127	printf("OK\n");
1128
1129	num_expected_ = 0;
1130	expected_metadata_sequence_[num_expected_++] = &application2_;
1131
1132	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1133		return false;
1134
1135	if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
1136		::fclose(dynamic_cast<StreamDecoder*>(decoder)->file_);
1137
1138	printf("freeing decoder instance... ");
1139	delete decoder;
1140	printf("OK\n");
1141
1142	printf("\nPASSED!\n");
1143
1144	return true;
1145}
1146
1147bool test_decoders()
1148{
1149	FLAC__bool is_ogg = false;
1150
1151	while(1) {
1152		init_metadata_blocks_();
1153
1154		if(!generate_file_(is_ogg))
1155			return false;
1156
1157		if(!test_stream_decoder(LAYER_STREAM, is_ogg))
1158			return false;
1159
1160		if(!test_stream_decoder(LAYER_SEEKABLE_STREAM, is_ogg))
1161			return false;
1162
1163		if(!test_stream_decoder(LAYER_FILE, is_ogg))
1164			return false;
1165
1166		if(!test_stream_decoder(LAYER_FILENAME, is_ogg))
1167			return false;
1168
1169		(void) grabbag__file_remove_file(flacfilename(is_ogg));
1170
1171		free_metadata_blocks_();
1172
1173		if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
1174			break;
1175		is_ogg = true;
1176	}
1177
1178	return true;
1179}
1180