Fix a number of gcc 9.2 compiler warnings
[flac.git] / src / test_libFLAC++ / decoders.cpp
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/metadata.h" // for ::FLAC__metadata_object_is_equal()
31 #include "FLAC++/decoder.h"
32 #include "share/grabbag.h"
33 #include "share/compat.h"
34 extern "C" {
35 #include "test_libs_common/file_utils_flac.h"
36 #include "test_libs_common/metadata_utils.h"
37 }
38
39 #ifdef _MSC_VER
40 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
41 #pragma warning ( disable : 4800 )
42 #endif
43
44 typedef enum {
45         LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
46         LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
47         LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
48         LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
49 } Layer;
50
51 static const char * const LayerString[] = {
52         "Stream",
53         "Seekable Stream",
54         "FILE*",
55         "Filename"
56 };
57
58 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
59 static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
60 static uint32_t num_expected_;
61 static FLAC__off_t flacfilesize_;
62
63 static const char *flacfilename(bool is_ogg)
64 {
65         return is_ogg? "metadata.oga" : "metadata.flac";
66 }
67
68 static bool die_(const char *msg)
69 {
70         printf("ERROR: %s\n", msg);
71         return false;
72 }
73
74 static FLAC__bool die_s_(const char *msg, const FLAC::Decoder::Stream *decoder)
75 {
76         FLAC::Decoder::Stream::State state = decoder->get_state();
77
78         if(msg)
79                 printf("FAILED, %s", msg);
80         else
81                 printf("FAILED");
82
83         printf(", state = %u (%s)\n", (uint32_t)((::FLAC__StreamDecoderState)state), state.as_cstring());
84
85         return false;
86 }
87
88 static void init_metadata_blocks_()
89 {
90         mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
91 }
92
93 static void free_metadata_blocks_()
94 {
95         mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
96 }
97
98 static bool generate_file_(FLAC__bool is_ogg)
99 {
100         printf("\n\ngenerating %sFLAC file for decoder tests...\n", is_ogg? "Ogg ":"");
101
102         num_expected_ = 0;
103         expected_metadata_sequence_[num_expected_++] = &padding_;
104         expected_metadata_sequence_[num_expected_++] = &seektable_;
105         expected_metadata_sequence_[num_expected_++] = &application1_;
106         expected_metadata_sequence_[num_expected_++] = &application2_;
107         expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
108         expected_metadata_sequence_[num_expected_++] = &cuesheet_;
109         expected_metadata_sequence_[num_expected_++] = &picture_;
110         expected_metadata_sequence_[num_expected_++] = &unknown_;
111         /* WATCHOUT: for Ogg FLAC the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
112
113         if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
114                 return die_("creating the encoded file");
115
116         return true;
117 }
118
119
120 class DecoderCommon {
121 public:
122         Layer layer_;
123         uint32_t current_metadata_number_;
124         bool ignore_errors_;
125         bool error_occurred_;
126
127         DecoderCommon(Layer layer): layer_(layer), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
128         virtual ~DecoderCommon(void) { }
129         ::FLAC__StreamDecoderWriteStatus common_write_callback_(const ::FLAC__Frame *frame);
130         void common_metadata_callback_(const ::FLAC__StreamMetadata *metadata);
131         void common_error_callback_(::FLAC__StreamDecoderErrorStatus status);
132 };
133
134 ::FLAC__StreamDecoderWriteStatus DecoderCommon::common_write_callback_(const ::FLAC__Frame *frame)
135 {
136         if(error_occurred_)
137                 return ::FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
138
139         if(
140                 (frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
141                 (frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
142         ) {
143                 printf("content... ");
144                 fflush(stdout);
145         }
146
147         return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
148 }
149
150 void DecoderCommon::common_metadata_callback_(const ::FLAC__StreamMetadata *metadata)
151 {
152         if(error_occurred_)
153                 return;
154
155         printf("%d... ", current_metadata_number_);
156         fflush(stdout);
157
158         if(current_metadata_number_ >= num_expected_) {
159                 (void)die_("got more metadata blocks than expected");
160                 error_occurred_ = true;
161         }
162         else {
163                 if(!::FLAC__metadata_object_is_equal(expected_metadata_sequence_[current_metadata_number_], metadata)) {
164                         (void)die_("metadata block mismatch");
165                         error_occurred_ = true;
166                 }
167         }
168         current_metadata_number_++;
169 }
170
171 void DecoderCommon::common_error_callback_(::FLAC__StreamDecoderErrorStatus status)
172 {
173         if(!ignore_errors_) {
174                 printf("ERROR: got error callback: err = %u (%s)\n", (uint32_t)status, ::FLAC__StreamDecoderErrorStatusString[status]);
175                 error_occurred_ = true;
176         }
177 }
178
179 class StreamDecoder : public FLAC::Decoder::Stream, public DecoderCommon {
180 public:
181         FILE *file_;
182
183         StreamDecoder(Layer layer): FLAC::Decoder::Stream(), DecoderCommon(layer), file_(0) { }
184         ~StreamDecoder() { }
185
186         // from FLAC::Decoder::Stream
187         ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
188         ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
189         ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
190         ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
191         bool eof_callback();
192         ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
193         void metadata_callback(const ::FLAC__StreamMetadata *metadata);
194         void error_callback(::FLAC__StreamDecoderErrorStatus status);
195
196         bool test_respond(bool is_ogg);
197 private:
198         StreamDecoder(const StreamDecoder&);
199         StreamDecoder&operator=(const StreamDecoder&);
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_, (FLAC__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         FLAC__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
276 bool 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
294 void StreamDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
295 {
296         common_metadata_callback_(metadata);
297 }
298
299 void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
300 {
301         common_error_callback_(status);
302 }
303
304 bool 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", (uint32_t)((::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", (uint32_t)((::FLAC__StreamDecoderState)state), state.as_cstring());
338                 return false;
339         }
340         printf("OK\n");
341
342         return true;
343 }
344
345 class FileDecoder : public FLAC::Decoder::File, public DecoderCommon {
346 public:
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
364 void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
365 {
366         common_metadata_callback_(metadata);
367 }
368
369 void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
370 {
371         common_error_callback_(status);
372 }
373
374 bool 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 = ::flac_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", (uint32_t)((::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", (uint32_t)((::FLAC__StreamDecoderState)state), state.as_cstring());
424                 return false;
425         }
426         printf("OK\n");
427
428         return true;
429 }
430
431
432 static 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
440 static 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                         delete decoder;
508                         return false;
509         }
510         if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
511                 return die_s_(0, decoder);
512         printf("OK\n");
513
514         printf("freeing decoder instance... ");
515         delete decoder;
516         printf("OK\n");
517
518         //
519         // test normal usage
520         //
521         num_expected_ = 0;
522         expected_metadata_sequence_[num_expected_++] = &streaminfo_;
523
524         printf("allocating decoder instance... ");
525         decoder = new_by_layer(layer);
526         if(0 == decoder) {
527                 printf("FAILED, new returned NULL\n");
528                 return false;
529         }
530         printf("OK\n");
531
532         printf("testing is_valid()... ");
533         if(!decoder->is_valid()) {
534                 printf("FAILED, returned false\n");
535                 return false;
536         }
537         printf("OK\n");
538
539         if(is_ogg) {
540                 printf("testing set_ogg_serial_number()... ");
541                 if(!decoder->set_ogg_serial_number(file_utils__ogg_serial_number))
542                         return die_s_("returned false", decoder);
543                 printf("OK\n");
544         }
545
546         if(!decoder->set_md5_checking(true)) {
547                 printf("FAILED at set_md5_checking(), returned false\n");
548                 return false;
549         }
550
551         switch(layer) {
552                 case LAYER_STREAM:
553                 case LAYER_SEEKABLE_STREAM:
554                         printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
555                         dynamic_cast<StreamDecoder*>(decoder)->file_ = ::flac_fopen(flacfilename(is_ogg), "rb");
556                         if(0 == dynamic_cast<StreamDecoder*>(decoder)->file_) {
557                                 printf("ERROR (%s)\n", strerror(errno));
558                                 return false;
559                         }
560                         printf("OK\n");
561
562                         printf("testing init%s()... ", is_ogg? "_ogg":"");
563                         init_status = is_ogg? decoder->init_ogg() : decoder->init();
564                         break;
565                 case LAYER_FILE:
566                         {
567                                 printf("opening FLAC file... ");
568                                 FILE *file = ::flac_fopen(flacfilename(is_ogg), "rb");
569                                 if(0 == file) {
570                                         printf("ERROR (%s)\n", strerror(errno));
571                                         return false;
572                                 }
573                                 printf("OK\n");
574
575                                 printf("testing init%s()... ", is_ogg? "_ogg":"");
576                                 init_status = is_ogg?
577                                         dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(file) :
578                                         dynamic_cast<FLAC::Decoder::File*>(decoder)->init(file);
579                         }
580                         break;
581                 case LAYER_FILENAME:
582                         printf("testing init%s()... ", is_ogg? "_ogg":"");
583                         init_status = is_ogg?
584                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
585                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
586                         break;
587                 default:
588                         die_("internal error 009");
589                         return false;
590         }
591         if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
592                 return die_s_(0, decoder);
593         printf("OK\n");
594
595         printf("testing get_state()... ");
596         FLAC::Decoder::Stream::State state = decoder->get_state();
597         printf("returned state = %u (%s)... OK\n", (uint32_t)((::FLAC__StreamDecoderState)state), state.as_cstring());
598
599         dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
600         dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
601         dynamic_cast<DecoderCommon*>(decoder)->error_occurred_ = false;
602
603         printf("testing get_md5_checking()... ");
604         if(!decoder->get_md5_checking()) {
605                 printf("FAILED, returned false, expected true\n");
606                 return false;
607         }
608         printf("OK\n");
609
610         printf("testing process_until_end_of_metadata()... ");
611         if(!decoder->process_until_end_of_metadata())
612                 return die_s_("returned false", decoder);
613         printf("OK\n");
614
615         printf("testing process_single()... ");
616         if(!decoder->process_single())
617                 return die_s_("returned false", decoder);
618         printf("OK\n");
619
620         printf("testing skip_single_frame()... ");
621         if(!decoder->skip_single_frame())
622                 return die_s_("returned false", decoder);
623         printf("OK\n");
624
625         if(layer < LAYER_FILE) {
626                 printf("testing flush()... ");
627                 if(!decoder->flush())
628                         return die_s_("returned false", decoder);
629                 printf("OK\n");
630
631                 dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = true;
632                 printf("testing process_single()... ");
633                 if(!decoder->process_single())
634                         return die_s_("returned false", decoder);
635                 printf("OK\n");
636                 dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
637         }
638
639         expect = (layer != LAYER_STREAM);
640         printf("testing seek_absolute()... ");
641         if(decoder->seek_absolute(0) != expect)
642                 return die_s_(expect? "returned false" : "returned true", decoder);
643         printf("OK\n");
644
645         printf("testing process_until_end_of_stream()... ");
646         if(!decoder->process_until_end_of_stream())
647                 return die_s_("returned false", decoder);
648         printf("OK\n");
649
650         expect = (layer != LAYER_STREAM);
651         printf("testing seek_absolute()... ");
652         if(decoder->seek_absolute(0) != expect)
653                 return die_s_(expect? "returned false" : "returned true", decoder);
654         printf("OK\n");
655
656         printf("testing get_channels()... ");
657         {
658                 uint32_t channels = decoder->get_channels();
659                 if(channels != streaminfo_.data.stream_info.channels) {
660                         printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
661                         return false;
662                 }
663         }
664         printf("OK\n");
665
666         printf("testing get_bits_per_sample()... ");
667         {
668                 uint32_t bits_per_sample = decoder->get_bits_per_sample();
669                 if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
670                         printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
671                         return false;
672                 }
673         }
674         printf("OK\n");
675
676         printf("testing get_sample_rate()... ");
677         {
678                 uint32_t sample_rate = decoder->get_sample_rate();
679                 if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
680                         printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
681                         return false;
682                 }
683         }
684         printf("OK\n");
685
686         printf("testing get_blocksize()... ");
687         {
688                 uint32_t blocksize = decoder->get_blocksize();
689                 /* value could be anything since we're at the last block, so accept any reasonable answer */
690                 printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
691                 if(blocksize == 0)
692                         return false;
693         }
694
695         printf("testing get_channel_assignment()... ");
696         {
697                 ::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
698                 printf("returned %u (%s)... OK\n", (uint32_t)ca, ::FLAC__ChannelAssignmentString[ca]);
699         }
700
701         if(layer < LAYER_FILE) {
702                 printf("testing reset()... ");
703                 if(!decoder->reset())
704                         return die_s_("returned false", decoder);
705                 printf("OK\n");
706
707                 if(layer == LAYER_STREAM) {
708                         /* after a reset() we have to rewind the input ourselves */
709                         printf("rewinding input... ");
710                         if(fseeko(dynamic_cast<StreamDecoder*>(decoder)->file_, 0, SEEK_SET) < 0) {
711                                 printf("FAILED, errno = %d\n", errno);
712                                 return false;
713                         }
714                         printf("OK\n");
715                 }
716
717                 dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
718
719                 printf("testing process_until_end_of_stream()... ");
720                 if(!decoder->process_until_end_of_stream())
721                         return die_s_("returned false", decoder);
722                 printf("OK\n");
723         }
724
725         printf("testing finish()... ");
726         if(!decoder->finish()) {
727                 state = decoder->get_state();
728                 printf("FAILED, returned false, state = %u (%s)\n", (uint32_t)((::FLAC__StreamDecoderState)state), state.as_cstring());
729                 return false;
730         }
731         printf("OK\n");
732
733         /*
734          * respond all
735          */
736
737         printf("testing set_metadata_respond_all()... ");
738         if(!decoder->set_metadata_respond_all()) {
739                 printf("FAILED, returned false\n");
740                 return false;
741         }
742         printf("OK\n");
743
744         num_expected_ = 0;
745         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
746                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
747                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
748                 expected_metadata_sequence_[num_expected_++] = &padding_;
749                 expected_metadata_sequence_[num_expected_++] = &seektable_;
750                 expected_metadata_sequence_[num_expected_++] = &application1_;
751                 expected_metadata_sequence_[num_expected_++] = &application2_;
752                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
753                 expected_metadata_sequence_[num_expected_++] = &picture_;
754                 expected_metadata_sequence_[num_expected_++] = &unknown_;
755         }
756         else {
757                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
758                 expected_metadata_sequence_[num_expected_++] = &padding_;
759                 expected_metadata_sequence_[num_expected_++] = &seektable_;
760                 expected_metadata_sequence_[num_expected_++] = &application1_;
761                 expected_metadata_sequence_[num_expected_++] = &application2_;
762                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
763                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
764                 expected_metadata_sequence_[num_expected_++] = &picture_;
765                 expected_metadata_sequence_[num_expected_++] = &unknown_;
766         }
767
768         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
769                 return false;
770
771         /*
772          * ignore all
773          */
774
775         printf("testing set_metadata_ignore_all()... ");
776         if(!decoder->set_metadata_ignore_all()) {
777                 printf("FAILED, returned false\n");
778                 return false;
779         }
780         printf("OK\n");
781
782         num_expected_ = 0;
783
784         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
785                 return false;
786
787         /*
788          * respond all, ignore VORBIS_COMMENT
789          */
790
791         printf("testing set_metadata_respond_all()... ");
792         if(!decoder->set_metadata_respond_all()) {
793                 printf("FAILED, returned false\n");
794                 return false;
795         }
796         printf("OK\n");
797
798         printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
799         if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
800                 printf("FAILED, returned false\n");
801                 return false;
802         }
803         printf("OK\n");
804
805         num_expected_ = 0;
806         expected_metadata_sequence_[num_expected_++] = &streaminfo_;
807         expected_metadata_sequence_[num_expected_++] = &padding_;
808         expected_metadata_sequence_[num_expected_++] = &seektable_;
809         expected_metadata_sequence_[num_expected_++] = &application1_;
810         expected_metadata_sequence_[num_expected_++] = &application2_;
811         expected_metadata_sequence_[num_expected_++] = &cuesheet_;
812         expected_metadata_sequence_[num_expected_++] = &picture_;
813         expected_metadata_sequence_[num_expected_++] = &unknown_;
814
815         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
816                 return false;
817
818         /*
819          * respond all, ignore APPLICATION
820          */
821
822         printf("testing set_metadata_respond_all()... ");
823         if(!decoder->set_metadata_respond_all()) {
824                 printf("FAILED, returned false\n");
825                 return false;
826         }
827         printf("OK\n");
828
829         printf("testing set_metadata_ignore(APPLICATION)... ");
830         if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
831                 printf("FAILED, returned false\n");
832                 return false;
833         }
834         printf("OK\n");
835
836         num_expected_ = 0;
837         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
838                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
839                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
840                 expected_metadata_sequence_[num_expected_++] = &padding_;
841                 expected_metadata_sequence_[num_expected_++] = &seektable_;
842                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
843                 expected_metadata_sequence_[num_expected_++] = &picture_;
844                 expected_metadata_sequence_[num_expected_++] = &unknown_;
845         }
846         else {
847                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
848                 expected_metadata_sequence_[num_expected_++] = &padding_;
849                 expected_metadata_sequence_[num_expected_++] = &seektable_;
850                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
851                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
852                 expected_metadata_sequence_[num_expected_++] = &picture_;
853                 expected_metadata_sequence_[num_expected_++] = &unknown_;
854         }
855
856         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
857                 return false;
858
859         /*
860          * respond all, ignore APPLICATION id of app#1
861          */
862
863         printf("testing set_metadata_respond_all()... ");
864         if(!decoder->set_metadata_respond_all()) {
865                 printf("FAILED, returned false\n");
866                 return false;
867         }
868         printf("OK\n");
869
870         printf("testing set_metadata_ignore_application(of app block #1)... ");
871         if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
872                 printf("FAILED, returned false\n");
873                 return false;
874         }
875         printf("OK\n");
876
877         num_expected_ = 0;
878         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
879                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
880                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
881                 expected_metadata_sequence_[num_expected_++] = &padding_;
882                 expected_metadata_sequence_[num_expected_++] = &seektable_;
883                 expected_metadata_sequence_[num_expected_++] = &application2_;
884                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
885                 expected_metadata_sequence_[num_expected_++] = &picture_;
886                 expected_metadata_sequence_[num_expected_++] = &unknown_;
887         }
888         else {
889                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
890                 expected_metadata_sequence_[num_expected_++] = &padding_;
891                 expected_metadata_sequence_[num_expected_++] = &seektable_;
892                 expected_metadata_sequence_[num_expected_++] = &application2_;
893                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
894                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
895                 expected_metadata_sequence_[num_expected_++] = &picture_;
896                 expected_metadata_sequence_[num_expected_++] = &unknown_;
897         }
898
899         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
900                 return false;
901
902         /*
903          * respond all, ignore APPLICATION id of app#1 & app#2
904          */
905
906         printf("testing set_metadata_respond_all()... ");
907         if(!decoder->set_metadata_respond_all()) {
908                 printf("FAILED, returned false\n");
909                 return false;
910         }
911         printf("OK\n");
912
913         printf("testing set_metadata_ignore_application(of app block #1)... ");
914         if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
915                 printf("FAILED, returned false\n");
916                 return false;
917         }
918         printf("OK\n");
919
920         printf("testing set_metadata_ignore_application(of app block #2)... ");
921         if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
922                 printf("FAILED, returned false\n");
923                 return false;
924         }
925         printf("OK\n");
926
927         num_expected_ = 0;
928         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
929                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
930                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
931                 expected_metadata_sequence_[num_expected_++] = &padding_;
932                 expected_metadata_sequence_[num_expected_++] = &seektable_;
933                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
934                 expected_metadata_sequence_[num_expected_++] = &picture_;
935                 expected_metadata_sequence_[num_expected_++] = &unknown_;
936         }
937         else {
938                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
939                 expected_metadata_sequence_[num_expected_++] = &padding_;
940                 expected_metadata_sequence_[num_expected_++] = &seektable_;
941                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
942                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
943                 expected_metadata_sequence_[num_expected_++] = &picture_;
944                 expected_metadata_sequence_[num_expected_++] = &unknown_;
945         }
946
947         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
948                 return false;
949
950         /*
951          * ignore all, respond VORBIS_COMMENT
952          */
953
954         printf("testing set_metadata_ignore_all()... ");
955         if(!decoder->set_metadata_ignore_all()) {
956                 printf("FAILED, returned false\n");
957                 return false;
958         }
959         printf("OK\n");
960
961         printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
962         if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
963                 printf("FAILED, returned false\n");
964                 return false;
965         }
966         printf("OK\n");
967
968         num_expected_ = 0;
969         expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
970
971         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
972                 return false;
973
974         /*
975          * ignore all, respond APPLICATION
976          */
977
978         printf("testing set_metadata_ignore_all()... ");
979         if(!decoder->set_metadata_ignore_all()) {
980                 printf("FAILED, returned false\n");
981                 return false;
982         }
983         printf("OK\n");
984
985         printf("testing set_metadata_respond(APPLICATION)... ");
986         if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
987                 printf("FAILED, returned false\n");
988                 return false;
989         }
990         printf("OK\n");
991
992         num_expected_ = 0;
993         expected_metadata_sequence_[num_expected_++] = &application1_;
994         expected_metadata_sequence_[num_expected_++] = &application2_;
995
996         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
997                 return false;
998
999         /*
1000          * ignore all, respond APPLICATION id of app#1
1001          */
1002
1003         printf("testing set_metadata_ignore_all()... ");
1004         if(!decoder->set_metadata_ignore_all()) {
1005                 printf("FAILED, returned false\n");
1006                 return false;
1007         }
1008         printf("OK\n");
1009
1010         printf("testing set_metadata_respond_application(of app block #1)... ");
1011         if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1012                 printf("FAILED, returned false\n");
1013                 return false;
1014         }
1015         printf("OK\n");
1016
1017         num_expected_ = 0;
1018         expected_metadata_sequence_[num_expected_++] = &application1_;
1019
1020         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1021                 return false;
1022
1023         /*
1024          * ignore all, respond APPLICATION id of app#1 & app#2
1025          */
1026
1027         printf("testing set_metadata_ignore_all()... ");
1028         if(!decoder->set_metadata_ignore_all()) {
1029                 printf("FAILED, returned false\n");
1030                 return false;
1031         }
1032         printf("OK\n");
1033
1034         printf("testing set_metadata_respond_application(of app block #1)... ");
1035         if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1036                 printf("FAILED, returned false\n");
1037                 return false;
1038         }
1039         printf("OK\n");
1040
1041         printf("testing set_metadata_respond_application(of app block #2)... ");
1042         if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
1043                 printf("FAILED, returned false\n");
1044                 return false;
1045         }
1046         printf("OK\n");
1047
1048         num_expected_ = 0;
1049         expected_metadata_sequence_[num_expected_++] = &application1_;
1050         expected_metadata_sequence_[num_expected_++] = &application2_;
1051
1052         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1053                 return false;
1054
1055         /*
1056          * respond all, ignore APPLICATION, respond APPLICATION id of app#1
1057          */
1058
1059         printf("testing set_metadata_respond_all()... ");
1060         if(!decoder->set_metadata_respond_all()) {
1061                 printf("FAILED, returned false\n");
1062                 return false;
1063         }
1064         printf("OK\n");
1065
1066         printf("testing set_metadata_ignore(APPLICATION)... ");
1067         if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
1068                 printf("FAILED, returned false\n");
1069                 return false;
1070         }
1071         printf("OK\n");
1072
1073         printf("testing set_metadata_respond_application(of app block #1)... ");
1074         if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1075                 printf("FAILED, returned false\n");
1076                 return false;
1077         }
1078         printf("OK\n");
1079
1080         num_expected_ = 0;
1081         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
1082                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
1083                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
1084                 expected_metadata_sequence_[num_expected_++] = &padding_;
1085                 expected_metadata_sequence_[num_expected_++] = &seektable_;
1086                 expected_metadata_sequence_[num_expected_++] = &application1_;
1087                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
1088                 expected_metadata_sequence_[num_expected_++] = &picture_;
1089                 expected_metadata_sequence_[num_expected_++] = &unknown_;
1090         }
1091         else {
1092                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
1093                 expected_metadata_sequence_[num_expected_++] = &padding_;
1094                 expected_metadata_sequence_[num_expected_++] = &seektable_;
1095                 expected_metadata_sequence_[num_expected_++] = &application1_;
1096                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
1097                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
1098                 expected_metadata_sequence_[num_expected_++] = &picture_;
1099                 expected_metadata_sequence_[num_expected_++] = &unknown_;
1100         }
1101
1102         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1103                 return false;
1104
1105         /*
1106          * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
1107          */
1108
1109         printf("testing set_metadata_ignore_all()... ");
1110         if(!decoder->set_metadata_ignore_all()) {
1111                 printf("FAILED, returned false\n");
1112                 return false;
1113         }
1114         printf("OK\n");
1115
1116         printf("testing set_metadata_respond(APPLICATION)... ");
1117         if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
1118                 printf("FAILED, returned false\n");
1119                 return false;
1120         }
1121         printf("OK\n");
1122
1123         printf("testing set_metadata_ignore_application(of app block #1)... ");
1124         if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
1125                 printf("FAILED, returned false\n");
1126                 return false;
1127         }
1128         printf("OK\n");
1129
1130         num_expected_ = 0;
1131         expected_metadata_sequence_[num_expected_++] = &application2_;
1132
1133         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1134                 return false;
1135
1136         if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
1137                 ::fclose(dynamic_cast<StreamDecoder*>(decoder)->file_);
1138
1139         printf("freeing decoder instance... ");
1140         delete decoder;
1141         printf("OK\n");
1142
1143         printf("\nPASSED!\n");
1144
1145         return true;
1146 }
1147
1148 bool test_decoders()
1149 {
1150         FLAC__bool is_ogg = false;
1151
1152         while(1) {
1153                 init_metadata_blocks_();
1154
1155                 if(!generate_file_(is_ogg))
1156                         return false;
1157
1158                 if(!test_stream_decoder(LAYER_STREAM, is_ogg))
1159                         return false;
1160
1161                 if(!test_stream_decoder(LAYER_SEEKABLE_STREAM, is_ogg))
1162                         return false;
1163
1164                 if(!test_stream_decoder(LAYER_FILE, is_ogg))
1165                         return false;
1166
1167                 if(!test_stream_decoder(LAYER_FILENAME, is_ogg))
1168                         return false;
1169
1170                 (void) grabbag__file_remove_file(flacfilename(is_ogg));
1171
1172                 free_metadata_blocks_();
1173
1174                 if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
1175                         break;
1176                 is_ogg = true;
1177         }
1178
1179         return true;
1180 }