dispatch_transform.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. /*
  2. * Copyright (c) 2011-2012 Apple Inc. All rights reserved.
  3. *
  4. * @APPLE_APACHE_LICENSE_HEADER_START@
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * @APPLE_APACHE_LICENSE_HEADER_END@
  19. */
  20. #include <bsdtests.h>
  21. #if DISPATCH_API_VERSION >= 20111008 && !TARGET_OS_EMBEDDED
  22. #include <Security/Security.h>
  23. #include <dispatch/dispatch.h>
  24. #include <dispatch/private.h>
  25. #include <fcntl.h>
  26. #define printf_data(p, s) ({ \
  27. __typeof__(s) _i; \
  28. for (_i=0; _i<s; _i++) { \
  29. printf("%c", ((uint8_t *)p)[_i]); \
  30. } \
  31. printf("\n"); \
  32. })
  33. #define test_data_equal(a, b, c) ({ \
  34. const void * ptr, * ptr2; \
  35. size_t size, size2; \
  36. dispatch_data_t map = dispatch_data_create_map(b, &ptr, &size); \
  37. assert(map); \
  38. dispatch_data_t map2 = dispatch_data_create_map(c, &ptr2, &size2); \
  39. assert(map); \
  40. test_long(a ": length", size, size2); \
  41. test_long(a ": memcmp", memcmp(ptr, ptr2, size), 0); \
  42. if (size != size2 || (memcmp(ptr, ptr2, size) != 0)) { \
  43. printf_data(ptr, size); \
  44. printf_data(ptr2, size2); \
  45. } \
  46. dispatch_release(map); \
  47. dispatch_release(map2); \
  48. })
  49. static bool
  50. dispatch_data_equal(dispatch_data_t a, dispatch_data_t b)
  51. {
  52. const void * ptr, * ptr2;
  53. size_t size, size2;
  54. bool equal = true;
  55. dispatch_data_t map = dispatch_data_create_map(a, &ptr, &size); \
  56. assert(map);
  57. dispatch_data_t map2 = dispatch_data_create_map(b, &ptr2, &size2); \
  58. assert(map2);
  59. if (size == size2) {
  60. if (memcmp(ptr, ptr2, size) != 0) {
  61. equal = false;
  62. }
  63. } else {
  64. equal = false;
  65. }
  66. dispatch_release(map);
  67. dispatch_release(map2);
  68. return equal;
  69. }
  70. static dispatch_data_t
  71. execute_sectransform(SecTransformRef transformRef, dispatch_data_t data)
  72. {
  73. const void * bytes;
  74. size_t size;
  75. dispatch_data_t map = dispatch_data_create_map(data, &bytes, &size);
  76. assert(map);
  77. CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, bytes, size);
  78. assert(dataRef);
  79. dispatch_release(map);
  80. SecTransformSetAttribute(transformRef, kSecTransformInputAttributeName, dataRef, NULL);
  81. CFDataRef transformedDataRef = SecTransformExecute(transformRef, NULL);
  82. assert(transformedDataRef);
  83. CFRelease(dataRef);
  84. dispatch_data_t output = dispatch_data_create(CFDataGetBytePtr(transformedDataRef), CFDataGetLength(transformedDataRef), dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT);
  85. CFRelease(transformedDataRef);
  86. return output;
  87. }
  88. #pragma mark - UTF tests
  89. static uint8_t utf8[] = {
  90. 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66, 0x6f,
  91. 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xeb, 0x84, 0x88, 0xeb, 0xac,
  92. 0xb4, 0x20, 0xec, 0x98, 0xa4, 0xeb, 0x9e, 0x98, 0x20, 0xea, 0xb7, 0xb8, 0xeb, 0xa6, 0xac, 0xea, 0xb3, 0xa0, 0x20, 0xea, 0xb7,
  93. 0xb8, 0x20, 0xeb, 0x8f, 0x99, 0xec, 0x95, 0x88, 0x20, 0xeb, 0xa7, 0x9b, 0xec, 0x9e, 0x88, 0xeb, 0x8a, 0x94, 0x20, 0xec, 0x83,
  94. 0x9d, 0xec, 0x84, 0xa0, 0xec, 0x9d, 0x80, 0x20, 0xea, 0xb3, 0xa0, 0xeb, 0xa7, 0x88, 0xec, 0x9b, 0xa0, 0xec, 0x96, 0xb4, 0x2e,
  95. 0x20, 0xf0, 0x9f, 0x98, 0x84, 0xf0, 0x9f, 0x98, 0x8a, 0xf0, 0x9f, 0x98, 0x83, 0xe2, 0x98, 0xba, 0xf0, 0x9f, 0x98, 0x89, 0xf0,
  96. 0x9f, 0x98, 0x8d, 0xf0, 0x9f, 0x92, 0xa8, 0xf0, 0x9f, 0x92, 0xa9, 0xf0, 0x9f, 0x91, 0x8e, 0x2e,
  97. };
  98. static uint16_t utf16[] = {
  99. 0xfeff, 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66,
  100. 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xb108, 0xbb34, 0x20,
  101. 0xc624, 0xb798, 0x20, 0xadf8, 0xb9ac, 0xace0, 0x20, 0xadf8, 0x20, 0xb3d9, 0xc548, 0x20, 0xb9db, 0xc788, 0xb294, 0x20, 0xc0dd,
  102. 0xc120, 0xc740, 0x20, 0xace0, 0xb9c8, 0xc6e0, 0xc5b4, 0x2e, 0x20, 0xd83d, 0xde04, 0xd83d, 0xde0a, 0xd83d, 0xde03, 0x263a, 0xd83d,
  103. 0xde09, 0xd83d, 0xde0d, 0xd83d, 0xdca8, 0xd83d, 0xdca9, 0xd83d, 0xdc4e, 0x2e,
  104. };
  105. static uint16_t utf16be[] = {
  106. 0xfffe, 0x5300, 0x6f00, 0x2000, 0x6c00, 0x6f00, 0x6e00, 0x6700, 0x2000, 0x6100, 0x6e00, 0x6400, 0x2000, 0x7400, 0x6800, 0x6100,
  107. 0x6e00, 0x6b00, 0x7300, 0x2000, 0x6600, 0x6f00, 0x7200, 0x2000, 0x6100, 0x6c00, 0x6c00, 0x2000, 0x7400, 0x6800, 0x6500, 0x2000,
  108. 0x6600, 0x6900, 0x7300, 0x6800, 0x2e00, 0x2000, 0x8b1, 0x34bb, 0x2000, 0x24c6, 0x98b7, 0x2000, 0xf8ad, 0xacb9, 0xe0ac, 0x2000,
  109. 0xf8ad, 0x2000, 0xd9b3, 0x48c5, 0x2000, 0xdbb9, 0x88c7, 0x94b2, 0x2000, 0xddc0, 0x20c1, 0x40c7, 0x2000, 0xe0ac, 0xc8b9, 0xe0c6,
  110. 0xb4c5, 0x2e00, 0x2000, 0x3dd8, 0x4de, 0x3dd8, 0xade, 0x3dd8, 0x3de, 0x3a26, 0x3dd8, 0x9de, 0x3dd8, 0xdde, 0x3dd8, 0xa8dc,
  111. 0x3dd8, 0xa9dc, 0x3dd8, 0x4edc, 0x2e00,
  112. };
  113. // Invalid due to half missing surrogate
  114. static uint16_t utf16le_invalid[] = {
  115. 0xfeff, 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66,
  116. 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xb108, 0xbb34, 0x20,
  117. 0xc624, 0xb798, 0x20, 0xadf8, 0xb9ac, 0xace0, 0x20, 0xadf8, 0x20, 0xb3d9, 0xc548, 0x20, 0xb9db, 0xc788, 0xb294, 0x20, 0xc0dd,
  118. 0xc120, 0xc740, 0x20, 0xace0, 0xb9c8, 0xc6e0, 0xc5b4, 0x2e, 0x20, 0xd83d, 0xde04, 0xd83d, 0xde0a, 0xd83d, 0xde03, 0x263a, 0xd83d,
  119. 0xde09, 0xd83d, 0xde0d, 0xd83d, 0xdca8, 0xd83d, 0xd83d, 0xdc4e, 0x2e,
  120. };
  121. void
  122. invalid_utf8_test(void * context)
  123. {
  124. dispatch_data_t utf8_data = dispatch_data_create(utf8 + sizeof(utf8) - 8, 8, NULL, ^{});
  125. dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
  126. test_ptr_null("dispatch_data_create_with_transform (UTF8 (invalid start) -> UTF16LE)", transformed);
  127. dispatch_release(utf8_data);
  128. (void)context;
  129. }
  130. void
  131. truncated_utf8_test(void * context)
  132. {
  133. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8) - 3, NULL, ^{});
  134. dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
  135. test_ptr_null("dispatch_data_create_with_transform (UTF8 (truncated) -> UTF16LE)", transformed);
  136. dispatch_release(utf8_data);
  137. dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf8_test);
  138. }
  139. void
  140. invalid_utf16le_surrogate_test(void * context)
  141. {
  142. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  143. dispatch_data_t utf16_data = dispatch_data_create(utf16le_invalid, sizeof(utf16le_invalid), NULL, ^{});
  144. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  145. test_ptr_null("dispatch_data_create_with_transform (UTF16LE (missing surrogate) -> UTF8)", transformed);
  146. dispatch_release(utf16_data);
  147. dispatch_release(utf8_data);
  148. dispatch_group_async_f(context, dispatch_get_main_queue(), context, truncated_utf8_test);
  149. }
  150. void
  151. invalid_utf16le_test(void * context)
  152. {
  153. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  154. dispatch_data_t utf16_data = dispatch_data_create(utf16, (sizeof(utf16) % 2) + 1, NULL, ^{});
  155. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  156. test_ptr_null("dispatch_data_create_with_transform (UTF16LE (invalid) -> UTF8)", transformed);
  157. dispatch_release(utf16_data);
  158. dispatch_release(utf8_data);
  159. dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf16le_surrogate_test);
  160. }
  161. void
  162. utf16le_bytes_to_utf8_test(void * context)
  163. {
  164. dispatch_data_t utf16_data = dispatch_data_empty;
  165. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  166. size_t i;
  167. for (i=0; i<sizeof(utf16); i++) {
  168. dispatch_data_t new = dispatch_data_create((char*)utf16 + i, 1, NULL, ^{});
  169. dispatch_data_t concat = dispatch_data_create_concat(utf16_data, new);
  170. dispatch_release(new);
  171. dispatch_release(utf16_data);
  172. utf16_data = concat;
  173. }
  174. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  175. test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE (any, single bytes) -> UTF8)", transformed);
  176. test_data_equal("utf16le_bytes_to_utf8_test", transformed, utf8_data);
  177. dispatch_release(transformed);
  178. dispatch_release(utf8_data);
  179. dispatch_release(utf16_data);
  180. dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf16le_test);
  181. }
  182. void
  183. utf8_bytes_to_utf16le_test(void * context)
  184. {
  185. dispatch_data_t utf8_data = dispatch_data_empty;
  186. dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
  187. size_t i;
  188. for (i=0; i<sizeof(utf8); i++) {
  189. dispatch_data_t new = dispatch_data_create(utf8 + i, 1, NULL, ^{});
  190. dispatch_data_t concat = dispatch_data_create_concat(utf8_data, new);
  191. dispatch_release(new);
  192. dispatch_release(utf8_data);
  193. utf8_data = concat;
  194. }
  195. dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
  196. test_ptr_notnull("dispatch_data_create_with_transform (UTF8 (any, single bytes) -> UTF16LE)", transformed);
  197. test_data_equal("utf8_bytes_to_utf16le_test", transformed, utf16_data);
  198. dispatch_release(transformed);
  199. dispatch_release(utf8_data);
  200. dispatch_release(utf16_data);
  201. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_bytes_to_utf8_test);
  202. }
  203. void
  204. utf16be_detect_to_utf16le_test(void * context)
  205. {
  206. dispatch_data_t utf16be_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
  207. dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
  208. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16be_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
  209. test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE (any) -> UTF16LE)", transformed);
  210. test_data_equal("utf16be_detect_to_utf16le_test", transformed, utf16_data);
  211. dispatch_release(transformed);
  212. dispatch_release(utf16be_data);
  213. dispatch_release(utf16_data);
  214. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_bytes_to_utf16le_test);
  215. }
  216. void
  217. utf16be_detect_to_utf8_test(void * context)
  218. {
  219. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  220. dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
  221. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  222. test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE (any) -> UTF8)", transformed);
  223. test_data_equal("utf16be_detect_to_utf8_test", transformed, utf8_data);
  224. dispatch_release(transformed);
  225. dispatch_release(utf16_data);
  226. dispatch_release(utf8_data);
  227. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_detect_to_utf16le_test);
  228. }
  229. void
  230. utf16le_detect_to_utf8_test(void * context)
  231. {
  232. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  233. dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
  234. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  235. test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE (any) -> UTF8)", transformed);
  236. test_data_equal("utf16le_detect_to_utf8_test", transformed, utf8_data);
  237. dispatch_release(transformed);
  238. dispatch_release(utf16_data);
  239. dispatch_release(utf8_data);
  240. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_detect_to_utf8_test);
  241. }
  242. void
  243. utf16be_to_utf8_test(void * context)
  244. {
  245. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  246. dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
  247. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16BE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  248. test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE -> UTF8)", transformed);
  249. test_data_equal("utf16be_to_utf8_test", transformed, utf8_data);
  250. dispatch_release(transformed);
  251. dispatch_release(utf16_data);
  252. dispatch_release(utf8_data);
  253. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_detect_to_utf8_test);
  254. }
  255. void
  256. utf16le_to_utf8_test(void * context)
  257. {
  258. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  259. dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
  260. dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
  261. test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE -> UTF8)", transformed);
  262. test_data_equal("utf16le_to_utf8_test", transformed, utf8_data);
  263. dispatch_release(transformed);
  264. dispatch_release(utf16_data);
  265. dispatch_release(utf8_data);
  266. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_to_utf8_test);
  267. }
  268. void
  269. utf8_to_utf16be_test(void * context)
  270. {
  271. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  272. dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
  273. dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16BE);
  274. test_ptr_notnull("dispatch_data_create_with_transform (UTF8 -> UTF16BE)", transformed);
  275. test_data_equal("utf8_to_utf16be_test", transformed, utf16_data);
  276. dispatch_release(transformed);
  277. dispatch_release(utf16_data);
  278. dispatch_release(utf8_data);
  279. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_to_utf8_test);
  280. }
  281. void
  282. utf8_to_utf16le_test(void * context)
  283. {
  284. dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
  285. dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
  286. dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
  287. test_ptr_notnull("dispatch_data_create_with_transform (UTF8 -> UTF16LE)", transformed);
  288. test_data_equal("utf8_to_utf16le_test", transformed, utf16_data);
  289. dispatch_release(transformed);
  290. dispatch_release(utf16_data);
  291. dispatch_release(utf8_data);
  292. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_to_utf16be_test);
  293. }
  294. #pragma mark - base32 tests
  295. void
  296. decode32_corrupt_test(void * context)
  297. {
  298. dispatch_group_enter((dispatch_group_t)context);
  299. int fd = open("/dev/random", O_RDONLY);
  300. assert(fd >= 0);
  301. dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
  302. assert(error == 0);
  303. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
  304. assert(transformRef);
  305. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  306. assert(sectransform_data);
  307. CFRelease(transformRef);
  308. void * corrupt_buffer = malloc(dispatch_data_get_size(sectransform_data));
  309. const void * source;
  310. size_t size;
  311. dispatch_data_t map = dispatch_data_create_map(sectransform_data, &source, &size);
  312. memcpy(corrupt_buffer, source, size);
  313. size_t i;
  314. for (i=0; i<size; i += (arc4random() % (int)(size * 0.05))) {
  315. char x = arc4random() & 0xff;
  316. while ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x >= '0' && x <= '9') || x == '/' || x == '+' || x == '=') {
  317. x = arc4random() & 0xff;
  318. }
  319. ((char*)corrupt_buffer)[i] = x;
  320. }
  321. dispatch_release(map);
  322. dispatch_release(sectransform_data);
  323. dispatch_data_t corrupt_data = dispatch_data_create(corrupt_buffer, size, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE);
  324. dispatch_data_t transform_data = dispatch_data_create_with_transform(corrupt_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE);
  325. test_ptr_null("decode32_corrupt_test: dispatch_data_create_with_transform", transform_data);
  326. dispatch_release(corrupt_data);
  327. close(fd);
  328. dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_to_utf16le_test);
  329. dispatch_group_leave((dispatch_group_t)context);
  330. });
  331. }
  332. void
  333. chunking_decode32_test(void * context)
  334. {
  335. (void)context;
  336. int fd = open("/dev/random", O_RDONLY);
  337. assert(fd >= 0);
  338. dispatch_data_t __block data = dispatch_data_empty;
  339. int i;
  340. dispatch_group_t group = dispatch_group_create();
  341. dispatch_queue_t queue = dispatch_queue_create("read", 0);
  342. for (i=0; i<4096; i++) {
  343. dispatch_group_enter(group);
  344. dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
  345. assert(error == 0);
  346. dispatch_data_t concat = dispatch_data_create_concat(data, d);
  347. dispatch_release(data);
  348. data = concat;
  349. dispatch_group_leave(group);
  350. });
  351. }
  352. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  353. dispatch_release(queue);
  354. dispatch_release(group);
  355. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
  356. assert(transformRef);
  357. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  358. assert(sectransform_data);
  359. CFRelease(transformRef);
  360. dispatch_data_t transformed_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE);
  361. test_ptr_notnull("chunking_decode32_test: dispatch_data_create_with_transform", transformed_data);
  362. test_data_equal("chunking_decode32_test", transformed_data, data);
  363. dispatch_release(sectransform_data);
  364. dispatch_release(transformed_data);
  365. dispatch_release(data);
  366. close(fd);
  367. dispatch_group_async_f(context, dispatch_get_main_queue(), context, decode32_corrupt_test);
  368. }
  369. void
  370. chunking_encode32_test(void * context)
  371. {
  372. (void)context;
  373. int fd = open("/dev/random", O_RDONLY);
  374. assert(fd >= 0);
  375. dispatch_data_t __block data = dispatch_data_empty;
  376. int i;
  377. dispatch_group_t group = dispatch_group_create();
  378. dispatch_queue_t queue = dispatch_queue_create("read", 0);
  379. for (i=0; i<4096; i++) {
  380. dispatch_group_enter(group);
  381. dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
  382. assert(error == 0);
  383. dispatch_data_t concat = dispatch_data_create_concat(data, d);
  384. dispatch_release(data);
  385. data = concat;
  386. dispatch_group_leave(group);
  387. });
  388. }
  389. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  390. dispatch_release(queue);
  391. dispatch_release(group);
  392. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
  393. assert(transformRef);
  394. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  395. assert(sectransform_data);
  396. CFRelease(transformRef);
  397. dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE32);
  398. test_ptr_notnull("chunking_encode32_test: dispatch_data_create_with_transform", transformed_data);
  399. test_data_equal("chunking_encode32_test", transformed_data, sectransform_data);
  400. dispatch_release(sectransform_data);
  401. dispatch_release(transformed_data);
  402. dispatch_release(data);
  403. close(fd);
  404. dispatch_group_async_f(context, dispatch_get_main_queue(), context, chunking_decode32_test);
  405. }
  406. void
  407. decode32_test(void * context)
  408. {
  409. dispatch_group_enter((dispatch_group_t)context);
  410. int fd = open("/dev/random", O_RDONLY);
  411. assert(fd >= 0);
  412. dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
  413. assert(error == 0);
  414. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
  415. assert(transformRef);
  416. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  417. assert(sectransform_data);
  418. CFRelease(transformRef);
  419. dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE);
  420. test_ptr_notnull("decode32_test: dispatch_data_create_with_transform", transform_data);
  421. test_data_equal("decode32_test", transform_data, data);
  422. dispatch_release(sectransform_data);
  423. dispatch_release(transform_data);
  424. close(fd);
  425. dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, chunking_encode32_test);
  426. dispatch_group_leave((dispatch_group_t)context);
  427. });
  428. }
  429. void
  430. encode32_test(void * context)
  431. {
  432. dispatch_group_enter((dispatch_group_t)context);
  433. int fd = open("/dev/random", O_RDONLY);
  434. assert(fd >= 0);
  435. dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
  436. assert(error == 0);
  437. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
  438. assert(transformRef);
  439. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  440. assert(sectransform_data);
  441. CFRelease(transformRef);
  442. dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE32);
  443. test_ptr_notnull("encode32_test: dispatch_data_create_with_transform", transformed_data);
  444. test_data_equal("encode32_test", transformed_data, sectransform_data);
  445. dispatch_release(sectransform_data);
  446. dispatch_release(transformed_data);
  447. close(fd);
  448. dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode32_test);
  449. dispatch_group_leave((dispatch_group_t)context);
  450. });
  451. }
  452. #pragma mark - base64 tests
  453. void
  454. decode64_loop_test(void * context)
  455. {
  456. if (getenv("LOOP_SKIP") == NULL)
  457. {
  458. int fd = open("/dev/random", O_RDONLY);
  459. assert(fd >= 0);
  460. dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  461. size_t i, __block tests = 0;
  462. for (i=1; i<4097; i++) {
  463. dispatch_read(fd, i, dispatch_get_global_queue(0, 0), ^(dispatch_data_t data, int error) {
  464. assert(error == 0);
  465. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
  466. assert(transformRef);
  467. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  468. assert(sectransform_data);
  469. CFRelease(transformRef);
  470. dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
  471. if (dispatch_data_equal(transform_data, data)) {
  472. tests++;
  473. }
  474. dispatch_release(sectransform_data);
  475. dispatch_release(transform_data);
  476. dispatch_semaphore_signal(sema);
  477. });
  478. dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
  479. }
  480. dispatch_release(sema);
  481. close(fd);
  482. test_long("decode64_loop_test", tests, 4096);
  483. }
  484. dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, encode32_test);
  485. }
  486. void
  487. decode64_corrupt_test(void * context)
  488. {
  489. dispatch_group_enter((dispatch_group_t)context);
  490. int fd = open("/dev/random", O_RDONLY);
  491. assert(fd >= 0);
  492. dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
  493. assert(error == 0);
  494. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
  495. assert(transformRef);
  496. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  497. assert(sectransform_data);
  498. CFRelease(transformRef);
  499. void * corrupt_buffer = malloc(dispatch_data_get_size(sectransform_data));
  500. const void * source;
  501. size_t size;
  502. dispatch_data_t map = dispatch_data_create_map(sectransform_data, &source, &size);
  503. memcpy(corrupt_buffer, source, size);
  504. size_t i;
  505. for (i=0; i<size; i += (arc4random() % (int)(size * 0.05))) {
  506. char x = arc4random() & 0xff;
  507. while ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x >= '0' && x <= '9') || x == '/' || x == '+' || x == '=') {
  508. x = arc4random() & 0xff;
  509. }
  510. ((char*)corrupt_buffer)[i] = x;
  511. }
  512. dispatch_release(map);
  513. dispatch_release(sectransform_data);
  514. dispatch_data_t corrupt_data = dispatch_data_create(corrupt_buffer, size, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE);
  515. dispatch_data_t transform_data = dispatch_data_create_with_transform(corrupt_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
  516. test_ptr_null("decode64_corrupt_test: dispatch_data_create_with_transform", transform_data);
  517. dispatch_release(corrupt_data);
  518. close(fd);
  519. dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode64_loop_test);
  520. dispatch_group_leave((dispatch_group_t)context);
  521. });
  522. }
  523. void
  524. chunking_decode64_test(void * context)
  525. {
  526. (void)context;
  527. int fd = open("/dev/random", O_RDONLY);
  528. assert(fd >= 0);
  529. dispatch_data_t __block data = dispatch_data_empty;
  530. int i;
  531. dispatch_group_t group = dispatch_group_create();
  532. dispatch_queue_t queue = dispatch_queue_create("read", 0);
  533. for (i=0; i<4096; i++) {
  534. dispatch_group_enter(group);
  535. dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
  536. assert(error == 0);
  537. dispatch_data_t concat = dispatch_data_create_concat(data, d);
  538. dispatch_release(data);
  539. data = concat;
  540. dispatch_group_leave(group);
  541. });
  542. }
  543. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  544. dispatch_release(queue);
  545. dispatch_release(group);
  546. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
  547. assert(transformRef);
  548. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  549. assert(sectransform_data);
  550. CFRelease(transformRef);
  551. dispatch_data_t transformed_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
  552. test_ptr_notnull("chunking_decode64_test: dispatch_data_create_with_transform", transformed_data);
  553. test_data_equal("chunking_decode64_test", transformed_data, data);
  554. dispatch_release(sectransform_data);
  555. dispatch_release(transformed_data);
  556. dispatch_release(data);
  557. close(fd);
  558. dispatch_group_async_f(context, dispatch_get_main_queue(), context, decode64_corrupt_test);
  559. }
  560. void
  561. chunking_encode64_test(void * context)
  562. {
  563. (void)context;
  564. int fd = open("/dev/random", O_RDONLY);
  565. assert(fd >= 0);
  566. dispatch_data_t __block data = dispatch_data_empty;
  567. int i;
  568. dispatch_group_t group = dispatch_group_create();
  569. dispatch_queue_t queue = dispatch_queue_create("read", 0);
  570. for (i=0; i<4097; i++) {
  571. dispatch_group_enter(group);
  572. dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
  573. assert(error == 0);
  574. dispatch_data_t concat = dispatch_data_create_concat(data, d);
  575. dispatch_release(data);
  576. data = concat;
  577. dispatch_group_leave(group);
  578. });
  579. }
  580. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  581. dispatch_release(queue);
  582. dispatch_release(group);
  583. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
  584. assert(transformRef);
  585. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  586. assert(sectransform_data);
  587. CFRelease(transformRef);
  588. dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE64);
  589. test_ptr_notnull("chunking_encode64_test: dispatch_data_create_with_transform", transformed_data);
  590. test_data_equal("chunking_encode64_test", transformed_data, sectransform_data);
  591. dispatch_release(sectransform_data);
  592. dispatch_release(transformed_data);
  593. dispatch_release(data);
  594. close(fd);
  595. dispatch_group_async_f(context, dispatch_get_main_queue(), context, chunking_decode64_test);
  596. }
  597. void
  598. decode64_test(void * context)
  599. {
  600. dispatch_group_enter((dispatch_group_t)context);
  601. int fd = open("/dev/random", O_RDONLY);
  602. assert(fd >= 0);
  603. dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
  604. assert(error == 0);
  605. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
  606. assert(transformRef);
  607. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  608. assert(sectransform_data);
  609. CFRelease(transformRef);
  610. dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
  611. test_ptr_notnull("decode64_test: dispatch_data_create_with_transform", transform_data);
  612. test_data_equal("decode64_test", transform_data, data);
  613. dispatch_release(sectransform_data);
  614. dispatch_release(transform_data);
  615. close(fd);
  616. dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, chunking_encode64_test);
  617. dispatch_group_leave((dispatch_group_t)context);
  618. });
  619. }
  620. void
  621. encode64_test(void * context)
  622. {
  623. dispatch_group_enter((dispatch_group_t)context);
  624. int fd = open("/dev/random", O_RDONLY);
  625. assert(fd >= 0);
  626. dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
  627. assert(error == 0);
  628. SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
  629. assert(transformRef);
  630. dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
  631. assert(sectransform_data);
  632. CFRelease(transformRef);
  633. dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE64);
  634. test_ptr_notnull("encode64_test: dispatch_data_create_with_transform", transformed_data);
  635. test_data_equal("encode64_test", transformed_data, sectransform_data);
  636. dispatch_release(sectransform_data);
  637. dispatch_release(transformed_data);
  638. close(fd);
  639. dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode64_test);
  640. dispatch_group_leave((dispatch_group_t)context);
  641. });
  642. }
  643. #pragma mark - main
  644. int
  645. main(void)
  646. {
  647. test_start("Dispatch data transforms test");
  648. dispatch_group_t group = dispatch_group_create();
  649. dispatch_group_async_f(group, dispatch_get_main_queue(), group, encode64_test);
  650. dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  651. dispatch_release(group);
  652. test_stop();
  653. exit(0);
  654. });
  655. dispatch_main();
  656. return 0;
  657. }
  658. #else
  659. int
  660. main(void)
  661. {
  662. test_skip("Dispatch data transforms test");
  663. return 0;
  664. }
  665. #endif