chunk_test.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. ** Copyright (C) 2003-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU General Public License as published by
  6. ** the Free Software Foundation; either version 2 of the License, or
  7. ** (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 "sfconfig.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <math.h>
  23. #if HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #include <sndfile.h>
  27. #include "utils.h"
  28. #define BUFFER_LEN (1 << 10)
  29. #define LOG_BUFFER_SIZE 1024
  30. static void chunk_test (const char *filename, int format) ;
  31. static void
  32. chunk_test_helper (const char *filename, int format, const char * testdata) ;
  33. int
  34. main (int argc, char *argv [])
  35. { int do_all = 0 ;
  36. int test_count = 0 ;
  37. if (argc != 2)
  38. { printf ("Usage : %s <test>\n", argv [0]) ;
  39. printf (" Where <test> is one of the following:\n") ;
  40. printf (" wav - test adding chunks to WAV files\n") ;
  41. printf (" aiff - test adding chunks to AIFF files\n") ;
  42. printf (" all - perform all tests\n") ;
  43. exit (1) ;
  44. } ;
  45. do_all = ! strcmp (argv [1], "all") ;
  46. if (do_all || ! strcmp (argv [1], "wav"))
  47. { chunk_test ("chunks_pcm16.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
  48. chunk_test ("chunks_pcm16.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
  49. chunk_test ("chunks_pcm16.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
  50. test_count++ ;
  51. } ;
  52. if (do_all || ! strcmp (argv [1], "aiff"))
  53. { chunk_test ("chunks_pcm16.aiff", SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
  54. test_count++ ;
  55. } ;
  56. if (do_all || ! strcmp (argv [1], "caf"))
  57. { chunk_test ("chunks_pcm16.caf", SF_FORMAT_CAF | SF_FORMAT_PCM_16) ;
  58. chunk_test ("chunks_alac.caf", SF_FORMAT_CAF | SF_FORMAT_ALAC_16) ;
  59. test_count++ ;
  60. } ;
  61. if (test_count == 0)
  62. { printf ("Mono : ************************************\n") ;
  63. printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
  64. printf ("Mono : ************************************\n") ;
  65. return 1 ;
  66. } ;
  67. return 0 ;
  68. } /* main */
  69. /*============================================================================================
  70. ** Here are the test functions.
  71. */
  72. static void
  73. chunk_test_helper (const char *filename, int format, const char * testdata)
  74. { SNDFILE *file ;
  75. SF_INFO sfinfo ;
  76. SF_CHUNK_INFO chunk_info ;
  77. SF_CHUNK_ITERATOR * iterator ;
  78. uint32_t length_before ;
  79. int err, allow_fd ;
  80. switch (format & SF_FORMAT_SUBMASK)
  81. { case SF_FORMAT_ALAC_16 :
  82. allow_fd = SF_FALSE ;
  83. break ;
  84. default :
  85. allow_fd = SF_TRUE ;
  86. break ;
  87. } ;
  88. sfinfo.samplerate = 44100 ;
  89. sfinfo.channels = 1 ;
  90. sfinfo.frames = 0 ;
  91. sfinfo.format = format ;
  92. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
  93. /* Set up the chunk to write. */
  94. memset (&chunk_info, 0, sizeof (chunk_info)) ;
  95. snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
  96. chunk_info.id_size = 4 ;
  97. chunk_info.data = strdup (testdata) ;
  98. chunk_info.datalen = strlen (chunk_info.data) ;
  99. length_before = chunk_info.datalen ;
  100. err = sf_set_chunk (file, &chunk_info) ;
  101. exit_if_true (
  102. err != SF_ERR_NO_ERROR,
  103. "\n\nLine %d : sf_set_chunk returned for testdata '%s' : %s\n\n", __LINE__, testdata, sf_error_number (err)
  104. ) ;
  105. memset (chunk_info.data, 0, chunk_info.datalen) ;
  106. free (chunk_info.data) ;
  107. sf_close (file) ;
  108. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
  109. memset (&chunk_info, 0, sizeof (chunk_info)) ;
  110. snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
  111. chunk_info.id_size = 4 ;
  112. iterator = sf_get_chunk_iterator (file, &chunk_info) ;
  113. err = sf_get_chunk_size (iterator, &chunk_info) ;
  114. exit_if_true (
  115. err != SF_ERR_NO_ERROR,
  116. "\n\nLine %d : sf_get_chunk_size returned for testdata '%s' : %s\n\n", __LINE__, testdata, sf_error_number (err)
  117. ) ;
  118. exit_if_true (
  119. length_before > chunk_info.datalen || chunk_info.datalen - length_before > 4,
  120. "\n\nLine %d : testdata '%s' : Bad chunk length %u (previous length %u)\n\n", __LINE__, testdata, chunk_info.datalen, length_before
  121. ) ;
  122. chunk_info.data = malloc (chunk_info.datalen) ;
  123. err = sf_get_chunk_data (iterator, &chunk_info) ;
  124. exit_if_true (
  125. err != SF_ERR_NO_ERROR,
  126. "\n\nLine %d : sf_get_chunk_size returned for testdata '%s' : %s\n\n", __LINE__, testdata, sf_error_number (err)
  127. ) ;
  128. exit_if_true (
  129. memcmp (testdata, chunk_info.data, length_before),
  130. "\n\nLine %d : Data compare failed.\n %s\n %s\n\n", __LINE__, testdata, (char*) chunk_info.data
  131. ) ;
  132. free (chunk_info.data) ;
  133. sf_close (file) ;
  134. unlink (filename) ;
  135. } /* chunk_test_helper */
  136. static void
  137. multichunk_test_helper (const char *filename, int format, const char * testdata [], size_t testdata_len)
  138. { SNDFILE *file ;
  139. SF_INFO sfinfo ;
  140. SF_CHUNK_INFO chunk_info ;
  141. SF_CHUNK_ITERATOR * iterator ;
  142. uint32_t length_before [testdata_len] ;
  143. int err, allow_fd ;
  144. size_t i ;
  145. sfinfo.samplerate = 44100 ;
  146. sfinfo.channels = 1 ;
  147. sfinfo.frames = 0 ;
  148. sfinfo.format = format ;
  149. switch (format & SF_FORMAT_SUBMASK)
  150. { case SF_FORMAT_ALAC_16 :
  151. allow_fd = SF_FALSE ;
  152. break ;
  153. default :
  154. allow_fd = SF_TRUE ;
  155. break ;
  156. } ;
  157. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, allow_fd, __LINE__) ;
  158. /* Set up the chunk to write. */
  159. for (i = 0 ; i < testdata_len ; i++)
  160. { memset (&chunk_info, 0, sizeof (chunk_info)) ;
  161. snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
  162. chunk_info.id_size = 4 ;
  163. chunk_info.data = strdup (testdata [i]) ;
  164. chunk_info.datalen = strlen (chunk_info.data) ;
  165. length_before [i] = chunk_info.datalen ;
  166. err = sf_set_chunk (file, &chunk_info) ;
  167. exit_if_true (
  168. err != SF_ERR_NO_ERROR,
  169. "\n\nLine %d : sf_set_chunk returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err)
  170. ) ;
  171. memset (chunk_info.data, 0, chunk_info.datalen) ;
  172. free (chunk_info.data) ;
  173. }
  174. sf_close (file) ;
  175. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, allow_fd, __LINE__) ;
  176. memset (&chunk_info, 0, sizeof (chunk_info)) ;
  177. snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ;
  178. chunk_info.id_size = 4 ;
  179. iterator = sf_get_chunk_iterator (file, &chunk_info) ;
  180. i = 0 ;
  181. while (iterator)
  182. { memset (&chunk_info, 0, sizeof (chunk_info)) ;
  183. err = sf_get_chunk_size (iterator, &chunk_info) ;
  184. exit_if_true (
  185. i > testdata_len,
  186. "\n\nLine %d : iterated to chunk #%d, but only %d chunks have been written\n\n", __LINE__, (int) i, (int) testdata_len
  187. ) ;
  188. exit_if_true (
  189. err != SF_ERR_NO_ERROR,
  190. "\n\nLine %d : sf_get_chunk_size returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err)
  191. ) ;
  192. exit_if_true (
  193. length_before [i] > chunk_info.datalen || chunk_info.datalen - length_before [i] > 4,
  194. "\n\nLine %d : testdata[%d] '%s' : Bad chunk length %u (previous length %u)\n\n", __LINE__, (int) i, testdata [i], chunk_info.datalen, length_before [i]
  195. ) ;
  196. chunk_info.data = malloc (chunk_info.datalen) ;
  197. err = sf_get_chunk_data (iterator, &chunk_info) ;
  198. exit_if_true (
  199. err != SF_ERR_NO_ERROR,
  200. "\n\nLine %d : sf_get_chunk_size returned for testdata[%d] '%s' : %s\n\n", __LINE__, (int) i, testdata [i], sf_error_number (err)
  201. ) ;
  202. exit_if_true (
  203. 4 != chunk_info.id_size,
  204. "\n\nLine %d : testdata[%d] : Bad ID length %u (previous length %u)\n\n", __LINE__, (int) i, chunk_info.id_size, 4
  205. ) ;
  206. exit_if_true (
  207. memcmp ("Test", chunk_info.id, 4),
  208. "\n\nLine %d : ID compare failed at %d.\n %s\n %s\n\n", __LINE__, (int) i, "Test", (char*) chunk_info.id
  209. ) ;
  210. exit_if_true (
  211. memcmp (testdata [i], chunk_info.data, length_before [i]),
  212. "\n\nLine %d : Data compare failed at %d.\n %s\n %s\n\n", __LINE__, (int) i, testdata [i], (char*) chunk_info.data
  213. ) ;
  214. free (chunk_info.data) ;
  215. iterator = sf_next_chunk_iterator (iterator) ;
  216. i++ ;
  217. }
  218. sf_close (file) ;
  219. unlink (filename) ;
  220. } /* multichunk_test_helper */
  221. static void
  222. chunk_test (const char *filename, int format)
  223. { const char* testdata [] =
  224. { "There can be only one.", "", "A", "AB", "ABC", "ABCD", "ABCDE" } ;
  225. uint32_t k ;
  226. print_test_name (__func__, filename) ;
  227. for (k = 0 ; k < ARRAY_LEN (testdata) ; k++)
  228. chunk_test_helper (filename, format, testdata [k]) ;
  229. multichunk_test_helper (filename, format, testdata, ARRAY_LEN (testdata)) ;
  230. puts ("ok") ;
  231. } /* chunk_test */