merge down from merged-API-layer branch: cvs -q up -dP -j API_LAYER_MERGING_BASELINE...
[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 "FLAC/assert.h"
38 #include "FLAC/stream_decoder.h"
39 #include "FLAC/metadata.h"
40 #include "share/grabbag.h"
41 #include "test_libs_common/file_utils_flac.h"
42 #include "test_libs_common/metadata_utils.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__StreamDecoder 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__StreamDecoder *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__StreamDecoder *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__StreamDecoder *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__StreamDecoder *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__StreamDecoderMetadataCallback metadata_callback)
563 {
564         FLAC__StreamDecoder *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__stream_decoder_new()))
577                 return die_("couldn't allocate decoder instance");
578
579         FLAC__stream_decoder_set_md5_checking(decoder, true);
580         FLAC__stream_decoder_set_metadata_respond_all(decoder);
581         if(FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
582                 FLAC__stream_decoder_finish(decoder);
583                 FLAC__stream_decoder_delete(decoder);
584                 return die_("initializing decoder\n");
585         }
586         if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
587                 FLAC__stream_decoder_finish(decoder);
588                 FLAC__stream_decoder_delete(decoder);
589                 return die_("decoding file\n");
590         }
591
592         FLAC__stream_decoder_finish(decoder);
593         FLAC__stream_decoder_delete(decoder);
594
595         if(decoder_client_data.error_occurred)
596                 return false;
597
598         if(mc_our_block_number_ != our_metadata_.num_blocks)
599                 return die_("short metadata block count");
600
601         printf("PASSED\n");
602         return true;
603 }
604
605 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
606 {
607         if(!grabbag__file_change_stats(filename, read_only))
608                 return die_("during grabbag__file_change_stats()");
609
610         return true;
611 }
612
613 static FLAC__bool remove_file_(const char *filename)
614 {
615         while(our_metadata_.num_blocks > 0)
616                 delete_from_our_metadata_(0);
617
618         if(!grabbag__file_remove_file(filename))
619                 return die_("removing file");
620
621         return true;
622 }
623
624 static FLAC__bool test_level_0_()
625 {
626         FLAC__StreamMetadata streaminfo;
627         FLAC__StreamMetadata *tags = 0;
628         FLAC__StreamMetadata *cuesheet = 0;
629
630         printf("\n\n++++++ testing level 0 interface\n");
631
632         if(!generate_file_(/*include_cuesheet=*/true))
633                 return false;
634
635         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
636                 return false;
637
638         printf("testing FLAC__metadata_get_streaminfo()... ");
639
640         if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
641                 return die_("during FLAC__metadata_get_streaminfo()");
642
643         /* check to see if some basic data matches (c.f. generate_file_()) */
644         if(streaminfo.data.stream_info.channels != 1)
645                 return die_("mismatch in streaminfo.data.stream_info.channels");
646         if(streaminfo.data.stream_info.bits_per_sample != 8)
647                 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
648         if(streaminfo.data.stream_info.sample_rate != 44100)
649                 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
650         if(streaminfo.data.stream_info.min_blocksize != 576)
651                 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
652         if(streaminfo.data.stream_info.max_blocksize != 576)
653                 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
654
655         printf("OK\n");
656
657         printf("testing FLAC__metadata_get_tags()... ");
658
659         if(!FLAC__metadata_get_tags(flacfile_, &tags))
660                 return die_("during FLAC__metadata_get_tags()");
661
662         /* check to see if some basic data matches (c.f. generate_file_()) */
663         if(tags->data.vorbis_comment.num_comments != 0)
664                 return die_("mismatch in tags->data.vorbis_comment.num_comments");
665
666         printf("OK\n");
667
668         FLAC__metadata_object_delete(tags);
669
670         printf("testing FLAC__metadata_get_cuesheet()... ");
671
672         if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
673                 return die_("during FLAC__metadata_get_cuesheet()");
674
675         /* check to see if some basic data matches (c.f. generate_file_()) */
676         if(cuesheet->data.cue_sheet.lead_in != 123)
677                 return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
678
679         printf("OK\n");
680
681         FLAC__metadata_object_delete(cuesheet);
682
683         if(!remove_file_(flacfile_))
684                 return false;
685
686         return true;
687 }
688
689 static FLAC__bool test_level_1_()
690 {
691         FLAC__Metadata_SimpleIterator *iterator;
692         FLAC__StreamMetadata *block, *app, *padding;
693         FLAC__byte data[1000];
694         unsigned our_current_position = 0;
695
696         /* initialize 'data' to avoid Valgrind errors */
697         memset(data, 0, sizeof(data));
698
699         printf("\n\n++++++ testing level 1 interface\n");
700
701         /************************************************************/
702
703         printf("simple iterator on read-only file\n");
704
705         if(!generate_file_(/*include_cuesheet=*/false))
706                 return false;
707
708         if(!change_stats_(flacfile_, /*read_only=*/true))
709                 return false;
710
711         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
712                 return false;
713
714         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
715                 return die_("FLAC__metadata_simple_iterator_new()");
716
717         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
718                 return die_("FLAC__metadata_simple_iterator_init() returned false");
719
720         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
721         if(FLAC__metadata_simple_iterator_is_writable(iterator))
722                 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
723
724         printf("iterate forwards\n");
725
726         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
727                 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
728         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
729                 return die_("getting block 0");
730         if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
731                 return die_("expected STREAMINFO type");
732         if(block->is_last)
733                 return die_("expected is_last to be false");
734         if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
735                 return die_("bad STREAMINFO length");
736         /* check to see if some basic data matches (c.f. generate_file_()) */
737         if(block->data.stream_info.channels != 1)
738                 return die_("mismatch in channels");
739         if(block->data.stream_info.bits_per_sample != 8)
740                 return die_("mismatch in bits_per_sample");
741         if(block->data.stream_info.sample_rate != 44100)
742                 return die_("mismatch in sample_rate");
743         if(block->data.stream_info.min_blocksize != 576)
744                 return die_("mismatch in min_blocksize");
745         if(block->data.stream_info.max_blocksize != 576)
746                 return die_("mismatch in max_blocksize");
747         FLAC__metadata_object_delete(block);
748
749         if(!FLAC__metadata_simple_iterator_next(iterator))
750                 return die_("forward iterator ended early");
751         our_current_position++;
752
753         if(!FLAC__metadata_simple_iterator_next(iterator))
754                 return die_("forward iterator ended early");
755         our_current_position++;
756
757         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
758                 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
759         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
760                 return die_("getting block 2");
761         if(block->type != FLAC__METADATA_TYPE_PADDING)
762                 return die_("expected PADDING type");
763         if(!block->is_last)
764                 return die_("expected is_last to be true");
765         /* check to see if some basic data matches (c.f. generate_file_()) */
766         if(block->length != 1234)
767                 return die_("bad PADDING length");
768         FLAC__metadata_object_delete(block);
769
770         if(FLAC__metadata_simple_iterator_next(iterator))
771                 return die_("forward iterator returned true but should have returned false");
772
773         printf("iterate backwards\n");
774         if(!FLAC__metadata_simple_iterator_prev(iterator))
775                 return die_("reverse iterator ended early");
776         if(!FLAC__metadata_simple_iterator_prev(iterator))
777                 return die_("reverse iterator ended early");
778         if(FLAC__metadata_simple_iterator_prev(iterator))
779                 return die_("reverse iterator returned true but should have returned false");
780
781         printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
782
783         if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
784                 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
785         else
786                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
787
788         FLAC__metadata_simple_iterator_delete(iterator);
789
790         /************************************************************/
791
792         printf("simple iterator on writable file\n");
793
794         if(!change_stats_(flacfile_, /*read-only=*/false))
795                 return false;
796
797         printf("creating APPLICATION block\n");
798
799         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
800                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
801         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
802
803         printf("creating PADDING block\n");
804
805         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
806                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
807         padding->length = 20;
808
809         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
810                 return die_("FLAC__metadata_simple_iterator_new()");
811
812         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
813                 return die_("FLAC__metadata_simple_iterator_init() returned false");
814         our_current_position = 0;
815
816         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
817
818         printf("[S]VP\ttry to write over STREAMINFO block...\n");
819         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
820                 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
821         else
822                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
823
824         printf("[S]VP\tnext\n");
825         if(!FLAC__metadata_simple_iterator_next(iterator))
826                 return die_("iterator ended early\n");
827         our_current_position++;
828
829         printf("S[V]P\tnext\n");
830         if(!FLAC__metadata_simple_iterator_next(iterator))
831                 return die_("iterator ended early\n");
832         our_current_position++;
833
834         printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
835         padding->length = 25;
836         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
837                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
838         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
839                 return false;
840
841         printf("SVP[P]\tprev\n");
842         if(!FLAC__metadata_simple_iterator_prev(iterator))
843                 return die_("iterator ended early\n");
844         our_current_position--;
845
846         printf("SV[P]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("S[V]PP\tinsert PADDING after, don't expand into padding\n");
852         padding->length = 30;
853         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
854                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
855         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
856                 return false;
857
858         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
859                 return false;
860
861         printf("SV[P]PP\tprev\n");
862         if(!FLAC__metadata_simple_iterator_prev(iterator))
863                 return die_("iterator ended early\n");
864         our_current_position--;
865
866         printf("S[V]PPP\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]VPPP\tdelete (STREAMINFO block), must fail\n");
872         if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
873                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
874
875         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
876                 return false;
877
878         printf("[S]VPPP\tnext\n");
879         if(!FLAC__metadata_simple_iterator_next(iterator))
880                 return die_("iterator ended early\n");
881         our_current_position++;
882
883         printf("S[V]PPP\tnext\n");
884         if(!FLAC__metadata_simple_iterator_next(iterator))
885                 return die_("iterator ended early\n");
886         our_current_position++;
887
888         printf("SV[P]PP\tdelete (middle block), replace with padding\n");
889         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
890                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
891         our_current_position--;
892
893         printf("S[V]PPP\tnext\n");
894         if(!FLAC__metadata_simple_iterator_next(iterator))
895                 return die_("iterator ended early\n");
896         our_current_position++;
897
898         printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
899         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
900                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
901         delete_from_our_metadata_(our_current_position--);
902
903         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
904                 return false;
905
906         printf("S[V]PP\tnext\n");
907         if(!FLAC__metadata_simple_iterator_next(iterator))
908                 return die_("iterator ended early\n");
909         our_current_position++;
910
911         printf("SV[P]P\tnext\n");
912         if(!FLAC__metadata_simple_iterator_next(iterator))
913                 return die_("iterator ended early\n");
914         our_current_position++;
915
916         printf("SVP[P]\tdelete (last block), replace with padding\n");
917         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
918                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
919         our_current_position--;
920
921         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
922                 return false;
923
924         printf("SV[P]P\tnext\n");
925         if(!FLAC__metadata_simple_iterator_next(iterator))
926                 return die_("iterator ended early\n");
927         our_current_position++;
928
929         printf("SVP[P]\tdelete (last block), don't replace with padding\n");
930         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
931                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
932         delete_from_our_metadata_(our_current_position--);
933
934         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
935                 return false;
936
937         printf("SV[P]\tprev\n");
938         if(!FLAC__metadata_simple_iterator_prev(iterator))
939                 return die_("iterator ended early\n");
940         our_current_position--;
941
942         printf("S[V]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]VP\tset STREAMINFO (change sample rate)\n");
948         FLAC__ASSERT(our_current_position == 0);
949         block = FLAC__metadata_simple_iterator_get_block(iterator);
950         block->data.stream_info.sample_rate = 32000;
951         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
952                 return die_("copying object");
953         if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
954                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
955         FLAC__metadata_object_delete(block);
956
957         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
958                 return false;
959
960         printf("[S]VP\tnext\n");
961         if(!FLAC__metadata_simple_iterator_next(iterator))
962                 return die_("iterator ended early\n");
963         our_current_position++;
964
965         printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
966         app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
967         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
968                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
969         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
970                 return false;
971         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
972
973         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
974                 return false;
975
976         printf("SV[A]P\tnext\n");
977         if(!FLAC__metadata_simple_iterator_next(iterator))
978                 return die_("iterator ended early\n");
979         our_current_position++;
980
981         printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
982         app->data.application.id[0] = 'f'; /* twiddle the id */
983         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
984                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
985         if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
986                 return false;
987         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
988
989         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
990                 return false;
991
992         printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
993         app->data.application.id[0] = 'g'; /* twiddle the id */
994         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
995                 return die_("setting APPLICATION data");
996         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
997                 return die_("copying object");
998         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
999                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1000
1001         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1002                 return false;
1003
1004         printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1005         app->data.application.id[0] = 'h'; /* twiddle the id */
1006         if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1007                 return die_("setting APPLICATION data");
1008         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1009                 return die_("copying object");
1010         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1011                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1012
1013         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1014                 return false;
1015
1016         printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1017         app->data.application.id[0] = 'i'; /* twiddle the id */
1018         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1019                 return die_("setting APPLICATION data");
1020         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1021                 return die_("copying object");
1022         our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1023         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1024                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1025
1026         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1027                 return false;
1028
1029         printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1030         app->data.application.id[0] = 'j'; /* twiddle the id */
1031         if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1032                 return die_("setting APPLICATION data");
1033         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1034                 return die_("copying object");
1035         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1036                 return die_("copying object");
1037         our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1038         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1039                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1040
1041         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1042                 return false;
1043
1044         printf("SVA[A]PP\tnext\n");
1045         if(!FLAC__metadata_simple_iterator_next(iterator))
1046                 return die_("iterator ended early\n");
1047         our_current_position++;
1048
1049         printf("SVAA[P]P\tnext\n");
1050         if(!FLAC__metadata_simple_iterator_next(iterator))
1051                 return die_("iterator ended early\n");
1052         our_current_position++;
1053
1054         printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1055         padding->length = 5;
1056         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1057                 return die_("copying object");
1058         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1059                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1060
1061         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1062                 return false;
1063
1064         printf("SVAAP[P]\tset APPLICATION (grow)\n");
1065         app->data.application.id[0] = 'k'; /* twiddle the id */
1066         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1067                 return die_("copying object");
1068         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1069                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1070
1071         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1072                 return false;
1073
1074         printf("SVAAP[A]\tset PADDING (equal)\n");
1075         padding->length = 27;
1076         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1077                 return die_("copying object");
1078         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1079                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1080
1081         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1082                 return false;
1083
1084         printf("SVAAP[P]\tprev\n");
1085         if(!FLAC__metadata_simple_iterator_prev(iterator))
1086                 return die_("iterator ended early\n");
1087         our_current_position--;
1088
1089         printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1090         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1091                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1092         delete_from_our_metadata_(our_current_position--);
1093
1094         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1095                 return false;
1096
1097         printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1098         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1099                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1100         delete_from_our_metadata_(our_current_position--);
1101
1102         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1103                 return false;
1104
1105         printf("SV[A]P\tnext\n");
1106         if(!FLAC__metadata_simple_iterator_next(iterator))
1107                 return die_("iterator ended early\n");
1108         our_current_position++;
1109
1110         printf("SVA[P]\tinsert PADDING after\n");
1111         padding->length = 5;
1112         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1113                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1114         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1115                 return false;
1116
1117         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1118                 return false;
1119
1120         printf("SVAP[P]\tprev\n");
1121         if(!FLAC__metadata_simple_iterator_prev(iterator))
1122                 return die_("iterator ended early\n");
1123         our_current_position--;
1124
1125         printf("SVA[P]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("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1131         if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1132                 return die_("setting APPLICATION data");
1133         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1134                 return die_("copying object");
1135         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1136                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1137
1138         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1139                 return false;
1140
1141         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1142         if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1143                 return die_("setting APPLICATION data");
1144         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1145                 return die_("copying object");
1146         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1147                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1148
1149         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1150                 return false;
1151
1152         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1153         if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1154                 return die_("setting APPLICATION data");
1155         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1156                 return die_("copying object");
1157         our_metadata_.blocks[our_current_position+1]->length = 0;
1158         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1159                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1160
1161         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1162                 return false;
1163
1164         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1165         if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1166                 return die_("setting APPLICATION data");
1167         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1168                 return die_("copying object");
1169         delete_from_our_metadata_(our_current_position+1);
1170         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1171                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1172
1173         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1174                 return false;
1175
1176         printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1177         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1178                 return die_("setting APPLICATION data");
1179         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1180                 return die_("copying object");
1181         delete_from_our_metadata_(our_current_position+1);
1182         our_metadata_.blocks[our_current_position]->is_last = true;
1183         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1184                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1185
1186         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1187                 return false;
1188
1189         printf("SV[A]\tset PADDING (equal size)\n");
1190         padding->length = app->length;
1191         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1192                 return die_("copying object");
1193         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1194                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1195
1196         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1197                 return false;
1198
1199         printf("SV[P]\tinsert PADDING after\n");
1200         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1201                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1202         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1203                 return false;
1204
1205         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1206                 return false;
1207
1208         printf("SVP[P]\tinsert PADDING after\n");
1209         padding->length = 5;
1210         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1211                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1212         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1213                 return false;
1214
1215         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1216                 return false;
1217
1218         printf("SVPP[P]\tprev\n");
1219         if(!FLAC__metadata_simple_iterator_prev(iterator))
1220                 return die_("iterator ended early\n");
1221         our_current_position--;
1222
1223         printf("SVP[P]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("SV[P]PP\tprev\n");
1229         if(!FLAC__metadata_simple_iterator_prev(iterator))
1230                 return die_("iterator ended early\n");
1231         our_current_position--;
1232
1233         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1234         if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1235                 return die_("setting APPLICATION data");
1236         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1237                 return die_("copying object");
1238         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1239                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1240
1241         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1242                 return false;
1243
1244         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1245         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1246                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1247         delete_from_our_metadata_(our_current_position--);
1248
1249         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1250                 return false;
1251
1252         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1253         if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1254                 return die_("setting APPLICATION data");
1255         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1256                 return die_("copying object");
1257         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1258                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1259
1260         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1261                 return false;
1262
1263         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1264         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1265                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1266         delete_from_our_metadata_(our_current_position--);
1267
1268         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1269                 return false;
1270
1271         printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1272         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1273                 return die_("setting APPLICATION data");
1274         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1275                 return die_("copying object");
1276         delete_from_our_metadata_(our_current_position+1);
1277         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1278                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1279
1280         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1281                 return false;
1282
1283         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1284         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1285                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1286         delete_from_our_metadata_(our_current_position--);
1287
1288         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1289                 return false;
1290
1291         printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1292         if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1293                 return die_("setting APPLICATION data");
1294         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1295                 return die_("copying object");
1296         our_metadata_.blocks[our_current_position+1]->length = 0;
1297         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1298                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1299
1300         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1301                 return false;
1302
1303         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1304         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1305                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1306         delete_from_our_metadata_(our_current_position--);
1307
1308         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1309                 return false;
1310
1311         printf("S[V]PP\tnext\n");
1312         if(!FLAC__metadata_simple_iterator_next(iterator))
1313                 return die_("iterator ended early\n");
1314         our_current_position++;
1315
1316         printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1317         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1318                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1319         delete_from_our_metadata_(our_current_position--);
1320
1321         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1322                 return false;
1323
1324         printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1325         if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1326                 return die_("setting APPLICATION data");
1327         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1328                 return die_("copying object");
1329         delete_from_our_metadata_(our_current_position+1);
1330         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1331                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1332
1333         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1334                 return false;
1335
1336         printf("delete simple iterator\n");
1337
1338         FLAC__metadata_simple_iterator_delete(iterator);
1339
1340         FLAC__metadata_object_delete(app);
1341         FLAC__metadata_object_delete(padding);
1342
1343         if(!remove_file_(flacfile_))
1344                 return false;
1345
1346         return true;
1347 }
1348
1349 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1350 {
1351         FLAC__Metadata_Iterator *iterator;
1352         FLAC__Metadata_Chain *chain;
1353         FLAC__StreamMetadata *block, *app, *padding;
1354         FLAC__byte data[2000];
1355         unsigned our_current_position;
1356
1357         /* initialize 'data' to avoid Valgrind errors */
1358         memset(data, 0, sizeof(data));
1359
1360         printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1361
1362         printf("generate read-only file\n");
1363
1364         if(!generate_file_(/*include_cuesheet=*/false))
1365                 return false;
1366
1367         if(!change_stats_(flacfile_, /*read_only=*/true))
1368                 return false;
1369
1370         printf("create chain\n");
1371
1372         if(0 == (chain = FLAC__metadata_chain_new()))
1373                 return die_("allocating chain");
1374
1375         printf("read chain\n");
1376
1377         if(!read_chain_(chain, flacfile_, filename_based))
1378                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1379
1380         printf("[S]VP\ttest initial metadata\n");
1381
1382         if(!compare_chain_(chain, 0, 0))
1383                 return false;
1384         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1385                 return false;
1386
1387         printf("switch file to read-write\n");
1388
1389         if(!change_stats_(flacfile_, /*read-only=*/false))
1390                 return false;
1391
1392         printf("create iterator\n");
1393         if(0 == (iterator = FLAC__metadata_iterator_new()))
1394                 return die_("allocating memory for iterator");
1395
1396         our_current_position = 0;
1397
1398         FLAC__metadata_iterator_init(iterator, chain);
1399
1400         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1401                 return die_("getting block from iterator");
1402
1403         FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1404
1405         printf("[S]VP\tmodify STREAMINFO, write\n");
1406
1407         block->data.stream_info.sample_rate = 32000;
1408         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1409                 return die_("copying object");
1410
1411         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1412                 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1413         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1414                 return false;
1415         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1416                 return false;
1417
1418         printf("[S]VP\tnext\n");
1419         if(!FLAC__metadata_iterator_next(iterator))
1420                 return die_("iterator ended early\n");
1421         our_current_position++;
1422
1423         printf("S[V]P\tnext\n");
1424         if(!FLAC__metadata_iterator_next(iterator))
1425                 return die_("iterator ended early\n");
1426         our_current_position++;
1427
1428         printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1429         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1430                 return die_("getting block from iterator");
1431         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1432                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1433         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1434         if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1435                 return die_("setting APPLICATION data");
1436         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1437                 return die_("copying object");
1438         if(!FLAC__metadata_iterator_set_block(iterator, app))
1439                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1440
1441         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1442                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1443         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1444                 return false;
1445         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1446                 return false;
1447
1448         printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1449         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1450                 return die_("copying object");
1451         if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1452                 return die_("setting APPLICATION data");
1453         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1454                 return die_("copying object");
1455         if(!FLAC__metadata_iterator_set_block(iterator, app))
1456                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1457
1458         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1459                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1460         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1461                 return false;
1462         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1463                 return false;
1464
1465         printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1466         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1467                 return die_("copying object");
1468         if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1469                 return die_("setting APPLICATION data");
1470         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1471                 return die_("copying object");
1472         if(!FLAC__metadata_iterator_set_block(iterator, app))
1473                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1474
1475         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1476                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1477         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1478                 return false;
1479         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1480                 return false;
1481
1482         printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1483         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1484                 return die_("copying object");
1485         if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1486                 return die_("setting APPLICATION data");
1487         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1488                 return die_("copying object");
1489         if(!FLAC__metadata_iterator_set_block(iterator, app))
1490                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1491
1492         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1493                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1494         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1495                 return false;
1496         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1497                 return false;
1498
1499         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1500         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1501                 return die_("copying object");
1502         if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1503                 return die_("setting APPLICATION data");
1504         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1505                 return die_("copying object");
1506         if(!FLAC__metadata_iterator_set_block(iterator, app))
1507                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1508
1509         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1510                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1511         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1512                 return false;
1513         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1514                 return false;
1515
1516         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1517         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1518                 return die_("creating PADDING block");
1519         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1520                 return die_("copying object");
1521         if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1522                 return die_("setting APPLICATION data");
1523         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1524                 return die_("copying object");
1525         padding->length = 0;
1526         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1527                 return die_("internal error");
1528         if(!FLAC__metadata_iterator_set_block(iterator, app))
1529                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1530
1531         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1532                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1533         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1534                 return false;
1535         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1536                 return false;
1537
1538         printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1539         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1540                 return die_("copying object");
1541         if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1542                 return die_("setting APPLICATION data");
1543         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1544                 return die_("copying object");
1545         our_metadata_.blocks[our_current_position+1]->length = 13;
1546         if(!FLAC__metadata_iterator_set_block(iterator, app))
1547                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1548
1549         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1550                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1551         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1552                 return false;
1553         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1554                 return false;
1555
1556         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1557         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1558                 return die_("copying object");
1559         if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1560                 return die_("setting APPLICATION data");
1561         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1562                 return die_("copying object");
1563         if(!FLAC__metadata_iterator_set_block(iterator, app))
1564                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1565
1566         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1567                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1568         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1569                 return false;
1570         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1571                 return false;
1572
1573         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1574         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1575                 return die_("copying object");
1576         if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1577                 return die_("setting APPLICATION data");
1578         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1579                 return die_("copying object");
1580         our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1581         if(!FLAC__metadata_iterator_set_block(iterator, app))
1582                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1583
1584         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1585                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1586         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1587                 return false;
1588         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1589                 return false;
1590
1591         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1592         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1593                 return die_("copying object");
1594         if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1595                 return die_("setting APPLICATION data");
1596         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1597                 return die_("copying object");
1598         delete_from_our_metadata_(our_current_position+1);
1599         if(!FLAC__metadata_iterator_set_block(iterator, app))
1600                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1601
1602         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1603                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1604         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1605                 return false;
1606         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1607                 return false;
1608
1609         printf("SV[A]\tprev\n");
1610         if(!FLAC__metadata_iterator_prev(iterator))
1611                 return die_("iterator ended early\n");
1612         our_current_position--;
1613
1614         printf("S[V]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]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1620         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1621                 return die_("creating PADDING block");
1622         padding->length = 30;
1623         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1624                 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1625         else
1626                 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1627
1628         printf("[S]VP\tnext\n");
1629         if(!FLAC__metadata_iterator_next(iterator))
1630                 return die_("iterator ended early\n");
1631         our_current_position++;
1632
1633         printf("S[V]A\tinsert PADDING after\n");
1634         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1635                 return die_("copying metadata");
1636         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1637                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1638
1639         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1640                 return false;
1641
1642         printf("SV[P]A\tinsert PADDING before\n");
1643         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1644                 return die_("creating PADDING block");
1645         padding->length = 17;
1646         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1647                 return die_("copying metadata");
1648         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1649                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1650
1651         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1652                 return false;
1653
1654         printf("SV[P]PA\tinsert PADDING before\n");
1655         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1656                 return die_("creating PADDING block");
1657         padding->length = 0;
1658         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1659                 return die_("copying metadata");
1660         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1661                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1662
1663         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1664                 return false;
1665
1666         printf("SV[P]PPA\tnext\n");
1667         if(!FLAC__metadata_iterator_next(iterator))
1668                 return die_("iterator ended early\n");
1669         our_current_position++;
1670
1671         printf("SVP[P]PA\tnext\n");
1672         if(!FLAC__metadata_iterator_next(iterator))
1673                 return die_("iterator ended early\n");
1674         our_current_position++;
1675
1676         printf("SVPP[P]A\tnext\n");
1677         if(!FLAC__metadata_iterator_next(iterator))
1678                 return die_("iterator ended early\n");
1679         our_current_position++;
1680
1681         printf("SVPPP[A]\tinsert PADDING after\n");
1682         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1683                 return die_("creating PADDING block");
1684         padding->length = 57;
1685         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1686                 return die_("copying metadata");
1687         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1688                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1689
1690         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1691                 return false;
1692
1693         printf("SVPPPA[P]\tinsert PADDING before\n");
1694         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1695                 return die_("creating PADDING block");
1696         padding->length = 99;
1697         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1698                 return die_("copying metadata");
1699         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1700                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1701
1702         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1703                 return false;
1704
1705         printf("delete iterator\n");
1706         FLAC__metadata_iterator_delete(iterator);
1707         our_current_position = 0;
1708
1709         printf("SVPPPAPP\tmerge padding\n");
1710         FLAC__metadata_chain_merge_padding(chain);
1711         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1712         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1713         our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1714         delete_from_our_metadata_(7);
1715         delete_from_our_metadata_(4);
1716         delete_from_our_metadata_(3);
1717
1718         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1719                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1720         if(!compare_chain_(chain, 0, 0))
1721                 return false;
1722         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1723                 return false;
1724
1725         printf("SVPAP\tsort padding\n");
1726         FLAC__metadata_chain_sort_padding(chain);
1727         our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1728         delete_from_our_metadata_(2);
1729
1730         if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1731                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1732         if(!compare_chain_(chain, 0, 0))
1733                 return false;
1734         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1735                 return false;
1736
1737         printf("create iterator\n");
1738         if(0 == (iterator = FLAC__metadata_iterator_new()))
1739                 return die_("allocating memory for iterator");
1740
1741         our_current_position = 0;
1742
1743         FLAC__metadata_iterator_init(iterator, chain);
1744
1745         printf("[S]VAP\tnext\n");
1746         if(!FLAC__metadata_iterator_next(iterator))
1747                 return die_("iterator ended early\n");
1748         our_current_position++;
1749
1750         printf("S[V]AP\tnext\n");
1751         if(!FLAC__metadata_iterator_next(iterator))
1752                 return die_("iterator ended early\n");
1753         our_current_position++;
1754
1755         printf("SV[A]P\tdelete middle block, replace with padding\n");
1756         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1757                 return die_("creating PADDING block");
1758         padding->length = 71;
1759         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1760                 return die_("copying object");
1761         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1762                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1763
1764         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1765                 return false;
1766
1767         printf("S[V]PP\tnext\n");
1768         if(!FLAC__metadata_iterator_next(iterator))
1769                 return die_("iterator ended early\n");
1770         our_current_position++;
1771
1772         printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1773         delete_from_our_metadata_(our_current_position--);
1774         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1775                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1776
1777         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1778                 return false;
1779
1780         printf("S[V]P\tnext\n");
1781         if(!FLAC__metadata_iterator_next(iterator))
1782                 return die_("iterator ended early\n");
1783         our_current_position++;
1784
1785         printf("SV[P]\tdelete last block, replace with padding\n");
1786         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1787                 return die_("creating PADDING block");
1788         padding->length = 219;
1789         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1790                 return die_("copying object");
1791         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1792                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1793
1794         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1795                 return false;
1796
1797         printf("S[V]P\tnext\n");
1798         if(!FLAC__metadata_iterator_next(iterator))
1799                 return die_("iterator ended early\n");
1800         our_current_position++;
1801
1802         printf("SV[P]\tdelete last block, don't replace with padding\n");
1803         delete_from_our_metadata_(our_current_position--);
1804         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1805                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1806
1807         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1808                 return false;
1809
1810         printf("S[V]\tprev\n");
1811         if(!FLAC__metadata_iterator_prev(iterator))
1812                 return die_("iterator ended early\n");
1813         our_current_position--;
1814
1815         printf("[S]V\tdelete STREAMINFO block, should fail\n");
1816         if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1817                 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1818
1819         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1820                 return false;
1821
1822         printf("delete iterator\n");
1823         FLAC__metadata_iterator_delete(iterator);
1824         our_current_position = 0;
1825
1826         printf("SV\tmerge padding\n");
1827         FLAC__metadata_chain_merge_padding(chain);
1828
1829         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1830                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1831         if(!compare_chain_(chain, 0, 0))
1832                 return false;
1833         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1834                 return false;
1835
1836         printf("SV\tsort padding\n");
1837         FLAC__metadata_chain_sort_padding(chain);
1838
1839         if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1840                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1841         if(!compare_chain_(chain, 0, 0))
1842                 return false;
1843         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1844                 return false;
1845
1846         printf("delete chain\n");
1847
1848         FLAC__metadata_chain_delete(chain);
1849
1850         if(!remove_file_(flacfile_))
1851                 return false;
1852
1853         return true;
1854 }
1855
1856 static FLAC__bool test_level_2_misc_()
1857 {
1858         FLAC__Metadata_Iterator *iterator;
1859         FLAC__Metadata_Chain *chain;
1860         FLAC__IOCallbacks callbacks;
1861
1862         memset(&callbacks, 0, sizeof(callbacks));
1863         callbacks.read = (FLAC__IOCallback_Read)fread;
1864 #ifdef FLAC__VALGRIND_TESTING
1865         callbacks.write = chain_write_cb_;
1866 #else
1867         callbacks.write = (FLAC__IOCallback_Write)fwrite;
1868 #endif
1869         callbacks.seek = chain_seek_cb_;
1870         callbacks.tell = chain_tell_cb_;
1871         callbacks.eof = chain_eof_cb_;
1872
1873         printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1874
1875         printf("generate file\n");
1876
1877         if(!generate_file_(/*include_cuesheet=*/false))
1878                 return false;
1879
1880         printf("create chain\n");
1881
1882         if(0 == (chain = FLAC__metadata_chain_new()))
1883                 return die_("allocating chain");
1884
1885         printf("read chain (filename-based)\n");
1886
1887         if(!FLAC__metadata_chain_read(chain, flacfile_))
1888                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1889
1890         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1891         {
1892                 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1893                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1894                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1895                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1896                 printf("  OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1897         }
1898
1899         printf("read chain (filename-based)\n");
1900
1901         if(!FLAC__metadata_chain_read(chain, flacfile_))
1902                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1903
1904         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1905         {
1906                 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1907                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1908                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1909                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1910                 printf("  OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1911         }
1912
1913         printf("read chain (callback-based)\n");
1914         {
1915                 FILE *file = fopen(flacfile_, "rb");
1916                 if(0 == file)
1917                         return die_("opening file");
1918                 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1919                         fclose(file);
1920                         return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1921                 }
1922                 fclose(file);
1923         }
1924
1925         printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1926         {
1927                 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1928                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1929                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1930                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1931                 printf("  OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1932         }
1933
1934         printf("read chain (callback-based)\n");
1935         {
1936                 FILE *file = fopen(flacfile_, "rb");
1937                 if(0 == file)
1938                         return die_("opening file");
1939                 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1940                         fclose(file);
1941                         return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1942                 }
1943                 fclose(file);
1944         }
1945
1946         printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1947
1948         if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1949                 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1950         else
1951                 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1952
1953         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1954         {
1955                 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1956                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1957                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1958                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1959                 printf("  OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1960         }
1961
1962         printf("read chain (callback-based)\n");
1963         {
1964                 FILE *file = fopen(flacfile_, "rb");
1965                 if(0 == file)
1966                         return die_("opening file");
1967                 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1968                         fclose(file);
1969                         return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1970                 }
1971                 fclose(file);
1972         }
1973
1974         printf("create iterator\n");
1975         if(0 == (iterator = FLAC__metadata_iterator_new()))
1976                 return die_("allocating memory for iterator");
1977
1978         FLAC__metadata_iterator_init(iterator, chain);
1979
1980         printf("[S]VP\tnext\n");
1981         if(!FLAC__metadata_iterator_next(iterator))
1982                 return die_("iterator ended early\n");
1983
1984         printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1985         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1986                 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1987
1988         printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1989
1990         if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1991                 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1992         else
1993                 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1994
1995         printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1996         {
1997                 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1998                         return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1999                 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2000                         return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2001                 printf("  OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2002         }
2003
2004         printf("delete iterator\n");
2005
2006         FLAC__metadata_iterator_delete(iterator);
2007
2008         printf("delete chain\n");
2009
2010         FLAC__metadata_chain_delete(chain);
2011
2012         if(!remove_file_(flacfile_))
2013                 return false;
2014
2015         return true;
2016 }
2017
2018 FLAC__bool test_metadata_file_manipulation()
2019 {
2020         printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2021
2022         our_metadata_.num_blocks = 0;
2023
2024         if(!test_level_0_())
2025                 return false;
2026
2027         if(!test_level_1_())
2028                 return false;
2029
2030         if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2031                 return false;
2032         if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2033                 return false;
2034         if(!test_level_2_misc_())
2035                 return false;
2036
2037         return true;
2038 }