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