1 /* test_libFLAC++ - Unit tester for libFLAC++
2 * Copyright (C) 2002,2003,2004 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.
20 #include "file_utils.h"
22 #include "FLAC/assert.h"
23 #include "FLAC++/decoder.h"
24 #include "FLAC++/metadata.h"
25 #include "share/grabbag.h"
27 #include <stdlib.h> /* for malloc() */
28 #include <string.h> /* for memcpy()/memset() */
30 #if defined _MSC_VER || defined __MINGW32__
31 #include <sys/utime.h> /* for utime() */
32 #include <io.h> /* for chmod() */
34 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
35 #include <utime.h> /* for utime() */
36 #include <unistd.h> /* for chown(), unlink() */
38 #include <sys/stat.h> /* for stat(), maybe chmod() */
40 /******************************************************************************
41 The general strategy of these tests (for interface levels 1 and 2) is
42 to create a dummy FLAC file with a known set of initial metadata
43 blocks, then keep a mirror locally of what we expect the metadata to be
44 after each operation. Then testing becomes a simple matter of running
45 a FLAC::Decoder::File over the dummy file after each operation, comparing
46 the decoded metadata to what's in our local copy. If there are any
47 differences in the metadata, or the actual audio data is corrupted, we
48 will catch it while decoding.
49 ******************************************************************************/
51 class OurFileDecoder: public FLAC::Decoder::File {
53 inline OurFileDecoder(bool ignore_metadata): ignore_metadata_(ignore_metadata), error_occurred_(false) { }
55 bool ignore_metadata_;
58 ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
59 void metadata_callback(const ::FLAC__StreamMetadata *metadata);
60 void error_callback(::FLAC__StreamDecoderErrorStatus status);
64 FLAC::Metadata::Prototype *blocks[64];
68 static const char *flacfile_ = "metadata.flac";
70 /* our copy of the metadata in flacfile_ */
71 static OurMetadata our_metadata_;
73 /* the current block number that corresponds to the position of the iterator we are testing */
74 static unsigned mc_our_block_number_ = 0;
76 static bool die_(const char *msg)
78 printf("ERROR: %s\n", msg);
82 static bool die_c_(const char *msg, FLAC::Metadata::Chain::Status status)
84 printf("ERROR: %s\n", msg);
85 printf(" status=%u (%s)\n", (unsigned)((::FLAC__Metadata_ChainStatus)status), status.as_cstring());
89 static bool die_ss_(const char *msg, FLAC::Metadata::SimpleIterator &iterator)
91 const FLAC::Metadata::SimpleIterator::Status status = iterator.status();
92 printf("ERROR: %s\n", msg);
93 printf(" status=%u (%s)\n", (unsigned)((::FLAC__Metadata_SimpleIteratorStatus)status), status.as_cstring());
97 static void *malloc_or_die_(size_t size)
99 void *x = malloc(size);
101 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
107 /* functions for working with our metadata copy */
109 static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
112 FLAC::Metadata::Prototype *obj = block;
113 FLAC__ASSERT(position < our_metadata_.num_blocks);
115 if(0 == (obj = FLAC::Metadata::clone(block)))
116 return die_("during FLAC::Metadata::clone()");
118 delete our_metadata_.blocks[position];
119 our_metadata_.blocks[position] = obj;
121 /* set the is_last flags */
122 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
123 our_metadata_.blocks[i]->set_is_last(false);
124 our_metadata_.blocks[i]->set_is_last(true);
129 static bool insert_to_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
132 FLAC::Metadata::Prototype *obj = block;
134 if(0 == (obj = FLAC::Metadata::clone(block)))
135 return die_("during FLAC::Metadata::clone()");
137 if(position > our_metadata_.num_blocks) {
138 position = our_metadata_.num_blocks;
141 for(i = our_metadata_.num_blocks; i > position; i--)
142 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
144 our_metadata_.blocks[position] = obj;
145 our_metadata_.num_blocks++;
147 /* set the is_last flags */
148 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
149 our_metadata_.blocks[i]->set_is_last(false);
150 our_metadata_.blocks[i]->set_is_last(true);
155 static void delete_from_our_metadata_(unsigned position)
158 FLAC__ASSERT(position < our_metadata_.num_blocks);
159 delete our_metadata_.blocks[position];
160 for(i = position; i < our_metadata_.num_blocks - 1; i++)
161 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
162 our_metadata_.num_blocks--;
164 /* set the is_last flags */
165 if(our_metadata_.num_blocks > 0) {
166 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
167 our_metadata_.blocks[i]->set_is_last(false);
168 our_metadata_.blocks[i]->set_is_last(true);
172 void add_to_padding_length_(unsigned index, int delta)
174 FLAC::Metadata::Padding *padding = dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[index]);
175 FLAC__ASSERT(0 != padding);
176 padding->set_length((unsigned)((int)padding->get_length() + delta));
180 * This wad of functions supports filename- and callback-based chain reading/writing.
181 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
183 bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
185 static const char *tempfile_suffix = ".metadata_edit";
187 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
189 strcpy(*tempfilename, filename);
190 strcat(*tempfilename, tempfile_suffix);
192 if(0 == (*tempfile = fopen(*tempfilename, "w+b")))
198 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
201 (void)fclose(*tempfile);
205 if(0 != *tempfilename) {
206 (void)unlink(*tempfilename);
212 bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
214 FLAC__ASSERT(0 != filename);
215 FLAC__ASSERT(0 != tempfile);
216 FLAC__ASSERT(0 != tempfilename);
217 FLAC__ASSERT(0 != *tempfilename);
220 (void)fclose(*tempfile);
224 #if defined _MSC_VER || defined __MINGW32__
225 if(unlink(filename) < 0) {
226 cleanup_tempfile_(tempfile, tempfilename);
231 if(0 != rename(*tempfilename, filename)) {
232 cleanup_tempfile_(tempfile, tempfilename);
236 cleanup_tempfile_(tempfile, tempfilename);
241 bool get_file_stats_(const char *filename, struct stat *stats)
243 FLAC__ASSERT(0 != filename);
244 FLAC__ASSERT(0 != stats);
245 return (0 == stat(filename, stats));
248 void set_file_stats_(const char *filename, struct stat *stats)
250 struct utimbuf srctime;
252 FLAC__ASSERT(0 != filename);
253 FLAC__ASSERT(0 != stats);
255 srctime.actime = stats->st_atime;
256 srctime.modtime = stats->st_mtime;
257 (void)chmod(filename, stats->st_mode);
258 (void)utime(filename, &srctime);
259 #if !defined _MSC_VER && !defined __MINGW32__
260 (void)chown(filename, stats->st_uid, (gid_t)(-1));
261 (void)chown(filename, (uid_t)(-1), stats->st_gid);
265 #ifdef FLAC__VALGRIND_TESTING
266 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, ::FLAC__IOHandle handle)
268 FILE *stream = (FILE*)handle;
269 size_t ret = fwrite(ptr, size, nmemb, stream);
276 static int chain_seek_cb_(::FLAC__IOHandle handle, FLAC__int64 offset, int whence)
278 long o = (long)offset;
279 FLAC__ASSERT(offset == o);
280 return fseek((FILE*)handle, o, whence);
283 static FLAC__int64 chain_tell_cb_(::FLAC__IOHandle handle)
285 return ftell((FILE*)handle);
288 static int chain_eof_cb_(::FLAC__IOHandle handle)
290 return feof((FILE*)handle);
293 static bool write_chain_(FLAC::Metadata::Chain &chain, bool use_padding, bool preserve_file_stats, bool filename_based, const char *filename)
296 return chain.write(use_padding, preserve_file_stats);
298 ::FLAC__IOCallbacks callbacks;
300 memset(&callbacks, 0, sizeof(callbacks));
301 callbacks.read = (::FLAC__IOCallback_Read)fread;
302 #ifdef FLAC__VALGRIND_TESTING
303 callbacks.write = chain_write_cb_;
305 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
307 callbacks.seek = chain_seek_cb_;
308 callbacks.eof = chain_eof_cb_;
310 if(chain.check_if_tempfile_needed(use_padding)) {
312 FILE *file, *tempfile;
314 if(preserve_file_stats) {
315 if(!get_file_stats_(filename, &stats))
318 if(0 == (file = fopen(filename, "rb")))
319 return false; /*@@@ chain status still says OK though */
320 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
322 cleanup_tempfile_(&tempfile, &tempfilename);
323 return false; /*@@@ chain status still says OK though */
325 if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks, (::FLAC__IOHandle)tempfile, callbacks)) {
333 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
335 if(preserve_file_stats)
336 set_file_stats_(filename, &stats);
339 FILE *file = fopen(filename, "r+b");
341 return false; /*@@@ chain status still says OK though */
342 if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks))
351 static bool read_chain_(FLAC::Metadata::Chain &chain, const char *filename, bool filename_based)
354 return chain.read(filename);
356 ::FLAC__IOCallbacks callbacks;
358 memset(&callbacks, 0, sizeof(callbacks));
359 callbacks.read = (::FLAC__IOCallback_Read)fread;
360 callbacks.seek = chain_seek_cb_;
361 callbacks.tell = chain_tell_cb_;
365 FILE *file = fopen(filename, "rb");
367 return false; /*@@@ chain status still says OK though */
368 ret = chain.read((::FLAC__IOHandle)file, callbacks);
375 /* function for comparing our metadata to a FLAC::Metadata::Chain */
377 static bool compare_chain_(FLAC::Metadata::Chain &chain, unsigned current_position, FLAC::Metadata::Prototype *current_block)
380 FLAC::Metadata::Iterator iterator;
383 printf("\tcomparing chain... ");
386 if(!iterator.is_valid())
387 return die_("allocating memory for iterator");
389 iterator.init(chain);
393 FLAC::Metadata::Prototype *block;
398 if(0 == (block = iterator.get_block()))
399 return die_("getting block from iterator");
401 if(*block != *our_metadata_.blocks[i])
402 return die_("metadata block mismatch");
406 next_ok = iterator.next();
407 } while(i < our_metadata_.num_blocks && next_ok);
410 return die_("chain has more blocks than expected");
412 if(i < our_metadata_.num_blocks)
413 return die_("short block count in chain");
415 if(0 != current_block) {
416 printf("CURRENT_POSITION... ");
419 if(*current_block != *our_metadata_.blocks[current_position])
420 return die_("metadata block mismatch");
428 ::FLAC__StreamDecoderWriteStatus OurFileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
433 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
434 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
436 printf("content... ");
440 return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
443 void OurFileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
445 /* don't bother checking if we've already hit an error */
449 printf("%d... ", mc_our_block_number_);
452 if(!ignore_metadata_) {
453 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
454 (void)die_("got more metadata blocks than expected");
455 error_occurred_ = true;
458 if(*our_metadata_.blocks[mc_our_block_number_] != metadata) {
459 (void)die_("metadata block mismatch");
460 error_occurred_ = true;
465 mc_our_block_number_++;
468 void OurFileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
470 error_occurred_ = true;
471 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
474 static bool generate_file_()
476 ::FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
477 ::FLAC__StreamMetadata *metadata[1];
479 printf("generating FLAC file for test\n");
481 while(our_metadata_.num_blocks > 0)
482 delete_from_our_metadata_(0);
484 streaminfo.is_last = false;
485 streaminfo.type = ::FLAC__METADATA_TYPE_STREAMINFO;
486 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
487 streaminfo.data.stream_info.min_blocksize = 576;
488 streaminfo.data.stream_info.max_blocksize = 576;
489 streaminfo.data.stream_info.min_framesize = 0;
490 streaminfo.data.stream_info.max_framesize = 0;
491 streaminfo.data.stream_info.sample_rate = 44100;
492 streaminfo.data.stream_info.channels = 1;
493 streaminfo.data.stream_info.bits_per_sample = 8;
494 streaminfo.data.stream_info.total_samples = 0;
495 memset(streaminfo.data.stream_info.md5sum, 0, 16);
498 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
499 vorbiscomment.is_last = false;
500 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
501 vorbiscomment.length = (4 + vendor_string_length) + 4;
502 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
503 vorbiscomment.data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length);
504 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length);
505 vorbiscomment.data.vorbis_comment.num_comments = 0;
506 vorbiscomment.data.vorbis_comment.comments = 0;
509 padding.is_last = true;
510 padding.type = ::FLAC__METADATA_TYPE_PADDING;
511 padding.length = 1234;
513 metadata[0] = &padding;
515 FLAC::Metadata::StreamInfo s(&streaminfo);
516 FLAC::Metadata::VorbisComment v(&vorbiscomment);
517 FLAC::Metadata::Padding p(&padding);
519 !insert_to_our_metadata_(&s, 0, /*copy=*/true) ||
520 !insert_to_our_metadata_(&v, 1, /*copy=*/true) ||
521 !insert_to_our_metadata_(&p, 2, /*copy=*/true)
523 return die_("priming our metadata");
525 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
526 return die_("creating the encoded file");
528 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
533 static bool test_file_(const char *filename, bool ignore_metadata)
535 OurFileDecoder decoder(ignore_metadata);
537 FLAC__ASSERT(0 != filename);
539 mc_our_block_number_ = 0;
540 decoder.error_occurred_ = false;
542 printf("\ttesting '%s'... ", filename);
545 if(!decoder.is_valid())
546 return die_("couldn't allocate decoder instance");
548 decoder.set_md5_checking(true);
549 decoder.set_filename(filename);
550 decoder.set_metadata_respond_all();
551 if(decoder.init() != ::FLAC__FILE_DECODER_OK) {
553 return die_("initializing decoder\n");
555 if(!decoder.process_until_end_of_file()) {
557 return die_("decoding file\n");
562 if(decoder.error_occurred_)
565 if(mc_our_block_number_ != our_metadata_.num_blocks)
566 return die_("short metadata block count");
572 static bool change_stats_(const char *filename, bool read_only)
574 if(!grabbag__file_change_stats(filename, read_only))
575 return die_("during grabbag__file_change_stats()");
580 static bool remove_file_(const char *filename)
582 while(our_metadata_.num_blocks > 0)
583 delete_from_our_metadata_(0);
585 if(!grabbag__file_remove_file(filename))
586 return die_("removing file");
591 static bool test_level_0_()
593 FLAC::Metadata::StreamInfo streaminfo;
595 printf("\n\n++++++ testing level 0 interface\n");
597 if(!generate_file_())
600 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
603 if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
604 return die_("during FLAC::Metadata::get_streaminfo()");
606 /* check to see if some basic data matches (c.f. generate_file_()) */
607 if(streaminfo.get_channels() != 1)
608 return die_("mismatch in streaminfo.get_channels()");
609 if(streaminfo.get_bits_per_sample() != 8)
610 return die_("mismatch in streaminfo.get_bits_per_sample()");
611 if(streaminfo.get_sample_rate() != 44100)
612 return die_("mismatch in streaminfo.get_sample_rate()");
613 if(streaminfo.get_min_blocksize() != 576)
614 return die_("mismatch in streaminfo.get_min_blocksize()");
615 if(streaminfo.get_max_blocksize() != 576)
616 return die_("mismatch in streaminfo.get_max_blocksize()");
618 if(!remove_file_(flacfile_))
624 static bool test_level_1_()
626 FLAC::Metadata::Prototype *block;
627 FLAC::Metadata::StreamInfo *streaminfo;
628 FLAC::Metadata::Padding *padding;
629 FLAC::Metadata::Application *app;
630 FLAC__byte data[1000];
631 unsigned our_current_position = 0;
633 // initialize 'data' to avoid Valgrind errors
634 memset(data, 0, sizeof(data));
636 printf("\n\n++++++ testing level 1 interface\n");
638 /************************************************************/
640 printf("simple iterator on read-only file\n");
642 if(!generate_file_())
645 if(!change_stats_(flacfile_, /*read_only=*/true))
648 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
651 FLAC::Metadata::SimpleIterator iterator;
653 if(!iterator.is_valid())
654 return die_("iterator.is_valid() returned false");
656 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
657 return die_("iterator.init() returned false");
659 printf("is writable = %u\n", (unsigned)iterator.is_writable());
660 if(iterator.is_writable())
661 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
663 printf("iterate forwards\n");
665 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
666 return die_("expected STREAMINFO type from iterator.get_block_type()");
667 if(0 == (block = iterator.get_block()))
668 return die_("getting block 0");
669 if(block->get_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
670 return die_("expected STREAMINFO type");
671 if(block->get_is_last())
672 return die_("expected is_last to be false");
673 if(block->get_length() != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
674 return die_("bad STREAMINFO length");
675 /* check to see if some basic data matches (c.f. generate_file_()) */
676 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
677 FLAC__ASSERT(0 != streaminfo);
678 if(streaminfo->get_channels() != 1)
679 return die_("mismatch in channels");
680 if(streaminfo->get_bits_per_sample() != 8)
681 return die_("mismatch in bits_per_sample");
682 if(streaminfo->get_sample_rate() != 44100)
683 return die_("mismatch in sample_rate");
684 if(streaminfo->get_min_blocksize() != 576)
685 return die_("mismatch in min_blocksize");
686 if(streaminfo->get_max_blocksize() != 576)
687 return die_("mismatch in max_blocksize");
688 // we will delete streaminfo a little later when we're really done with it...
691 return die_("forward iterator ended early");
692 our_current_position++;
695 return die_("forward iterator ended early");
696 our_current_position++;
698 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_PADDING)
699 return die_("expected PADDING type from iterator.get_block_type()");
700 if(0 == (block = iterator.get_block()))
701 return die_("getting block 1");
702 if(block->get_type() != ::FLAC__METADATA_TYPE_PADDING)
703 return die_("expected PADDING type");
704 if(!block->get_is_last())
705 return die_("expected is_last to be true");
706 /* check to see if some basic data matches (c.f. generate_file_()) */
707 if(block->get_length() != 1234)
708 return die_("bad PADDING length");
712 return die_("forward iterator returned true but should have returned false");
714 printf("iterate backwards\n");
716 return die_("reverse iterator ended early");
718 return die_("reverse iterator ended early");
720 return die_("reverse iterator returned true but should have returned false");
722 printf("testing iterator.set_block() on read-only file...\n");
724 if(!iterator.set_block(streaminfo, false))
725 printf("PASSED. iterator.set_block() returned false like it should\n");
727 return die_("iterator.set_block() returned true but shouldn't have");
731 /************************************************************/
733 printf("simple iterator on writable file\n");
735 if(!change_stats_(flacfile_, /*read-only=*/false))
738 printf("creating APPLICATION block\n");
740 if(0 == (app = new FLAC::Metadata::Application()))
741 return die_("new FLAC::Metadata::Application()");
742 app->set_id((const unsigned char *)"duh");
744 printf("creating PADDING block\n");
746 if(0 == (padding = new FLAC::Metadata::Padding()))
747 return die_("new FLAC::Metadata::Padding()");
748 padding->set_length(20);
750 FLAC::Metadata::SimpleIterator iterator;
752 if(!iterator.is_valid())
753 return die_("iterator.is_valid() returned false");
755 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
756 return die_("iterator.init() returned false");
757 our_current_position = 0;
759 printf("is writable = %u\n", (unsigned)iterator.is_writable());
761 printf("[S]VP\ttry to write over STREAMINFO block...\n");
762 if(!iterator.set_block(app, false))
763 printf("\titerator.set_block() returned false like it should\n");
765 return die_("iterator.set_block() returned true but shouldn't have");
767 printf("[S]VP\tnext\n");
769 return die_("iterator ended early\n");
770 our_current_position++;
772 printf("S[V]P\tnext\n");
774 return die_("iterator ended early\n");
775 our_current_position++;
777 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
778 padding->set_length(25);
779 if(!iterator.insert_block_after(padding, false))
780 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
781 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
784 printf("SVP[P]\tprev\n");
786 return die_("iterator ended early\n");
787 our_current_position--;
789 printf("SV[P]P\tprev\n");
791 return die_("iterator ended early\n");
792 our_current_position--;
794 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
795 padding->set_length(30);
796 if(!iterator.insert_block_after(padding, false))
797 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
798 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
801 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
804 printf("SV[P]PP\tprev\n");
806 return die_("iterator ended early\n");
807 our_current_position--;
809 printf("S[V]PPP\tprev\n");
811 return die_("iterator ended early\n");
812 our_current_position--;
814 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
815 if(iterator.delete_block(false))
816 return die_ss_("iterator.delete_block(false) should have returned false", iterator);
818 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
821 printf("[S]VPPP\tnext\n");
823 return die_("iterator ended early\n");
824 our_current_position++;
826 printf("S[V]PPP\tnext\n");
828 return die_("iterator ended early\n");
829 our_current_position++;
831 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
832 if(!iterator.delete_block(true))
833 return die_ss_("iterator.delete_block(true)", iterator);
834 our_current_position--;
836 printf("S[V]PPP\tnext\n");
838 return die_("iterator ended early\n");
839 our_current_position++;
841 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
842 if(!iterator.delete_block(false))
843 return die_ss_("iterator.delete_block(false)", iterator);
844 delete_from_our_metadata_(our_current_position--);
846 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
849 printf("S[V]PP\tnext\n");
851 return die_("iterator ended early\n");
852 our_current_position++;
854 printf("SV[P]P\tnext\n");
856 return die_("iterator ended early\n");
857 our_current_position++;
859 printf("SVP[P]\tdelete (last block), replace with padding\n");
860 if(!iterator.delete_block(true))
861 return die_ss_("iterator.delete_block(false)", iterator);
862 our_current_position--;
864 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
867 printf("SV[P]P\tnext\n");
869 return die_("iterator ended early\n");
870 our_current_position++;
872 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
873 if(!iterator.delete_block(false))
874 return die_ss_("iterator.delete_block(false)", iterator);
875 delete_from_our_metadata_(our_current_position--);
877 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
880 printf("SV[P]\tprev\n");
882 return die_("iterator ended early\n");
883 our_current_position--;
885 printf("S[V]P\tprev\n");
887 return die_("iterator ended early\n");
888 our_current_position--;
890 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
891 FLAC__ASSERT(our_current_position == 0);
892 block = iterator.get_block();
893 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
894 FLAC__ASSERT(0 != streaminfo);
895 streaminfo->set_sample_rate(32000);
896 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
897 return die_("copying object");
898 if(!iterator.set_block(block, false))
899 return die_ss_("iterator.set_block(block, false)", iterator);
902 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
905 printf("[S]VP\tnext\n");
907 return die_("iterator ended early\n");
908 our_current_position++;
910 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
911 app->set_id((const unsigned char *)"euh"); /* twiddle the id so that our comparison doesn't miss transposition */
912 if(!iterator.insert_block_after(app, true))
913 return die_ss_("iterator.insert_block_after(app, true)", iterator);
914 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
916 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
918 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
921 printf("SV[A]P\tnext\n");
923 return die_("iterator ended early\n");
924 our_current_position++;
926 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
927 app->set_id((const unsigned char *)"fuh"); /* twiddle the id */
928 if(!iterator.set_block(app, true))
929 return die_ss_("iterator.set_block(app, true)", iterator);
930 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
932 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
934 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
937 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
938 app->set_id((const unsigned char *)"guh"); /* twiddle the id */
939 if(!app->set_data(data, sizeof(data), true))
940 return die_("setting APPLICATION data");
941 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
942 return die_("copying object");
943 if(!iterator.set_block(app, false))
944 return die_ss_("iterator.set_block(app, false)", iterator);
946 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
949 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
950 app->set_id((const unsigned char *)"huh"); /* twiddle the id */
951 if(!app->set_data(data, 12, true))
952 return die_("setting APPLICATION data");
953 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
954 return die_("copying object");
955 if(!iterator.set_block(app, false))
956 return die_ss_("iterator.set_block(app, false)", iterator);
958 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
961 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
962 app->set_id((const unsigned char *)"iuh"); /* twiddle the id */
963 if(!app->set_data(data, sizeof(data), true))
964 return die_("setting APPLICATION data");
965 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
966 return die_("copying object");
967 add_to_padding_length_(our_current_position+1, -((int)sizeof(data) - 12));
968 if(!iterator.set_block(app, true))
969 return die_ss_("iterator.set_block(app, true)", iterator);
971 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
974 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
975 app->set_id((const unsigned char *)"juh"); /* twiddle the id */
976 if(!app->set_data(data, 23, true))
977 return die_("setting APPLICATION data");
978 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
979 return die_("copying object");
980 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
981 return die_("copying object");
982 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH);
983 if(!iterator.set_block(app, true))
984 return die_ss_("iterator.set_block(app, true)", iterator);
986 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
989 printf("SVA[A]PP\tnext\n");
991 return die_("iterator ended early\n");
992 our_current_position++;
994 printf("SVAA[P]P\tnext\n");
996 return die_("iterator ended early\n");
997 our_current_position++;
999 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1000 padding->set_length(5);
1001 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1002 return die_("copying object");
1003 if(!iterator.set_block(padding, false))
1004 return die_ss_("iterator.set_block(padding, false)", iterator);
1006 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1009 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1010 app->set_id((const unsigned char *)"kuh"); /* twiddle the id */
1011 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1012 return die_("copying object");
1013 if(!iterator.set_block(app, false))
1014 return die_ss_("iterator.set_block(app, false)", iterator);
1016 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1019 printf("SVAAP[A]\tset PADDING (equal)\n");
1020 padding->set_length(27);
1021 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1022 return die_("copying object");
1023 if(!iterator.set_block(padding, false))
1024 return die_ss_("iterator.set_block(padding, false)", iterator);
1026 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1029 printf("SVAAP[P]\tprev\n");
1030 if(!iterator.prev())
1031 return die_("iterator ended early\n");
1032 our_current_position--;
1034 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1035 if(!iterator.delete_block(false))
1036 return die_ss_("iterator.delete_block(false)", iterator);
1037 delete_from_our_metadata_(our_current_position--);
1039 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1042 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1043 if(!iterator.delete_block(false))
1044 return die_ss_("iterator.delete_block(false)", iterator);
1045 delete_from_our_metadata_(our_current_position--);
1047 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1050 printf("SV[A]P\tnext\n");
1051 if(!iterator.next())
1052 return die_("iterator ended early\n");
1053 our_current_position++;
1055 printf("SVA[P]\tinsert PADDING after\n");
1056 padding->set_length(5);
1057 if(!iterator.insert_block_after(padding, false))
1058 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1059 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1062 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1065 printf("SVAP[P]\tprev\n");
1066 if(!iterator.prev())
1067 return die_("iterator ended early\n");
1068 our_current_position--;
1070 printf("SVA[P]P\tprev\n");
1071 if(!iterator.prev())
1072 return die_("iterator ended early\n");
1073 our_current_position--;
1075 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1076 if(!app->set_data(data, 32, true))
1077 return die_("setting APPLICATION data");
1078 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1079 return die_("copying object");
1080 if(!iterator.set_block(app, true))
1081 return die_ss_("iterator.set_block(app, true)", iterator);
1083 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1086 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1087 if(!app->set_data(data, 60, true))
1088 return die_("setting APPLICATION data");
1089 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1090 return die_("copying object");
1091 if(!iterator.set_block(app, true))
1092 return die_ss_("iterator.set_block(app, true)", iterator);
1094 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1097 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1098 if(!app->set_data(data, 87, true))
1099 return die_("setting APPLICATION data");
1100 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1101 return die_("copying object");
1102 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1103 if(!iterator.set_block(app, true))
1104 return die_ss_("iterator.set_block(app, true)", iterator);
1106 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1109 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1110 if(!app->set_data(data, 91, true))
1111 return die_("setting APPLICATION data");
1112 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1113 return die_("copying object");
1114 delete_from_our_metadata_(our_current_position+1);
1115 if(!iterator.set_block(app, true))
1116 return die_ss_("iterator.set_block(app, true)", iterator);
1118 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1121 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1122 if(!app->set_data(data, 100, true))
1123 return die_("setting APPLICATION data");
1124 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1125 return die_("copying object");
1126 delete_from_our_metadata_(our_current_position+1);
1127 our_metadata_.blocks[our_current_position]->set_is_last(true);
1128 if(!iterator.set_block(app, true))
1129 return die_ss_("iterator.set_block(app, true)", iterator);
1131 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1134 printf("SV[A]\tset PADDING (equal size)\n");
1135 padding->set_length(app->get_length());
1136 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1137 return die_("copying object");
1138 if(!iterator.set_block(padding, true))
1139 return die_ss_("iterator.set_block(padding, true)", iterator);
1141 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1144 printf("SV[P]\tinsert PADDING after\n");
1145 if(!iterator.insert_block_after(padding, false))
1146 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1147 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1150 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1153 printf("SVP[P]\tinsert PADDING after\n");
1154 padding->set_length(5);
1155 if(!iterator.insert_block_after(padding, false))
1156 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1157 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1160 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1163 printf("SVPP[P]\tprev\n");
1164 if(!iterator.prev())
1165 return die_("iterator ended early\n");
1166 our_current_position--;
1168 printf("SVP[P]P\tprev\n");
1169 if(!iterator.prev())
1170 return die_("iterator ended early\n");
1171 our_current_position--;
1173 printf("SV[P]PP\tprev\n");
1174 if(!iterator.prev())
1175 return die_("iterator ended early\n");
1176 our_current_position--;
1178 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1179 if(!app->set_data(data, 101, true))
1180 return die_("setting APPLICATION data");
1181 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1182 return die_("copying object");
1183 if(!iterator.insert_block_after(app, true))
1184 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1186 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1189 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1190 if(!iterator.delete_block(false))
1191 return die_ss_("iterator.delete_block(false)", iterator);
1192 delete_from_our_metadata_(our_current_position--);
1194 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1197 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1198 if(!app->set_data(data, 97, true))
1199 return die_("setting APPLICATION data");
1200 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1201 return die_("copying object");
1202 if(!iterator.insert_block_after(app, true))
1203 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1205 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1208 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1209 if(!iterator.delete_block(false))
1210 return die_ss_("iterator.delete_block(false)", iterator);
1211 delete_from_our_metadata_(our_current_position--);
1213 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1216 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1217 if(!app->set_data(data, 100, true))
1218 return die_("setting APPLICATION data");
1219 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1220 return die_("copying object");
1221 delete_from_our_metadata_(our_current_position+1);
1222 if(!iterator.insert_block_after(app, true))
1223 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1225 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1228 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1229 if(!iterator.delete_block(false))
1230 return die_ss_("iterator.delete_block(false)", iterator);
1231 delete_from_our_metadata_(our_current_position--);
1233 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1236 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1237 if(!app->set_data(data, 96, true))
1238 return die_("setting APPLICATION data");
1239 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1240 return die_("copying object");
1241 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1242 if(!iterator.insert_block_after(app, true))
1243 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1245 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1248 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1249 if(!iterator.delete_block(false))
1250 return die_ss_("iterator.delete_block(false)", iterator);
1251 delete_from_our_metadata_(our_current_position--);
1253 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1256 printf("S[V]PP\tnext\n");
1257 if(!iterator.next())
1258 return die_("iterator ended early\n");
1259 our_current_position++;
1261 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1262 if(!iterator.delete_block(false))
1263 return die_ss_("iterator.delete_block(false)", iterator);
1264 delete_from_our_metadata_(our_current_position--);
1266 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1269 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1270 if(!app->set_data(data, 1, true))
1271 return die_("setting APPLICATION data");
1272 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1273 return die_("copying object");
1274 delete_from_our_metadata_(our_current_position+1);
1275 if(!iterator.insert_block_after(app, true))
1276 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1278 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1285 if(!remove_file_(flacfile_))
1291 static bool test_level_2_(bool filename_based)
1293 FLAC::Metadata::Prototype *block;
1294 FLAC::Metadata::StreamInfo *streaminfo;
1295 FLAC::Metadata::Application *app;
1296 FLAC::Metadata::Padding *padding;
1297 FLAC__byte data[2000];
1298 unsigned our_current_position;
1300 // initialize 'data' to avoid Valgrind errors
1301 memset(data, 0, sizeof(data));
1303 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1305 printf("generate read-only file\n");
1307 if(!generate_file_())
1310 if(!change_stats_(flacfile_, /*read_only=*/true))
1313 printf("create chain\n");
1314 FLAC::Metadata::Chain chain;
1315 if(!chain.is_valid())
1316 return die_("allocating memory for chain");
1318 printf("read chain\n");
1320 if(!read_chain_(chain, flacfile_, filename_based))
1321 return die_c_("reading chain", chain.status());
1323 printf("[S]VP\ttest initial metadata\n");
1325 if(!compare_chain_(chain, 0, 0))
1327 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1330 printf("switch file to read-write\n");
1332 if(!change_stats_(flacfile_, /*read-only=*/false))
1335 printf("create iterator\n");
1337 FLAC::Metadata::Iterator iterator;
1338 if(!iterator.is_valid())
1339 return die_("allocating memory for iterator");
1341 our_current_position = 0;
1343 iterator.init(chain);
1345 if(0 == (block = iterator.get_block()))
1346 return die_("getting block from iterator");
1348 FLAC__ASSERT(block->get_type() == FLAC__METADATA_TYPE_STREAMINFO);
1350 printf("[S]VP\tmodify STREAMINFO, write\n");
1352 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1353 FLAC__ASSERT(0 != streaminfo);
1354 streaminfo->set_sample_rate(32000);
1355 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1356 return die_("copying object");
1359 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1360 return die_c_("during chain.write(false, true)", chain.status());
1361 block = iterator.get_block();
1362 if(!compare_chain_(chain, our_current_position, block))
1365 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1368 printf("[S]VP\tnext\n");
1369 if(!iterator.next())
1370 return die_("iterator ended early\n");
1371 our_current_position++;
1373 printf("S[V]P\tnext\n");
1374 if(!iterator.next())
1375 return die_("iterator ended early\n");
1376 our_current_position++;
1378 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1379 if(0 == (block = iterator.get_block()))
1380 return die_("getting block from iterator");
1381 if(0 == (app = new FLAC::Metadata::Application()))
1382 return die_("new FLAC::Metadata::Application()");
1383 app->set_id((const unsigned char *)"duh");
1384 if(!app->set_data(data, block->get_length()-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1385 return die_("setting APPLICATION data");
1387 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1388 return die_("copying object");
1389 if(!iterator.set_block(app))
1390 return die_c_("iterator.set_block(app)", chain.status());
1392 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1393 return die_c_("during chain.write(false, false)", chain.status());
1394 block = iterator.get_block();
1395 if(!compare_chain_(chain, our_current_position, block))
1398 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1401 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1402 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1403 return die_("copying object");
1404 if(!app->set_data(data, 26, true))
1405 return die_("setting APPLICATION data");
1406 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1407 return die_("copying object");
1408 if(!iterator.set_block(app))
1409 return die_c_("iterator.set_block(app)", chain.status());
1411 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1412 return die_c_("during chain.write(false, false)", chain.status());
1413 block = iterator.get_block();
1414 if(!compare_chain_(chain, our_current_position, block))
1417 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1420 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1421 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1422 return die_("copying object");
1423 if(!app->set_data(data, 28, true))
1424 return die_("setting APPLICATION data");
1425 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1426 return die_("copying object");
1427 if(!iterator.set_block(app))
1428 return die_c_("iterator.set_block(app)", chain.status());
1430 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1431 return die_c_("during chain.write(false, false)", chain.status());
1432 block = iterator.get_block();
1433 if(!compare_chain_(chain, our_current_position, block))
1436 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1439 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1440 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1441 return die_("copying object");
1442 if(!app->set_data(data, 36, true))
1443 return die_("setting APPLICATION data");
1444 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1445 return die_("copying object");
1446 if(!iterator.set_block(app))
1447 return die_c_("iterator.set_block(app)", chain.status());
1449 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1450 return die_c_("during chain.write(false, false)", chain.status());
1451 block = iterator.get_block();
1452 if(!compare_chain_(chain, our_current_position, block))
1455 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1458 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1459 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1460 return die_("copying object");
1461 if(!app->set_data(data, 33, true))
1462 return die_("setting APPLICATION data");
1463 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1464 return die_("copying object");
1465 if(!iterator.set_block(app))
1466 return die_c_("iterator.set_block(app)", chain.status());
1468 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1469 return die_c_("during chain.write(true, false)", chain.status());
1470 block = iterator.get_block();
1471 if(!compare_chain_(chain, our_current_position, block))
1474 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1477 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1478 if(0 == (padding = new FLAC::Metadata::Padding()))
1479 return die_("creating PADDING block");
1480 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1481 return die_("copying object");
1482 if(!app->set_data(data, 29, true))
1483 return die_("setting APPLICATION data");
1484 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1485 return die_("copying object");
1486 padding->set_length(0);
1487 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1488 return die_("internal error");
1489 if(!iterator.set_block(app))
1490 return die_c_("iterator.set_block(app)", chain.status());
1492 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1493 return die_c_("during chain.write(true, false)", chain.status());
1494 block = iterator.get_block();
1495 if(!compare_chain_(chain, our_current_position, block))
1498 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1501 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1502 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1503 return die_("copying object");
1504 if(!app->set_data(data, 16, true))
1505 return die_("setting APPLICATION data");
1506 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1507 return die_("copying object");
1508 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(13);
1509 if(!iterator.set_block(app))
1510 return die_c_("iterator.set_block(app)", chain.status());
1512 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1513 return die_c_("during chain.write(true, false)", chain.status());
1514 block = iterator.get_block();
1515 if(!compare_chain_(chain, our_current_position, block))
1518 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1521 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1522 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1523 return die_("copying object");
1524 if(!app->set_data(data, 50, true))
1525 return die_("setting APPLICATION data");
1526 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1527 return die_("copying object");
1528 if(!iterator.set_block(app))
1529 return die_c_("iterator.set_block(app)", chain.status());
1531 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1532 return die_c_("during chain.write(true, false)", chain.status());
1533 block = iterator.get_block();
1534 if(!compare_chain_(chain, our_current_position, block))
1537 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1540 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1541 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1542 return die_("copying object");
1543 if(!app->set_data(data, 56, true))
1544 return die_("setting APPLICATION data");
1545 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1546 return die_("copying object");
1547 add_to_padding_length_(our_current_position+1, -(56 - 50));
1548 if(!iterator.set_block(app))
1549 return die_c_("iterator.set_block(app)", chain.status());
1551 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1552 return die_c_("during chain.write(true, false)", chain.status());
1553 block = iterator.get_block();
1554 if(!compare_chain_(chain, our_current_position, block))
1557 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1560 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1561 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1562 return die_("copying object");
1563 if(!app->set_data(data, 67, true))
1564 return die_("setting APPLICATION data");
1565 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1566 return die_("copying object");
1567 delete_from_our_metadata_(our_current_position+1);
1568 if(!iterator.set_block(app))
1569 return die_c_("iterator.set_block(app)", chain.status());
1571 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1572 return die_c_("during chain.write(true, false)", chain.status());
1573 block = iterator.get_block();
1574 if(!compare_chain_(chain, our_current_position, block))
1577 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1580 printf("SV[A]\tprev\n");
1581 if(!iterator.prev())
1582 return die_("iterator ended early\n");
1583 our_current_position--;
1585 printf("S[V]A\tprev\n");
1586 if(!iterator.prev())
1587 return die_("iterator ended early\n");
1588 our_current_position--;
1590 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1591 if(0 == (padding = new FLAC::Metadata::Padding()))
1592 return die_("creating PADDING block");
1593 padding->set_length(30);
1594 if(!iterator.insert_block_before(padding))
1595 printf("\titerator.insert_block_before() returned false like it should\n");
1597 return die_("iterator.insert_block_before() should have returned false");
1599 printf("[S]VA\tnext\n");
1600 if(!iterator.next())
1601 return die_("iterator ended early\n");
1602 our_current_position++;
1604 printf("S[V]A\tinsert PADDING after\n");
1605 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1606 return die_("copying metadata");
1607 if(!iterator.insert_block_after(padding))
1608 return die_("iterator.insert_block_after(padding)");
1610 block = iterator.get_block();
1611 if(!compare_chain_(chain, our_current_position, block))
1615 printf("SV[P]A\tinsert PADDING before\n");
1616 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1617 return die_("creating PADDING block");
1618 padding->set_length(17);
1619 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1620 return die_("copying metadata");
1621 if(!iterator.insert_block_before(padding))
1622 return die_("iterator.insert_block_before(padding)");
1624 block = iterator.get_block();
1625 if(!compare_chain_(chain, our_current_position, block))
1629 printf("SV[P]PA\tinsert PADDING before\n");
1630 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1631 return die_("creating PADDING block");
1632 padding->set_length(0);
1633 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1634 return die_("copying metadata");
1635 if(!iterator.insert_block_before(padding))
1636 return die_("iterator.insert_block_before(padding)");
1638 block = iterator.get_block();
1639 if(!compare_chain_(chain, our_current_position, block))
1643 printf("SV[P]PPA\tnext\n");
1644 if(!iterator.next())
1645 return die_("iterator ended early\n");
1646 our_current_position++;
1648 printf("SVP[P]PA\tnext\n");
1649 if(!iterator.next())
1650 return die_("iterator ended early\n");
1651 our_current_position++;
1653 printf("SVPP[P]A\tnext\n");
1654 if(!iterator.next())
1655 return die_("iterator ended early\n");
1656 our_current_position++;
1658 printf("SVPPP[A]\tinsert PADDING after\n");
1659 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1660 return die_("creating PADDING block");
1661 padding->set_length(57);
1662 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1663 return die_("copying metadata");
1664 if(!iterator.insert_block_after(padding))
1665 return die_("iterator.insert_block_after(padding)");
1667 block = iterator.get_block();
1668 if(!compare_chain_(chain, our_current_position, block))
1672 printf("SVPPPA[P]\tinsert PADDING before\n");
1673 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1674 return die_("creating PADDING block");
1675 padding->set_length(99);
1676 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1677 return die_("copying metadata");
1678 if(!iterator.insert_block_before(padding))
1679 return die_("iterator.insert_block_before(padding)");
1681 block = iterator.get_block();
1682 if(!compare_chain_(chain, our_current_position, block))
1687 our_current_position = 0;
1689 printf("SVPPPAPP\tmerge padding\n");
1690 chain.merge_padding();
1691 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->get_length());
1692 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->get_length());
1693 add_to_padding_length_(6, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->get_length());
1694 delete_from_our_metadata_(7);
1695 delete_from_our_metadata_(4);
1696 delete_from_our_metadata_(3);
1698 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1699 return die_c_("during chain.write(true, false)", chain.status());
1700 if(!compare_chain_(chain, 0, 0))
1702 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1705 printf("SVPAP\tsort padding\n");
1706 chain.sort_padding();
1707 add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length());
1708 delete_from_our_metadata_(2);
1710 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1711 return die_c_("during chain.write(true, false)", chain.status());
1712 if(!compare_chain_(chain, 0, 0))
1714 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1717 printf("create iterator\n");
1719 FLAC::Metadata::Iterator iterator;
1720 if(!iterator.is_valid())
1721 return die_("allocating memory for iterator");
1723 our_current_position = 0;
1725 iterator.init(chain);
1727 printf("[S]VAP\tnext\n");
1728 if(!iterator.next())
1729 return die_("iterator ended early\n");
1730 our_current_position++;
1732 printf("S[V]AP\tnext\n");
1733 if(!iterator.next())
1734 return die_("iterator ended early\n");
1735 our_current_position++;
1737 printf("SV[A]P\tdelete middle block, replace with padding\n");
1738 if(0 == (padding = new FLAC::Metadata::Padding()))
1739 return die_("creating PADDING block");
1740 padding->set_length(71);
1741 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1742 return die_("copying object");
1743 if(!iterator.delete_block(/*replace_with_padding=*/true))
1744 return die_c_("iterator.delete_block(true)", chain.status());
1746 block = iterator.get_block();
1747 if(!compare_chain_(chain, our_current_position, block))
1751 printf("S[V]PP\tnext\n");
1752 if(!iterator.next())
1753 return die_("iterator ended early\n");
1754 our_current_position++;
1756 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1757 delete_from_our_metadata_(our_current_position--);
1758 if(!iterator.delete_block(/*replace_with_padding=*/false))
1759 return die_c_("iterator.delete_block(false)", chain.status());
1761 block = iterator.get_block();
1762 if(!compare_chain_(chain, our_current_position, block))
1766 printf("S[V]P\tnext\n");
1767 if(!iterator.next())
1768 return die_("iterator ended early\n");
1769 our_current_position++;
1771 printf("SV[P]\tdelete last block, replace with padding\n");
1772 if(0 == (padding = new FLAC::Metadata::Padding()))
1773 return die_("creating PADDING block");
1774 padding->set_length(219);
1775 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1776 return die_("copying object");
1777 if(!iterator.delete_block(/*replace_with_padding=*/true))
1778 return die_c_("iterator.delete_block(true)", chain.status());
1780 block = iterator.get_block();
1781 if(!compare_chain_(chain, our_current_position, block))
1785 printf("S[V]P\tnext\n");
1786 if(!iterator.next())
1787 return die_("iterator ended early\n");
1788 our_current_position++;
1790 printf("SV[P]\tdelete last block, don't replace with padding\n");
1791 delete_from_our_metadata_(our_current_position--);
1792 if(!iterator.delete_block(/*replace_with_padding=*/false))
1793 return die_c_("iterator.delete_block(false)", chain.status());
1795 block = iterator.get_block();
1796 if(!compare_chain_(chain, our_current_position, block))
1800 printf("S[V]\tprev\n");
1801 if(!iterator.prev())
1802 return die_("iterator ended early\n");
1803 our_current_position--;
1805 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1806 if(iterator.delete_block(/*replace_with_padding=*/false))
1807 return die_("iterator.delete_block() on STREAMINFO should have failed but didn't");
1809 block = iterator.get_block();
1810 if(!compare_chain_(chain, our_current_position, block))
1814 } // delete iterator
1815 our_current_position = 0;
1817 printf("SV\tmerge padding\n");
1818 chain.merge_padding();
1820 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1821 return die_c_("during chain.write(false, false)", chain.status());
1822 if(!compare_chain_(chain, 0, 0))
1824 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1827 printf("SV\tsort padding\n");
1828 chain.sort_padding();
1830 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1831 return die_c_("during chain.write(false, false)", chain.status());
1832 if(!compare_chain_(chain, 0, 0))
1834 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1837 if(!remove_file_(flacfile_))
1843 static bool test_level_2_misc_()
1845 ::FLAC__IOCallbacks callbacks;
1847 memset(&callbacks, 0, sizeof(callbacks));
1848 callbacks.read = (::FLAC__IOCallback_Read)fread;
1849 #ifdef FLAC__VALGRIND_TESTING
1850 callbacks.write = chain_write_cb_;
1852 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
1854 callbacks.seek = chain_seek_cb_;
1855 callbacks.tell = chain_tell_cb_;
1856 callbacks.eof = chain_eof_cb_;
1858 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1860 printf("generate file\n");
1862 if(!generate_file_())
1865 printf("create chain\n");
1866 FLAC::Metadata::Chain chain;
1867 if(!chain.is_valid())
1868 return die_("allocating chain");
1870 printf("read chain (filename-based)\n");
1872 if(!chain.read(flacfile_))
1873 return die_c_("reading chain", chain.status());
1875 printf("write chain with wrong method Chain::write(with callbacks)\n");
1877 if(chain.write(/*use_padding=*/false, 0, callbacks))
1878 return die_c_("mismatched write should have failed", chain.status());
1879 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1880 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1881 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1884 printf("read chain (filename-based)\n");
1886 if(!chain.read(flacfile_))
1887 return die_c_("reading chain", chain.status());
1889 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
1891 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
1892 return die_c_("mismatched write should have failed", chain.status());
1893 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1894 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1895 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1898 printf("read chain (callback-based)\n");
1900 FILE *file = fopen(flacfile_, "rb");
1902 return die_("opening file");
1903 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1905 return die_c_("reading chain", chain.status());
1910 printf("write chain with wrong method write()\n");
1912 if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false))
1913 return die_c_("mismatched write should have failed", chain.status());
1914 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1915 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1916 printf(" OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1919 printf("read chain (callback-based)\n");
1921 FILE *file = fopen(flacfile_, "rb");
1923 return die_("opening file");
1924 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1926 return die_c_("reading chain", chain.status());
1931 printf("testing Chain::check_if_tempfile_needed()... ");
1933 if(!chain.check_if_tempfile_needed(/*use_padding=*/false))
1934 printf("OK: Chain::check_if_tempfile_needed() returned false like it should\n");
1936 return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have");
1938 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
1940 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
1941 return die_c_("mismatched write should have failed", chain.status());
1942 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1943 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
1944 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1947 printf("read chain (callback-based)\n");
1949 FILE *file = fopen(flacfile_, "rb");
1951 return die_("opening file");
1952 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1954 return die_c_("reading chain", chain.status());
1959 printf("create iterator\n");
1961 FLAC::Metadata::Iterator iterator;
1962 if(!iterator.is_valid())
1963 return die_("allocating memory for iterator");
1965 iterator.init(chain);
1967 printf("[S]VP\tnext\n");
1968 if(!iterator.next())
1969 return die_("iterator ended early\n");
1971 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1972 if(!iterator.delete_block(/*replace_with_padding=*/false))
1973 return die_c_("block delete failed\n", chain.status());
1975 printf("testing Chain::check_if_tempfile_needed()... ");
1977 if(chain.check_if_tempfile_needed(/*use_padding=*/false))
1978 printf("OK: Chain::check_if_tempfile_needed() returned true like it should\n");
1980 return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have");
1982 printf("write chain with wrong method Chain::write(with callbacks)\n");
1984 if(chain.write(/*use_padding=*/false, 0, callbacks))
1985 return die_c_("mismatched write should have failed", chain.status());
1986 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1987 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
1988 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1991 } // delete iterator
1993 if(!remove_file_(flacfile_))
1999 bool test_metadata_file_manipulation()
2001 printf("\n+++ libFLAC++ unit test: metadata manipulation\n\n");
2003 our_metadata_.num_blocks = 0;
2005 if(!test_level_0_())
2008 if(!test_level_1_())
2011 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2013 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2015 if(!test_level_2_misc_())