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