Fix for autoreconf failures.
[flac.git] / src / test_libFLAC++ / decoders.cpp
index f9d2b52..f7f5a42 100644 (file)
@@ -1,5 +1,5 @@
 /* test_libFLAC++ - Unit tester for libFLAC++
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
+ * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009  Josh Coalson
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#if defined _MSC_VER || defined __MINGW32__
-#if _MSC_VER <= 1200 /* @@@ [2G limit] */
-#define fseeko fseek
-#define ftello ftell
-#endif
-#endif
 #include "decoders.h"
 #include "FLAC/assert.h"
 #include "FLAC/metadata.h" // for ::FLAC__metadata_object_is_equal()
 #include "FLAC++/decoder.h"
 #include "share/grabbag.h"
+#include "share/compat.h"
 extern "C" {
 #include "test_libs_common/file_utils_flac.h"
 #include "test_libs_common/metadata_utils.h"
@@ -62,9 +57,13 @@ static const char * const LayerString[] = {
 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
 static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
 static unsigned num_expected_;
-static const char *flacfilename_ = "metadata.flac";
 static off_t flacfilesize_;
 
+static const char *flacfilename(bool is_ogg)
+{
+       return is_ogg? "metadata.oga" : "metadata.flac";
+}
+
 static bool die_(const char *msg)
 {
        printf("ERROR: %s\n", msg);
@@ -95,9 +94,9 @@ static void free_metadata_blocks_()
        mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
-static bool generate_file_()
+static bool generate_file_(FLAC__bool is_ogg)
 {
-       printf("\n\ngenerating FLAC file for decoder tests...\n");
+       printf("\n\ngenerating %sFLAC file for decoder tests...\n", is_ogg? "Ogg ":"");
 
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &padding_;
@@ -108,8 +107,9 @@ static bool generate_file_()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &picture_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
+       /* WATCHOUT: for Ogg FLAC the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
 
-       if(!file_utils__generate_flacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
+       if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
                return die_("creating the encoded file");
 
        return true;
@@ -182,7 +182,7 @@ public:
        ~StreamDecoder() { }
 
        // from FLAC::Decoder::Stream
-       ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
+       ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
        ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
        ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
        ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
@@ -191,12 +191,12 @@ public:
        void metadata_callback(const ::FLAC__StreamMetadata *metadata);
        void error_callback(::FLAC__StreamDecoderErrorStatus status);
 
-       bool test_respond();
+       bool test_respond(bool is_ogg);
 };
 
-::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
+::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], size_t *bytes)
 {
-       const unsigned requested_bytes = *bytes;
+       const size_t requested_bytes = *bytes;
 
        if(error_occurred_)
                return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
@@ -296,15 +296,18 @@ void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
        common_error_callback_(status);
 }
 
-bool StreamDecoder::test_respond()
+bool StreamDecoder::test_respond(bool is_ogg)
 {
+       ::FLAC__StreamDecoderInitStatus init_status;
+
        if(!set_md5_checking(true)) {
                printf("FAILED at set_md5_checking(), returned false\n");
                return false;
        }
 
-       printf("testing init()... ");
-       if(init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+       printf("testing init%s()... ", is_ogg? "_ogg":"");
+       init_status = is_ogg? init_ogg() : init();
+       if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
                return die_s_(0, this);
        printf("OK\n");
 
@@ -324,7 +327,11 @@ bool StreamDecoder::test_respond()
        printf("OK\n");
 
        printf("testing finish()... ");
-       finish();
+       if(!finish()) {
+               State state = get_state();
+               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
+               return false;
+       }
        printf("OK\n");
 
        return true;
@@ -340,7 +347,7 @@ public:
        void metadata_callback(const ::FLAC__StreamMetadata *metadata);
        void error_callback(::FLAC__StreamDecoderErrorStatus status);
 
-       bool test_respond();
+       bool test_respond(bool is_ogg);
 };
 
 ::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
@@ -359,8 +366,10 @@ void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
        common_error_callback_(status);
 }
 
-bool FileDecoder::test_respond()
+bool FileDecoder::test_respond(bool is_ogg)
 {
+       ::FLAC__StreamDecoderInitStatus init_status;
+
        if(!set_md5_checking(true)) {
                printf("FAILED at set_md5_checking(), returned false\n");
                return false;
@@ -369,28 +378,28 @@ bool FileDecoder::test_respond()
        switch(layer_) {
                case LAYER_FILE:
                        {
-                               printf("opening FLAC file... ");
-                               FILE *file = ::fopen(flacfilename_, "rb");
+                               printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
+                               FILE *file = ::fopen(flacfilename(is_ogg), "rb");
                                if(0 == file) {
                                        printf("ERROR (%s)\n", strerror(errno));
                                        return false;
                                }
                                printf("OK\n");
 
-                               printf("testing init()... ");
-                               if(init(file) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                                       return die_s_(0, this);
+                               printf("testing init%s()... ", is_ogg? "_ogg":"");
+                               init_status = is_ogg? init_ogg(file) : init(file);
                        }
                        break;
                case LAYER_FILENAME:
-                       printf("testing init()... ");
-                       if(init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                               return die_s_(0, this);
+                       printf("testing init%s()... ", is_ogg? "_ogg":"");
+                       init_status = is_ogg? init_ogg(flacfilename(is_ogg)) : init(flacfilename(is_ogg));
                        break;
                default:
                        die_("internal error 001");
                        return false;
        }
+       if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_s_(0, this);
        printf("OK\n");
 
        current_metadata_number_ = 0;
@@ -404,7 +413,11 @@ bool FileDecoder::test_respond()
        printf("OK\n");
 
        printf("testing finish()... ");
-       finish();
+       if(!finish()) {
+               State state = get_state();
+               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
+               return false;
+       }
        printf("OK\n");
 
        return true;
@@ -419,12 +432,13 @@ static FLAC::Decoder::Stream *new_by_layer(Layer layer)
                return new FileDecoder(layer);
 }
 
-static bool test_stream_decoder(Layer layer)
+static bool test_stream_decoder(Layer layer, bool is_ogg)
 {
        FLAC::Decoder::Stream *decoder;
+       ::FLAC__StreamDecoderInitStatus init_status;
        bool expect;
 
-       printf("\n+++ libFLAC++ unit test: FLAC::Decoder::%s (layer: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer]);
+       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");
 
        //
        // test new -> delete
@@ -466,26 +480,29 @@ static bool test_stream_decoder(Layer layer)
        }
        printf("OK\n");
 
-       printf("testing init()... ");
+       printf("testing init%s()... ", is_ogg? "_ogg":"");
        switch(layer) {
                case LAYER_STREAM:
                case LAYER_SEEKABLE_STREAM:
                        dynamic_cast<StreamDecoder*>(decoder)->file_ = stdin;
-                       if(decoder->init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                               return die_s_(0, decoder);
+                       init_status = is_ogg? decoder->init_ogg() : decoder->init();
                        break;
                case LAYER_FILE:
-                       if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(stdin) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                               return die_s_(0, decoder);
+                       init_status = is_ogg?
+                               dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(stdin) :
+                               dynamic_cast<FLAC::Decoder::File*>(decoder)->init(stdin);
                        break;
                case LAYER_FILENAME:
-                       if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                               return die_s_(0, decoder);
+                       init_status = is_ogg?
+                               dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
+                               dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
                        break;
                default:
                        die_("internal error 006");
                        return false;
        }
+       if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_s_(0, decoder);
        printf("OK\n");
 
        printf("freeing decoder instance... ");
@@ -513,6 +530,13 @@ static bool test_stream_decoder(Layer layer)
        }
        printf("OK\n");
 
+       if(is_ogg) {
+               printf("testing set_ogg_serial_number()... ");
+               if(!decoder->set_ogg_serial_number(file_utils__ogg_serial_number))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+       }
+
        if(!decoder->set_md5_checking(true)) {
                printf("FAILED at set_md5_checking(), returned false\n");
                return false;
@@ -521,42 +545,45 @@ static bool test_stream_decoder(Layer layer)
        switch(layer) {
                case LAYER_STREAM:
                case LAYER_SEEKABLE_STREAM:
-                       printf("opening FLAC file... ");
-                       dynamic_cast<StreamDecoder*>(decoder)->file_ = ::fopen(flacfilename_, "rb");
+                       printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
+                       dynamic_cast<StreamDecoder*>(decoder)->file_ = ::fopen(flacfilename(is_ogg), "rb");
                        if(0 == dynamic_cast<StreamDecoder*>(decoder)->file_) {
                                printf("ERROR (%s)\n", strerror(errno));
                                return false;
                        }
                        printf("OK\n");
 
-                       printf("testing init()... ");
-                       if(decoder->init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                               return die_s_(0, decoder);
+                       printf("testing init%s()... ", is_ogg? "_ogg":"");
+                       init_status = is_ogg? decoder->init_ogg() : decoder->init();
                        break;
                case LAYER_FILE:
                        {
                                printf("opening FLAC file... ");
-                               FILE *file = ::fopen(flacfilename_, "rb");
+                               FILE *file = ::fopen(flacfilename(is_ogg), "rb");
                                if(0 == file) {
                                        printf("ERROR (%s)\n", strerror(errno));
                                        return false;
                                }
                                printf("OK\n");
 
-                               printf("testing init()... ");
-                               if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(file) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                                       return die_s_(0, decoder);
+                               printf("testing init%s()... ", is_ogg? "_ogg":"");
+                               init_status = is_ogg?
+                                       dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(file) :
+                                       dynamic_cast<FLAC::Decoder::File*>(decoder)->init(file);
                        }
                        break;
                case LAYER_FILENAME:
-                       printf("testing init()... ");
-                       if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
-                               return die_s_(0, decoder);
+                       printf("testing init%s()... ", is_ogg? "_ogg":"");
+                       init_status = is_ogg?
+                               dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
+                               dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
                        break;
                default:
                        die_("internal error 009");
                        return false;
        }
+       if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_s_(0, decoder);
        printf("OK\n");
 
        printf("testing get_state()... ");
@@ -690,7 +717,11 @@ static bool test_stream_decoder(Layer layer)
        }
 
        printf("testing finish()... ");
-       decoder->finish();
+       if(!decoder->finish()) {
+               FLAC::Decoder::Stream::State state = decoder->get_state();
+               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
+               return false;
+       }
        printf("OK\n");
 
        /*
@@ -705,17 +736,30 @@ static bool test_stream_decoder(Layer layer)
        printf("OK\n");
 
        num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &picture_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &application1_;
+               expected_metadata_sequence_[num_expected_++] = &application2_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
+       else {
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &application1_;
+               expected_metadata_sequence_[num_expected_++] = &application2_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -731,7 +775,7 @@ static bool test_stream_decoder(Layer layer)
 
        num_expected_ = 0;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -762,7 +806,7 @@ static bool test_stream_decoder(Layer layer)
        expected_metadata_sequence_[num_expected_++] = &picture_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -784,15 +828,26 @@ static bool test_stream_decoder(Layer layer)
        printf("OK\n");
 
        num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &picture_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
+       else {
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -814,16 +869,28 @@ static bool test_stream_decoder(Layer layer)
        printf("OK\n");
 
        num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &picture_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &application2_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
+       else {
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &application2_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -852,15 +919,26 @@ static bool test_stream_decoder(Layer layer)
        printf("OK\n");
 
        num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &picture_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
+       else {
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -884,7 +962,7 @@ static bool test_stream_decoder(Layer layer)
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -909,7 +987,7 @@ static bool test_stream_decoder(Layer layer)
        expected_metadata_sequence_[num_expected_++] = &application1_;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -933,7 +1011,7 @@ static bool test_stream_decoder(Layer layer)
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &application1_;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -965,7 +1043,7 @@ static bool test_stream_decoder(Layer layer)
        expected_metadata_sequence_[num_expected_++] = &application1_;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -994,16 +1072,28 @@ static bool test_stream_decoder(Layer layer)
        printf("OK\n");
 
        num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &picture_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &application1_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
+       else {
+               expected_metadata_sequence_[num_expected_++] = &streaminfo_;
+               expected_metadata_sequence_[num_expected_++] = &padding_;
+               expected_metadata_sequence_[num_expected_++] = &seektable_;
+               expected_metadata_sequence_[num_expected_++] = &application1_;
+               expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
+               expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+               expected_metadata_sequence_[num_expected_++] = &picture_;
+               expected_metadata_sequence_[num_expected_++] = &unknown_;
+       }
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        /*
@@ -1034,7 +1124,7 @@ static bool test_stream_decoder(Layer layer)
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
                return false;
 
        if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
@@ -1051,26 +1141,34 @@ static bool test_stream_decoder(Layer layer)
 
 bool test_decoders()
 {
-       init_metadata_blocks_();
+       FLAC__bool is_ogg = false;
 
-       if(!generate_file_())
-               return false;
+       while(1) {
+               init_metadata_blocks_();
 
-       if(!test_stream_decoder(LAYER_STREAM))
-               return false;
+               if(!generate_file_(is_ogg))
+                       return false;
 
-       if(!test_stream_decoder(LAYER_SEEKABLE_STREAM))
-               return false;
+               if(!test_stream_decoder(LAYER_STREAM, is_ogg))
+                       return false;
 
-       if(!test_stream_decoder(LAYER_FILE))
-               return false;
+               if(!test_stream_decoder(LAYER_SEEKABLE_STREAM, is_ogg))
+                       return false;
 
-       if(!test_stream_decoder(LAYER_FILENAME))
-               return false;
+               if(!test_stream_decoder(LAYER_FILE, is_ogg))
+                       return false;
 
-       (void) grabbag__file_remove_file(flacfilename_);
+               if(!test_stream_decoder(LAYER_FILENAME, is_ogg))
+                       return false;
+
+               (void) grabbag__file_remove_file(flacfilename(is_ogg));
+
+               free_metadata_blocks_();
 
-       free_metadata_blocks_();
+               if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
+                       break;
+               is_ogg = true;
+       }
 
        return true;
 }