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