blob: c9ffb5d916375d295a3d6c4ebf2d335ad9b814f1 [file] [log] [blame]
Yann Colletdb4c0122014-08-30 18:14:44 +01001/*
2 frameTest - test tool for lz4frame
3 Copyright (C) Yann Collet 2014
4 GPL v2 License
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 You can contact the author at :
21 - LZ4 source repository : http://code.google.com/p/lz4/
22 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
23*/
24
25/**************************************
26 Compiler specific
27**************************************/
28#define _CRT_SECURE_NO_WARNINGS // fgets
29#ifdef _MSC_VER /* Visual Studio */
30# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
31# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
32#endif
Yann Collet23effdb2014-08-31 23:14:20 +010033#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
34#ifdef __GNUC__
35# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
36# pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
37#endif
Yann Colletdb4c0122014-08-30 18:14:44 +010038
39
40/**************************************
41 Includes
42**************************************/
43#include <stdlib.h>
44#include <stdio.h> // fgets, sscanf
45#include <sys/timeb.h> // timeb
46#include <string.h> // strcmp
47#include "lz4frame.h"
Yann Collet1ffc02e2014-09-05 16:32:04 +010048#include "xxhash.h" // XXH64
Yann Colletdb4c0122014-08-30 18:14:44 +010049
50
51/**************************************
52 Basic Types
53**************************************/
54#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
55# include <stdint.h>
56 typedef uint8_t BYTE;
57 typedef uint16_t U16;
58 typedef uint32_t U32;
59 typedef int32_t S32;
60 typedef uint64_t U64;
61#else
62 typedef unsigned char BYTE;
63 typedef unsigned short U16;
64 typedef unsigned int U32;
65 typedef signed int S32;
66 typedef unsigned long long U64;
67#endif
68
69
70/**************************************
71 Constants
72**************************************/
73#ifndef LZ4_VERSION
74# define LZ4_VERSION ""
75#endif
76
Yann Colletfc8e3f52014-09-01 22:44:02 +010077#define KB *(1U<<10)
78#define MB *(1U<<20)
79#define GB *(1U<<30)
80
81#define NB_ATTEMPTS (64 KB)
82#define COMPRESSIBLE_NOISE_LENGTH (2 MB)
83#define FUZ_MAX_BLOCK_SIZE (128 KB)
84#define FUZ_MAX_DICT_SIZE (32 KB)
Yann Colletdb4c0122014-08-30 18:14:44 +010085#define FUZ_COMPRESSIBILITY_DEFAULT 50
86#define PRIME1 2654435761U
87#define PRIME2 2246822519U
88#define PRIME3 3266489917U
89
Yann Colletdb4c0122014-08-30 18:14:44 +010090
91
92/**************************************
93 Macros
94**************************************/
Yann Collet1ffc02e2014-09-05 16:32:04 +010095#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
96#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
97#define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { if (FUZ_GetMilliStart() > g_time + 200) { g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); } }
98static int g_time = 0;
Yann Colletdb4c0122014-08-30 18:14:44 +010099
100
101/*****************************************
102 Local Parameters
103*****************************************/
104static int no_prompt = 0;
105static char* programName;
Yann Collet20ae8b92014-09-06 09:47:28 +0100106static int displayLevel = 2;
Yann Colletdb4c0122014-08-30 18:14:44 +0100107
108
109/*********************************************************
110 Fuzzer functions
111*********************************************************/
112static int FUZ_GetMilliStart(void)
113{
114 struct timeb tb;
115 int nCount;
116 ftime( &tb );
117 nCount = (int) (tb.millitm + (tb.time & 0xfffff) * 1000);
118 return nCount;
119}
120
Yann Colletfc8e3f52014-09-01 22:44:02 +0100121/*
Yann Colletdb4c0122014-08-30 18:14:44 +0100122static int FUZ_GetMilliSpan( int nTimeStart )
123{
124 int nSpan = FUZ_GetMilliStart() - nTimeStart;
125 if ( nSpan < 0 )
126 nSpan += 0x100000 * 1000;
127 return nSpan;
128}
Yann Colletfc8e3f52014-09-01 22:44:02 +0100129*/
Yann Colletdb4c0122014-08-30 18:14:44 +0100130
131
132# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
133unsigned int FUZ_rand(unsigned int* src)
134{
135 U32 rand32 = *src;
136 rand32 *= PRIME1;
137 rand32 += PRIME2;
138 rand32 = FUZ_rotl32(rand32, 13);
139 *src = rand32;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100140 return rand32 >> 5;
Yann Colletdb4c0122014-08-30 18:14:44 +0100141}
142
143
Yann Collet1ffc02e2014-09-05 16:32:04 +0100144#define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
145#define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
Yann Collet23effdb2014-08-31 23:14:20 +0100146static void FUZ_fillCompressibleNoiseBuffer(void* buffer, unsigned bufferSize, double proba, U32* seed)
Yann Colletdb4c0122014-08-30 18:14:44 +0100147{
148 BYTE* BBuffer = (BYTE*)buffer;
Yann Collet23effdb2014-08-31 23:14:20 +0100149 unsigned pos = 0;
Yann Colletdb4c0122014-08-30 18:14:44 +0100150 U32 P32 = (U32)(32768 * proba);
151
152 // First Byte
153 BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
154
155 while (pos < bufferSize)
156 {
157 // Select : Literal (noise) or copy (within 64K)
158 if (FUZ_RAND15BITS < P32)
159 {
160 // Copy (within 64K)
Yann Collet23effdb2014-08-31 23:14:20 +0100161 unsigned match, end;
162 unsigned length = FUZ_RANDLENGTH + 4;
163 unsigned offset = FUZ_RAND15BITS + 1;
Yann Colletdb4c0122014-08-30 18:14:44 +0100164 if (offset > pos) offset = pos;
165 if (pos + length > bufferSize) length = bufferSize - pos;
Yann Collet23effdb2014-08-31 23:14:20 +0100166 match = pos - offset;
167 end = pos + length;
168 while (pos < end) BBuffer[pos++] = BBuffer[match++];
Yann Colletdb4c0122014-08-30 18:14:44 +0100169 }
170 else
171 {
172 // Literal (noise)
Yann Collet23effdb2014-08-31 23:14:20 +0100173 unsigned end;
174 unsigned length = FUZ_RANDLENGTH;
Yann Colletdb4c0122014-08-30 18:14:44 +0100175 if (pos + length > bufferSize) length = bufferSize - pos;
Yann Collet23effdb2014-08-31 23:14:20 +0100176 end = pos + length;
177 while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
Yann Colletdb4c0122014-08-30 18:14:44 +0100178 }
179 }
180}
181
182
Yann Collet1ffc02e2014-09-05 16:32:04 +0100183static unsigned FUZ_highbit(U32 v32)
184{
185 unsigned nbBits = 0;
186 if (v32==0) return 0;
187 while (v32) { v32 >>= 1; nbBits ++; }
188 return nbBits;
189}
Yann Colletdb4c0122014-08-30 18:14:44 +0100190
Yann Collet1ffc02e2014-09-05 16:32:04 +0100191
192int basicTests(U32 seed, int nbCycles, int startCycle, double compressibility)
Yann Colletdb4c0122014-08-30 18:14:44 +0100193{
194 int testResult = 0;
195 void* CNBuffer;
196 void* compressedBuffer;
197 void* decodedBuffer;
198 U32 randState = seed;
Yann Collet23effdb2014-08-31 23:14:20 +0100199 size_t cSize, testSize;
200 LZ4F_preferences_t prefs = { 0 };
Yann Collet0ac00ee2014-09-03 19:49:59 +0100201 LZ4F_decompressionContext_t dCtx;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100202 U64 crcOrig;
Yann Colletdb4c0122014-08-30 18:14:44 +0100203
204 (void)nbCycles; (void)startCycle;
205 // Create compressible test buffer
206 CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
Yann Colletdb4c0122014-08-30 18:14:44 +0100207 compressedBuffer = malloc(LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL));
208 decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100209 FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
210 crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
Yann Colletdb4c0122014-08-30 18:14:44 +0100211
Yann Collet23effdb2014-08-31 23:14:20 +0100212 // Trivial tests : one-step frame
213 testSize = COMPRESSIBLE_NOISE_LENGTH;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100214 DISPLAYLEVEL(3, "Using NULL preferences : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100215 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL);
Yann Colletdb4c0122014-08-30 18:14:44 +0100216 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100217 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100218
Yann Collet1ffc02e2014-09-05 16:32:04 +0100219 DISPLAYLEVEL(3, "Decompression test : \n");
Yann Collet0ac00ee2014-09-03 19:49:59 +0100220 {
Yann Collet0ac00ee2014-09-03 19:49:59 +0100221 size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
222 size_t compressedBufferSize = cSize;
Yann Collet8fbacf42014-09-04 22:56:51 +0100223 BYTE* op = (BYTE*)decodedBuffer;
224 BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
225 BYTE* ip = (BYTE*)compressedBuffer;
226 BYTE* const iend = (BYTE*)compressedBuffer + cSize;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100227 U64 crcDest;
228
229 LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
Yann Collet0ac00ee2014-09-03 19:49:59 +0100230 if (LZ4F_isError(errorCode)) goto _output_error;
Yann Collet8fbacf42014-09-04 22:56:51 +0100231
Yann Collet1ffc02e2014-09-05 16:32:04 +0100232 DISPLAYLEVEL(3, "Single Block : \n");
Yann Collet0ac00ee2014-09-03 19:49:59 +0100233 errorCode = LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100234 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
235 if (crcDest != crcOrig) goto _output_error;
236 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
Yann Collet8fbacf42014-09-04 22:56:51 +0100237
Yann Collet1ffc02e2014-09-05 16:32:04 +0100238 DISPLAYLEVEL(3, "Byte after byte : \n");
Yann Collet8fbacf42014-09-04 22:56:51 +0100239 while (ip < iend)
240 {
241 size_t oSize = oend-op;
242 size_t iSize = 1;
243 //DISPLAY("%7i \n", (int)(ip-(BYTE*)compressedBuffer));
244 errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
245 if (LZ4F_isError(errorCode)) goto _output_error;
246 op += oSize;
247 ip += iSize;
248 }
Yann Collet1ffc02e2014-09-05 16:32:04 +0100249 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
250 if (crcDest != crcOrig) goto _output_error;
251 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
Yann Collet8fbacf42014-09-04 22:56:51 +0100252
Yann Collet0ac00ee2014-09-03 19:49:59 +0100253 errorCode = LZ4F_freeDecompressionContext(dCtx);
254 if (LZ4F_isError(errorCode)) goto _output_error;
255 }
256
Yann Collet1ffc02e2014-09-05 16:32:04 +0100257 DISPLAYLEVEL(3, "Using 64 KB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100258 prefs.frameInfo.blockSizeID = max64KB;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100259 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
Yann Collet23effdb2014-08-31 23:14:20 +0100260 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
261 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100262 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100263
Yann Collet1ffc02e2014-09-05 16:32:04 +0100264 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100265 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
266 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
267 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100268 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100269
Yann Collet1ffc02e2014-09-05 16:32:04 +0100270 DISPLAYLEVEL(3, "Using 256 KB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100271 prefs.frameInfo.blockSizeID = max256KB;
272 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
273 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
274 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100275 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100276
Yann Collet1ffc02e2014-09-05 16:32:04 +0100277 DISPLAYLEVEL(3, "Decompression test : \n");
278 {
279 size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
280 unsigned maxBits = FUZ_highbit(decodedBufferSize);
281 BYTE* op = (BYTE*)decodedBuffer;
282 BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
283 BYTE* ip = (BYTE*)compressedBuffer;
284 BYTE* const iend = (BYTE*)compressedBuffer + cSize;
285 U64 crcDest;
286
287 LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
288 if (LZ4F_isError(errorCode)) goto _output_error;
289
290 DISPLAYLEVEL(3, "random segment sizes : \n");
291 while (ip < iend)
292 {
293 unsigned nbBits = FUZ_rand(&randState) % maxBits;
294 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
295 size_t oSize = oend-op;
296 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
297 //DISPLAY("%7i : + %6i\n", (int)(ip-(BYTE*)compressedBuffer), (int)iSize);
298 errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
299 if (LZ4F_isError(errorCode)) goto _output_error;
300 op += oSize;
301 ip += iSize;
302 }
303 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
304 if (crcDest != crcOrig) goto _output_error;
305 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
306
307 errorCode = LZ4F_freeDecompressionContext(dCtx);
308 if (LZ4F_isError(errorCode)) goto _output_error;
309 }
310
311 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100312 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
313 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
314 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100315 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100316
Yann Collet1ffc02e2014-09-05 16:32:04 +0100317 DISPLAYLEVEL(3, "Using 1 MB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100318 prefs.frameInfo.blockSizeID = max1MB;
319 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
320 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
321 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100322 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100323
Yann Collet1ffc02e2014-09-05 16:32:04 +0100324 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100325 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
326 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
327 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100328 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100329
Yann Collet1ffc02e2014-09-05 16:32:04 +0100330 DISPLAYLEVEL(3, "Using 4 MB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100331 prefs.frameInfo.blockSizeID = max4MB;
332 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
333 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
334 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100335 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100336
Yann Collet1ffc02e2014-09-05 16:32:04 +0100337 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100338 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
339 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
340 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100341 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Colletdb4c0122014-08-30 18:14:44 +0100342
Yann Collet20ae8b92014-09-06 09:47:28 +0100343 DISPLAY("Basic tests completed \n");
Yann Colletdb4c0122014-08-30 18:14:44 +0100344_end:
345 free(CNBuffer);
346 free(compressedBuffer);
347 free(decodedBuffer);
348 return testResult;
349
350_output_error:
351 testResult = 1;
Yann Collet0ac00ee2014-09-03 19:49:59 +0100352 DISPLAY("Error detected ! \n");
Yann Colletdb4c0122014-08-30 18:14:44 +0100353 if(!no_prompt) getchar();
354 goto _end;
355}
356
357
Yann Collet1ffc02e2014-09-05 16:32:04 +0100358static const U32 srcDataLength = 4 MB;
359
360int fuzzerTests(U32 seed, unsigned nbTests, int startCycle, double compressibility)
361{
362 unsigned testResult = 0;
363 unsigned testNb = 0;
364 void* srcBuffer;
365 void* compressedBuffer;
366 void* decodedBuffer;
367 U32 randState = seed;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100368 LZ4F_decompressionContext_t dCtx;
Yann Colletb73b2af2014-09-06 12:19:26 +0100369 size_t result;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100370
Yann Collet20ae8b92014-09-06 09:47:28 +0100371 (void)startCycle;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100372 // Create compressible test buffer
373 LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
374 srcBuffer = malloc(srcDataLength);
375 compressedBuffer = malloc(LZ4F_compressFrameBound(srcDataLength, NULL));
376 decodedBuffer = malloc(srcDataLength);
377 FUZ_fillCompressibleNoiseBuffer(srcBuffer, srcDataLength, compressibility, &randState);
378
379 // Select components of compression test
380 for (testNb=0; testNb < nbTests; testNb++)
381 {
Yann Collet20ae8b92014-09-06 09:47:28 +0100382 unsigned CCflag = FUZ_rand(&randState) & 1;
383 unsigned BSId = 4 + (FUZ_rand(&randState) & 3);
384 LZ4F_preferences_t prefs = { { BSId, 0, CCflag, 0,0,0 }, 0,0, 0,0,0,0 };
Yann Collet1ffc02e2014-09-05 16:32:04 +0100385 unsigned nbBits = (FUZ_rand(&randState) % (FUZ_highbit(srcDataLength-1) - 1)) + 1;
386 size_t srcSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
387 size_t srcStart = FUZ_rand(&randState) % (srcDataLength - srcSize);
Yann Colletb73b2af2014-09-06 12:19:26 +0100388 size_t cSize, decodedSize;
389 U64 crcOrig, crcDecoded;
390
Yann Collet1ffc02e2014-09-05 16:32:04 +0100391 DISPLAYUPDATE(2, "%5i \r", testNb);
Yann Colletb73b2af2014-09-06 12:19:26 +0100392 result = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(srcSize, &(prefs.frameInfo)), srcBuffer+srcStart, srcSize, &prefs );
393 if (LZ4F_isError(result)) goto _output_error;
394 crcOrig = XXH64(srcBuffer+srcStart, srcSize, 1);
395
396 cSize = result;
397 decodedSize = srcDataLength;
398 result = LZ4F_decompress(dCtx, decodedBuffer, &decodedSize, compressedBuffer, &cSize, NULL);
399 if (LZ4F_isError(result)) goto _output_error;
400 if (decodedSize != srcSize) goto _output_error;
401 crcDecoded = XXH64(decodedBuffer, srcSize, 1);
402 if (crcDecoded != crcOrig) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100403 }
404
405 DISPLAYLEVEL(2, "All tests completed \n");
406
407_end:
408 free(srcBuffer);
409 free(compressedBuffer);
410 free(decodedBuffer);
411 return testResult;
412
413_output_error:
414 testResult = 1;
415 DISPLAY("Error detected ! \n");
416 if(!no_prompt) getchar();
417 goto _end;
418}
419
420
Yann Colletdb4c0122014-08-30 18:14:44 +0100421int FUZ_usage(void)
422{
423 DISPLAY( "Usage :\n");
424 DISPLAY( " %s [args]\n", programName);
425 DISPLAY( "\n");
426 DISPLAY( "Arguments :\n");
427 DISPLAY( " -i# : Nb of tests (default:%i) \n", NB_ATTEMPTS);
428 DISPLAY( " -s# : Select seed (default:prompt user)\n");
429 DISPLAY( " -t# : Select starting test number (default:0)\n");
430 DISPLAY( " -p# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
431 DISPLAY( " -v : verbose\n");
432 DISPLAY( " -h : display help and exit\n");
433 return 0;
434}
435
436
Yann Colletfc8e3f52014-09-01 22:44:02 +0100437int main(int argc, char** argv)
438{
Yann Colletdb4c0122014-08-30 18:14:44 +0100439 U32 seed=0;
440 int seedset=0;
441 int argNb;
442 int nbTests = NB_ATTEMPTS;
443 int testNb = 0;
444 int proba = FUZ_COMPRESSIBILITY_DEFAULT;
445
446 // Check command line
447 programName = argv[0];
448 for(argNb=1; argNb<argc; argNb++)
449 {
450 char* argument = argv[argNb];
451
452 if(!argument) continue; // Protection if argument empty
453
454 // Decode command (note : aggregated commands are allowed)
455 if (argument[0]=='-')
456 {
457 if (!strcmp(argument, "--no-prompt")) { no_prompt=1; seedset=1; displayLevel=1; continue; }
458
459 while (argument[1]!=0)
460 {
461 argument++;
462 switch(*argument)
463 {
464 case 'h':
465 return FUZ_usage();
466 case 'v':
467 argument++;
468 displayLevel=4;
469 break;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100470 case 'q':
471 argument++;
472 displayLevel--;
473 break;
Yann Colletdb4c0122014-08-30 18:14:44 +0100474 case 'i':
475 argument++;
476 nbTests=0;
477 while ((*argument>='0') && (*argument<='9'))
478 {
479 nbTests *= 10;
480 nbTests += *argument - '0';
481 argument++;
482 }
483 break;
484 case 's':
485 argument++;
486 seed=0; seedset=1;
487 while ((*argument>='0') && (*argument<='9'))
488 {
489 seed *= 10;
490 seed += *argument - '0';
491 argument++;
492 }
493 break;
494 case 't':
495 argument++;
496 testNb=0;
497 while ((*argument>='0') && (*argument<='9'))
498 {
499 testNb *= 10;
500 testNb += *argument - '0';
501 argument++;
502 }
503 break;
504 case 'p':
505 argument++;
506 proba=0;
507 while ((*argument>='0') && (*argument<='9'))
508 {
509 proba *= 10;
510 proba += *argument - '0';
511 argument++;
512 }
513 if (proba<0) proba=0;
514 if (proba>100) proba=100;
515 break;
516 default: ;
517 }
518 }
519 }
520 }
521
522 // Get Seed
523 printf("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
524
Yann Colletfc8e3f52014-09-01 22:44:02 +0100525 if (!seedset) seed = FUZ_GetMilliStart() % 10000;
Yann Colletdb4c0122014-08-30 18:14:44 +0100526 printf("Seed = %u\n", seed);
527 if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba);
528
529 if (nbTests<=0) nbTests=1;
530
Yann Collet1ffc02e2014-09-05 16:32:04 +0100531 basicTests(seed, nbTests, testNb, ((double)proba) / 100);
532 return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
Yann Colletdb4c0122014-08-30 18:14:44 +0100533}