1
/* test_libOggFLAC++ - Unit tester for libOggFLAC++
2
* Copyright (C) 2002,2003 Josh Coalson
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.
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.
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.
21
#include "file_utils.h"
22
#include "metadata_utils.h"
24
#include "FLAC/assert.h"
25
#include "FLAC/metadata.h" // for ::FLAC__metadata_object_is_equal()
26
#include "OggFLAC++/decoder.h"
27
#include "share/grabbag.h"
33
static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
34
static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
35
static unsigned num_expected_;
36
static const char *oggflacfilename_ = "metadata.ogg";
37
static unsigned oggflacfilesize_;
39
static bool die_(const char *msg)
41
printf("ERROR: %s\n", msg);
45
static void init_metadata_blocks_()
47
mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
50
static void free_metadata_blocks_()
52
mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
55
static bool generate_file_()
57
printf("\n\ngenerating Ogg FLAC file for decoder tests...\n");
60
expected_metadata_sequence_[num_expected_++] = &padding_;
61
expected_metadata_sequence_[num_expected_++] = &seektable_;
62
expected_metadata_sequence_[num_expected_++] = &application1_;
63
expected_metadata_sequence_[num_expected_++] = &application2_;
64
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
65
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
66
expected_metadata_sequence_[num_expected_++] = &unknown_;
68
if(!file_utils__generate_oggflacfile(oggflacfilename_, &oggflacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
69
return die_("creating the encoded file");
78
unsigned current_metadata_number_;
82
DecoderCommon(): file_(0), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
83
::FLAC__StreamDecoderReadStatus common_read_callback_(FLAC__byte buffer[], unsigned *bytes);
84
::FLAC__StreamDecoderWriteStatus common_write_callback_(const ::FLAC__Frame *frame);
85
void common_metadata_callback_(const ::FLAC__StreamMetadata *metadata);
86
void common_error_callback_(::FLAC__StreamDecoderErrorStatus status);
89
::FLAC__StreamDecoderReadStatus DecoderCommon::common_read_callback_(FLAC__byte buffer[], unsigned *bytes)
92
return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
95
return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
97
unsigned bytes_read = ::fread(buffer, 1, *bytes, file_);
100
return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
102
return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
106
return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
110
return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
113
::FLAC__StreamDecoderWriteStatus DecoderCommon::common_write_callback_(const ::FLAC__Frame *frame)
116
return ::FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
119
(frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
120
(frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
122
printf("content... ");
126
return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
129
void DecoderCommon::common_metadata_callback_(const ::FLAC__StreamMetadata *metadata)
134
printf("%d... ", current_metadata_number_);
137
if(current_metadata_number_ >= num_expected_) {
138
(void)die_("got more metadata blocks than expected");
139
error_occurred_ = true;
142
if(!::FLAC__metadata_object_is_equal(expected_metadata_sequence_[current_metadata_number_], metadata)) {
143
(void)die_("metadata block mismatch");
144
error_occurred_ = true;
147
current_metadata_number_++;
150
void DecoderCommon::common_error_callback_(::FLAC__StreamDecoderErrorStatus status)
152
if(!ignore_errors_) {
153
printf("ERROR: got error callback: err = %u (%s)\n", (unsigned)status, ::FLAC__StreamDecoderErrorStatusString[status]);
154
error_occurred_ = true;
158
class StreamDecoder : public OggFLAC::Decoder::Stream, public DecoderCommon {
160
StreamDecoder(): OggFLAC::Decoder::Stream(), DecoderCommon() { }
163
// from OggFLAC::Decoder::Stream
164
::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
165
::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
166
void metadata_callback(const ::FLAC__StreamMetadata *metadata);
167
void error_callback(::FLAC__StreamDecoderErrorStatus status);
169
bool die(const char *msg = 0) const;
174
::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
176
return common_read_callback_(buffer, bytes);
179
::FLAC__StreamDecoderWriteStatus StreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
183
return common_write_callback_(frame);
186
void StreamDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
188
common_metadata_callback_(metadata);
191
void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
193
common_error_callback_(status);
196
bool StreamDecoder::die(const char *msg) const
198
State state = get_state();
201
printf("FAILED, %s", msg);
205
printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state), state.as_cstring());
210
bool StreamDecoder::test_respond()
212
printf("testing init()... ");
213
if(init() != ::OggFLAC__STREAM_DECODER_OK)
217
current_metadata_number_ = 0;
219
if(::fseek(file_, 0, SEEK_SET) < 0) {
220
printf("FAILED rewinding input, errno = %d\n", errno);
224
printf("testing process_until_end_of_stream()... ");
225
if(!process_until_end_of_stream()) {
226
State state = get_state();
227
printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state), state.as_cstring());
232
printf("testing finish()... ");
239
static bool test_stream_decoder()
241
StreamDecoder *decoder;
243
printf("\n+++ libOggFLAC++ unit test: OggFLAC::Decoder::Stream\n\n");
246
// test new -> delete
248
printf("allocating decoder instance... ");
249
decoder = new StreamDecoder();
251
printf("FAILED, new returned NULL\n");
256
printf("testing is_valid()... ");
257
if(!decoder->is_valid()) {
258
printf("FAILED, returned false\n");
263
printf("freeing decoder instance... ");
268
// test new -> init -> delete
270
printf("allocating decoder instance... ");
271
decoder = new StreamDecoder();
273
printf("FAILED, new returned NULL\n");
278
printf("testing is_valid()... ");
279
if(!decoder->is_valid()) {
280
printf("FAILED, returned false\n");
285
printf("testing init()... ");
286
if(decoder->init() != ::OggFLAC__STREAM_DECODER_OK)
287
return decoder->die();
290
printf("freeing decoder instance... ");
298
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
300
printf("allocating decoder instance... ");
301
decoder = new StreamDecoder();
303
printf("FAILED, new returned NULL\n");
308
printf("testing is_valid()... ");
309
if(!decoder->is_valid()) {
310
printf("FAILED, returned false\n");
315
printf("testing set_serial_number()... ");
316
if(!decoder->set_serial_number(file_utils__serial_number))
317
return decoder->die("returned false");
320
printf("testing init()... ");
321
if(decoder->init() != ::OggFLAC__STREAM_DECODER_OK)
322
return decoder->die();
325
printf("testing get_state()... ");
326
OggFLAC::Decoder::Stream::State state = decoder->get_state();
327
printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamDecoderState)state), state.as_cstring());
329
printf("testing get_FLAC_stream_decoder_state()... ");
330
FLAC::Decoder::Stream::State state_ = decoder->get_FLAC_stream_decoder_state();
331
printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state_), state_.as_cstring());
333
decoder->current_metadata_number_ = 0;
334
decoder->ignore_errors_ = false;
335
decoder->error_occurred_ = false;
337
printf("opening Ogg FLAC file... ");
338
decoder->file_ = ::fopen(oggflacfilename_, "rb");
339
if(0 == decoder->file_) {
345
printf("testing process_until_end_of_metadata()... ");
346
if(!decoder->process_until_end_of_metadata())
347
return decoder->die("returned false");
350
printf("testing process_single()... ");
351
if(!decoder->process_single())
352
return decoder->die("returned false");
355
printf("testing flush()... ");
356
if(!decoder->flush())
357
return decoder->die("returned false");
360
decoder->ignore_errors_ = true;
361
printf("testing process_single()... ");
362
if(!decoder->process_single())
363
return decoder->die("returned false");
365
decoder->ignore_errors_ = false;
367
printf("testing process_until_end_of_stream()... ");
368
if(!decoder->process_until_end_of_stream())
369
return decoder->die("returned false");
372
printf("testing get_channels()... ");
374
unsigned channels = decoder->get_channels();
375
if(channels != streaminfo_.data.stream_info.channels) {
376
printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
382
printf("testing get_bits_per_sample()... ");
384
unsigned bits_per_sample = decoder->get_bits_per_sample();
385
if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
386
printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
392
printf("testing get_sample_rate()... ");
394
unsigned sample_rate = decoder->get_sample_rate();
395
if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
396
printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
402
printf("testing get_blocksize()... ");
404
unsigned blocksize = decoder->get_blocksize();
405
/* value could be anything since we're at the last block, so accept any answer */
406
printf("returned %u... OK\n", blocksize);
409
printf("testing get_channel_assignment()... ");
411
::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
412
printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
415
printf("testing reset()... ");
416
if(!decoder->reset())
417
return decoder->die("returned false");
420
decoder->current_metadata_number_ = 0;
422
printf("rewinding input... ");
423
if(::fseek(decoder->file_, 0, SEEK_SET) < 0) {
424
printf("FAILED, errno = %d\n", errno);
429
printf("testing process_until_end_of_stream()... ");
430
if(!decoder->process_until_end_of_stream())
431
return decoder->die("returned false");
434
printf("testing finish()... ");
442
printf("testing set_metadata_respond_all()... ");
443
if(!decoder->set_metadata_respond_all()) {
444
printf("FAILED, returned false\n");
450
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
451
expected_metadata_sequence_[num_expected_++] = &padding_;
452
expected_metadata_sequence_[num_expected_++] = &seektable_;
453
expected_metadata_sequence_[num_expected_++] = &application1_;
454
expected_metadata_sequence_[num_expected_++] = &application2_;
455
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
456
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
457
expected_metadata_sequence_[num_expected_++] = &unknown_;
459
if(!decoder->test_respond())
466
printf("testing set_metadata_ignore_all()... ");
467
if(!decoder->set_metadata_ignore_all()) {
468
printf("FAILED, returned false\n");
475
if(!decoder->test_respond())
479
* respond all, ignore VORBIS_COMMENT
482
printf("testing set_metadata_respond_all()... ");
483
if(!decoder->set_metadata_respond_all()) {
484
printf("FAILED, returned false\n");
489
printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
490
if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
491
printf("FAILED, returned false\n");
497
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
498
expected_metadata_sequence_[num_expected_++] = &padding_;
499
expected_metadata_sequence_[num_expected_++] = &seektable_;
500
expected_metadata_sequence_[num_expected_++] = &application1_;
501
expected_metadata_sequence_[num_expected_++] = &application2_;
502
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
503
expected_metadata_sequence_[num_expected_++] = &unknown_;
505
if(!decoder->test_respond())
509
* respond all, ignore APPLICATION
512
printf("testing set_metadata_respond_all()... ");
513
if(!decoder->set_metadata_respond_all()) {
514
printf("FAILED, returned false\n");
519
printf("testing set_metadata_ignore(APPLICATION)... ");
520
if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
521
printf("FAILED, returned false\n");
527
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
528
expected_metadata_sequence_[num_expected_++] = &padding_;
529
expected_metadata_sequence_[num_expected_++] = &seektable_;
530
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
531
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
532
expected_metadata_sequence_[num_expected_++] = &unknown_;
534
if(!decoder->test_respond())
538
* respond all, ignore APPLICATION id of app#1
541
printf("testing set_metadata_respond_all()... ");
542
if(!decoder->set_metadata_respond_all()) {
543
printf("FAILED, returned false\n");
548
printf("testing set_metadata_ignore_application(of app block #1)... ");
549
if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
550
printf("FAILED, returned false\n");
556
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
557
expected_metadata_sequence_[num_expected_++] = &padding_;
558
expected_metadata_sequence_[num_expected_++] = &seektable_;
559
expected_metadata_sequence_[num_expected_++] = &application2_;
560
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
561
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
562
expected_metadata_sequence_[num_expected_++] = &unknown_;
564
if(!decoder->test_respond())
568
* respond all, ignore APPLICATION id of app#1 & app#2
571
printf("testing set_metadata_respond_all()... ");
572
if(!decoder->set_metadata_respond_all()) {
573
printf("FAILED, returned false\n");
578
printf("testing set_metadata_ignore_application(of app block #1)... ");
579
if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
580
printf("FAILED, returned false\n");
585
printf("testing set_metadata_ignore_application(of app block #2)... ");
586
if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
587
printf("FAILED, returned false\n");
593
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
594
expected_metadata_sequence_[num_expected_++] = &padding_;
595
expected_metadata_sequence_[num_expected_++] = &seektable_;
596
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
597
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
598
expected_metadata_sequence_[num_expected_++] = &unknown_;
600
if(!decoder->test_respond())
604
* ignore all, respond VORBIS_COMMENT
607
printf("testing set_metadata_ignore_all()... ");
608
if(!decoder->set_metadata_ignore_all()) {
609
printf("FAILED, returned false\n");
614
printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
615
if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
616
printf("FAILED, returned false\n");
622
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
624
if(!decoder->test_respond())
628
* ignore all, respond APPLICATION
631
printf("testing set_metadata_ignore_all()... ");
632
if(!decoder->set_metadata_ignore_all()) {
633
printf("FAILED, returned false\n");
638
printf("testing set_metadata_respond(APPLICATION)... ");
639
if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
640
printf("FAILED, returned false\n");
646
expected_metadata_sequence_[num_expected_++] = &application1_;
647
expected_metadata_sequence_[num_expected_++] = &application2_;
649
if(!decoder->test_respond())
653
* ignore all, respond APPLICATION id of app#1
656
printf("testing set_metadata_ignore_all()... ");
657
if(!decoder->set_metadata_ignore_all()) {
658
printf("FAILED, returned false\n");
663
printf("testing set_metadata_respond_application(of app block #1)... ");
664
if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
665
printf("FAILED, returned false\n");
671
expected_metadata_sequence_[num_expected_++] = &application1_;
673
if(!decoder->test_respond())
677
* ignore all, respond APPLICATION id of app#1 & app#2
680
printf("testing set_metadata_ignore_all()... ");
681
if(!decoder->set_metadata_ignore_all()) {
682
printf("FAILED, returned false\n");
687
printf("testing set_metadata_respond_application(of app block #1)... ");
688
if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
689
printf("FAILED, returned false\n");
694
printf("testing set_metadata_respond_application(of app block #2)... ");
695
if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
696
printf("FAILED, returned false\n");
702
expected_metadata_sequence_[num_expected_++] = &application1_;
703
expected_metadata_sequence_[num_expected_++] = &application2_;
705
if(!decoder->test_respond())
709
* respond all, ignore APPLICATION, respond APPLICATION id of app#1
712
printf("testing set_metadata_respond_all()... ");
713
if(!decoder->set_metadata_respond_all()) {
714
printf("FAILED, returned false\n");
719
printf("testing set_metadata_ignore(APPLICATION)... ");
720
if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
721
printf("FAILED, returned false\n");
726
printf("testing set_metadata_respond_application(of app block #1)... ");
727
if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
728
printf("FAILED, returned false\n");
734
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
735
expected_metadata_sequence_[num_expected_++] = &padding_;
736
expected_metadata_sequence_[num_expected_++] = &seektable_;
737
expected_metadata_sequence_[num_expected_++] = &application1_;
738
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
739
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
740
expected_metadata_sequence_[num_expected_++] = &unknown_;
742
if(!decoder->test_respond())
746
* ignore all, respond APPLICATION, ignore APPLICATION id of app#1
749
printf("testing set_metadata_ignore_all()... ");
750
if(!decoder->set_metadata_ignore_all()) {
751
printf("FAILED, returned false\n");
756
printf("testing set_metadata_respond(APPLICATION)... ");
757
if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
758
printf("FAILED, returned false\n");
763
printf("testing set_metadata_ignore_application(of app block #1)... ");
764
if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
765
printf("FAILED, returned false\n");
771
expected_metadata_sequence_[num_expected_++] = &application2_;
773
if(!decoder->test_respond())
776
/* done, now leave the sequence the way we found it... */
778
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
779
expected_metadata_sequence_[num_expected_++] = &padding_;
780
expected_metadata_sequence_[num_expected_++] = &seektable_;
781
expected_metadata_sequence_[num_expected_++] = &application1_;
782
expected_metadata_sequence_[num_expected_++] = &application2_;
783
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
784
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
785
expected_metadata_sequence_[num_expected_++] = &unknown_;
787
::fclose(decoder->file_);
789
printf("freeing decoder instance... ");
793
printf("\nPASSED!\n");
800
init_metadata_blocks_();
801
if(!generate_file_())
804
if(!test_stream_decoder())
807
(void) grabbag__file_remove_file(oggflacfilename_);
808
free_metadata_blocks_();