blob: 57689d8e033ecb687ce559dee4c63271fa9794b4 [file] [log] [blame]
Josh Coalson57ba6f42002-06-07 05:27:37 +00001/* test_libFLAC - Unit tester for libFLAC
Josh Coalsona78fac62005-01-25 04:17:55 +00002 * Copyright (C) 2002,2003,2004,2005 Josh Coalson
Josh Coalson4860ed72002-05-07 05:33:49 +00003 *
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
Josh Coalson6e62e8f2002-05-17 06:28:09 +000019#include "file_utils.h"
Josh Coalson275f6842002-05-09 05:52:40 +000020#include "metadata_utils.h"
Josh Coalsonc11b5dd2002-05-07 06:08:40 +000021#include "FLAC/assert.h"
22#include "FLAC/file_decoder.h"
Josh Coalson4860ed72002-05-07 05:33:49 +000023#include "FLAC/metadata.h"
Josh Coalsonb8f8a072002-11-07 05:07:30 +000024#include "share/grabbag.h"
Josh Coalson4860ed72002-05-07 05:33:49 +000025#include <stdio.h>
26#include <stdlib.h> /* for malloc() */
Josh Coalson4860ed72002-05-07 05:33:49 +000027
Josh Coalson65831dd2004-07-14 00:50:52 +000028#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
Josh Coalsond34f03d2002-05-11 05:41:42 +000039/******************************************************************************
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
Josh Coalsoncc682512002-06-08 04:53:42 +000046 differences in the metadata, or the actual audio data is corrupted, we
Josh Coalsond34f03d2002-05-11 05:41:42 +000047 will catch it while decoding.
48******************************************************************************/
49
Josh Coalsonc11b5dd2002-05-07 06:08:40 +000050typedef struct {
51 FLAC__bool error_occurred;
52} decoder_client_struct;
53
54typedef struct {
Josh Coalsoncc682512002-06-08 04:53:42 +000055 FLAC__StreamMetadata *blocks[64];
Josh Coalson275f6842002-05-09 05:52:40 +000056 unsigned num_blocks;
57} our_metadata_struct;
58
59static const char *flacfile_ = "metadata.flac";
Josh Coalsond34f03d2002-05-11 05:41:42 +000060
61/* our copy of the metadata in flacfile_ */
Josh Coalson275f6842002-05-09 05:52:40 +000062static our_metadata_struct our_metadata_;
Josh Coalsond34f03d2002-05-11 05:41:42 +000063
64/* the current block number that corresponds to the position of the iterator we are testing */
65static unsigned mc_our_block_number_ = 0;
Josh Coalson275f6842002-05-09 05:52:40 +000066
67static FLAC__bool die_(const char *msg)
Josh Coalson4860ed72002-05-07 05:33:49 +000068{
Josh Coalsonc11b5dd2002-05-07 06:08:40 +000069 printf("ERROR: %s\n", msg);
70 return false;
71}
72
Josh Coalsoncc682512002-06-08 04:53:42 +000073static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
Josh Coalsond34f03d2002-05-11 05:41:42 +000074{
75 printf("ERROR: %s\n", msg);
Josh Coalsoncc682512002-06-08 04:53:42 +000076 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
Josh Coalsond34f03d2002-05-11 05:41:42 +000077 return false;
78}
79
Josh Coalsoncc682512002-06-08 04:53:42 +000080static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
Josh Coalson275f6842002-05-09 05:52:40 +000081{
82 printf("ERROR: %s\n", msg);
Josh Coalsoncc682512002-06-08 04:53:42 +000083 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
Josh Coalson275f6842002-05-09 05:52:40 +000084 return false;
85}
86
Josh Coalsonfedb0ae2002-08-25 05:10:37 +000087static 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
Josh Coalsond34f03d2002-05-11 05:41:42 +000097/* functions for working with our metadata copy */
98
Josh Coalsoncc682512002-06-08 04:53:42 +000099static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
Josh Coalson275f6842002-05-09 05:52:40 +0000100{
101 unsigned i;
Josh Coalsoncc682512002-06-08 04:53:42 +0000102 FLAC__StreamMetadata *obj = block;
Josh Coalson275f6842002-05-09 05:52:40 +0000103 FLAC__ASSERT(position < our_metadata_.num_blocks);
104 if(copy) {
Josh Coalsoncc682512002-06-08 04:53:42 +0000105 if(0 == (obj = FLAC__metadata_object_clone(block)))
106 return die_("during FLAC__metadata_object_clone()");
Josh Coalson275f6842002-05-09 05:52:40 +0000107 }
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
Josh Coalsoncc682512002-06-08 04:53:42 +0000119static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
Josh Coalson275f6842002-05-09 05:52:40 +0000120{
121 unsigned i;
Josh Coalsoncc682512002-06-08 04:53:42 +0000122 FLAC__StreamMetadata *obj = block;
Josh Coalson275f6842002-05-09 05:52:40 +0000123 if(copy) {
Josh Coalsoncc682512002-06-08 04:53:42 +0000124 if(0 == (obj = FLAC__metadata_object_clone(block)))
125 return die_("during FLAC__metadata_object_clone()");
Josh Coalson275f6842002-05-09 05:52:40 +0000126 }
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
145static 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
Josh Coalson65831dd2004-07-14 00:50:52 +0000162/*
Josh Coalson967360b2004-07-15 16:21:52 +0000163 * This wad of functions supports filename- and callback-based chain reading/writing.
Josh Coalson65831dd2004-07-14 00:50:52 +0000164 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
165 */
166FLAC__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
Josh Coalson89f161c2004-07-16 00:31:43 +0000175 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
Josh Coalson65831dd2004-07-14 00:50:52 +0000176 return false;
177
178 return true;
179}
180
181void 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
195FLAC__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
Josh Coalsone9a638d2005-09-03 03:54:16 +0000207#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
Josh Coalson65831dd2004-07-14 00:50:52 +0000208 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
224FLAC__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
231void 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);
Josh Coalsone9a638d2005-09-03 03:54:16 +0000242#if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
Josh Coalson65831dd2004-07-14 00:50:52 +0000243 (void)chown(filename, stats->st_uid, -1);
244 (void)chown(filename, -1, stats->st_gid);
245#endif
246}
247
248#ifdef FLAC__VALGRIND_TESTING
249static 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
259static 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
266static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
267{
268 return ftell((FILE*)handle);
269}
270
271static int chain_eof_cb_(FLAC__IOHandle handle)
272{
273 return feof((FILE*)handle);
274}
275
276static 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_;
Josh Coalson65831dd2004-07-14 00:50:52 +0000292
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 }
Josh Coalson0b8b5642004-07-15 00:04:09 +0000308 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);
Josh Coalson65831dd2004-07-14 00:50:52 +0000311 return false;
Josh Coalson0b8b5642004-07-15 00:04:09 +0000312 }
313 fclose(file);
314 fclose(tempfile);
315 file = tempfile = 0;
Josh Coalson65831dd2004-07-14 00:50:52 +0000316 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;
Josh Coalson0b8b5642004-07-15 00:04:09 +0000327 fclose(file);
Josh Coalson65831dd2004-07-14 00:50:52 +0000328 }
329 }
330
331 return true;
332}
333
Josh Coalson0b8b5642004-07-15 00:04:09 +0000334static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
Josh Coalson65831dd2004-07-14 00:50:52 +0000335{
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_;
Josh Coalson65831dd2004-07-14 00:50:52 +0000345
346 {
Josh Coalson0b8b5642004-07-15 00:04:09 +0000347 FLAC__bool ret;
Josh Coalson65831dd2004-07-14 00:50:52 +0000348 FILE *file = fopen(filename, "rb");
349 if(0 == file)
350 return false; /*@@@ chain status still says OK though */
Josh Coalson0b8b5642004-07-15 00:04:09 +0000351 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
352 fclose(file);
353 return ret;
Josh Coalson65831dd2004-07-14 00:50:52 +0000354 }
355 }
356}
357
Josh Coalsoncc682512002-06-08 04:53:42 +0000358/* function for comparing our metadata to a FLAC__Metadata_Chain */
Josh Coalsond34f03d2002-05-11 05:41:42 +0000359
Josh Coalsoncc682512002-06-08 04:53:42 +0000360static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
Josh Coalsond34f03d2002-05-11 05:41:42 +0000361{
362 unsigned i;
Josh Coalsoncc682512002-06-08 04:53:42 +0000363 FLAC__Metadata_Iterator *iterator;
364 FLAC__StreamMetadata *block;
Josh Coalsond34f03d2002-05-11 05:41:42 +0000365 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
Josh Coalson613dae42003-01-10 05:45:48 +0000387 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
Josh Coalsond34f03d2002-05-11 05:41:42 +0000388 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
Josh Coalson76eb8632002-05-14 06:04:47 +0000404 if(0 != current_block) {
405 printf("CURRENT_POSITION... ");
406 fflush(stdout);
407
Josh Coalson613dae42003-01-10 05:45:48 +0000408 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
Josh Coalson76eb8632002-05-14 06:04:47 +0000409 return die_("metadata block mismatch");
410 }
411
Josh Coalsond34f03d2002-05-11 05:41:42 +0000412 printf("PASSED\n");
413
414 return true;
415}
416
417/* decoder callbacks for checking the file */
418
Josh Coalson57ba6f42002-06-07 05:27:37 +0000419static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000420{
Josh Coalsond34f03d2002-05-11 05:41:42 +0000421 (void)decoder, (void)buffer, (void)client_data;
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000422
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000423 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
Josh Coalson2835f432002-06-04 05:54:44 +0000431 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000432}
433
Josh Coalsond34f03d2002-05-11 05:41:42 +0000434/* this version pays no attention to the metadata */
Josh Coalsoncc682512002-06-08 04:53:42 +0000435static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
Josh Coalsond34f03d2002-05-11 05:41:42 +0000436{
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 */
Josh Coalsoncc682512002-06-08 04:53:42 +0000446static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
Josh Coalsond34f03d2002-05-11 05:41:42 +0000447{
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 {
Josh Coalson613dae42003-01-10 05:45:48 +0000464 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
Josh Coalsond34f03d2002-05-11 05:41:42 +0000465 (void)die_("metadata block mismatch");
466 dcd->error_occurred = true;
467 }
468 }
469 mc_our_block_number_++;
470}
471
Josh Coalsoncc682512002-06-08 04:53:42 +0000472static 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
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000481static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000482{
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000483 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
484 FLAC__StreamMetadata *metadata[3];
485 unsigned i = 0, n = 0;
Josh Coalson275f6842002-05-09 05:52:40 +0000486
Josh Coalson275f6842002-05-09 05:52:40 +0000487 printf("generating FLAC file for test\n");
488
Josh Coalsond34f03d2002-05-11 05:41:42 +0000489 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000505 {
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;
Josh Coalsondef597e2004-12-30 00:59:30 +0000511 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);
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000513 vorbiscomment.data.vorbis_comment.num_comments = 0;
514 vorbiscomment.data.vorbis_comment.comments = 0;
515 }
516
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000517 {
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
Josh Coalsond34f03d2002-05-11 05:41:42 +0000531 padding.is_last = true;
532 padding.type = FLAC__METADATA_TYPE_PADDING;
533 padding.length = 1234;
534
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000535 metadata[n++] = &vorbiscomment;
536 if (include_cuesheet)
537 metadata[n++] = cuesheet;
538 metadata[n++] = &padding;
Josh Coalsonf2cc2702002-06-01 05:27:12 +0000539
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000540 if(
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000541 !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)
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000545 )
Josh Coalsond34f03d2002-05-11 05:41:42 +0000546 return die_("priming our metadata");
547
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000548 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
Josh Coalson765ff502002-08-27 05:46:11 +0000549 return die_("creating the encoded file");
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000550
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000551 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
552
Josh Coalson4860ed72002-05-07 05:33:49 +0000553 return true;
554}
555
Josh Coalson65831dd2004-07-14 00:50:52 +0000556static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
Josh Coalson4860ed72002-05-07 05:33:49 +0000557{
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000558 FLAC__FileDecoder *decoder;
559 decoder_client_struct decoder_client_data;
560
561 FLAC__ASSERT(0 != filename);
562 FLAC__ASSERT(0 != metadata_callback);
563
Josh Coalsond34f03d2002-05-11 05:41:42 +0000564 mc_our_block_number_ = 0;
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000565 decoder_client_data.error_occurred = false;
566
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000567 printf("\ttesting '%s'... ", filename);
568 fflush(stdout);
Josh Coalson275f6842002-05-09 05:52:40 +0000569
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000570 if(0 == (decoder = FLAC__file_decoder_new()))
Josh Coalsoncc682512002-06-08 04:53:42 +0000571 return die_("couldn't allocate decoder instance");
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000572
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);
Josh Coalson275f6842002-05-09 05:52:40 +0000583 return die_("initializing decoder\n");
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000584 }
Josh Coalsoncfdfc822002-08-02 06:12:36 +0000585 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000586 FLAC__file_decoder_finish(decoder);
587 FLAC__file_decoder_delete(decoder);
Josh Coalson275f6842002-05-09 05:52:40 +0000588 return die_("decoding file\n");
Josh Coalsonc11b5dd2002-05-07 06:08:40 +0000589 }
590
591 FLAC__file_decoder_finish(decoder);
592 FLAC__file_decoder_delete(decoder);
593
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000594 if(decoder_client_data.error_occurred)
595 return false;
Josh Coalson275f6842002-05-09 05:52:40 +0000596
Josh Coalsond34f03d2002-05-11 05:41:42 +0000597 if(mc_our_block_number_ != our_metadata_.num_blocks)
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000598 return die_("short metadata block count");
599
600 printf("PASSED\n");
601 return true;
Josh Coalson4860ed72002-05-07 05:33:49 +0000602}
603
Josh Coalson275f6842002-05-09 05:52:40 +0000604static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
605{
Josh Coalsonb8f8a072002-11-07 05:07:30 +0000606 if(!grabbag__file_change_stats(filename, read_only))
607 return die_("during grabbag__file_change_stats()");
Josh Coalson275f6842002-05-09 05:52:40 +0000608
609 return true;
610}
611
612static FLAC__bool remove_file_(const char *filename)
613{
Josh Coalsond34f03d2002-05-11 05:41:42 +0000614 while(our_metadata_.num_blocks > 0)
615 delete_from_our_metadata_(0);
616
Josh Coalsonb8f8a072002-11-07 05:07:30 +0000617 if(!grabbag__file_remove_file(filename))
Josh Coalson275f6842002-05-09 05:52:40 +0000618 return die_("removing file");
619
620 return true;
621}
622
Josh Coalson6e62e8f2002-05-17 06:28:09 +0000623static FLAC__bool test_level_0_()
Josh Coalson275f6842002-05-09 05:52:40 +0000624{
Josh Coalson999be3b2002-06-10 04:42:35 +0000625 FLAC__StreamMetadata streaminfo;
Josh Coalson1aca6b12004-07-30 01:54:29 +0000626 FLAC__StreamMetadata *tags = 0;
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000627 FLAC__StreamMetadata *cuesheet = 0;
Josh Coalson275f6842002-05-09 05:52:40 +0000628
629 printf("\n\n++++++ testing level 0 interface\n");
630
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000631 if(!generate_file_(/*include_cuesheet=*/true))
Josh Coalson275f6842002-05-09 05:52:40 +0000632 return false;
633
Josh Coalsond34f03d2002-05-11 05:41:42 +0000634 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
Josh Coalson275f6842002-05-09 05:52:40 +0000635 return false;
636
Josh Coalson1aca6b12004-07-30 01:54:29 +0000637 printf("testing FLAC__metadata_get_streaminfo()... ");
638
Josh Coalson275f6842002-05-09 05:52:40 +0000639 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_()) */
Josh Coalson999be3b2002-06-10 04:42:35 +0000643 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");
Josh Coalson275f6842002-05-09 05:52:40 +0000653
Josh Coalson1aca6b12004-07-30 01:54:29 +0000654 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
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000669 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
Josh Coalson275f6842002-05-09 05:52:40 +0000682 if(!remove_file_(flacfile_))
683 return false;
684
685 return true;
686}
687
Josh Coalson6e62e8f2002-05-17 06:28:09 +0000688static FLAC__bool test_level_1_()
Josh Coalson275f6842002-05-09 05:52:40 +0000689{
Josh Coalsoncc682512002-06-08 04:53:42 +0000690 FLAC__Metadata_SimpleIterator *iterator;
691 FLAC__StreamMetadata *block, *app, *padding;
Josh Coalson275f6842002-05-09 05:52:40 +0000692 FLAC__byte data[1000];
Josh Coalsond34f03d2002-05-11 05:41:42 +0000693 unsigned our_current_position = 0;
Josh Coalson275f6842002-05-09 05:52:40 +0000694
Josh Coalson45062b82002-12-28 07:06:38 +0000695 /* initialize 'data' to avoid Valgrind errors */
696 memset(data, 0, sizeof(data));
697
Josh Coalson275f6842002-05-09 05:52:40 +0000698 printf("\n\n++++++ testing level 1 interface\n");
699
700 /************************************************************/
701
702 printf("simple iterator on read-only file\n");
703
Josh Coalson7cfac0b2006-04-10 05:37:34 +0000704 if(!generate_file_(/*include_cuesheet=*/false))
Josh Coalson275f6842002-05-09 05:52:40 +0000705 return false;
706
707 if(!change_stats_(flacfile_, /*read_only=*/true))
708 return false;
709
Josh Coalsond34f03d2002-05-11 05:41:42 +0000710 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
Josh Coalson275f6842002-05-09 05:52:40 +0000711 return false;
712
Josh Coalsoncc682512002-06-08 04:53:42 +0000713 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
Josh Coalson275f6842002-05-09 05:52:40 +0000714 return die_("FLAC__metadata_simple_iterator_new()");
715
Josh Coalson3ac66932002-08-30 05:41:31 +0000716 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
Josh Coalsoncc682512002-06-08 04:53:42 +0000717 return die_("FLAC__metadata_simple_iterator_init() returned false");
Josh Coalson275f6842002-05-09 05:52:40 +0000718
Josh Coalsoncc682512002-06-08 04:53:42 +0000719 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
720 if(FLAC__metadata_simple_iterator_is_writable(iterator))
Josh Coalson47303c82002-06-13 06:59:53 +0000721 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
Josh Coalson275f6842002-05-09 05:52:40 +0000722
723 printf("iterate forwards\n");
724
Josh Coalsoncc682512002-06-08 04:53:42 +0000725 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
Josh Coalson275f6842002-05-09 05:52:40 +0000726 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
Josh Coalsoncc682512002-06-08 04:53:42 +0000727 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
Josh Coalson275f6842002-05-09 05:52:40 +0000728 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");
Josh Coalson4fa90592002-12-04 07:01:37 +0000746 FLAC__metadata_object_delete(block);
Josh Coalson275f6842002-05-09 05:52:40 +0000747
Josh Coalsoncc682512002-06-08 04:53:42 +0000748 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000749 return die_("forward iterator ended early");
750 our_current_position++;
751
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000752 if(!FLAC__metadata_simple_iterator_next(iterator))
753 return die_("forward iterator ended early");
754 our_current_position++;
755
Josh Coalsoncc682512002-06-08 04:53:42 +0000756 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
Josh Coalson275f6842002-05-09 05:52:40 +0000757 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
Josh Coalsoncc682512002-06-08 04:53:42 +0000758 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000759 return die_("getting block 2");
Josh Coalson275f6842002-05-09 05:52:40 +0000760 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_()) */
Josh Coalsond34f03d2002-05-11 05:41:42 +0000765 if(block->length != 1234)
Josh Coalsoncc682512002-06-08 04:53:42 +0000766 return die_("bad PADDING length");
Josh Coalson4fa90592002-12-04 07:01:37 +0000767 FLAC__metadata_object_delete(block);
Josh Coalson275f6842002-05-09 05:52:40 +0000768
Josh Coalsoncc682512002-06-08 04:53:42 +0000769 if(FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000770 return die_("forward iterator returned true but should have returned false");
771
772 printf("iterate backwards\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000773 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000774 return die_("reverse iterator ended early");
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000775 if(!FLAC__metadata_simple_iterator_prev(iterator))
776 return die_("reverse iterator ended early");
Josh Coalsoncc682512002-06-08 04:53:42 +0000777 if(FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000778 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
Josh Coalsoncc682512002-06-08 04:53:42 +0000782 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
Josh Coalsond32b0df2003-01-15 03:16:26 +0000783 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
Josh Coalson275f6842002-05-09 05:52:40 +0000784 else
785 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
786
Josh Coalsoncc682512002-06-08 04:53:42 +0000787 FLAC__metadata_simple_iterator_delete(iterator);
Josh Coalson275f6842002-05-09 05:52:40 +0000788
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)");
Josh Coalsond34f03d2002-05-11 05:41:42 +0000800 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
Josh Coalson275f6842002-05-09 05:52:40 +0000801
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
Josh Coalsoncc682512002-06-08 04:53:42 +0000808 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
Josh Coalson275f6842002-05-09 05:52:40 +0000809 return die_("FLAC__metadata_simple_iterator_new()");
810
Josh Coalson3ac66932002-08-30 05:41:31 +0000811 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
Josh Coalsoncc682512002-06-08 04:53:42 +0000812 return die_("FLAC__metadata_simple_iterator_init() returned false");
Josh Coalson275f6842002-05-09 05:52:40 +0000813 our_current_position = 0;
814
Josh Coalsoncc682512002-06-08 04:53:42 +0000815 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
Josh Coalson275f6842002-05-09 05:52:40 +0000816
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000817 printf("[S]VP\ttry to write over STREAMINFO block...\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000818 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
Josh Coalsonf331ac22002-05-25 02:14:26 +0000819 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
Josh Coalson275f6842002-05-09 05:52:40 +0000820 else
821 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
822
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000823 printf("[S]VP\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000824 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000825 return die_("iterator ended early\n");
826 our_current_position++;
827
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000828 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");
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000834 padding->length = 25;
Josh Coalsoncc682512002-06-08 04:53:42 +0000835 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000837 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
838 return false;
839
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000840 printf("SVP[P]\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000841 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000842 return die_("iterator ended early\n");
843 our_current_position--;
844
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000845 printf("SV[P]P\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000846 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000847 return die_("iterator ended early\n");
848 our_current_position--;
849
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000850 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000851 padding->length = 30;
Josh Coalsoncc682512002-06-08 04:53:42 +0000852 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);
Josh Coalson275f6842002-05-09 05:52:40 +0000854 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
855 return false;
856
Josh Coalsond34f03d2002-05-11 05:41:42 +0000857 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +0000858 return false;
Josh Coalson765ff502002-08-27 05:46:11 +0000859
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000860 printf("SV[P]PP\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000861 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000862 return die_("iterator ended early\n");
863 our_current_position--;
864
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000865 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");
Josh Coalsoncc682512002-06-08 04:53:42 +0000871 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);
Josh Coalson275f6842002-05-09 05:52:40 +0000873
Josh Coalsond34f03d2002-05-11 05:41:42 +0000874 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +0000875 return false;
876
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000877 printf("[S]VPPP\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000878 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000879 return die_("iterator ended early\n");
880 our_current_position++;
881
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000882 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");
Josh Coalsoncc682512002-06-08 04:53:42 +0000888 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
889 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000890 our_current_position--;
891
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000892 printf("S[V]PPP\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000893 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000894 return die_("iterator ended early\n");
895 our_current_position++;
896
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000897 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000898 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
899 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson275f6842002-05-09 05:52:40 +0000900 delete_from_our_metadata_(our_current_position--);
901
Josh Coalsond34f03d2002-05-11 05:41:42 +0000902 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +0000903 return false;
904
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000905 printf("S[V]PP\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000906 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000907 return die_("iterator ended early\n");
908 our_current_position++;
909
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000910 printf("SV[P]P\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000911 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000912 return die_("iterator ended early\n");
913 our_current_position++;
914
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000915 printf("SVP[P]\tdelete (last block), replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000916 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
917 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000918 our_current_position--;
919
Josh Coalsond34f03d2002-05-11 05:41:42 +0000920 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000921 return false;
922
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000923 printf("SV[P]P\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000924 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000925 return die_("iterator ended early\n");
926 our_current_position++;
927
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000928 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000929 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
930 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson275f6842002-05-09 05:52:40 +0000931 delete_from_our_metadata_(our_current_position--);
932
Josh Coalsond34f03d2002-05-11 05:41:42 +0000933 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +0000934 return false;
935
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000936 printf("SV[P]\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000937 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000938 return die_("iterator ended early\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000939 our_current_position--;
Josh Coalson275f6842002-05-09 05:52:40 +0000940
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000941 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");
Josh Coalson275f6842002-05-09 05:52:40 +0000947 FLAC__ASSERT(our_current_position == 0);
Josh Coalsoncc682512002-06-08 04:53:42 +0000948 block = FLAC__metadata_simple_iterator_get_block(iterator);
Josh Coalson275f6842002-05-09 05:52:40 +0000949 block->data.stream_info.sample_rate = 32000;
950 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
951 return die_("copying object");
Josh Coalsoncc682512002-06-08 04:53:42 +0000952 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
953 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
Josh Coalson275f6842002-05-09 05:52:40 +0000954 FLAC__metadata_object_delete(block);
955
Josh Coalsond34f03d2002-05-11 05:41:42 +0000956 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +0000957 return false;
958
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000959 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");
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000965 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
Josh Coalsoncc682512002-06-08 04:53:42 +0000966 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000968 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
969 return false;
Josh Coalsond34f03d2002-05-11 05:41:42 +0000970 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000971
Josh Coalsond34f03d2002-05-11 05:41:42 +0000972 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000973 return false;
974
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000975 printf("SV[A]P\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +0000976 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson275f6842002-05-09 05:52:40 +0000977 return die_("iterator ended early\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000978 our_current_position++;
979
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000980 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000981 app->data.application.id[0] = 'f'; /* twiddle the id */
Josh Coalsoncc682512002-06-08 04:53:42 +0000982 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
983 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000984 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
985 return false;
Josh Coalsond34f03d2002-05-11 05:41:42 +0000986 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000987
Josh Coalsond34f03d2002-05-11 05:41:42 +0000988 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +0000989 return false;
990
Josh Coalsonfedb0ae2002-08-25 05:10:37 +0000991 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
Josh Coalson275f6842002-05-09 05:52:40 +0000992 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");
Josh Coalsoncc682512002-06-08 04:53:42 +0000997 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
998 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
Josh Coalson275f6842002-05-09 05:52:40 +0000999
Josh Coalsond34f03d2002-05-11 05:41:42 +00001000 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +00001001 return false;
1002
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001003 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
Josh Coalson275f6842002-05-09 05:52:40 +00001004 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");
Josh Coalsoncc682512002-06-08 04:53:42 +00001009 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1010 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
Josh Coalson275f6842002-05-09 05:52:40 +00001011
Josh Coalsond34f03d2002-05-11 05:41:42 +00001012 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +00001013 return false;
1014
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001015 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
Josh Coalson275f6842002-05-09 05:52:40 +00001016 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);
Josh Coalsoncc682512002-06-08 04:53:42 +00001022 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1023 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001024
Josh Coalsond34f03d2002-05-11 05:41:42 +00001025 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001026 return false;
1027
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001028 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001029 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");
Josh Coalsoneb643a22002-05-20 05:58:50 +00001036 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
Josh Coalsoncc682512002-06-08 04:53:42 +00001037 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1038 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001039
Josh Coalsond34f03d2002-05-11 05:41:42 +00001040 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001041 return false;
1042
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001043 printf("SVA[A]PP\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001044 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001045 return die_("iterator ended early\n");
1046 our_current_position++;
1047
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001048 printf("SVAA[P]P\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001049 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001050 return die_("iterator ended early\n");
1051 our_current_position++;
1052
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001053 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001054 padding->length = 5;
1055 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1056 return die_("copying object");
Josh Coalsoncc682512002-06-08 04:53:42 +00001057 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1058 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001059
Josh Coalsond34f03d2002-05-11 05:41:42 +00001060 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001061 return false;
1062
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001063 printf("SVAAP[P]\tset APPLICATION (grow)\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001064 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");
Josh Coalsoncc682512002-06-08 04:53:42 +00001067 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1068 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001069
Josh Coalsond34f03d2002-05-11 05:41:42 +00001070 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001071 return false;
1072
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001073 printf("SVAAP[A]\tset PADDING (equal)\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001074 padding->length = 27;
1075 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1076 return die_("copying object");
Josh Coalsoncc682512002-06-08 04:53:42 +00001077 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1078 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001079
Josh Coalsond34f03d2002-05-11 05:41:42 +00001080 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001081 return false;
1082
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001083 printf("SVAAP[P]\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001084 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001085 return die_("iterator ended early\n");
1086 our_current_position--;
1087
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001088 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001089 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1090 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001091 delete_from_our_metadata_(our_current_position--);
1092
Josh Coalsond34f03d2002-05-11 05:41:42 +00001093 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001094 return false;
1095
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001096 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001097 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1098 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001099 delete_from_our_metadata_(our_current_position--);
1100
Josh Coalsond34f03d2002-05-11 05:41:42 +00001101 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001102 return false;
1103
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001104 printf("SV[A]P\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001105 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001106 return die_("iterator ended early\n");
1107 our_current_position++;
1108
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001109 printf("SVA[P]\tinsert PADDING after\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001110 padding->length = 5;
Josh Coalsoncc682512002-06-08 04:53:42 +00001111 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001113 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1114 return false;
1115
Josh Coalsond34f03d2002-05-11 05:41:42 +00001116 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001117 return false;
1118
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001119 printf("SVAP[P]\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001120 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001121 return die_("iterator ended early\n");
1122 our_current_position--;
1123
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001124 printf("SVA[P]P\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001125 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001126 return die_("iterator ended early\n");
1127 our_current_position--;
1128
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001129 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001130 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");
Josh Coalsoncc682512002-06-08 04:53:42 +00001134 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1135 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001136
Josh Coalsond34f03d2002-05-11 05:41:42 +00001137 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001138 return false;
1139
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001140 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001141 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");
Josh Coalsoncc682512002-06-08 04:53:42 +00001145 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1146 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001147
Josh Coalsond34f03d2002-05-11 05:41:42 +00001148 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1149 return false;
1150
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001151 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001152 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;
Josh Coalsoncc682512002-06-08 04:53:42 +00001157 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1158 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalsond34f03d2002-05-11 05:41:42 +00001159
1160 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001161 return false;
1162
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001163 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001164 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);
Josh Coalsoncc682512002-06-08 04:53:42 +00001169 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1170 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001171
Josh Coalsond34f03d2002-05-11 05:41:42 +00001172 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001173 return false;
1174
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001175 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001176 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;
Josh Coalsoncc682512002-06-08 04:53:42 +00001182 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1183 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001184
Josh Coalsond34f03d2002-05-11 05:41:42 +00001185 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001186 return false;
1187
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001188 printf("SV[A]\tset PADDING (equal size)\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001189 padding->length = app->length;
1190 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1191 return die_("copying object");
Josh Coalsoncc682512002-06-08 04:53:42 +00001192 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1193 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001194
Josh Coalsond34f03d2002-05-11 05:41:42 +00001195 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001196 return false;
1197
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001198 printf("SV[P]\tinsert PADDING after\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001199 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001201 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1202 return false;
1203
Josh Coalsond34f03d2002-05-11 05:41:42 +00001204 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001205 return false;
1206
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001207 printf("SVP[P]\tinsert PADDING after\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001208 padding->length = 5;
Josh Coalsoncc682512002-06-08 04:53:42 +00001209 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001211 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1212 return false;
1213
Josh Coalsond34f03d2002-05-11 05:41:42 +00001214 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001215 return false;
1216
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001217 printf("SVPP[P]\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001218 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001219 return die_("iterator ended early\n");
1220 our_current_position--;
1221
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001222 printf("SVP[P]P\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001223 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001224 return die_("iterator ended early\n");
1225 our_current_position--;
1226
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001227 printf("SV[P]PP\tprev\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001228 if(!FLAC__metadata_simple_iterator_prev(iterator))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001229 return die_("iterator ended early\n");
1230 our_current_position--;
1231
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001232 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001233 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");
Josh Coalsoncc682512002-06-08 04:53:42 +00001237 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001239
Josh Coalsond34f03d2002-05-11 05:41:42 +00001240 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001241 return false;
1242
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001243 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001244 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1245 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001246 delete_from_our_metadata_(our_current_position--);
1247
Josh Coalsond34f03d2002-05-11 05:41:42 +00001248 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001249 return false;
1250
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001251 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001252 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");
Josh Coalsoncc682512002-06-08 04:53:42 +00001256 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001258
Josh Coalsond34f03d2002-05-11 05:41:42 +00001259 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001260 return false;
1261
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001262 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001263 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1264 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001265 delete_from_our_metadata_(our_current_position--);
1266
Josh Coalsond34f03d2002-05-11 05:41:42 +00001267 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001268 return false;
1269
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001270 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001271 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1272 return die_("setting APPLICATION data");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001273 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001274 return die_("copying object");
1275 delete_from_our_metadata_(our_current_position+1);
Josh Coalsoncc682512002-06-08 04:53:42 +00001276 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001278
Josh Coalsond34f03d2002-05-11 05:41:42 +00001279 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001280 return false;
1281
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001282 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001283 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1284 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001285 delete_from_our_metadata_(our_current_position--);
1286
Josh Coalsond34f03d2002-05-11 05:41:42 +00001287 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001288 return false;
1289
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001290 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001291 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1292 return die_("setting APPLICATION data");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001293 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001294 return die_("copying object");
1295 our_metadata_.blocks[our_current_position+1]->length = 0;
Josh Coalsoncc682512002-06-08 04:53:42 +00001296 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);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001298
Josh Coalsond34f03d2002-05-11 05:41:42 +00001299 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001300 return false;
1301
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001302 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001303 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1304 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001305 delete_from_our_metadata_(our_current_position--);
1306
Josh Coalsond34f03d2002-05-11 05:41:42 +00001307 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001308 return false;
1309
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001310 printf("S[V]PP\tnext\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001311 if(!FLAC__metadata_simple_iterator_next(iterator))
Josh Coalsond34f03d2002-05-11 05:41:42 +00001312 return die_("iterator ended early\n");
1313 our_current_position++;
1314
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001315 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001316 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1317 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
Josh Coalsond34f03d2002-05-11 05:41:42 +00001318 delete_from_our_metadata_(our_current_position--);
1319
1320 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1321 return false;
1322
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001323 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001324 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001325 return die_("setting APPLICATION data");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001326 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001327 return die_("copying object");
1328 delete_from_our_metadata_(our_current_position+1);
Josh Coalsoncc682512002-06-08 04:53:42 +00001329 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);
Josh Coalson275f6842002-05-09 05:52:40 +00001331
Josh Coalsond34f03d2002-05-11 05:41:42 +00001332 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
Josh Coalson275f6842002-05-09 05:52:40 +00001333 return false;
1334
Josh Coalsond34f03d2002-05-11 05:41:42 +00001335 printf("delete simple iterator\n");
1336
Josh Coalsoncc682512002-06-08 04:53:42 +00001337 FLAC__metadata_simple_iterator_delete(iterator);
Josh Coalson275f6842002-05-09 05:52:40 +00001338
1339 FLAC__metadata_object_delete(app);
Josh Coalson8c03c2f2002-05-10 06:43:17 +00001340 FLAC__metadata_object_delete(padding);
Josh Coalson275f6842002-05-09 05:52:40 +00001341
1342 if(!remove_file_(flacfile_))
1343 return false;
1344
1345 return true;
1346}
1347
Josh Coalson65831dd2004-07-14 00:50:52 +00001348static FLAC__bool test_level_2_(FLAC__bool filename_based)
Josh Coalson275f6842002-05-09 05:52:40 +00001349{
Josh Coalsoncc682512002-06-08 04:53:42 +00001350 FLAC__Metadata_Iterator *iterator;
1351 FLAC__Metadata_Chain *chain;
1352 FLAC__StreamMetadata *block, *app, *padding;
Josh Coalsond34f03d2002-05-11 05:41:42 +00001353 FLAC__byte data[2000];
1354 unsigned our_current_position;
1355
Josh Coalson45062b82002-12-28 07:06:38 +00001356 /* initialize 'data' to avoid Valgrind errors */
1357 memset(data, 0, sizeof(data));
1358
Josh Coalson65831dd2004-07-14 00:50:52 +00001359 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
Josh Coalson275f6842002-05-09 05:52:40 +00001360
Josh Coalsond34f03d2002-05-11 05:41:42 +00001361 printf("generate read-only file\n");
1362
Josh Coalson7cfac0b2006-04-10 05:37:34 +00001363 if(!generate_file_(/*include_cuesheet=*/false))
Josh Coalsond34f03d2002-05-11 05:41:42 +00001364 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
Josh Coalson0b8b5642004-07-15 00:04:09 +00001376 if(!read_chain_(chain, flacfile_, filename_based))
Josh Coalsond34f03d2002-05-11 05:41:42 +00001377 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1378
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001379 printf("[S]VP\ttest initial metadata\n");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001380
Josh Coalson76eb8632002-05-14 06:04:47 +00001381 if(!compare_chain_(chain, 0, 0))
Josh Coalsond34f03d2002-05-11 05:41:42 +00001382 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
Josh Coalsonf331ac22002-05-25 02:14:26 +00001391 printf("create iterator\n");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001392 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001404 printf("[S]VP\tmodify STREAMINFO, write\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001405
Josh Coalsond34f03d2002-05-11 05:41:42 +00001406 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001410 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
Josh Coalsond34f03d2002-05-11 05:41:42 +00001411 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001412 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1413 return false;
Josh Coalsond34f03d2002-05-11 05:41:42 +00001414 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1415 return false;
1416
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001417 printf("[S]VP\tnext\n");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001418 if(!FLAC__metadata_iterator_next(iterator))
1419 return die_("iterator ended early\n");
1420 our_current_position++;
1421
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001422 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");
Josh Coalson76eb8632002-05-14 06:04:47 +00001428 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1429 return die_("getting block from iterator");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001430 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");
Josh Coalsona4bbe462002-05-14 06:16:02 +00001435 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
Josh Coalsond34f03d2002-05-11 05:41:42 +00001436 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001440 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001441 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001442 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1443 return false;
Josh Coalsond34f03d2002-05-11 05:41:42 +00001444 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1445 return false;
1446
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001447 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001448 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001449 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001457 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001458 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001459 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001464 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001465 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001466 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001474 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001475 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001476 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001481 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001482 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001483 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001491 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001492 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001493 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001498 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001499 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001500 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001508 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001509 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001510 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001515 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001516 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1517 return die_("creating PADDING block");
Josh Coalsoncc682512002-06-08 04:53:42 +00001518 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001519 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001530 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001531 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001532 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001537 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001538 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001539 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001548 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001549 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001550 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001555 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001556 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001557 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001565 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001566 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001567 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001572 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001573 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001574 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001583 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001584 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001585 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001590 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001591 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001592 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
Josh Coalson65831dd2004-07-14 00:50:52 +00001601 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001602 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001603 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001608 printf("SV[A]\tprev\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001609 if(!FLAC__metadata_iterator_prev(iterator))
1610 return die_("iterator ended early\n");
1611 our_current_position--;
1612
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001613 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");
Josh Coalson76eb8632002-05-14 06:04:47 +00001619 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001627 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");
Josh Coalson76eb8632002-05-14 06:04:47 +00001633 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001641 printf("SV[P]A\tinsert PADDING before\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001642 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001643 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001653 printf("SV[P]PA\tinsert PADDING before\n");
Josh Coalsoncc682512002-06-08 04:53:42 +00001654 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001655 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001665 printf("SV[P]PPA\tnext\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001666 if(!FLAC__metadata_iterator_next(iterator))
1667 return die_("iterator ended early\n");
1668 our_current_position++;
1669
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001670 printf("SVP[P]PA\tnext\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001671 if(!FLAC__metadata_iterator_next(iterator))
1672 return die_("iterator ended early\n");
1673 our_current_position++;
1674
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001675 printf("SVPP[P]A\tnext\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001676 if(!FLAC__metadata_iterator_next(iterator))
1677 return die_("iterator ended early\n");
1678 our_current_position++;
1679
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001680 printf("SVPPP[A]\tinsert PADDING after\n");
1681 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001682 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001692 printf("SVPPPA[P]\tinsert PADDING before\n");
1693 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
Josh Coalson76eb8632002-05-14 06:04:47 +00001694 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");
Josh Coalsond34f03d2002-05-11 05:41:42 +00001705 FLAC__metadata_iterator_delete(iterator);
Josh Coalson76eb8632002-05-14 06:04:47 +00001706 our_current_position = 0;
1707
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001708 printf("SVPPPAPP\tmerge padding\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001709 FLAC__metadata_chain_merge_padding(chain);
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001710 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);
Josh Coalson76eb8632002-05-14 06:04:47 +00001715 delete_from_our_metadata_(3);
Josh Coalson76eb8632002-05-14 06:04:47 +00001716
Josh Coalson65831dd2004-07-14 00:50:52 +00001717 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001718 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001719 if(!compare_chain_(chain, 0, 0))
1720 return false;
1721 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1722 return false;
1723
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001724 printf("SVPAP\tsort padding\n");
Josh Coalson76eb8632002-05-14 06:04:47 +00001725 FLAC__metadata_chain_sort_padding(chain);
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001726 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1727 delete_from_our_metadata_(2);
Josh Coalson76eb8632002-05-14 06:04:47 +00001728
Josh Coalson65831dd2004-07-14 00:50:52 +00001729 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001730 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001744 printf("[S]VAP\tnext\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001745 if(!FLAC__metadata_iterator_next(iterator))
1746 return die_("iterator ended early\n");
1747 our_current_position++;
1748
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001749 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");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001755 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001766 printf("S[V]PP\tnext\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001767 if(!FLAC__metadata_iterator_next(iterator))
1768 return die_("iterator ended early\n");
1769 our_current_position++;
1770
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001771 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001772 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001779 printf("S[V]P\tnext\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001780 if(!FLAC__metadata_iterator_next(iterator))
1781 return die_("iterator ended early\n");
1782 our_current_position++;
1783
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001784 printf("SV[P]\tdelete last block, replace with padding\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001785 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001796 printf("S[V]P\tnext\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001797 if(!FLAC__metadata_iterator_next(iterator))
1798 return die_("iterator ended early\n");
1799 our_current_position++;
1800
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001801 printf("SV[P]\tdelete last block, don't replace with padding\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001802 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001809 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");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001815 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001825 printf("SV\tmerge padding\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001826 FLAC__metadata_chain_merge_padding(chain);
1827
Josh Coalson65831dd2004-07-14 00:50:52 +00001828 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001829 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
Josh Coalsonfedb0ae2002-08-25 05:10:37 +00001835 printf("SV\tsort padding\n");
Josh Coalsonf331ac22002-05-25 02:14:26 +00001836 FLAC__metadata_chain_sort_padding(chain);
1837
Josh Coalson65831dd2004-07-14 00:50:52 +00001838 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
Josh Coalsonf331ac22002-05-25 02:14:26 +00001839 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
Josh Coalson76eb8632002-05-14 06:04:47 +00001840 if(!compare_chain_(chain, 0, 0))
1841 return false;
1842 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1843 return false;
Josh Coalsond34f03d2002-05-11 05:41:42 +00001844
1845 printf("delete chain\n");
1846
1847 FLAC__metadata_chain_delete(chain);
1848
1849 if(!remove_file_(flacfile_))
1850 return false;
1851
Josh Coalson275f6842002-05-09 05:52:40 +00001852 return true;
1853}
1854
Josh Coalson0b8b5642004-07-15 00:04:09 +00001855static 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
Josh Coalson7cfac0b2006-04-10 05:37:34 +00001876 if(!generate_file_(/*include_cuesheet=*/false))
Josh Coalson0b8b5642004-07-15 00:04:09 +00001877 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
Josh Coalson57ba6f42002-06-07 05:27:37 +00002017FLAC__bool test_metadata_file_manipulation()
Josh Coalson4860ed72002-05-07 05:33:49 +00002018{
Josh Coalsoncc682512002-06-08 04:53:42 +00002019 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
Josh Coalson4860ed72002-05-07 05:33:49 +00002020
Josh Coalsond34f03d2002-05-11 05:41:42 +00002021 our_metadata_.num_blocks = 0;
2022
Josh Coalson6e62e8f2002-05-17 06:28:09 +00002023 if(!test_level_0_())
Josh Coalson57ba6f42002-06-07 05:27:37 +00002024 return false;
Josh Coalson275f6842002-05-09 05:52:40 +00002025
Josh Coalson6e62e8f2002-05-17 06:28:09 +00002026 if(!test_level_1_())
Josh Coalson57ba6f42002-06-07 05:27:37 +00002027 return false;
Josh Coalson275f6842002-05-09 05:52:40 +00002028
Josh Coalson65831dd2004-07-14 00:50:52 +00002029 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2030 return false;
2031 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
Josh Coalson57ba6f42002-06-07 05:27:37 +00002032 return false;
Josh Coalson0b8b5642004-07-15 00:04:09 +00002033 if(!test_level_2_misc_())
2034 return false;
Josh Coalson275f6842002-05-09 05:52:40 +00002035
Josh Coalson57ba6f42002-06-07 05:27:37 +00002036 return true;
Josh Coalson4860ed72002-05-07 05:33:49 +00002037}