metadata_manip.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:76k
源码类别:

Windows CE

开发平台:

C/C++

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