frametest.c 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. /*
  2. frameTest - test tool for lz4frame
  3. Copyright (C) Yann Collet 2014-2020
  4. GPL v2 License
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  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. You should have received a copy of the GNU General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. You can contact the author at :
  17. - LZ4 homepage : http://www.lz4.org
  18. - LZ4 source repository : https://github.com/lz4/lz4
  19. */
  20. /*-************************************
  21. * Compiler specific
  22. **************************************/
  23. #ifdef _MSC_VER /* Visual Studio */
  24. # pragma warning(disable : 26451) /* disable: Arithmetic overflow */
  25. #endif
  26. /*-************************************
  27. * Includes
  28. **************************************/
  29. #include "util.h" /* U32 */
  30. #include <stdlib.h> /* malloc, free */
  31. #include <stdio.h> /* fprintf */
  32. #include <string.h> /* strcmp */
  33. #include <time.h> /* clock_t, clock(), CLOCKS_PER_SEC */
  34. #include <assert.h>
  35. #include "lz4frame.h" /* included multiple times to test correctness/safety */
  36. #include "lz4frame.h"
  37. #define LZ4F_STATIC_LINKING_ONLY
  38. #include "lz4frame.h"
  39. #include "lz4frame.h"
  40. #define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */
  41. #include "lz4.h" /* LZ4_VERSION_STRING */
  42. #define XXH_STATIC_LINKING_ONLY
  43. #include "xxhash.h" /* XXH64 */
  44. /* unoptimized version; solves endianness & alignment issues */
  45. static void FUZ_writeLE32 (void* dstVoidPtr, U32 value32)
  46. {
  47. BYTE* const dstPtr = (BYTE*)dstVoidPtr;
  48. dstPtr[0] = (BYTE) value32;
  49. dstPtr[1] = (BYTE)(value32 >> 8);
  50. dstPtr[2] = (BYTE)(value32 >> 16);
  51. dstPtr[3] = (BYTE)(value32 >> 24);
  52. }
  53. /*-************************************
  54. * Constants
  55. **************************************/
  56. #define KB *(1U<<10)
  57. #define MB *(1U<<20)
  58. #define GB *(1U<<30)
  59. static const U32 nbTestsDefault = 256 KB;
  60. #define FUZ_COMPRESSIBILITY_DEFAULT 50
  61. static const U32 prime1 = 2654435761U;
  62. static const U32 prime2 = 2246822519U;
  63. /*-************************************
  64. * Macros
  65. **************************************/
  66. #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
  67. #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
  68. #define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \
  69. if ((FUZ_GetClockSpan(g_clockTime) > refreshRate) || (displayLevel>=4)) \
  70. { g_clockTime = clock(); DISPLAY(__VA_ARGS__); \
  71. if (displayLevel>=4) fflush(stdout); } }
  72. static const clock_t refreshRate = CLOCKS_PER_SEC / 6;
  73. static clock_t g_clockTime = 0;
  74. /*-***************************************
  75. * Local Parameters
  76. *****************************************/
  77. static U32 no_prompt = 0;
  78. static U32 displayLevel = 2;
  79. static U32 use_pause = 0;
  80. /*-*******************************************************
  81. * Fuzzer functions
  82. *********************************************************/
  83. #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
  84. #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
  85. typedef struct {
  86. int nbAllocs;
  87. } Test_alloc_state;
  88. static Test_alloc_state g_testAllocState = { 0 };
  89. static void* dummy_malloc(void* state, size_t s)
  90. {
  91. Test_alloc_state* const t = (Test_alloc_state*)state;
  92. void* const p = malloc(s);
  93. if (p==NULL) return NULL;
  94. assert(t != NULL);
  95. t->nbAllocs += 1;
  96. DISPLAYLEVEL(6, "Allocating %zu bytes at address %p \n", s, p);
  97. DISPLAYLEVEL(5, "nb allocated memory segments : %i \n", t->nbAllocs);
  98. return p;
  99. }
  100. static void* dummy_calloc(void* state, size_t s)
  101. {
  102. Test_alloc_state* const t = (Test_alloc_state*)state;
  103. void* const p = calloc(1, s);
  104. if (p==NULL) return NULL;
  105. assert(t != NULL);
  106. t->nbAllocs += 1;
  107. DISPLAYLEVEL(6, "Allocating and zeroing %zu bytes at address %p \n", s, p);
  108. DISPLAYLEVEL(5, "nb allocated memory segments : %i \n", t->nbAllocs);
  109. return p;
  110. }
  111. static void dummy_free(void* state, void* p)
  112. {
  113. Test_alloc_state* const t = (Test_alloc_state*)state;
  114. if (p==NULL) {
  115. DISPLAYLEVEL(5, "free() on NULL \n");
  116. return;
  117. }
  118. DISPLAYLEVEL(6, "freeing memory at address %p \n", p);
  119. free(p);
  120. assert(t != NULL);
  121. t->nbAllocs -= 1;
  122. DISPLAYLEVEL(5, "nb of allocated memory segments after this free : %i \n", t->nbAllocs);
  123. assert(t->nbAllocs >= 0);
  124. }
  125. static const LZ4F_CustomMem lz4f_cmem_test = {
  126. dummy_malloc,
  127. dummy_calloc,
  128. dummy_free,
  129. &g_testAllocState
  130. };
  131. static clock_t FUZ_GetClockSpan(clock_t clockStart)
  132. {
  133. return clock() - clockStart; /* works even if overflow; max span ~ 30 mn */
  134. }
  135. #define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
  136. unsigned int FUZ_rand(unsigned int* src)
  137. {
  138. U32 rand32 = *src;
  139. rand32 *= prime1;
  140. rand32 += prime2;
  141. rand32 = FUZ_rotl32(rand32, 13);
  142. *src = rand32;
  143. return rand32 >> 5;
  144. }
  145. #define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
  146. #define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
  147. static void FUZ_fillCompressibleNoiseBuffer(void* buffer, size_t bufferSize, double proba, U32* seed)
  148. {
  149. BYTE* BBuffer = (BYTE*)buffer;
  150. size_t pos = 0;
  151. U32 P32 = (U32)(32768 * proba);
  152. /* First Byte */
  153. BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
  154. while (pos < bufferSize) {
  155. /* Select : Literal (noise) or copy (within 64K) */
  156. if (FUZ_RAND15BITS < P32) {
  157. /* Copy (within 64K) */
  158. size_t const lengthRand = FUZ_RANDLENGTH + 4;
  159. size_t const length = MIN(lengthRand, bufferSize - pos);
  160. size_t const end = pos + length;
  161. size_t const offsetRand = FUZ_RAND15BITS + 1;
  162. size_t const offset = MIN(offsetRand, pos);
  163. size_t match = pos - offset;
  164. while (pos < end) BBuffer[pos++] = BBuffer[match++];
  165. } else {
  166. /* Literal (noise) */
  167. size_t const lengthRand = FUZ_RANDLENGTH + 4;
  168. size_t const length = MIN(lengthRand, bufferSize - pos);
  169. size_t const end = pos + length;
  170. while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
  171. } }
  172. }
  173. static unsigned FUZ_highbit(U32 v32)
  174. {
  175. unsigned nbBits = 0;
  176. if (v32==0) return 0;
  177. while (v32) {v32 >>= 1; nbBits ++;}
  178. return nbBits;
  179. }
  180. /*-*******************************************************
  181. * Tests
  182. *********************************************************/
  183. #define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s \n", LZ4F_getErrorName(v)); goto _output_error; }
  184. #define CHECK(f) { LZ4F_errorCode_t const CHECK_V(err_ , f); }
  185. int basicTests(U32 seed, double compressibility)
  186. {
  187. #define COMPRESSIBLE_NOISE_LENGTH (2 MB)
  188. void* const CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
  189. size_t const cBuffSize = LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL);
  190. void* const compressedBuffer = malloc(cBuffSize);
  191. void* const decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
  192. U32 randState = seed;
  193. size_t cSize, testSize;
  194. LZ4F_decompressionContext_t dCtx = NULL;
  195. LZ4F_compressionContext_t cctx = NULL;
  196. U64 crcOrig;
  197. int basicTests_error = 0;
  198. LZ4F_preferences_t prefs;
  199. memset(&prefs, 0, sizeof(prefs));
  200. if (!CNBuffer || !compressedBuffer || !decodedBuffer) {
  201. DISPLAY("allocation error, not enough memory to start fuzzer tests \n");
  202. goto _output_error;
  203. }
  204. FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
  205. crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
  206. /* LZ4F_compressBound() : special case : srcSize == 0 */
  207. DISPLAYLEVEL(3, "LZ4F_compressBound(0) = ");
  208. { size_t const cBound = LZ4F_compressBound(0, NULL);
  209. if (cBound < 64 KB) goto _output_error;
  210. DISPLAYLEVEL(3, " %u \n", (U32)cBound);
  211. }
  212. /* LZ4F_compressBound() : special case : automatic flushing enabled */
  213. DISPLAYLEVEL(3, "LZ4F_compressBound(1 KB, autoFlush=1) = ");
  214. { size_t cBound;
  215. LZ4F_preferences_t autoFlushPrefs;
  216. memset(&autoFlushPrefs, 0, sizeof(autoFlushPrefs));
  217. autoFlushPrefs.autoFlush = 1;
  218. cBound = LZ4F_compressBound(1 KB, &autoFlushPrefs);
  219. if (cBound > 64 KB) goto _output_error;
  220. DISPLAYLEVEL(3, " %u \n", (U32)cBound);
  221. }
  222. /* LZ4F_compressBound() : special case : automatic flushing disabled */
  223. DISPLAYLEVEL(3, "LZ4F_compressBound(1 KB, autoFlush=0) = ");
  224. { size_t const cBound = LZ4F_compressBound(1 KB, &prefs);
  225. if (cBound < 64 KB) goto _output_error;
  226. DISPLAYLEVEL(3, " %u \n", (U32)cBound);
  227. }
  228. /* Special case : null-content frame */
  229. testSize = 0;
  230. DISPLAYLEVEL(3, "LZ4F_compressFrame, compress null content : ");
  231. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL));
  232. DISPLAYLEVEL(3, "null content encoded into a %u bytes frame \n", (unsigned)cSize);
  233. DISPLAYLEVEL(3, "LZ4F_createDecompressionContext \n");
  234. CHECK ( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
  235. DISPLAYLEVEL(3, "LZ4F_getFrameInfo on null-content frame (#157) \n");
  236. assert(cSize >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
  237. { LZ4F_frameInfo_t frame_info;
  238. size_t const fhs = LZ4F_headerSize(compressedBuffer, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
  239. size_t avail_in = fhs;
  240. CHECK( fhs );
  241. CHECK( LZ4F_getFrameInfo(dCtx, &frame_info, compressedBuffer, &avail_in) );
  242. if (avail_in != fhs) goto _output_error; /* must consume all, since header size is supposed to be exact */
  243. }
  244. DISPLAYLEVEL(3, "LZ4F_freeDecompressionContext \n");
  245. CHECK( LZ4F_freeDecompressionContext(dCtx) );
  246. dCtx = NULL;
  247. /* test one-pass frame compression */
  248. testSize = COMPRESSIBLE_NOISE_LENGTH;
  249. DISPLAYLEVEL(3, "LZ4F_compressFrame, using fast level -3 : ");
  250. { LZ4F_preferences_t fastCompressPrefs;
  251. memset(&fastCompressPrefs, 0, sizeof(fastCompressPrefs));
  252. fastCompressPrefs.compressionLevel = -3;
  253. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, &fastCompressPrefs));
  254. DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
  255. }
  256. DISPLAYLEVEL(3, "LZ4F_compressFrame, using default preferences : ");
  257. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL));
  258. DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
  259. DISPLAYLEVEL(3, "Decompression test : \n");
  260. { size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
  261. size_t compressedBufferSize = cSize;
  262. CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
  263. DISPLAYLEVEL(3, "Single Pass decompression : ");
  264. CHECK( LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL) );
  265. { U64 const crcDest = XXH64(decodedBuffer, decodedBufferSize, 1);
  266. if (crcDest != crcOrig) goto _output_error; }
  267. DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedBufferSize);
  268. DISPLAYLEVEL(3, "Reusing decompression context \n");
  269. { size_t const missingBytes = 4;
  270. size_t iSize = compressedBufferSize - missingBytes;
  271. const BYTE* cBuff = (const BYTE*) compressedBuffer;
  272. BYTE* const ostart = (BYTE*)decodedBuffer;
  273. BYTE* op = ostart;
  274. BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
  275. size_t decResult, oSize = COMPRESSIBLE_NOISE_LENGTH;
  276. DISPLAYLEVEL(3, "Missing last %u bytes : ", (U32)missingBytes);
  277. CHECK_V(decResult, LZ4F_decompress(dCtx, op, &oSize, cBuff, &iSize, NULL));
  278. if (decResult != missingBytes) {
  279. DISPLAY("%u bytes missing != %u bytes requested \n", (U32)missingBytes, (U32)decResult);
  280. goto _output_error;
  281. }
  282. DISPLAYLEVEL(3, "indeed, requests %u bytes \n", (unsigned)decResult);
  283. cBuff += iSize;
  284. iSize = decResult;
  285. op += oSize;
  286. oSize = (size_t)(oend-op);
  287. decResult = LZ4F_decompress(dCtx, op, &oSize, cBuff, &iSize, NULL);
  288. if (decResult != 0) goto _output_error; /* should finish now */
  289. op += oSize;
  290. if (op>oend) { DISPLAY("decompression write overflow \n"); goto _output_error; }
  291. { U64 const crcDest = XXH64(decodedBuffer, (size_t)(op-ostart), 1);
  292. if (crcDest != crcOrig) goto _output_error;
  293. } }
  294. { size_t oSize = 0;
  295. size_t iSize = 0;
  296. LZ4F_frameInfo_t fi;
  297. const BYTE* ip = (BYTE*)compressedBuffer;
  298. DISPLAYLEVEL(3, "Start by feeding 0 bytes, to get next input size : ");
  299. CHECK( LZ4F_decompress(dCtx, NULL, &oSize, ip, &iSize, NULL) );
  300. //DISPLAYLEVEL(3, " %u \n", (unsigned)errorCode);
  301. DISPLAYLEVEL(3, " OK \n");
  302. DISPLAYLEVEL(3, "LZ4F_getFrameInfo on zero-size input : ");
  303. { size_t nullSize = 0;
  304. size_t const fiError = LZ4F_getFrameInfo(dCtx, &fi, ip, &nullSize);
  305. if (LZ4F_getErrorCode(fiError) != LZ4F_ERROR_frameHeader_incomplete) {
  306. DISPLAYLEVEL(3, "incorrect error : %s != ERROR_frameHeader_incomplete \n",
  307. LZ4F_getErrorName(fiError));
  308. goto _output_error;
  309. }
  310. DISPLAYLEVEL(3, " correctly failed : %s \n", LZ4F_getErrorName(fiError));
  311. }
  312. DISPLAYLEVEL(3, "LZ4F_getFrameInfo on not enough input : ");
  313. { size_t inputSize = 6;
  314. size_t const fiError = LZ4F_getFrameInfo(dCtx, &fi, ip, &inputSize);
  315. if (LZ4F_getErrorCode(fiError) != LZ4F_ERROR_frameHeader_incomplete) {
  316. DISPLAYLEVEL(3, "incorrect error : %s != ERROR_frameHeader_incomplete \n", LZ4F_getErrorName(fiError));
  317. goto _output_error;
  318. }
  319. DISPLAYLEVEL(3, " correctly failed : %s \n", LZ4F_getErrorName(fiError));
  320. }
  321. DISPLAYLEVEL(3, "LZ4F_getFrameInfo on enough input : ");
  322. iSize = LZ4F_headerSize(ip, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH);
  323. CHECK( iSize );
  324. CHECK( LZ4F_getFrameInfo(dCtx, &fi, ip, &iSize) );
  325. DISPLAYLEVEL(3, " correctly decoded \n");
  326. }
  327. DISPLAYLEVEL(3, "Decode a buggy input : ");
  328. assert(COMPRESSIBLE_NOISE_LENGTH > 64);
  329. assert(cSize > 48);
  330. memcpy(decodedBuffer, (char*)compressedBuffer+16, 32); /* save correct data */
  331. memcpy((char*)compressedBuffer+16, (const char*)decodedBuffer+32, 32); /* insert noise */
  332. { size_t dbSize = COMPRESSIBLE_NOISE_LENGTH;
  333. size_t cbSize = cSize;
  334. size_t const decompressError = LZ4F_decompress(dCtx, decodedBuffer, &dbSize,
  335. compressedBuffer, &cbSize,
  336. NULL);
  337. if (!LZ4F_isError(decompressError)) goto _output_error;
  338. DISPLAYLEVEL(3, "error detected : %s \n", LZ4F_getErrorName(decompressError));
  339. }
  340. memcpy((char*)compressedBuffer+16, decodedBuffer, 32); /* restore correct data */
  341. DISPLAYLEVEL(3, "Reset decompression context, since it's left in error state \n");
  342. LZ4F_resetDecompressionContext(dCtx); /* always successful */
  343. DISPLAYLEVEL(3, "Byte after byte : ");
  344. { BYTE* const ostart = (BYTE*)decodedBuffer;
  345. BYTE* op = ostart;
  346. BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
  347. const BYTE* ip = (const BYTE*) compressedBuffer;
  348. const BYTE* const iend = ip + cSize;
  349. while (ip < iend) {
  350. size_t oSize = (size_t)(oend-op);
  351. size_t iSize = 1;
  352. CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
  353. op += oSize;
  354. ip += iSize;
  355. }
  356. { U64 const crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
  357. if (crcDest != crcOrig) goto _output_error;
  358. }
  359. DISPLAYLEVEL(3, "Regenerated %u/%u bytes \n", (unsigned)(op-ostart), (unsigned)COMPRESSIBLE_NOISE_LENGTH);
  360. }
  361. }
  362. DISPLAYLEVEL(3, "Using 64 KB block : ");
  363. prefs.frameInfo.blockSizeID = LZ4F_max64KB;
  364. prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
  365. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs));
  366. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  367. DISPLAYLEVEL(3, "without checksum : ");
  368. prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
  369. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs));
  370. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  371. DISPLAYLEVEL(3, "Using 256 KB block : ");
  372. prefs.frameInfo.blockSizeID = LZ4F_max256KB;
  373. prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
  374. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs));
  375. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  376. DISPLAYLEVEL(3, "Decompression test : \n");
  377. { size_t const decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
  378. unsigned const maxBits = FUZ_highbit((U32)decodedBufferSize);
  379. BYTE* const ostart = (BYTE*)decodedBuffer;
  380. BYTE* op = ostart;
  381. BYTE* const oend = ostart + COMPRESSIBLE_NOISE_LENGTH;
  382. const BYTE* ip = (const BYTE*)compressedBuffer;
  383. const BYTE* const iend = (const BYTE*)compressedBuffer + cSize;
  384. DISPLAYLEVEL(3, "random segment sizes : ");
  385. while (ip < iend) {
  386. unsigned const nbBits = FUZ_rand(&randState) % maxBits;
  387. size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
  388. size_t oSize = (size_t)(oend-op);
  389. if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
  390. CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
  391. op += oSize;
  392. ip += iSize;
  393. }
  394. { size_t const decodedSize = (size_t)(op - ostart);
  395. U64 const crcDest = XXH64(decodedBuffer, decodedSize, 1);
  396. if (crcDest != crcOrig) goto _output_error;
  397. DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
  398. }
  399. CHECK( LZ4F_freeDecompressionContext(dCtx) );
  400. dCtx = NULL;
  401. }
  402. DISPLAYLEVEL(3, "without checksum : ");
  403. prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
  404. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
  405. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  406. DISPLAYLEVEL(3, "Using 1 MB block : ");
  407. prefs.frameInfo.blockSizeID = LZ4F_max1MB;
  408. prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
  409. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
  410. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  411. DISPLAYLEVEL(3, "without frame checksum : ");
  412. prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
  413. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
  414. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  415. DISPLAYLEVEL(3, "Using 4 MB block : ");
  416. prefs.frameInfo.blockSizeID = LZ4F_max4MB;
  417. prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
  418. { size_t const dstCapacity = LZ4F_compressFrameBound(testSize, &prefs);
  419. DISPLAYLEVEL(4, "dstCapacity = %u ; ", (U32)dstCapacity)
  420. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, dstCapacity, CNBuffer, testSize, &prefs) );
  421. DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
  422. }
  423. DISPLAYLEVEL(3, "without frame checksum : ");
  424. prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum;
  425. { size_t const dstCapacity = LZ4F_compressFrameBound(testSize, &prefs);
  426. DISPLAYLEVEL(4, "dstCapacity = %u ; ", (U32)dstCapacity)
  427. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, dstCapacity, CNBuffer, testSize, &prefs) );
  428. DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize);
  429. }
  430. DISPLAYLEVEL(3, "LZ4F_compressFrame with block checksum : ");
  431. memset(&prefs, 0, sizeof(prefs));
  432. prefs.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled;
  433. CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) );
  434. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
  435. DISPLAYLEVEL(3, "Decompress with block checksum : ");
  436. { size_t iSize = cSize;
  437. size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH;
  438. LZ4F_decompressionContext_t dctx;
  439. CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
  440. CHECK( LZ4F_decompress(dctx, decodedBuffer, &decodedSize, compressedBuffer, &iSize, NULL) );
  441. if (decodedSize != testSize) goto _output_error;
  442. if (iSize != cSize) goto _output_error;
  443. { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 1);
  444. U64 const crcSrc = XXH64(CNBuffer, testSize, 1);
  445. if (crcDest != crcSrc) goto _output_error;
  446. }
  447. DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
  448. CHECK( LZ4F_freeDecompressionContext(dctx) );
  449. }
  450. /* frame content size tests */
  451. { size_t cErr;
  452. BYTE* const ostart = (BYTE*)compressedBuffer;
  453. BYTE* op = ostart;
  454. CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
  455. DISPLAYLEVEL(3, "compress without frameSize : ");
  456. memset(&(prefs.frameInfo), 0, sizeof(prefs.frameInfo));
  457. CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
  458. op += cErr;
  459. CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL));
  460. op += cErr;
  461. CHECK( LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL) );
  462. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart));
  463. DISPLAYLEVEL(3, "compress with frameSize : ");
  464. prefs.frameInfo.contentSize = testSize;
  465. op = ostart;
  466. CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
  467. op += cErr;
  468. CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL));
  469. op += cErr;
  470. CHECK( LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL) );
  471. DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart));
  472. DISPLAYLEVEL(3, "compress with wrong frameSize : ");
  473. prefs.frameInfo.contentSize = testSize+1;
  474. op = ostart;
  475. CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
  476. op += cErr;
  477. CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL));
  478. op += cErr;
  479. cErr = LZ4F_compressEnd(cctx, op, testSize, NULL);
  480. if (!LZ4F_isError(cErr)) goto _output_error;
  481. DISPLAYLEVEL(3, "Error correctly detected : %s \n", LZ4F_getErrorName(cErr));
  482. CHECK( LZ4F_freeCompressionContext(cctx) );
  483. cctx = NULL;
  484. }
  485. /* dictID tests */
  486. { size_t cErr;
  487. U32 const dictID = 0x99;
  488. /* test advanced variant with custom allocator functions */
  489. cctx = LZ4F_createCompressionContext_advanced(lz4f_cmem_test, LZ4F_VERSION);
  490. if (cctx==NULL) goto _output_error;
  491. DISPLAYLEVEL(3, "insert a dictID : ");
  492. memset(&prefs.frameInfo, 0, sizeof(prefs.frameInfo));
  493. prefs.frameInfo.dictID = dictID;
  494. CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs));
  495. DISPLAYLEVEL(3, "created frame header of size %i bytes \n", (int)cErr);
  496. DISPLAYLEVEL(3, "read a dictID : ");
  497. CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
  498. memset(&prefs.frameInfo, 0, sizeof(prefs.frameInfo));
  499. CHECK( LZ4F_getFrameInfo(dCtx, &prefs.frameInfo, compressedBuffer, &cErr) );
  500. if (prefs.frameInfo.dictID != dictID) goto _output_error;
  501. DISPLAYLEVEL(3, "%u \n", (U32)prefs.frameInfo.dictID);
  502. CHECK( LZ4F_freeDecompressionContext(dCtx) ); dCtx = NULL;
  503. CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL;
  504. }
  505. /* Dictionary compression test */
  506. { size_t const dictSize = 7 KB; /* small enough for LZ4_MEMORY_USAGE == 10 */
  507. size_t const srcSize = 65 KB; /* must be > 64 KB to avoid short-size optimizations */
  508. size_t const dstCapacity = LZ4F_compressFrameBound(srcSize, NULL);
  509. size_t cSizeNoDict, cSizeWithDict;
  510. LZ4F_CDict* const cdict = LZ4F_createCDict(CNBuffer, dictSize);
  511. if (cdict == NULL) goto _output_error;
  512. CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
  513. DISPLAYLEVEL(3, "Testing LZ4F_createCDict_advanced : ");
  514. { LZ4F_CDict* const cda = LZ4F_createCDict_advanced(lz4f_cmem_test, CNBuffer, dictSize);
  515. if (cda == NULL) goto _output_error;
  516. LZ4F_freeCDict(cda);
  517. }
  518. DISPLAYLEVEL(3, "OK \n");
  519. DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with NULL dict : ");
  520. CHECK_V(cSizeNoDict,
  521. LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
  522. CNBuffer, srcSize,
  523. NULL, NULL) );
  524. DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeNoDict);
  525. CHECK( LZ4F_freeCompressionContext(cctx) );
  526. CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) );
  527. DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict : ");
  528. CHECK_V(cSizeWithDict,
  529. LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
  530. CNBuffer, srcSize,
  531. cdict, NULL) );
  532. DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n",
  533. (unsigned)srcSize, (unsigned)cSizeWithDict);
  534. if (cSizeWithDict > cSizeNoDict) {
  535. DISPLAYLEVEL(3, "cSizeWithDict (%zu) should have been more compact than cSizeNoDict(%zu) \n", cSizeWithDict, cSizeNoDict);
  536. goto _output_error; /* must be more efficient */
  537. }
  538. crcOrig = XXH64(CNBuffer, srcSize, 0);
  539. DISPLAYLEVEL(3, "LZ4F_decompress_usingDict : ");
  540. { LZ4F_dctx* dctx;
  541. size_t decodedSize = srcSize;
  542. size_t compressedSize = cSizeWithDict;
  543. CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
  544. CHECK( LZ4F_decompress_usingDict(dctx,
  545. decodedBuffer, &decodedSize,
  546. compressedBuffer, &compressedSize,
  547. CNBuffer, dictSize,
  548. NULL) );
  549. if (compressedSize != cSizeWithDict) goto _output_error;
  550. if (decodedSize != srcSize) goto _output_error;
  551. { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
  552. if (crcDest != crcOrig) goto _output_error; }
  553. DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
  554. CHECK( LZ4F_freeDecompressionContext(dctx) );
  555. }
  556. DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict, negative level : ");
  557. { size_t cSizeLevelMax;
  558. LZ4F_preferences_t cParams;
  559. memset(&cParams, 0, sizeof(cParams));
  560. cParams.compressionLevel = -3;
  561. CHECK_V(cSizeLevelMax,
  562. LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
  563. CNBuffer, dictSize,
  564. cdict, &cParams) );
  565. DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax);
  566. }
  567. DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict, level max : ");
  568. { size_t cSizeLevelMax;
  569. LZ4F_preferences_t cParams;
  570. memset(&cParams, 0, sizeof(cParams));
  571. cParams.compressionLevel = LZ4F_compressionLevel_max();
  572. CHECK_V(cSizeLevelMax,
  573. LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity,
  574. CNBuffer, dictSize,
  575. cdict, &cParams) );
  576. DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax);
  577. }
  578. DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, multiple linked blocks : ");
  579. { size_t cSizeContiguous;
  580. size_t const inSize = dictSize * 3;
  581. size_t const outCapacity = LZ4F_compressFrameBound(inSize, NULL);
  582. LZ4F_preferences_t cParams;
  583. memset(&cParams, 0, sizeof(cParams));
  584. cParams.frameInfo.blockMode = LZ4F_blockLinked;
  585. cParams.frameInfo.blockSizeID = LZ4F_max64KB;
  586. CHECK_V(cSizeContiguous,
  587. LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity,
  588. CNBuffer, inSize,
  589. cdict, &cParams) );
  590. DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n",
  591. (unsigned)inSize, (unsigned)cSizeContiguous);
  592. DISPLAYLEVEL(3, "LZ4F_decompress_usingDict on multiple linked blocks : ");
  593. { LZ4F_dctx* dctx;
  594. size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH;
  595. size_t compressedSize = cSizeContiguous;
  596. CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
  597. CHECK( LZ4F_decompress_usingDict(dctx,
  598. decodedBuffer, &decodedSize,
  599. compressedBuffer, &compressedSize,
  600. CNBuffer, dictSize,
  601. NULL) );
  602. if (compressedSize != cSizeContiguous) goto _output_error;
  603. if (decodedSize != inSize) goto _output_error;
  604. crcOrig = XXH64(CNBuffer, inSize, 0);
  605. { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
  606. if (crcDest != crcOrig) goto _output_error; }
  607. DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
  608. CHECK( LZ4F_freeDecompressionContext(dctx) );
  609. }
  610. }
  611. DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, multiple independent blocks : ");
  612. { size_t cSizeIndep;
  613. size_t const inSize = dictSize * 3;
  614. size_t const outCapacity = LZ4F_compressFrameBound(inSize, NULL);
  615. LZ4F_preferences_t cParams;
  616. memset(&cParams, 0, sizeof(cParams));
  617. cParams.frameInfo.blockMode = LZ4F_blockIndependent;
  618. cParams.frameInfo.blockSizeID = LZ4F_max64KB;
  619. CHECK_V(cSizeIndep,
  620. LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity,
  621. CNBuffer, inSize,
  622. cdict, &cParams) );
  623. DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n",
  624. (unsigned)inSize, (unsigned)cSizeIndep);
  625. DISPLAYLEVEL(3, "LZ4F_decompress_usingDict on multiple independent blocks : ");
  626. { LZ4F_dctx* dctx;
  627. size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH;
  628. size_t compressedSize = cSizeIndep;
  629. CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) );
  630. CHECK( LZ4F_decompress_usingDict(dctx,
  631. decodedBuffer, &decodedSize,
  632. compressedBuffer, &compressedSize,
  633. CNBuffer, dictSize,
  634. NULL) );
  635. if (compressedSize != cSizeIndep) goto _output_error;
  636. if (decodedSize != inSize) goto _output_error;
  637. crcOrig = XXH64(CNBuffer, inSize, 0);
  638. { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0);
  639. if (crcDest != crcOrig) goto _output_error; }
  640. DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize);
  641. CHECK( LZ4F_freeDecompressionContext(dctx) );
  642. }
  643. }
  644. LZ4F_freeCDict(cdict);
  645. CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL;
  646. }
  647. DISPLAYLEVEL(3, "getBlockSize test: \n");
  648. { size_t result;
  649. unsigned blockSizeID;
  650. for (blockSizeID = 4; blockSizeID < 8; ++blockSizeID) {
  651. result = LZ4F_getBlockSize((LZ4F_blockSizeID_t)blockSizeID);
  652. CHECK(result);
  653. DISPLAYLEVEL(3, "Returned block size of %u bytes for blockID %u \n",
  654. (unsigned)result, blockSizeID);
  655. }
  656. /* Test an invalid input that's too large */
  657. result = LZ4F_getBlockSize((LZ4F_blockSizeID_t)8);
  658. if(!LZ4F_isError(result) ||
  659. LZ4F_getErrorCode(result) != LZ4F_ERROR_maxBlockSize_invalid)
  660. goto _output_error;
  661. /* Test an invalid input that's too small */
  662. result = LZ4F_getBlockSize((LZ4F_blockSizeID_t)3);
  663. if(!LZ4F_isError(result) ||
  664. LZ4F_getErrorCode(result) != LZ4F_ERROR_maxBlockSize_invalid)
  665. goto _output_error;
  666. }
  667. DISPLAYLEVEL(3, "Skippable frame test : \n");
  668. { size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
  669. unsigned maxBits = FUZ_highbit((U32)decodedBufferSize);
  670. BYTE* op = (BYTE*)decodedBuffer;
  671. BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
  672. BYTE* ip = (BYTE*)compressedBuffer;
  673. BYTE* iend = (BYTE*)compressedBuffer + cSize + 8;
  674. CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) );
  675. /* generate skippable frame */
  676. FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START);
  677. FUZ_writeLE32(ip+4, (U32)cSize);
  678. DISPLAYLEVEL(3, "random segment sizes : \n");
  679. while (ip < iend) {
  680. unsigned nbBits = FUZ_rand(&randState) % maxBits;
  681. size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
  682. size_t oSize = (size_t)(oend-op);
  683. if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
  684. CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
  685. op += oSize;
  686. ip += iSize;
  687. }
  688. DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)decodedBufferSize);
  689. /* generate zero-size skippable frame */
  690. DISPLAYLEVEL(3, "zero-size skippable frame\n");
  691. ip = (BYTE*)compressedBuffer;
  692. op = (BYTE*)decodedBuffer;
  693. FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+1);
  694. FUZ_writeLE32(ip+4, 0);
  695. iend = ip+8;
  696. while (ip < iend) {
  697. unsigned const nbBits = FUZ_rand(&randState) % maxBits;
  698. size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
  699. size_t oSize = (size_t)(oend-op);
  700. if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
  701. CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
  702. op += oSize;
  703. ip += iSize;
  704. }
  705. DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8));
  706. DISPLAYLEVEL(3, "Skippable frame header complete in first call \n");
  707. ip = (BYTE*)compressedBuffer;
  708. op = (BYTE*)decodedBuffer;
  709. FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+2);
  710. FUZ_writeLE32(ip+4, 10);
  711. iend = ip+18;
  712. while (ip < iend) {
  713. size_t iSize = 10;
  714. size_t oSize = 10;
  715. if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip);
  716. CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) );
  717. op += oSize;
  718. ip += iSize;
  719. }
  720. DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8));
  721. }
  722. DISPLAY("Basic tests completed \n");
  723. _end:
  724. free(CNBuffer);
  725. free(compressedBuffer);
  726. free(decodedBuffer);
  727. LZ4F_freeDecompressionContext(dCtx); dCtx = NULL;
  728. LZ4F_freeCompressionContext(cctx); cctx = NULL;
  729. return basicTests_error;
  730. _output_error:
  731. basicTests_error = 1;
  732. DISPLAY("Error detected ! \n");
  733. goto _end;
  734. }
  735. typedef enum { o_contiguous, o_noncontiguous, o_overwrite } o_scenario_e;
  736. static void locateBuffDiff(const void* buff1, const void* buff2, size_t size, o_scenario_e o_scenario)
  737. {
  738. if (displayLevel >= 2) {
  739. size_t p=0;
  740. const BYTE* b1=(const BYTE*)buff1;
  741. const BYTE* b2=(const BYTE*)buff2;
  742. DISPLAY("locateBuffDiff: looking for error position \n");
  743. if (o_scenario != o_contiguous) {
  744. DISPLAY("mode %i: non-contiguous output (%u bytes), cannot search \n",
  745. (int)o_scenario, (unsigned)size);
  746. return;
  747. }
  748. while (p < size && b1[p]==b2[p]) p++;
  749. if (p != size) {
  750. DISPLAY("Error at pos %i/%i : %02X != %02X \n", (int)p, (int)size, b1[p], b2[p]);
  751. }
  752. }
  753. }
  754. # define EXIT_MSG(...) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
  755. DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); exit(1); }
  756. # undef CHECK
  757. # define CHECK(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__); } }
  758. size_t test_lz4f_decompression_wBuffers(
  759. const void* cSrc, size_t cSize,
  760. void* dst, size_t dstCapacity, o_scenario_e o_scenario,
  761. const void* srcRef, size_t decompressedSize,
  762. U64 crcOrig,
  763. U32* const randState,
  764. LZ4F_dctx* const dCtx,
  765. U32 seed, U32 testNb,
  766. int findErrorPos)
  767. {
  768. const BYTE* ip = (const BYTE*)cSrc;
  769. const BYTE* const iend = ip + cSize;
  770. BYTE* op = (BYTE*)dst;
  771. BYTE* const oend = op + dstCapacity;
  772. unsigned const suggestedBits = FUZ_highbit((U32)cSize);
  773. unsigned const maxBits = MAX(3, suggestedBits);
  774. size_t totalOut = 0;
  775. size_t moreToFlush = 0;
  776. XXH64_state_t xxh64;
  777. XXH64_reset(&xxh64, 1);
  778. assert(ip < iend);
  779. while (ip < iend) {
  780. unsigned const nbBitsI = (FUZ_rand(randState) % (maxBits-1)) + 1;
  781. unsigned const nbBitsO = (FUZ_rand(randState) % (maxBits)) + 1;
  782. size_t const iSizeCand = (FUZ_rand(randState) & ((1<<nbBitsI)-1)) + 1;
  783. size_t const iSizeMax = MIN(iSizeCand, (size_t)(iend-ip));
  784. size_t iSize = iSizeMax;
  785. size_t const oSizeCand = (FUZ_rand(randState) & ((1<<nbBitsO)-1)) + 2;
  786. size_t const oSizeMax = MIN(oSizeCand, (size_t)(oend-op));
  787. int const sentinelTest = (op + oSizeMax < oend);
  788. size_t oSize = oSizeMax;
  789. BYTE const mark = (BYTE)(FUZ_rand(randState) & 255);
  790. LZ4F_decompressOptions_t dOptions;
  791. memset(&dOptions, 0, sizeof(dOptions));
  792. dOptions.stableDst = FUZ_rand(randState) & 1;
  793. if (o_scenario == o_overwrite) dOptions.stableDst = 0; /* overwrite mode */
  794. dOptions.skipChecksums = FUZ_rand(randState) & 127;
  795. if (sentinelTest) op[oSizeMax] = mark;
  796. DISPLAYLEVEL(7, "dstCapacity=%u, presentedInput=%u \n", (unsigned)oSize, (unsigned)iSize);
  797. /* read data from byte-exact buffer to catch out-of-bound reads */
  798. { void* const iBuffer = malloc(iSizeMax);
  799. void* const tmpop = (FUZ_rand(randState) & (oSize == 0)) ? NULL : op;
  800. const void* const tmpip = (FUZ_rand(randState) & (iSize == 0)) ? NULL : iBuffer;
  801. assert(iBuffer != NULL);
  802. memcpy(iBuffer, ip, iSizeMax);
  803. moreToFlush = LZ4F_decompress(dCtx, tmpop, &oSize, tmpip, &iSize, &dOptions);
  804. free(iBuffer);
  805. }
  806. DISPLAYLEVEL(7, "oSize=%u, readSize=%u \n", (unsigned)oSize, (unsigned)iSize);
  807. if (sentinelTest) {
  808. CHECK(op[oSizeMax] != mark, "op[oSizeMax] = %02X != %02X : "
  809. "Decompression overwrites beyond assigned dst size",
  810. op[oSizeMax], mark);
  811. }
  812. if (LZ4F_getErrorCode(moreToFlush) == LZ4F_ERROR_contentChecksum_invalid) {
  813. if (findErrorPos) DISPLAYLEVEL(2, "checksum error detected \n");
  814. if (findErrorPos) locateBuffDiff(srcRef, dst, decompressedSize, o_scenario);
  815. }
  816. if (LZ4F_isError(moreToFlush)) return moreToFlush;
  817. XXH64_update(&xxh64, op, oSize);
  818. totalOut += oSize;
  819. op += oSize;
  820. ip += iSize;
  821. if (o_scenario == o_noncontiguous) {
  822. if (op == oend) return LZ4F_ERROR_GENERIC; /* can theoretically happen with bogus data */
  823. op++; /* create a gap between consecutive output */
  824. }
  825. if (o_scenario==o_overwrite) op = (BYTE*)dst; /* overwrite destination */
  826. if ( (op == oend) /* no more room for output; can happen with bogus input */
  827. && (iSize == 0)) /* no input consumed */
  828. break;
  829. }
  830. if (moreToFlush != 0) return LZ4F_ERROR_decompressionFailed;
  831. if (totalOut) { /* otherwise, it's a skippable frame */
  832. U64 const crcDecoded = XXH64_digest(&xxh64);
  833. if (crcDecoded != crcOrig) {
  834. if (findErrorPos) locateBuffDiff(srcRef, dst, decompressedSize, o_scenario);
  835. return LZ4F_ERROR_contentChecksum_invalid;
  836. } }
  837. return 0;
  838. }
  839. size_t test_lz4f_decompression(const void* cSrc, size_t cSize,
  840. const void* srcRef, size_t decompressedSize,
  841. U64 crcOrig,
  842. U32* const randState,
  843. LZ4F_dctx* const dCtx,
  844. U32 seed, U32 testNb,
  845. int findErrorPos)
  846. {
  847. o_scenario_e const o_scenario = (o_scenario_e)(FUZ_rand(randState) % 3); /* 0 : contiguous; 1 : non-contiguous; 2 : dst overwritten */
  848. /* tighten dst buffer conditions */
  849. size_t const dstCapacity = (o_scenario == o_noncontiguous) ?
  850. (decompressedSize * 2) + 128 :
  851. decompressedSize;
  852. size_t result;
  853. void* const dstBuffer = malloc(dstCapacity);
  854. assert(dstBuffer != NULL);
  855. result = test_lz4f_decompression_wBuffers(cSrc, cSize,
  856. dstBuffer, dstCapacity, o_scenario,
  857. srcRef, decompressedSize,
  858. crcOrig,
  859. randState,
  860. dCtx,
  861. seed, testNb, findErrorPos);
  862. free(dstBuffer);
  863. return result;
  864. }
  865. int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility, U32 duration_s)
  866. {
  867. unsigned testNb = 0;
  868. size_t const CNBufferLength = 9 MB; /* needs to be > 2x4MB to test large blocks */
  869. void* CNBuffer = NULL;
  870. size_t const compressedBufferSize = LZ4F_compressFrameBound(CNBufferLength, NULL) + 4 MB; /* needs some margin */
  871. void* compressedBuffer = NULL;
  872. void* decodedBuffer = NULL;
  873. U32 coreRand = seed;
  874. LZ4F_decompressionContext_t dCtx = NULL;
  875. LZ4F_decompressionContext_t dCtxNoise = NULL;
  876. LZ4F_compressionContext_t cCtx = NULL;
  877. clock_t const startClock = clock();
  878. clock_t const clockDuration = duration_s * CLOCKS_PER_SEC;
  879. /* Create states & buffers */
  880. { size_t const creationStatus = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
  881. CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); }
  882. { size_t const creationStatus = LZ4F_createDecompressionContext(&dCtxNoise, LZ4F_VERSION);
  883. CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); }
  884. { size_t const creationStatus = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION);
  885. CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); }
  886. CNBuffer = malloc(CNBufferLength);
  887. CHECK(CNBuffer==NULL, "CNBuffer Allocation failed");
  888. compressedBuffer = malloc(compressedBufferSize);
  889. CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed");
  890. decodedBuffer = calloc(1, CNBufferLength); /* calloc avoids decodedBuffer being considered "garbage" by scan-build */
  891. CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed");
  892. FUZ_fillCompressibleNoiseBuffer(CNBuffer, CNBufferLength, compressibility, &coreRand);
  893. /* jump to requested testNb */
  894. for (testNb =0; (testNb < startTest); testNb++) (void)FUZ_rand(&coreRand); /* sync randomizer */
  895. /* main fuzzer test loop */
  896. for ( ; (testNb < nbTests) || (clockDuration > FUZ_GetClockSpan(startClock)) ; testNb++) {
  897. U32 randState = coreRand ^ prime1;
  898. unsigned const srcBits = (FUZ_rand(&randState) % (FUZ_highbit((U32)(CNBufferLength-1)) - 1)) + 1;
  899. size_t const srcSize = (FUZ_rand(&randState) & ((1<<srcBits)-1)) + 1;
  900. size_t const srcStartId = FUZ_rand(&randState) % (CNBufferLength - srcSize);
  901. const BYTE* const srcStart = (const BYTE*)CNBuffer + srcStartId;
  902. unsigned const neverFlush = (FUZ_rand(&randState) & 15) == 1;
  903. U64 const crcOrig = XXH64(srcStart, srcSize, 1);
  904. LZ4F_preferences_t prefs;
  905. const LZ4F_preferences_t* prefsPtr = &prefs;
  906. size_t cSize;
  907. (void)FUZ_rand(&coreRand); /* update seed */
  908. memset(&prefs, 0, sizeof(prefs));
  909. prefs.frameInfo.blockMode = (LZ4F_blockMode_t)(FUZ_rand(&randState) & 1);
  910. prefs.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)(4 + (FUZ_rand(&randState) & 3));
  911. prefs.frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)(FUZ_rand(&randState) & 1);
  912. prefs.frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)(FUZ_rand(&randState) & 1);
  913. prefs.frameInfo.contentSize = ((FUZ_rand(&randState) & 0xF) == 1) ? srcSize : 0;
  914. prefs.autoFlush = neverFlush ? 0 : (FUZ_rand(&randState) & 7) == 2;
  915. prefs.compressionLevel = -5 + (int)(FUZ_rand(&randState) % 11);
  916. if ((FUZ_rand(&randState) & 0xF) == 1) prefsPtr = NULL;
  917. DISPLAYUPDATE(2, "\r%5u ", testNb);
  918. if ((FUZ_rand(&randState) & 0xFFF) == 0) {
  919. /* create a skippable frame (rare case) */
  920. BYTE* op = (BYTE*)compressedBuffer;
  921. FUZ_writeLE32(op, LZ4F_MAGIC_SKIPPABLE_START + (FUZ_rand(&randState) & 15));
  922. FUZ_writeLE32(op+4, (U32)srcSize);
  923. cSize = srcSize+8;
  924. } else if ((FUZ_rand(&randState) & 0xF) == 2) { /* single pass compression (simple) */
  925. cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(srcSize, prefsPtr), srcStart, srcSize, prefsPtr);
  926. CHECK(LZ4F_isError(cSize), "LZ4F_compressFrame failed : error %i (%s)", (int)cSize, LZ4F_getErrorName(cSize));
  927. } else { /* multi-segments compression */
  928. const BYTE* ip = srcStart;
  929. const BYTE* const iend = srcStart + srcSize;
  930. BYTE* op = (BYTE*)compressedBuffer;
  931. BYTE* const oend = op + (neverFlush ? LZ4F_compressFrameBound(srcSize, prefsPtr) : compressedBufferSize); /* when flushes are possible, can't guarantee a max compressed size */
  932. unsigned const maxBits = FUZ_highbit((U32)srcSize);
  933. LZ4F_compressOptions_t cOptions;
  934. memset(&cOptions, 0, sizeof(cOptions));
  935. { size_t const fhSize = LZ4F_compressBegin(cCtx, op, (size_t)(oend-op), prefsPtr);
  936. CHECK(LZ4F_isError(fhSize), "Compression header failed (error %i)",
  937. (int)fhSize);
  938. op += fhSize;
  939. }
  940. while (ip < iend) {
  941. unsigned const nbBitsSeg = FUZ_rand(&randState) % maxBits;
  942. size_t const sampleMax = (FUZ_rand(&randState) & ((1<<nbBitsSeg)-1)) + 1;
  943. size_t iSize = MIN(sampleMax, (size_t)(iend-ip));
  944. size_t const oSize = LZ4F_compressBound(iSize, prefsPtr);
  945. cOptions.stableSrc = ((FUZ_rand(&randState) & 3) == 1);
  946. DISPLAYLEVEL(6, "Sending %u bytes to compress (stableSrc:%u) \n",
  947. (unsigned)iSize, cOptions.stableSrc);
  948. #if 1
  949. /* insert uncompressed segment */
  950. if ( (iSize>0)
  951. && !neverFlush /* do not mess with compressBound when neverFlush is set */
  952. && prefsPtr != NULL /* prefs are set */
  953. && prefs.frameInfo.blockMode == LZ4F_blockIndependent /* uncompressedUpdate is only valid with blockMode==independent */
  954. && (FUZ_rand(&randState) & 15) == 1 ) {
  955. size_t const uSize = FUZ_rand(&randState) % iSize;
  956. size_t const flushedSize = LZ4F_uncompressedUpdate(cCtx, op, (size_t)(oend-op), ip, uSize, &cOptions);
  957. CHECK(LZ4F_isError(flushedSize), "Insert uncompressed data failed (error %i : %s)",
  958. (int)flushedSize, LZ4F_getErrorName(flushedSize));
  959. op += flushedSize;
  960. ip += uSize;
  961. iSize -= uSize;
  962. }
  963. #endif
  964. { size_t const flushedSize = LZ4F_compressUpdate(cCtx, op, oSize, ip, iSize, &cOptions);
  965. CHECK(LZ4F_isError(flushedSize), "Compression failed (error %i : %s)",
  966. (int)flushedSize, LZ4F_getErrorName(flushedSize));
  967. op += flushedSize;
  968. ip += iSize;
  969. }
  970. { unsigned const forceFlush = neverFlush ? 0 : ((FUZ_rand(&randState) & 3) == 1);
  971. if (forceFlush) {
  972. size_t const flushSize = LZ4F_flush(cCtx, op, (size_t)(oend-op), &cOptions);
  973. DISPLAYLEVEL(6,"flushing %u bytes \n", (unsigned)flushSize);
  974. CHECK(LZ4F_isError(flushSize), "Compression failed (error %i)", (int)flushSize);
  975. op += flushSize;
  976. if ((FUZ_rand(&randState) % 1024) == 3) {
  977. /* add an empty block (requires uncompressed flag) */
  978. op[0] = op[1] = op[2] = 0;
  979. op[3] = 0x80; /* 0x80000000U in little-endian format */
  980. op += 4;
  981. if ((prefsPtr!= NULL) && prefsPtr->frameInfo.blockChecksumFlag) {
  982. /* add block checksum (even for empty blocks) */
  983. FUZ_writeLE32(op, XXH32(op, 0, 0));
  984. op += 4;
  985. } } } }
  986. } /* while (ip<iend) */
  987. CHECK(op>=oend, "LZ4F_compressFrameBound overflow");
  988. { size_t const dstEndSafeSize = LZ4F_compressBound(0, prefsPtr);
  989. int const tooSmallDstEnd = ((FUZ_rand(&randState) & 31) == 3);
  990. size_t const dstEndTooSmallSize = (FUZ_rand(&randState) % dstEndSafeSize) + 1;
  991. size_t const dstEndSize = tooSmallDstEnd ? dstEndTooSmallSize : dstEndSafeSize;
  992. BYTE const canaryByte = (BYTE)(FUZ_rand(&randState) & 255);
  993. size_t flushedSize;
  994. DISPLAYLEVEL(7,"canaryByte at pos %u / %u \n",
  995. (unsigned)((size_t)(op - (BYTE*)compressedBuffer) + dstEndSize),
  996. (unsigned)compressedBufferSize);
  997. assert(op + dstEndSize < (BYTE*)compressedBuffer + compressedBufferSize);
  998. op[dstEndSize] = canaryByte;
  999. flushedSize = LZ4F_compressEnd(cCtx, op, dstEndSize, &cOptions);
  1000. CHECK(op[dstEndSize] != canaryByte, "LZ4F_compressEnd writes beyond dstCapacity !");
  1001. if (LZ4F_isError(flushedSize)) {
  1002. if (tooSmallDstEnd) /* failure is allowed */ continue;
  1003. CHECK(!tooSmallDstEnd, "Compression completion failed (error %i : %s)",
  1004. (int)flushedSize, LZ4F_getErrorName(flushedSize));
  1005. }
  1006. op += flushedSize;
  1007. }
  1008. cSize = (size_t)(op - (BYTE*)compressedBuffer);
  1009. DISPLAYLEVEL(5, "\nCompressed %u bytes into %u \n", (U32)srcSize, (U32)cSize);
  1010. }
  1011. /* multi-segments decompression */
  1012. DISPLAYLEVEL(6, "normal decompression \n");
  1013. { size_t result = test_lz4f_decompression(compressedBuffer, cSize, srcStart, srcSize, crcOrig, &randState, dCtx, seed, testNb, 1 /*findError*/ );
  1014. CHECK (LZ4F_isError(result), "multi-segment decompression failed (error %i => %s)",
  1015. (int)result, LZ4F_getErrorName(result));
  1016. }
  1017. #if 1
  1018. /* insert noise into src */
  1019. { U32 const maxNbBits = FUZ_highbit((U32)cSize);
  1020. size_t pos = 0;
  1021. for (;;) {
  1022. /* keep some original src */
  1023. { U32 const nbBits = FUZ_rand(&randState) % maxNbBits;
  1024. size_t const mask = (1<<nbBits) - 1;
  1025. size_t const skipLength = FUZ_rand(&randState) & mask;
  1026. pos += skipLength;
  1027. }
  1028. if (pos >= cSize) break;
  1029. /* add noise */
  1030. { U32 const nbBitsCodes = FUZ_rand(&randState) % maxNbBits;
  1031. U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0;
  1032. size_t const mask = (1<<nbBits) - 1;
  1033. size_t const rNoiseLength = (FUZ_rand(&randState) & mask) + 1;
  1034. size_t const noiseLength = MIN(rNoiseLength, cSize-pos);
  1035. size_t const noiseStart = FUZ_rand(&randState) % (CNBufferLength - noiseLength);
  1036. memcpy((BYTE*)compressedBuffer + pos, (const char*)CNBuffer + noiseStart, noiseLength);
  1037. pos += noiseLength;
  1038. } } }
  1039. /* test decompression on noisy src */
  1040. DISPLAYLEVEL(6, "noisy decompression \n");
  1041. test_lz4f_decompression(compressedBuffer, cSize, srcStart, srcSize, crcOrig, &randState, dCtxNoise, seed, testNb, 0 /*don't search error Pos*/ );
  1042. /* note : we don't analyze result here : it probably failed, which is expected.
  1043. * The sole purpose is to catch potential out-of-bound reads and writes. */
  1044. LZ4F_resetDecompressionContext(dCtxNoise); /* context must be reset after an error */
  1045. #endif
  1046. } /* for ( ; (testNb < nbTests) ; ) */
  1047. DISPLAYLEVEL(2, "\rAll tests completed \n");
  1048. LZ4F_freeDecompressionContext(dCtx);
  1049. LZ4F_freeDecompressionContext(dCtxNoise);
  1050. LZ4F_freeCompressionContext(cCtx);
  1051. free(CNBuffer);
  1052. free(compressedBuffer);
  1053. free(decodedBuffer);
  1054. if (use_pause) {
  1055. DISPLAY("press enter to finish \n");
  1056. (void)getchar();
  1057. }
  1058. return 0;
  1059. }
  1060. int FUZ_usage(const char* programName)
  1061. {
  1062. DISPLAY( "Usage :\n");
  1063. DISPLAY( " %s [args]\n", programName);
  1064. DISPLAY( "\n");
  1065. DISPLAY( "Arguments :\n");
  1066. DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault);
  1067. DISPLAY( " -T# : Duration of tests, in seconds (default: use Nb of tests) \n");
  1068. DISPLAY( " -s# : Select seed (default:prompt user)\n");
  1069. DISPLAY( " -t# : Select starting test number (default:0)\n");
  1070. DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
  1071. DISPLAY( " -v : verbose\n");
  1072. DISPLAY( " -h : display help and exit\n");
  1073. return 0;
  1074. }
  1075. int main(int argc, const char** argv)
  1076. {
  1077. U32 seed=0;
  1078. int seedset=0;
  1079. int argNb;
  1080. unsigned nbTests = nbTestsDefault;
  1081. unsigned testNb = 0;
  1082. int proba = FUZ_COMPRESSIBILITY_DEFAULT;
  1083. int result=0;
  1084. U32 duration=0;
  1085. const char* const programName = argv[0];
  1086. /* Check command line */
  1087. for (argNb=1; argNb<argc; argNb++) {
  1088. const char* argument = argv[argNb];
  1089. if(!argument) continue; /* Protection if argument empty */
  1090. /* Decode command (note : aggregated short commands are allowed) */
  1091. if (argument[0]=='-') {
  1092. if (!strcmp(argument, "--no-prompt")) {
  1093. no_prompt=1;
  1094. seedset=1;
  1095. displayLevel=1;
  1096. continue;
  1097. }
  1098. argument++;
  1099. while (*argument!=0) {
  1100. switch(*argument)
  1101. {
  1102. case 'h':
  1103. return FUZ_usage(programName);
  1104. case 'v':
  1105. argument++;
  1106. displayLevel++;
  1107. break;
  1108. case 'q':
  1109. argument++;
  1110. displayLevel--;
  1111. break;
  1112. case 'p': /* pause at the end */
  1113. argument++;
  1114. use_pause = 1;
  1115. break;
  1116. case 'i':
  1117. argument++;
  1118. nbTests=0; duration=0;
  1119. while ((*argument>='0') && (*argument<='9')) {
  1120. nbTests *= 10;
  1121. nbTests += (unsigned)(*argument - '0');
  1122. argument++;
  1123. }
  1124. break;
  1125. case 'T':
  1126. argument++;
  1127. nbTests = 0; duration = 0;
  1128. for (;;) {
  1129. switch(*argument)
  1130. {
  1131. case 'm': duration *= 60; argument++; continue;
  1132. case 's':
  1133. case 'n': argument++; continue;
  1134. case '0':
  1135. case '1':
  1136. case '2':
  1137. case '3':
  1138. case '4':
  1139. case '5':
  1140. case '6':
  1141. case '7':
  1142. case '8':
  1143. case '9': duration *= 10; duration += (U32)(*argument++ - '0'); continue;
  1144. }
  1145. break;
  1146. }
  1147. break;
  1148. case 's':
  1149. argument++;
  1150. seed=0;
  1151. seedset=1;
  1152. while ((*argument>='0') && (*argument<='9')) {
  1153. seed *= 10;
  1154. seed += (U32)(*argument - '0');
  1155. argument++;
  1156. }
  1157. break;
  1158. case 't':
  1159. argument++;
  1160. testNb=0;
  1161. while ((*argument>='0') && (*argument<='9')) {
  1162. testNb *= 10;
  1163. testNb += (unsigned)(*argument - '0');
  1164. argument++;
  1165. }
  1166. break;
  1167. case 'P': /* compressibility % */
  1168. argument++;
  1169. proba=0;
  1170. while ((*argument>='0') && (*argument<='9')) {
  1171. proba *= 10;
  1172. proba += *argument - '0';
  1173. argument++;
  1174. }
  1175. if (proba<0) proba=0;
  1176. if (proba>100) proba=100;
  1177. break;
  1178. default:
  1179. ;
  1180. return FUZ_usage(programName);
  1181. }
  1182. }
  1183. }
  1184. }
  1185. /* Get Seed */
  1186. DISPLAY("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION_STRING);
  1187. if (!seedset) {
  1188. time_t const t = time(NULL);
  1189. U32 const h = XXH32(&t, sizeof(t), 1);
  1190. seed = h % 10000;
  1191. }
  1192. DISPLAY("Seed = %u\n", seed);
  1193. if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba);
  1194. nbTests += (nbTests==0); /* avoid zero */
  1195. if (testNb==0) result = basicTests(seed, ((double)proba) / 100);
  1196. if (result) return 1;
  1197. return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, duration);
  1198. }