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