55d85ef965424f34cf0c2555d3183629f4f019bf
[platform/upstream/flac.git] / src / test_libFLAC / metadata_manip.c
1 /* test_libFLAC - Unit tester for libFLAC
2  * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #if HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <stdlib.h> /* for malloc() */
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 //@@@ [2G limit] hacks for MSVC6
29 #define fseeko fseek
30 #define ftello ftell
31 #else
32 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
33 #include <utime.h> /* for utime() */
34 #include <unistd.h> /* for chown(), unlink() */
35 #endif
36 #include <sys/stat.h> /* for stat(), maybe chmod() */
37 #include "file_utils.h"
38 #include "metadata_utils.h"
39 #include "FLAC/assert.h"
40 #include "FLAC/file_decoder.h"
41 #include "FLAC/metadata.h"
42 #include "share/grabbag.h"
43
44
45 /******************************************************************************
46         The general strategy of these tests (for interface levels 1 and 2) is
47         to create a dummy FLAC file with a known set of initial metadata
48         blocks, then keep a mirror locally of what we expect the metadata to be
49         after each operation.  Then testing becomes a simple matter of running
50         a FLAC__FileDecoder over the dummy file after each operation, comparing
51         the decoded metadata to what's in our local copy.  If there are any
52         differences in the metadata, or the actual audio data is corrupted, we
53         will catch it while decoding.
54 ******************************************************************************/
55
56 typedef struct {
57         FLAC__bool error_occurred;
58 } decoder_client_struct;
59
60 typedef struct {
61         FLAC__StreamMetadata *blocks[64];
62         unsigned num_blocks;
63 } our_metadata_struct;
64
65 static const char *flacfile_ = "metadata.flac";
66
67 /* our copy of the metadata in flacfile_ */
68 static our_metadata_struct our_metadata_;
69
70 /* the current block number that corresponds to the position of the iterator we are testing */
71 static unsigned mc_our_block_number_ = 0;
72
73 static FLAC__bool die_(const char *msg)
74 {
75         printf("ERROR: %s\n", msg);
76         return false;
77 }
78
79 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
80 {
81         printf("ERROR: %s\n", msg);
82         printf("       status=%s\n", FLAC__Metadata_ChainStatusString[status]);
83         return false;
84 }
85
86 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
87 {
88         printf("ERROR: %s\n", msg);
89         printf("       status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
90         return false;
91 }
92
93 static void *malloc_or_die_(size_t size)
94 {
95         void *x = malloc(size);
96         if(0 == x) {
97                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
98                 exit(1);
99         }
100         return x;
101 }
102
103 /* functions for working with our metadata copy */
104
105 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
106 {
107         unsigned i;
108         FLAC__StreamMetadata *obj = block;
109         FLAC__ASSERT(position < our_metadata_.num_blocks);
110         if(copy) {
111                 if(0 == (obj = FLAC__metadata_object_clone(block)))
112                         return die_("during FLAC__metadata_object_clone()");
113         }
114         FLAC__metadata_object_delete(our_metadata_.blocks[position]);
115         our_metadata_.blocks[position] = obj;
116
117         /* set the is_last flags */
118         for(i = 0; i < our_metadata_.num_blocks - 1; i++)
119                 our_metadata_.blocks[i]->is_last = false;
120         our_metadata_.blocks[i]->is_last = true;
121
122         return true;
123 }
124
125 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
126 {
127         unsigned i;
128         FLAC__StreamMetadata *obj = block;
129         if(copy) {
130                 if(0 == (obj = FLAC__metadata_object_clone(block)))
131                         return die_("during FLAC__metadata_object_clone()");
132         }
133         if(position > our_metadata_.num_blocks) {
134                 position = our_metadata_.num_blocks;
135         }
136         else {
137                 for(i = our_metadata_.num_blocks; i > position; i--)
138                         our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
139         }
140         our_metadata_.blocks[position] = obj;
141         our_metadata_.num_blocks++;
142
143         /* set the is_last flags */
144         for(i = 0; i < our_metadata_.num_blocks - 1; i++)
145                 our_metadata_.blocks[i]->is_last = false;
146         our_metadata_.blocks[i]->is_last = true;
147
148         return true;
149 }
150
151 static void delete_from_our_metadata_(unsigned position)
152 {
153         unsigned i;
154         FLAC__ASSERT(position < our_metadata_.num_blocks);
155         FLAC__metadata_object_delete(our_metadata_.blocks[position]);
156         for(i = position; i < our_metadata_.num_blocks - 1; i++)
157                 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
158         our_metadata_.num_blocks--;
159
160         /* set the is_last flags */
161         if(our_metadata_.num_blocks > 0) {
162                 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
163                         our_metadata_.blocks[i]->is_last = false;
164                 our_metadata_.blocks[i]->is_last = true;
165         }
166 }
167
168 /*
169  * This wad of functions supports filename- and callback-based chain reading/writing.
170  * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
171  */
172 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
173 {
174         static const char *tempfile_suffix = ".metadata_edit";
175
176         if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
177                 return false;
178         strcpy(*tempfilename, filename);
179         strcat(*tempfilename, tempfile_suffix);
180
181         if(0 == (*tempfile = fopen(*tempfilename, "wb")))
182                 return false;
183
184         return true;
185 }
186
187 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
188 {
189         if(0 != *tempfile) {
190                 (void)fclose(*tempfile);
191                 *tempfile = 0;
192         }
193
194         if(0 != *tempfilename) {
195                 (void)unlink(*tempfilename);
196                 free(*tempfilename);
197                 *tempfilename = 0;
198         }
199 }
200
201 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
202 {
203         FLAC__ASSERT(0 != filename);
204         FLAC__ASSERT(0 != tempfile);
205         FLAC__ASSERT(0 != tempfilename);
206         FLAC__ASSERT(0 != *tempfilename);
207
208         if(0 != *tempfile) {
209                 (void)fclose(*tempfile);
210                 *tempfile = 0;
211         }
212
213 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
214         if(unlink(filename) < 0) {
215                 cleanup_tempfile_(tempfile, tempfilename);
216                 return false;
217         }
218 #endif
219
220         if(0 != rename(*tempfilename, filename)) {
221                 cleanup_tempfile_(tempfile, tempfilename);
222                 return false;
223         }
224
225         cleanup_tempfile_(tempfile, tempfilename);
226
227         return true;
228 }
229
230 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
231 {
232         FLAC__ASSERT(0 != filename);
233         FLAC__ASSERT(0 != stats);
234         return (0 == stat(filename, stats));
235 }
236
237 void set_file_stats_(const char *filename, struct stat *stats)
238 {
239         struct utimbuf srctime;
240
241         FLAC__ASSERT(0 != filename);
242         FLAC__ASSERT(0 != stats);
243
244         srctime.actime = stats->st_atime;
245         srctime.modtime = stats->st_mtime;
246         (void)chmod(filename, stats->st_mode);
247         (void)utime(filename, &srctime);
248 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
249         (void)chown(filename, stats->st_uid, -1);
250         (void)chown(filename, -1, stats->st_gid);
251 #endif
252 }
253
254 #ifdef FLAC__VALGRIND_TESTING
255 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
256 {
257         FILE *stream = (FILE*)handle;
258         size_t ret = fwrite(ptr, size, nmemb, stream);
259         if(!ferror(stream))
260                 fflush(stream);
261         return ret;
262 }
263 #endif
264
265 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
266 {
267         off_t o = (off_t)offset;
268         FLAC__ASSERT(offset == o);
269         return fseeko((FILE*)handle, o, whence);
270 }
271
272 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
273 {
274         return ftello((FILE*)handle);
275 }
276
277 static int chain_eof_cb_(FLAC__IOHandle handle)
278 {
279         return feof((FILE*)handle);
280 }
281
282 static FLAC__bool write_chain_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats, FLAC__bool filename_based, const char *filename)
283 {
284         if(filename_based)
285                 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
286         else {
287                 FLAC__IOCallbacks callbacks;
288
289                 memset(&callbacks, 0, sizeof(callbacks));
290                 callbacks.read = (FLAC__IOCallback_Read)fread;
291 #ifdef FLAC__VALGRIND_TESTING
292                 callbacks.write = chain_write_cb_;
293 #else
294                 callbacks.write = (FLAC__IOCallback_Write)fwrite;
295 #endif
296                 callbacks.seek = chain_seek_cb_;
297                 callbacks.eof = chain_eof_cb_;
298
299                 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
300                         struct stat stats;
301                         FILE *file, *tempfile;
302                         char *tempfilename;
303                         if(preserve_file_stats) {
304                                 if(!get_file_stats_(filename, &stats))
305                                         return false;
306                         }
307                         if(0 == (file = fopen(filename, "rb")))
308                                 return false; /*@@@ chain status still says OK though */
309                         if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
310                                 fclose(file);
311                                 cleanup_tempfile_(&tempfile, &tempfilename);
312                                 return false; /*@@@ chain status still says OK though */
313                         }
314                         if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
315                                 fclose(file);
316                                 fclose(tempfile);
317                                 return false;
318                         }
319                         fclose(file);
320                         fclose(tempfile);
321                         file = tempfile = 0;
322                         if(!transport_tempfile_(filename, &tempfile, &tempfilename))
323                                 return false;
324                         if(preserve_file_stats)
325                                 set_file_stats_(filename, &stats);
326                 }
327                 else {
328                         FILE *file = fopen(filename, "r+b");
329                         if(0 == file)
330                                 return false; /*@@@ chain status still says OK though */
331                         if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
332                                 return false;
333                         fclose(file);
334                 }
335         }
336
337         return true;
338 }
339
340 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
341 {
342         if(filename_based)
343                 return FLAC__metadata_chain_read(chain, flacfile_);
344         else {
345                 FLAC__IOCallbacks callbacks;
346
347                 memset(&callbacks, 0, sizeof(callbacks));
348                 callbacks.read = (FLAC__IOCallback_Read)fread;
349                 callbacks.seek = chain_seek_cb_;
350                 callbacks.tell = chain_tell_cb_;
351
352                 {
353                         FLAC__bool ret;
354                         FILE *file = fopen(filename, "rb");
355                         if(0 == file)
356                                 return false; /*@@@ chain status still says OK though */
357                         ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
358                         fclose(file);
359                         return ret;
360                 }
361         }
362 }
363
364 /* function for comparing our metadata to a FLAC__Metadata_Chain */
365
366 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
367 {
368         unsigned i;
369         FLAC__Metadata_Iterator *iterator;
370         FLAC__StreamMetadata *block;
371         FLAC__bool next_ok = true;
372
373         FLAC__ASSERT(0 != chain);
374
375         printf("\tcomparing chain... ");
376         fflush(stdout);
377
378         if(0 == (iterator = FLAC__metadata_iterator_new()))
379                 return die_("allocating memory for iterator");
380
381         FLAC__metadata_iterator_init(iterator, chain);
382
383         i = 0;
384         do {
385                 printf("%u... ", i);
386                 fflush(stdout);
387
388                 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
389                         FLAC__metadata_iterator_delete(iterator);
390                         return die_("getting block from iterator");
391                 }
392
393                 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
394                         FLAC__metadata_iterator_delete(iterator);
395                         return die_("metadata block mismatch");
396                 }
397
398                 i++;
399                 next_ok = FLAC__metadata_iterator_next(iterator);
400         } while(i < our_metadata_.num_blocks && next_ok);
401
402         FLAC__metadata_iterator_delete(iterator);
403
404         if(next_ok)
405                 return die_("chain has more blocks than expected");
406
407         if(i < our_metadata_.num_blocks)
408                 return die_("short block count in chain");
409
410         if(0 != current_block) {
411                 printf("CURRENT_POSITION... ");
412                 fflush(stdout);
413
414                 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
415                         return die_("metadata block mismatch");
416         }
417
418         printf("PASSED\n");
419
420         return true;
421 }
422
423 /* decoder callbacks for checking the file */
424
425 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
426 {
427         (void)decoder, (void)buffer, (void)client_data;
428
429         if(
430                 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
431                 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
432         ) {
433                 printf("content... ");
434                 fflush(stdout);
435         }
436
437         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
438 }
439
440 /* this version pays no attention to the metadata */
441 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
442 {
443         (void)decoder, (void)metadata, (void)client_data;
444
445         printf("%d... ", mc_our_block_number_);
446         fflush(stdout);
447
448         mc_our_block_number_++;
449 }
450
451 /* this version is used when we want to compare to our metadata copy */
452 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
453 {
454         decoder_client_struct *dcd = (decoder_client_struct*)client_data;
455
456         (void)decoder;
457
458         /* don't bother checking if we've already hit an error */
459         if(dcd->error_occurred)
460                 return;
461
462         printf("%d... ", mc_our_block_number_);
463         fflush(stdout);
464
465         if(mc_our_block_number_ >= our_metadata_.num_blocks) {
466                 (void)die_("got more metadata blocks than expected");
467                 dcd->error_occurred = true;
468         }
469         else {
470                 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
471                         (void)die_("metadata block mismatch");
472                         dcd->error_occurred = true;
473                 }
474         }
475         mc_our_block_number_++;
476 }
477
478 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
479 {
480         decoder_client_struct *dcd = (decoder_client_struct*)client_data;
481         (void)decoder;
482
483         dcd->error_occurred = true;
484         printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
485 }
486
487 static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
488 {
489         FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
490         FLAC__StreamMetadata *metadata[3];
491         unsigned i = 0, n = 0;
492
493         printf("generating FLAC file for test\n");
494
495         while(our_metadata_.num_blocks > 0)
496                 delete_from_our_metadata_(0);
497
498         streaminfo.is_last = false;
499         streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
500         streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
501         streaminfo.data.stream_info.min_blocksize = 576;
502         streaminfo.data.stream_info.max_blocksize = 576;
503         streaminfo.data.stream_info.min_framesize = 0;
504         streaminfo.data.stream_info.max_framesize = 0;
505         streaminfo.data.stream_info.sample_rate = 44100;
506         streaminfo.data.stream_info.channels = 1;
507         streaminfo.data.stream_info.bits_per_sample = 8;
508         streaminfo.data.stream_info.total_samples = 0;
509         memset(streaminfo.data.stream_info.md5sum, 0, 16);
510
511         {
512                 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
513                 vorbiscomment.is_last = false;
514                 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
515                 vorbiscomment.length = (4 + vendor_string_length) + 4;
516                 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
517                 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
518                 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
519                 vorbiscomment.data.vorbis_comment.num_comments = 0;
520                 vorbiscomment.data.vorbis_comment.comments = 0;
521         }
522
523         {
524                 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
525                         return die_("priming our metadata");
526                 cuesheet->is_last = false;
527                 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
528                 cuesheet->data.cue_sheet.lead_in = 123;
529                 cuesheet->data.cue_sheet.is_cd = false;
530                 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
531                         return die_("priming our metadata");
532                 cuesheet->data.cue_sheet.tracks[0].number = 1;
533                 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
534                         return die_("priming our metadata");
535         }
536
537         padding.is_last = true;
538         padding.type = FLAC__METADATA_TYPE_PADDING;
539         padding.length = 1234;
540
541         metadata[n++] = &vorbiscomment;
542         if (include_cuesheet)
543                 metadata[n++] = cuesheet;
544         metadata[n++] = &padding;
545
546         if(
547                 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
548                 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
549                 (include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
550                 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
551         )
552                 return die_("priming our metadata");
553
554         if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
555                 return die_("creating the encoded file");
556
557         free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
558
559         return true;
560 }
561
562 static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
563 {
564         FLAC__FileDecoder *decoder;
565         decoder_client_struct decoder_client_data;
566
567         FLAC__ASSERT(0 != filename);
568         FLAC__ASSERT(0 != metadata_callback);
569
570         mc_our_block_number_ = 0;
571         decoder_client_data.error_occurred = false;
572
573         printf("\ttesting '%s'... ", filename);
574         fflush(stdout);
575
576         if(0 == (decoder = FLAC__file_decoder_new()))
577                 return die_("couldn't allocate decoder instance");
578
579         FLAC__file_decoder_set_md5_checking(decoder, true);
580         FLAC__file_decoder_set_filename(decoder, filename);
581         FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
582         FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
583         FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
584         FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
585         FLAC__file_decoder_set_metadata_respond_all(decoder);
586         if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
587                 FLAC__file_decoder_finish(decoder);
588                 FLAC__file_decoder_delete(decoder);
589                 return die_("initializing decoder\n");
590         }
591         if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
592                 FLAC__file_decoder_finish(decoder);
593                 FLAC__file_decoder_delete(decoder);
594                 return die_("decoding file\n");
595         }
596
597         FLAC__file_decoder_finish(decoder);
598         FLAC__file_decoder_delete(decoder);
599
600         if(decoder_client_data.error_occurred)
601                 return false;
602
603         if(mc_our_block_number_ != our_metadata_.num_blocks)
604                 return die_("short metadata block count");
605
606         printf("PASSED\n");
607         return true;
608 }
609
610 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
611 {
612         if(!grabbag__file_change_stats(filename, read_only))
613                 return die_("during grabbag__file_change_stats()");
614
615         return true;
616 }
617
618 static FLAC__bool remove_file_(const char *filename)
619 {
620         while(our_metadata_.num_blocks > 0)
621                 delete_from_our_metadata_(0);
622
623         if(!grabbag__file_remove_file(filename))
624                 return die_("removing file");
625
626         return true;
627 }
628
629 static FLAC__bool test_level_0_()
630 {
631         FLAC__StreamMetadata streaminfo;
632         FLAC__StreamMetadata *tags = 0;
633         FLAC__StreamMetadata *cuesheet = 0;
634
635         printf("\n\n++++++ testing level 0 interface\n");
636
637         if(!generate_file_(/*include_cuesheet=*/true))
638                 return false;
639
640         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
641                 return false;
642
643         printf("testing FLAC__metadata_get_streaminfo()... ");
644
645         if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
646                 return die_("during FLAC__metadata_get_streaminfo()");
647
648         /* check to see if some basic data matches (c.f. generate_file_()) */
649         if(streaminfo.data.stream_info.channels != 1)
650                 return die_("mismatch in streaminfo.data.stream_info.channels");
651         if(streaminfo.data.stream_info.bits_per_sample != 8)
652                 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
653         if(streaminfo.data.stream_info.sample_rate != 44100)
654                 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
655         if(streaminfo.data.stream_info.min_blocksize != 576)
656                 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
657         if(streaminfo.data.stream_info.max_blocksize != 576)
658                 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
659
660         printf("OK\n");
661
662         printf("testing FLAC__metadata_get_tags()... ");
663
664         if(!FLAC__metadata_get_tags(flacfile_, &tags))
665                 return die_("during FLAC__metadata_get_tags()");
666
667         /* check to see if some basic data matches (c.f. generate_file_()) */
668         if(tags->data.vorbis_comment.num_comments != 0)
669                 return die_("mismatch in tags->data.vorbis_comment.num_comments");
670
671         printf("OK\n");
672
673         FLAC__metadata_object_delete(tags);
674
675         printf("testing FLAC__metadata_get_cuesheet()... ");
676
677         if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
678                 return die_("during FLAC__metadata_get_cuesheet()");
679
680         /* check to see if some basic data matches (c.f. generate_file_()) */
681         if(cuesheet->data.cue_sheet.lead_in != 123)
682                 return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
683
684         printf("OK\n");
685
686         FLAC__metadata_object_delete(cuesheet);
687
688         if(!remove_file_(flacfile_))
689                 return false;
690
691         return true;
692 }
693
694 static FLAC__bool test_level_1_()
695 {
696         FLAC__Metadata_SimpleIterator *iterator;
697         FLAC__StreamMetadata *block, *app, *padding;
698         FLAC__byte data[1000];
699         unsigned our_current_position = 0;
700
701         /* initialize 'data' to avoid Valgrind errors */
702         memset(data, 0, sizeof(data));
703
704         printf("\n\n++++++ testing level 1 interface\n");
705
706         /************************************************************/
707
708         printf("simple iterator on read-only file\n");
709
710         if(!generate_file_(/*include_cuesheet=*/false))
711                 return false;
712
713         if(!change_stats_(flacfile_, /*read_only=*/true))
714                 return false;
715
716         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
717                 return false;
718
719         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
720                 return die_("FLAC__metadata_simple_iterator_new()");
721
722         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
723                 return die_("FLAC__metadata_simple_iterator_init() returned false");
724
725         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
726         if(FLAC__metadata_simple_iterator_is_writable(iterator))
727                 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
728
729         printf("iterate forwards\n");
730
731         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
732                 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
733         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
734                 return die_("getting block 0");
735         if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
736                 return die_("expected STREAMINFO type");
737         if(block->is_last)
738                 return die_("expected is_last to be false");
739         if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
740                 return die_("bad STREAMINFO length");
741         /* check to see if some basic data matches (c.f. generate_file_()) */
742         if(block->data.stream_info.channels != 1)
743                 return die_("mismatch in channels");
744         if(block->data.stream_info.bits_per_sample != 8)
745                 return die_("mismatch in bits_per_sample");
746         if(block->data.stream_info.sample_rate != 44100)
747                 return die_("mismatch in sample_rate");
748         if(block->data.stream_info.min_blocksize != 576)
749                 return die_("mismatch in min_blocksize");
750         if(block->data.stream_info.max_blocksize != 576)
751                 return die_("mismatch in max_blocksize");
752         FLAC__metadata_object_delete(block);
753
754         if(!FLAC__metadata_simple_iterator_next(iterator))
755                 return die_("forward iterator ended early");
756         our_current_position++;
757
758         if(!FLAC__metadata_simple_iterator_next(iterator))
759                 return die_("forward iterator ended early");
760         our_current_position++;
761
762         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
763                 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
764         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
765                 return die_("getting block 2");
766         if(block->type != FLAC__METADATA_TYPE_PADDING)
767                 return die_("expected PADDING type");
768         if(!block->is_last)
769                 return die_("expected is_last to be true");
770         /* check to see if some basic data matches (c.f. generate_file_()) */
771         if(block->length != 1234)
772                 return die_("bad PADDING length");
773         FLAC__metadata_object_delete(block);
774
775         if(FLAC__metadata_simple_iterator_next(iterator))
776                 return die_("forward iterator returned true but should have returned false");
777
778         printf("iterate backwards\n");
779         if(!FLAC__metadata_simple_iterator_prev(iterator))
780                 return die_("reverse iterator ended early");
781         if(!FLAC__metadata_simple_iterator_prev(iterator))
782                 return die_("reverse iterator ended early");
783         if(FLAC__metadata_simple_iterator_prev(iterator))
784                 return die_("reverse iterator returned true but should have returned false");
785
786         printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
787
788         if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
789                 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
790         else
791                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
792
793         FLAC__metadata_simple_iterator_delete(iterator);
794
795         /************************************************************/
796
797         printf("simple iterator on writable file\n");
798
799         if(!change_stats_(flacfile_, /*read-only=*/false))
800                 return false;
801
802         printf("creating APPLICATION block\n");
803
804         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
805                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
806         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
807
808         printf("creating PADDING block\n");
809
810         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
811                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
812         padding->length = 20;
813
814         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
815                 return die_("FLAC__metadata_simple_iterator_new()");
816
817         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
818                 return die_("FLAC__metadata_simple_iterator_init() returned false");
819         our_current_position = 0;
820
821         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
822
823         printf("[S]VP\ttry to write over STREAMINFO block...\n");
824         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
825                 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
826         else
827                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
828
829         printf("[S]VP\tnext\n");
830         if(!FLAC__metadata_simple_iterator_next(iterator))
831                 return die_("iterator ended early\n");
832         our_current_position++;
833
834         printf("S[V]P\tnext\n");
835         if(!FLAC__metadata_simple_iterator_next(iterator))
836                 return die_("iterator ended early\n");
837         our_current_position++;
838
839         printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
840         padding->length = 25;
841         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
842                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
843         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
844                 return false;
845
846         printf("SVP[P]\tprev\n");
847         if(!FLAC__metadata_simple_iterator_prev(iterator))
848                 return die_("iterator ended early\n");
849         our_current_position--;
850
851         printf("SV[P]P\tprev\n");
852         if(!FLAC__metadata_simple_iterator_prev(iterator))
853                 return die_("iterator ended early\n");
854         our_current_position--;
855
856         printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
857         padding->length = 30;
858         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
859                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
860         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
861                 return false;
862
863         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
864                 return false;
865
866         printf("SV[P]PP\tprev\n");
867         if(!FLAC__metadata_simple_iterator_prev(iterator))
868                 return die_("iterator ended early\n");
869         our_current_position--;
870
871         printf("S[V]PPP\tprev\n");
872         if(!FLAC__metadata_simple_iterator_prev(iterator))
873                 return die_("iterator ended early\n");
874         our_current_position--;
875
876         printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
877         if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
878                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
879
880         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
881                 return false;
882
883         printf("[S]VPPP\tnext\n");
884         if(!FLAC__metadata_simple_iterator_next(iterator))
885                 return die_("iterator ended early\n");
886         our_current_position++;
887
888         printf("S[V]PPP\tnext\n");
889         if(!FLAC__metadata_simple_iterator_next(iterator))
890                 return die_("iterator ended early\n");
891         our_current_position++;
892
893         printf("SV[P]PP\tdelete (middle block), replace with padding\n");
894         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
895                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
896         our_current_position--;
897
898         printf("S[V]PPP\tnext\n");
899         if(!FLAC__metadata_simple_iterator_next(iterator))
900                 return die_("iterator ended early\n");
901         our_current_position++;
902
903         printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
904         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
905                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
906         delete_from_our_metadata_(our_current_position--);
907
908         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
909                 return false;
910
911         printf("S[V]PP\tnext\n");
912         if(!FLAC__metadata_simple_iterator_next(iterator))
913                 return die_("iterator ended early\n");
914         our_current_position++;
915
916         printf("SV[P]P\tnext\n");
917         if(!FLAC__metadata_simple_iterator_next(iterator))
918                 return die_("iterator ended early\n");
919         our_current_position++;
920
921         printf("SVP[P]\tdelete (last block), replace with padding\n");
922         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
923                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
924         our_current_position--;
925
926         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
927                 return false;
928
929         printf("SV[P]P\tnext\n");
930         if(!FLAC__metadata_simple_iterator_next(iterator))
931                 return die_("iterator ended early\n");
932         our_current_position++;
933
934         printf("SVP[P]\tdelete (last block), don't replace with padding\n");
935         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
936                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
937         delete_from_our_metadata_(our_current_position--);
938
939         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
940                 return false;
941
942         printf("SV[P]\tprev\n");
943         if(!FLAC__metadata_simple_iterator_prev(iterator))
944                 return die_("iterator ended early\n");
945         our_current_position--;
946
947         printf("S[V]P\tprev\n");
948         if(!FLAC__metadata_simple_iterator_prev(iterator))
949                 return die_("iterator ended early\n");
950         our_current_position--;
951
952         printf("[S]VP\tset STREAMINFO (change sample rate)\n");
953         FLAC__ASSERT(our_current_position == 0);
954         block = FLAC__metadata_simple_iterator_get_block(iterator);
955         block->data.stream_info.sample_rate = 32000;
956         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
957                 return die_("copying object");
958         if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
959                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
960         FLAC__metadata_object_delete(block);
961
962         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
963                 return false;
964
965         printf("[S]VP\tnext\n");
966         if(!FLAC__metadata_simple_iterator_next(iterator))
967                 return die_("iterator ended early\n");
968         our_current_position++;
969
970         printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
971         app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
972         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
973                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
974         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
975                 return false;
976         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
977
978         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
979                 return false;
980
981         printf("SV[A]P\tnext\n");
982         if(!FLAC__metadata_simple_iterator_next(iterator))
983                 return die_("iterator ended early\n");
984         our_current_position++;
985
986         printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
987         app->data.application.id[0] = 'f'; /* twiddle the id */
988         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
989                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
990         if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
991                 return false;
992         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
993
994         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
995                 return false;
996
997         printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
998         app->data.application.id[0] = 'g'; /* twiddle the id */
999         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1000                 return die_("setting APPLICATION data");
1001         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1002                 return die_("copying object");
1003         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1004                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1005
1006         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1007                 return false;
1008
1009         printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1010         app->data.application.id[0] = 'h'; /* twiddle the id */
1011         if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1012                 return die_("setting APPLICATION data");
1013         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1014                 return die_("copying object");
1015         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1016                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1017
1018         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1019                 return false;
1020
1021         printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1022         app->data.application.id[0] = 'i'; /* twiddle the id */
1023         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1024                 return die_("setting APPLICATION data");
1025         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1026                 return die_("copying object");
1027         our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1028         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1029                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1030
1031         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1032                 return false;
1033
1034         printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1035         app->data.application.id[0] = 'j'; /* twiddle the id */
1036         if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1037                 return die_("setting APPLICATION data");
1038         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1039                 return die_("copying object");
1040         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1041                 return die_("copying object");
1042         our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1043         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1044                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1045
1046         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1047                 return false;
1048
1049         printf("SVA[A]PP\tnext\n");
1050         if(!FLAC__metadata_simple_iterator_next(iterator))
1051                 return die_("iterator ended early\n");
1052         our_current_position++;
1053
1054         printf("SVAA[P]P\tnext\n");
1055         if(!FLAC__metadata_simple_iterator_next(iterator))
1056                 return die_("iterator ended early\n");
1057         our_current_position++;
1058
1059         printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1060         padding->length = 5;
1061         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1062                 return die_("copying object");
1063         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1064                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1065
1066         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1067                 return false;
1068
1069         printf("SVAAP[P]\tset APPLICATION (grow)\n");
1070         app->data.application.id[0] = 'k'; /* twiddle the id */
1071         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1072                 return die_("copying object");
1073         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1074                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1075
1076         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1077                 return false;
1078
1079         printf("SVAAP[A]\tset PADDING (equal)\n");
1080         padding->length = 27;
1081         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1082                 return die_("copying object");
1083         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1084                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1085
1086         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1087                 return false;
1088
1089         printf("SVAAP[P]\tprev\n");
1090         if(!FLAC__metadata_simple_iterator_prev(iterator))
1091                 return die_("iterator ended early\n");
1092         our_current_position--;
1093
1094         printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1095         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1096                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1097         delete_from_our_metadata_(our_current_position--);
1098
1099         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1100                 return false;
1101
1102         printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1103         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1104                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1105         delete_from_our_metadata_(our_current_position--);
1106
1107         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1108                 return false;
1109
1110         printf("SV[A]P\tnext\n");
1111         if(!FLAC__metadata_simple_iterator_next(iterator))
1112                 return die_("iterator ended early\n");
1113         our_current_position++;
1114
1115         printf("SVA[P]\tinsert PADDING after\n");
1116         padding->length = 5;
1117         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1118                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1119         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1120                 return false;
1121
1122         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1123                 return false;
1124
1125         printf("SVAP[P]\tprev\n");
1126         if(!FLAC__metadata_simple_iterator_prev(iterator))
1127                 return die_("iterator ended early\n");
1128         our_current_position--;
1129
1130         printf("SVA[P]P\tprev\n");
1131         if(!FLAC__metadata_simple_iterator_prev(iterator))
1132                 return die_("iterator ended early\n");
1133         our_current_position--;
1134
1135         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1136         if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1137                 return die_("setting APPLICATION data");
1138         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1139                 return die_("copying object");
1140         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1141                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1142
1143         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1144                 return false;
1145
1146         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1147         if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1148                 return die_("setting APPLICATION data");
1149         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1150                 return die_("copying object");
1151         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1152                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1153
1154         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1155                 return false;
1156
1157         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1158         if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1159                 return die_("setting APPLICATION data");
1160         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1161                 return die_("copying object");
1162         our_metadata_.blocks[our_current_position+1]->length = 0;
1163         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1164                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1165
1166         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1167                 return false;
1168
1169         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1170         if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1171                 return die_("setting APPLICATION data");
1172         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1173                 return die_("copying object");
1174         delete_from_our_metadata_(our_current_position+1);
1175         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1176                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1177
1178         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1179                 return false;
1180
1181         printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1182         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1183                 return die_("setting APPLICATION data");
1184         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1185                 return die_("copying object");
1186         delete_from_our_metadata_(our_current_position+1);
1187         our_metadata_.blocks[our_current_position]->is_last = true;
1188         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1189                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1190
1191         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1192                 return false;
1193
1194         printf("SV[A]\tset PADDING (equal size)\n");
1195         padding->length = app->length;
1196         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1197                 return die_("copying object");
1198         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1199                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1200
1201         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1202                 return false;
1203
1204         printf("SV[P]\tinsert PADDING after\n");
1205         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1206                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1207         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1208                 return false;
1209
1210         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1211                 return false;
1212
1213         printf("SVP[P]\tinsert PADDING after\n");
1214         padding->length = 5;
1215         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1216                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1217         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1218                 return false;
1219
1220         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1221                 return false;
1222
1223         printf("SVPP[P]\tprev\n");
1224         if(!FLAC__metadata_simple_iterator_prev(iterator))
1225                 return die_("iterator ended early\n");
1226         our_current_position--;
1227
1228         printf("SVP[P]P\tprev\n");
1229         if(!FLAC__metadata_simple_iterator_prev(iterator))
1230                 return die_("iterator ended early\n");
1231         our_current_position--;
1232
1233         printf("SV[P]PP\tprev\n");
1234         if(!FLAC__metadata_simple_iterator_prev(iterator))
1235                 return die_("iterator ended early\n");
1236         our_current_position--;
1237
1238         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1239         if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1240                 return die_("setting APPLICATION data");
1241         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1242                 return die_("copying object");
1243         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1244                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1245
1246         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1247                 return false;
1248
1249         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1250         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1251                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1252         delete_from_our_metadata_(our_current_position--);
1253
1254         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1255                 return false;
1256
1257         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1258         if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1259                 return die_("setting APPLICATION data");
1260         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1261                 return die_("copying object");
1262         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1263                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1264
1265         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1266                 return false;
1267
1268         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1269         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1270                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1271         delete_from_our_metadata_(our_current_position--);
1272
1273         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1274                 return false;
1275
1276         printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1277         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1278                 return die_("setting APPLICATION data");
1279         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1280                 return die_("copying object");
1281         delete_from_our_metadata_(our_current_position+1);
1282         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1283                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1284
1285         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1286                 return false;
1287
1288         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1289         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1290                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1291         delete_from_our_metadata_(our_current_position--);
1292
1293         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1294                 return false;
1295
1296         printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1297         if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1298                 return die_("setting APPLICATION data");
1299         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1300                 return die_("copying object");
1301         our_metadata_.blocks[our_current_position+1]->length = 0;
1302         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1303                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1304
1305         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1306                 return false;
1307
1308         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1309         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1310                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1311         delete_from_our_metadata_(our_current_position--);
1312
1313         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1314                 return false;
1315
1316         printf("S[V]PP\tnext\n");
1317         if(!FLAC__metadata_simple_iterator_next(iterator))
1318                 return die_("iterator ended early\n");
1319         our_current_position++;
1320
1321         printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1322         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1323                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1324         delete_from_our_metadata_(our_current_position--);
1325
1326         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1327                 return false;
1328
1329         printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1330         if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1331                 return die_("setting APPLICATION data");
1332         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1333                 return die_("copying object");
1334         delete_from_our_metadata_(our_current_position+1);
1335         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1336                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1337
1338         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1339                 return false;
1340
1341         printf("delete simple iterator\n");
1342
1343         FLAC__metadata_simple_iterator_delete(iterator);
1344
1345         FLAC__metadata_object_delete(app);
1346         FLAC__metadata_object_delete(padding);
1347
1348         if(!remove_file_(flacfile_))
1349                 return false;
1350
1351         return true;
1352 }
1353
1354 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1355 {
1356         FLAC__Metadata_Iterator *iterator;
1357         FLAC__Metadata_Chain *chain;
1358         FLAC__StreamMetadata *block, *app, *padding;
1359         FLAC__byte data[2000];
1360         unsigned our_current_position;
1361
1362         /* initialize 'data' to avoid Valgrind errors */
1363         memset(data, 0, sizeof(data));
1364
1365         printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1366
1367         printf("generate read-only file\n");
1368
1369         if(!generate_file_(/*include_cuesheet=*/false))
1370                 return false;
1371
1372         if(!change_stats_(flacfile_, /*read_only=*/true))
1373                 return false;
1374
1375         printf("create chain\n");
1376
1377         if(0 == (chain = FLAC__metadata_chain_new()))
1378                 return die_("allocating chain");
1379
1380         printf("read chain\n");
1381
1382         if(!read_chain_(chain, flacfile_, filename_based))
1383                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1384
1385         printf("[S]VP\ttest initial metadata\n");
1386
1387         if(!compare_chain_(chain, 0, 0))
1388                 return false;
1389         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1390                 return false;
1391
1392         printf("switch file to read-write\n");
1393
1394         if(!change_stats_(flacfile_, /*read-only=*/false))
1395                 return false;
1396
1397         printf("create iterator\n");
1398         if(0 == (iterator = FLAC__metadata_iterator_new()))
1399                 return die_("allocating memory for iterator");
1400
1401         our_current_position = 0;
1402
1403         FLAC__metadata_iterator_init(iterator, chain);
1404
1405         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1406                 return die_("getting block from iterator");
1407
1408         FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1409
1410         printf("[S]VP\tmodify STREAMINFO, write\n");
1411
1412         block->data.stream_info.sample_rate = 32000;
1413         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1414                 return die_("copying object");
1415
1416         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1417                 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1418         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1419                 return false;
1420         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1421                 return false;
1422
1423         printf("[S]VP\tnext\n");
1424         if(!FLAC__metadata_iterator_next(iterator))
1425                 return die_("iterator ended early\n");
1426         our_current_position++;
1427
1428         printf("S[V]P\tnext\n");
1429         if(!FLAC__metadata_iterator_next(iterator))
1430                 return die_("iterator ended early\n");
1431         our_current_position++;
1432
1433         printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1434         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1435                 return die_("getting block from iterator");
1436         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1437                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1438         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1439         if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1440                 return die_("setting APPLICATION data");
1441         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1442                 return die_("copying object");
1443         if(!FLAC__metadata_iterator_set_block(iterator, app))
1444                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1445
1446         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1447                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1448         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1449                 return false;
1450         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1451                 return false;
1452
1453         printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1454         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1455                 return die_("copying object");
1456         if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1457                 return die_("setting APPLICATION data");
1458         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1459                 return die_("copying object");
1460         if(!FLAC__metadata_iterator_set_block(iterator, app))
1461                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1462
1463         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1464                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1465         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1466                 return false;
1467         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1468                 return false;
1469
1470         printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1471         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1472                 return die_("copying object");
1473         if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1474                 return die_("setting APPLICATION data");
1475         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1476                 return die_("copying object");
1477         if(!FLAC__metadata_iterator_set_block(iterator, app))
1478                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1479
1480         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1481                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1482         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1483                 return false;
1484         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1485                 return false;
1486
1487         printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1488         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1489                 return die_("copying object");
1490         if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1491                 return die_("setting APPLICATION data");
1492         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1493                 return die_("copying object");
1494         if(!FLAC__metadata_iterator_set_block(iterator, app))
1495                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1496
1497         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1498                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1499         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1500                 return false;
1501         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1502                 return false;
1503
1504         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1505         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1506                 return die_("copying object");
1507         if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1508                 return die_("setting APPLICATION data");
1509         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1510                 return die_("copying object");
1511         if(!FLAC__metadata_iterator_set_block(iterator, app))
1512                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1513
1514         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1515                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1516         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1517                 return false;
1518         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1519                 return false;
1520
1521         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1522         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1523                 return die_("creating PADDING block");
1524         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1525                 return die_("copying object");
1526         if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1527                 return die_("setting APPLICATION data");
1528         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1529                 return die_("copying object");
1530         padding->length = 0;
1531         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1532                 return die_("internal error");
1533         if(!FLAC__metadata_iterator_set_block(iterator, app))
1534                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1535
1536         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1537                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1538         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1539                 return false;
1540         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1541                 return false;
1542
1543         printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1544         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1545                 return die_("copying object");
1546         if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1547                 return die_("setting APPLICATION data");
1548         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1549                 return die_("copying object");
1550         our_metadata_.blocks[our_current_position+1]->length = 13;
1551         if(!FLAC__metadata_iterator_set_block(iterator, app))
1552                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1553
1554         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1555                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1556         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1557                 return false;
1558         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1559                 return false;
1560
1561         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1562         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1563                 return die_("copying object");
1564         if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1565                 return die_("setting APPLICATION data");
1566         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1567                 return die_("copying object");
1568         if(!FLAC__metadata_iterator_set_block(iterator, app))
1569                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1570
1571         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1572                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1573         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1574                 return false;
1575         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1576                 return false;
1577
1578         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1579         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1580                 return die_("copying object");
1581         if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1582                 return die_("setting APPLICATION data");
1583         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1584                 return die_("copying object");
1585         our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1586         if(!FLAC__metadata_iterator_set_block(iterator, app))
1587                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1588
1589         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1590                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1591         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1592                 return false;
1593         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1594                 return false;
1595
1596         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1597         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1598                 return die_("copying object");
1599         if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1600                 return die_("setting APPLICATION data");
1601         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1602                 return die_("copying object");
1603         delete_from_our_metadata_(our_current_position+1);
1604         if(!FLAC__metadata_iterator_set_block(iterator, app))
1605                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1606
1607         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1608                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1609         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1610                 return false;
1611         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1612                 return false;
1613
1614         printf("SV[A]\tprev\n");
1615         if(!FLAC__metadata_iterator_prev(iterator))
1616                 return die_("iterator ended early\n");
1617         our_current_position--;
1618
1619         printf("S[V]A\tprev\n");
1620         if(!FLAC__metadata_iterator_prev(iterator))
1621                 return die_("iterator ended early\n");
1622         our_current_position--;
1623
1624         printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1625         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1626                 return die_("creating PADDING block");
1627         padding->length = 30;
1628         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1629                 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1630         else
1631                 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1632
1633         printf("[S]VP\tnext\n");
1634         if(!FLAC__metadata_iterator_next(iterator))
1635                 return die_("iterator ended early\n");
1636         our_current_position++;
1637
1638         printf("S[V]A\tinsert PADDING after\n");
1639         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1640                 return die_("copying metadata");
1641         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1642                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1643
1644         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1645                 return false;
1646
1647         printf("SV[P]A\tinsert PADDING before\n");
1648         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1649                 return die_("creating PADDING block");
1650         padding->length = 17;
1651         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1652                 return die_("copying metadata");
1653         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1654                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1655
1656         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1657                 return false;
1658
1659         printf("SV[P]PA\tinsert PADDING before\n");
1660         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1661                 return die_("creating PADDING block");
1662         padding->length = 0;
1663         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1664                 return die_("copying metadata");
1665         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1666                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1667
1668         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1669                 return false;
1670
1671         printf("SV[P]PPA\tnext\n");
1672         if(!FLAC__metadata_iterator_next(iterator))
1673                 return die_("iterator ended early\n");
1674         our_current_position++;
1675
1676         printf("SVP[P]PA\tnext\n");
1677         if(!FLAC__metadata_iterator_next(iterator))
1678                 return die_("iterator ended early\n");
1679         our_current_position++;
1680
1681         printf("SVPP[P]A\tnext\n");
1682         if(!FLAC__metadata_iterator_next(iterator))
1683                 return die_("iterator ended early\n");
1684         our_current_position++;
1685
1686         printf("SVPPP[A]\tinsert PADDING after\n");
1687         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1688                 return die_("creating PADDING block");
1689         padding->length = 57;
1690         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1691                 return die_("copying metadata");
1692         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1693                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1694
1695         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1696                 return false;
1697
1698         printf("SVPPPA[P]\tinsert PADDING before\n");
1699         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1700                 return die_("creating PADDING block");
1701         padding->length = 99;
1702         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1703                 return die_("copying metadata");
1704         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1705                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1706
1707         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1708                 return false;
1709
1710         printf("delete iterator\n");
1711         FLAC__metadata_iterator_delete(iterator);
1712         our_current_position = 0;
1713
1714         printf("SVPPPAPP\tmerge padding\n");
1715         FLAC__metadata_chain_merge_padding(chain);
1716         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1717         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1718         our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1719         delete_from_our_metadata_(7);
1720         delete_from_our_metadata_(4);
1721         delete_from_our_metadata_(3);
1722
1723         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1724                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1725         if(!compare_chain_(chain, 0, 0))
1726                 return false;
1727         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1728                 return false;
1729
1730         printf("SVPAP\tsort padding\n");
1731         FLAC__metadata_chain_sort_padding(chain);
1732         our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1733         delete_from_our_metadata_(2);
1734
1735         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1736                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1737         if(!compare_chain_(chain, 0, 0))
1738                 return false;
1739         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1740                 return false;
1741
1742         printf("create iterator\n");
1743         if(0 == (iterator = FLAC__metadata_iterator_new()))
1744                 return die_("allocating memory for iterator");
1745
1746         our_current_position = 0;
1747
1748         FLAC__metadata_iterator_init(iterator, chain);
1749
1750         printf("[S]VAP\tnext\n");
1751         if(!FLAC__metadata_iterator_next(iterator))
1752                 return die_("iterator ended early\n");
1753         our_current_position++;
1754
1755         printf("S[V]AP\tnext\n");
1756         if(!FLAC__metadata_iterator_next(iterator))
1757                 return die_("iterator ended early\n");
1758         our_current_position++;
1759
1760         printf("SV[A]P\tdelete middle block, replace with padding\n");
1761         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1762                 return die_("creating PADDING block");
1763         padding->length = 71;
1764         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1765                 return die_("copying object");
1766         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1767                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1768
1769         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1770                 return false;
1771
1772         printf("S[V]PP\tnext\n");
1773         if(!FLAC__metadata_iterator_next(iterator))
1774                 return die_("iterator ended early\n");
1775         our_current_position++;
1776
1777         printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1778         delete_from_our_metadata_(our_current_position--);
1779         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1780                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1781
1782         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1783                 return false;
1784
1785         printf("S[V]P\tnext\n");
1786         if(!FLAC__metadata_iterator_next(iterator))
1787                 return die_("iterator ended early\n");
1788         our_current_position++;
1789
1790         printf("SV[P]\tdelete last block, replace with padding\n");
1791         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1792                 return die_("creating PADDING block");
1793         padding->length = 219;
1794         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1795                 return die_("copying object");
1796         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1797                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1798
1799         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1800                 return false;
1801
1802         printf("S[V]P\tnext\n");
1803         if(!FLAC__metadata_iterator_next(iterator))
1804                 return die_("iterator ended early\n");
1805         our_current_position++;
1806
1807         printf("SV[P]\tdelete last block, don't replace with padding\n");
1808         delete_from_our_metadata_(our_current_position--);
1809         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1810                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1811
1812         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1813                 return false;
1814
1815         printf("S[V]\tprev\n");
1816         if(!FLAC__metadata_iterator_prev(iterator))
1817                 return die_("iterator ended early\n");
1818         our_current_position--;
1819
1820         printf("[S]V\tdelete STREAMINFO block, should fail\n");
1821         if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1822                 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1823
1824         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1825                 return false;
1826
1827         printf("delete iterator\n");
1828         FLAC__metadata_iterator_delete(iterator);
1829         our_current_position = 0;
1830
1831         printf("SV\tmerge padding\n");
1832         FLAC__metadata_chain_merge_padding(chain);
1833
1834         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1835                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1836         if(!compare_chain_(chain, 0, 0))
1837                 return false;
1838         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1839                 return false;
1840
1841         printf("SV\tsort padding\n");
1842         FLAC__metadata_chain_sort_padding(chain);
1843
1844         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1845                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1846         if(!compare_chain_(chain, 0, 0))
1847                 return false;
1848         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1849                 return false;
1850
1851         printf("delete chain\n");
1852
1853         FLAC__metadata_chain_delete(chain);
1854
1855         if(!remove_file_(flacfile_))
1856                 return false;
1857
1858         return true;
1859 }
1860
1861 static FLAC__bool test_level_2_misc_()
1862 {
1863         FLAC__Metadata_Iterator *iterator;
1864         FLAC__Metadata_Chain *chain;
1865         FLAC__IOCallbacks callbacks;
1866
1867         memset(&callbacks, 0, sizeof(callbacks));
1868         callbacks.read = (FLAC__IOCallback_Read)fread;
1869 #ifdef FLAC__VALGRIND_TESTING
1870         callbacks.write = chain_write_cb_;
1871 #else
1872         callbacks.write = (FLAC__IOCallback_Write)fwrite;
1873 #endif
1874         callbacks.seek = chain_seek_cb_;
1875         callbacks.tell = chain_tell_cb_;
1876         callbacks.eof = chain_eof_cb_;
1877
1878         printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1879
1880         printf("generate file\n");
1881
1882         if(!generate_file_(/*include_cuesheet=*/false))
1883                 return false;
1884
1885         printf("create chain\n");
1886
1887         if(0 == (chain = FLAC__metadata_chain_new()))
1888                 return die_("allocating chain");
1889
1890         printf("read chain (filename-based)\n");
1891
1892         if(!FLAC__metadata_chain_read(chain, flacfile_))
1893                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1894
1895         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1896         {
1897                 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1898                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1899                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1900                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1901                 printf("  OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1902         }
1903
1904         printf("read chain (filename-based)\n");
1905
1906         if(!FLAC__metadata_chain_read(chain, flacfile_))
1907                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1908
1909         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1910         {
1911                 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1912                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1913                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1914                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1915                 printf("  OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1916         }
1917
1918         printf("read chain (callback-based)\n");
1919         {
1920                 FILE *file = fopen(flacfile_, "rb");
1921                 if(0 == file)
1922                         return die_("opening file");
1923                 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1924                         fclose(file);
1925                         return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1926                 }
1927                 fclose(file);
1928         }
1929
1930         printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1931         {
1932                 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1933                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1934                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1935                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1936                 printf("  OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1937         }
1938
1939         printf("read chain (callback-based)\n");
1940         {
1941                 FILE *file = fopen(flacfile_, "rb");
1942                 if(0 == file)
1943                         return die_("opening file");
1944                 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1945                         fclose(file);
1946                         return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1947                 }
1948                 fclose(file);
1949         }
1950
1951         printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1952
1953         if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1954                 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1955         else
1956                 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1957
1958         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1959         {
1960                 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1961                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1962                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1963                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1964                 printf("  OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1965         }
1966
1967         printf("read chain (callback-based)\n");
1968         {
1969                 FILE *file = fopen(flacfile_, "rb");
1970                 if(0 == file)
1971                         return die_("opening file");
1972                 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1973                         fclose(file);
1974                         return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1975                 }
1976                 fclose(file);
1977         }
1978
1979         printf("create iterator\n");
1980         if(0 == (iterator = FLAC__metadata_iterator_new()))
1981                 return die_("allocating memory for iterator");
1982
1983         FLAC__metadata_iterator_init(iterator, chain);
1984
1985         printf("[S]VP\tnext\n");
1986         if(!FLAC__metadata_iterator_next(iterator))
1987                 return die_("iterator ended early\n");
1988
1989         printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1990         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1991                 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1992
1993         printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1994
1995         if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1996                 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1997         else
1998                 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1999
2000         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2001         {
2002                 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2003                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2004                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2005                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2006                 printf("  OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2007         }
2008
2009         printf("delete iterator\n");
2010
2011         FLAC__metadata_iterator_delete(iterator);
2012
2013         printf("delete chain\n");
2014
2015         FLAC__metadata_chain_delete(chain);
2016
2017         if(!remove_file_(flacfile_))
2018                 return false;
2019
2020         return true;
2021 }
2022
2023 FLAC__bool test_metadata_file_manipulation()
2024 {
2025         printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2026
2027         our_metadata_.num_blocks = 0;
2028
2029         if(!test_level_0_())
2030                 return false;
2031
2032         if(!test_level_1_())
2033                 return false;
2034
2035         if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2036                 return false;
2037         if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2038                 return false;
2039         if(!test_level_2_misc_())
2040                 return false;
2041
2042         return true;
2043 }