blob: c33e1acf0325d8d34d7edfc6632602645c25247b [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
Yann Collet837551f2014-09-07 09:13:02 +010081static const U32 nbTestsDefault = 128 KB;
Yann Colletfc8e3f52014-09-01 22:44:02 +010082#define COMPRESSIBLE_NOISE_LENGTH (2 MB)
Yann Colletdb4c0122014-08-30 18:14:44 +010083#define FUZ_COMPRESSIBILITY_DEFAULT 50
Yann Collet837551f2014-09-07 09:13:02 +010084static const U32 prime1 = 2654435761U;
85static const U32 prime2 = 2246822519U;
Yann Colletdb4c0122014-08-30 18:14:44 +010086
Yann Colletdb4c0122014-08-30 18:14:44 +010087
88
89/**************************************
90 Macros
91**************************************/
Yann Collet1ffc02e2014-09-05 16:32:04 +010092#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
93#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
Yann Colletda1b0c12014-09-06 13:06:28 +010094#define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \
95 if ((FUZ_GetMilliSpan(g_time) > refreshRate) || (displayLevel>=4)) \
96 { g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \
97 if (displayLevel>=4) fflush(stdout); } }
98static const U32 refreshRate = 150;
99static U32 g_time = 0;
Yann Colletdb4c0122014-08-30 18:14:44 +0100100
101
102/*****************************************
103 Local Parameters
104*****************************************/
Yann Colletda1b0c12014-09-06 13:06:28 +0100105static U32 no_prompt = 0;
Yann Colletdb4c0122014-08-30 18:14:44 +0100106static char* programName;
Yann Colletda1b0c12014-09-06 13:06:28 +0100107static U32 displayLevel = 2;
Yann Colletdb4c0122014-08-30 18:14:44 +0100108
109
110/*********************************************************
111 Fuzzer functions
112*********************************************************/
Yann Colletda1b0c12014-09-06 13:06:28 +0100113static U32 FUZ_GetMilliStart(void)
Yann Colletdb4c0122014-08-30 18:14:44 +0100114{
115 struct timeb tb;
Yann Colletda1b0c12014-09-06 13:06:28 +0100116 U32 nCount;
Yann Colletdb4c0122014-08-30 18:14:44 +0100117 ftime( &tb );
Yann Collet837551f2014-09-07 09:13:02 +0100118 nCount = (U32) (((tb.time & 0xFFFFF) * 1000) + tb.millitm);
Yann Colletdb4c0122014-08-30 18:14:44 +0100119 return nCount;
120}
121
Yann Colletda1b0c12014-09-06 13:06:28 +0100122
123static U32 FUZ_GetMilliSpan(U32 nTimeStart)
Yann Colletdb4c0122014-08-30 18:14:44 +0100124{
Yann Colletda1b0c12014-09-06 13:06:28 +0100125 U32 nCurrent = FUZ_GetMilliStart();
126 U32 nSpan = nCurrent - nTimeStart;
127 if (nTimeStart > nCurrent)
Yann Colletdb4c0122014-08-30 18:14:44 +0100128 nSpan += 0x100000 * 1000;
129 return nSpan;
130}
Yann Colletda1b0c12014-09-06 13:06:28 +0100131
Yann Colletdb4c0122014-08-30 18:14:44 +0100132
133
134# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
135unsigned int FUZ_rand(unsigned int* src)
136{
137 U32 rand32 = *src;
Yann Collet837551f2014-09-07 09:13:02 +0100138 rand32 *= prime1;
139 rand32 += prime2;
Yann Colletdb4c0122014-08-30 18:14:44 +0100140 rand32 = FUZ_rotl32(rand32, 13);
141 *src = rand32;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100142 return rand32 >> 5;
Yann Colletdb4c0122014-08-30 18:14:44 +0100143}
144
145
Yann Collet1ffc02e2014-09-05 16:32:04 +0100146#define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF)
147#define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
Yann Collet23effdb2014-08-31 23:14:20 +0100148static void FUZ_fillCompressibleNoiseBuffer(void* buffer, unsigned bufferSize, double proba, U32* seed)
Yann Colletdb4c0122014-08-30 18:14:44 +0100149{
150 BYTE* BBuffer = (BYTE*)buffer;
Yann Collet23effdb2014-08-31 23:14:20 +0100151 unsigned pos = 0;
Yann Colletdb4c0122014-08-30 18:14:44 +0100152 U32 P32 = (U32)(32768 * proba);
153
154 // First Byte
155 BBuffer[pos++] = (BYTE)(FUZ_rand(seed));
156
157 while (pos < bufferSize)
158 {
159 // Select : Literal (noise) or copy (within 64K)
160 if (FUZ_RAND15BITS < P32)
161 {
162 // Copy (within 64K)
Yann Collet23effdb2014-08-31 23:14:20 +0100163 unsigned match, end;
164 unsigned length = FUZ_RANDLENGTH + 4;
165 unsigned offset = FUZ_RAND15BITS + 1;
Yann Colletdb4c0122014-08-30 18:14:44 +0100166 if (offset > pos) offset = pos;
167 if (pos + length > bufferSize) length = bufferSize - pos;
Yann Collet23effdb2014-08-31 23:14:20 +0100168 match = pos - offset;
169 end = pos + length;
170 while (pos < end) BBuffer[pos++] = BBuffer[match++];
Yann Colletdb4c0122014-08-30 18:14:44 +0100171 }
172 else
173 {
174 // Literal (noise)
Yann Collet23effdb2014-08-31 23:14:20 +0100175 unsigned end;
176 unsigned length = FUZ_RANDLENGTH;
Yann Colletdb4c0122014-08-30 18:14:44 +0100177 if (pos + length > bufferSize) length = bufferSize - pos;
Yann Collet23effdb2014-08-31 23:14:20 +0100178 end = pos + length;
179 while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5);
Yann Colletdb4c0122014-08-30 18:14:44 +0100180 }
181 }
182}
183
184
Yann Collet1ffc02e2014-09-05 16:32:04 +0100185static unsigned FUZ_highbit(U32 v32)
186{
187 unsigned nbBits = 0;
188 if (v32==0) return 0;
189 while (v32) { v32 >>= 1; nbBits ++; }
190 return nbBits;
191}
Yann Colletdb4c0122014-08-30 18:14:44 +0100192
Yann Collet1ffc02e2014-09-05 16:32:04 +0100193
194int basicTests(U32 seed, int nbCycles, int startCycle, double compressibility)
Yann Colletdb4c0122014-08-30 18:14:44 +0100195{
196 int testResult = 0;
197 void* CNBuffer;
198 void* compressedBuffer;
199 void* decodedBuffer;
200 U32 randState = seed;
Yann Collet23effdb2014-08-31 23:14:20 +0100201 size_t cSize, testSize;
202 LZ4F_preferences_t prefs = { 0 };
Yann Collet0ac00ee2014-09-03 19:49:59 +0100203 LZ4F_decompressionContext_t dCtx;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100204 U64 crcOrig;
Yann Colletdb4c0122014-08-30 18:14:44 +0100205
206 (void)nbCycles; (void)startCycle;
207 // Create compressible test buffer
208 CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
Yann Colletdb4c0122014-08-30 18:14:44 +0100209 compressedBuffer = malloc(LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL));
210 decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100211 FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState);
212 crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
Yann Colletdb4c0122014-08-30 18:14:44 +0100213
Yann Collet23effdb2014-08-31 23:14:20 +0100214 // Trivial tests : one-step frame
215 testSize = COMPRESSIBLE_NOISE_LENGTH;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100216 DISPLAYLEVEL(3, "Using NULL preferences : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100217 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL);
Yann Colletdb4c0122014-08-30 18:14:44 +0100218 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100219 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100220
Yann Collet1ffc02e2014-09-05 16:32:04 +0100221 DISPLAYLEVEL(3, "Decompression test : \n");
Yann Collet0ac00ee2014-09-03 19:49:59 +0100222 {
Yann Collet0ac00ee2014-09-03 19:49:59 +0100223 size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
224 size_t compressedBufferSize = cSize;
Yann Collet8fbacf42014-09-04 22:56:51 +0100225 BYTE* op = (BYTE*)decodedBuffer;
226 BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
227 BYTE* ip = (BYTE*)compressedBuffer;
228 BYTE* const iend = (BYTE*)compressedBuffer + cSize;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100229 U64 crcDest;
230
231 LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
Yann Collet0ac00ee2014-09-03 19:49:59 +0100232 if (LZ4F_isError(errorCode)) goto _output_error;
Yann Collet8fbacf42014-09-04 22:56:51 +0100233
Yann Collet1ffc02e2014-09-05 16:32:04 +0100234 DISPLAYLEVEL(3, "Single Block : \n");
Yann Collet0ac00ee2014-09-03 19:49:59 +0100235 errorCode = LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100236 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
237 if (crcDest != crcOrig) goto _output_error;
238 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
Yann Collet8fbacf42014-09-04 22:56:51 +0100239
Yann Collet1ffc02e2014-09-05 16:32:04 +0100240 DISPLAYLEVEL(3, "Byte after byte : \n");
Yann Collet8fbacf42014-09-04 22:56:51 +0100241 while (ip < iend)
242 {
243 size_t oSize = oend-op;
244 size_t iSize = 1;
245 //DISPLAY("%7i \n", (int)(ip-(BYTE*)compressedBuffer));
246 errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
247 if (LZ4F_isError(errorCode)) goto _output_error;
248 op += oSize;
249 ip += iSize;
250 }
Yann Collet1ffc02e2014-09-05 16:32:04 +0100251 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
252 if (crcDest != crcOrig) goto _output_error;
253 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
Yann Collet8fbacf42014-09-04 22:56:51 +0100254
Yann Collet0ac00ee2014-09-03 19:49:59 +0100255 errorCode = LZ4F_freeDecompressionContext(dCtx);
256 if (LZ4F_isError(errorCode)) goto _output_error;
257 }
258
Yann Collet1ffc02e2014-09-05 16:32:04 +0100259 DISPLAYLEVEL(3, "Using 64 KB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100260 prefs.frameInfo.blockSizeID = max64KB;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100261 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
Yann Collet23effdb2014-08-31 23:14:20 +0100262 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
263 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100264 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100265
Yann Collet1ffc02e2014-09-05 16:32:04 +0100266 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100267 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
268 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
269 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100270 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100271
Yann Collet1ffc02e2014-09-05 16:32:04 +0100272 DISPLAYLEVEL(3, "Using 256 KB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100273 prefs.frameInfo.blockSizeID = max256KB;
274 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
275 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
276 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100277 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100278
Yann Collet1ffc02e2014-09-05 16:32:04 +0100279 DISPLAYLEVEL(3, "Decompression test : \n");
280 {
281 size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH;
282 unsigned maxBits = FUZ_highbit(decodedBufferSize);
283 BYTE* op = (BYTE*)decodedBuffer;
284 BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH;
285 BYTE* ip = (BYTE*)compressedBuffer;
286 BYTE* const iend = (BYTE*)compressedBuffer + cSize;
287 U64 crcDest;
288
289 LZ4F_errorCode_t errorCode = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
290 if (LZ4F_isError(errorCode)) goto _output_error;
291
292 DISPLAYLEVEL(3, "random segment sizes : \n");
293 while (ip < iend)
294 {
295 unsigned nbBits = FUZ_rand(&randState) % maxBits;
296 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
297 size_t oSize = oend-op;
298 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
299 //DISPLAY("%7i : + %6i\n", (int)(ip-(BYTE*)compressedBuffer), (int)iSize);
300 errorCode = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
301 if (LZ4F_isError(errorCode)) goto _output_error;
302 op += oSize;
303 ip += iSize;
304 }
305 crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
306 if (crcDest != crcOrig) goto _output_error;
307 DISPLAYLEVEL(3, "Regenerated %i bytes \n", (int)decodedBufferSize);
308
309 errorCode = LZ4F_freeDecompressionContext(dCtx);
310 if (LZ4F_isError(errorCode)) goto _output_error;
311 }
312
313 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100314 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
315 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
316 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100317 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100318
Yann Collet1ffc02e2014-09-05 16:32:04 +0100319 DISPLAYLEVEL(3, "Using 1 MB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100320 prefs.frameInfo.blockSizeID = max1MB;
321 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
322 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
323 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100324 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100325
Yann Collet1ffc02e2014-09-05 16:32:04 +0100326 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100327 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
328 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
329 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100330 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100331
Yann Collet1ffc02e2014-09-05 16:32:04 +0100332 DISPLAYLEVEL(3, "Using 4 MB block : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100333 prefs.frameInfo.blockSizeID = max4MB;
334 prefs.frameInfo.contentChecksumFlag = contentChecksumEnabled;
335 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
336 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100337 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Collet23effdb2014-08-31 23:14:20 +0100338
Yann Collet1ffc02e2014-09-05 16:32:04 +0100339 DISPLAYLEVEL(3, "without checksum : \n");
Yann Collet23effdb2014-08-31 23:14:20 +0100340 prefs.frameInfo.contentChecksumFlag = noContentChecksum;
341 cSize = LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &(prefs.frameInfo)), CNBuffer, testSize, &prefs);
342 if (LZ4F_isError(cSize)) goto _output_error;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100343 DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize);
Yann Colletdb4c0122014-08-30 18:14:44 +0100344
Yann Collet20ae8b92014-09-06 09:47:28 +0100345 DISPLAY("Basic tests completed \n");
Yann Colletdb4c0122014-08-30 18:14:44 +0100346_end:
347 free(CNBuffer);
348 free(compressedBuffer);
349 free(decodedBuffer);
350 return testResult;
351
352_output_error:
353 testResult = 1;
Yann Collet0ac00ee2014-09-03 19:49:59 +0100354 DISPLAY("Error detected ! \n");
Yann Colletdb4c0122014-08-30 18:14:44 +0100355 if(!no_prompt) getchar();
356 goto _end;
357}
358
359
Yann Collet1ffc02e2014-09-05 16:32:04 +0100360static const U32 srcDataLength = 4 MB;
361
Yann Collet3d9d1782014-09-07 12:12:46 +0100362int fuzzerTests(U32 seed, unsigned nbTests, unsigned startTest, double compressibility)
Yann Collet1ffc02e2014-09-05 16:32:04 +0100363{
364 unsigned testResult = 0;
365 unsigned testNb = 0;
Yann Collet5929de42014-09-07 12:57:09 +0100366 void* srcBuffer = NULL;
367 void* compressedBuffer = NULL;
368 void* decodedBuffer = NULL;
Yann Collet3d9d1782014-09-07 12:12:46 +0100369 U32 coreRand = seed;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100370 LZ4F_decompressionContext_t dCtx;
Yann Collet5929de42014-09-07 12:57:09 +0100371 LZ4F_compressionContext_t cCtx;
372 size_t result;
Yann Colletda1b0c12014-09-06 13:06:28 +0100373# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
374 DISPLAY(" (seed %u, test nb %i) \n", seed, testNb); goto _output_error; }
Yann Collet1ffc02e2014-09-05 16:32:04 +0100375
Yann Collet5929de42014-09-07 12:57:09 +0100376 // Create buffers
377 result = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION);
378 CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result);
379 result = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION);
380 CHECK(LZ4F_isError(result), "Allocation failed (error %i)", (int)result);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100381 srcBuffer = malloc(srcDataLength);
Yann Collet5929de42014-09-07 12:57:09 +0100382 CHECK(srcBuffer==NULL, "srcBuffer Allocation failed");
Yann Collet1ffc02e2014-09-05 16:32:04 +0100383 compressedBuffer = malloc(LZ4F_compressFrameBound(srcDataLength, NULL));
Yann Collet5929de42014-09-07 12:57:09 +0100384 CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed");
Yann Collet1ffc02e2014-09-05 16:32:04 +0100385 decodedBuffer = malloc(srcDataLength);
Yann Collet5929de42014-09-07 12:57:09 +0100386 CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed");
Yann Collet3d9d1782014-09-07 12:12:46 +0100387 FUZ_fillCompressibleNoiseBuffer(srcBuffer, srcDataLength, compressibility, &coreRand);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100388
Yann Collet3d9d1782014-09-07 12:12:46 +0100389 // jump to requested testNb
390 for (testNb =0; testNb < startTest; testNb++) (void)FUZ_rand(&coreRand); // sync randomizer
391
392 // main fuzzer loop
393 for ( ; testNb < nbTests; testNb++)
Yann Collet1ffc02e2014-09-05 16:32:04 +0100394 {
Yann Collet3d9d1782014-09-07 12:12:46 +0100395 U32 randState = coreRand ^ prime1;
Yann Collet20ae8b92014-09-06 09:47:28 +0100396 unsigned CCflag = FUZ_rand(&randState) & 1;
397 unsigned BSId = 4 + (FUZ_rand(&randState) & 3);
398 LZ4F_preferences_t prefs = { { BSId, 0, CCflag, 0,0,0 }, 0,0, 0,0,0,0 };
Yann Collet1ffc02e2014-09-05 16:32:04 +0100399 unsigned nbBits = (FUZ_rand(&randState) % (FUZ_highbit(srcDataLength-1) - 1)) + 1;
400 size_t srcSize = (FUZ_rand(&randState) & ((1<<nbBits)-1)) + 1;
401 size_t srcStart = FUZ_rand(&randState) % (srcDataLength - srcSize);
Yann Collet837551f2014-09-07 09:13:02 +0100402 size_t cSize;
Yann Colletb73b2af2014-09-06 12:19:26 +0100403 U64 crcOrig, crcDecoded;
404
Yann Colletb18d4092014-09-06 22:48:03 +0100405 DISPLAYUPDATE(2, "\r%5i ", testNb);
Yann Colletb73b2af2014-09-06 12:19:26 +0100406 crcOrig = XXH64(srcBuffer+srcStart, srcSize, 1);
Yann Collet837551f2014-09-07 09:13:02 +0100407
408 {
409 const BYTE* ip = srcBuffer + srcStart;
410 const BYTE* const iend = ip + srcSize;
411 BYTE* op = compressedBuffer;
412 BYTE* const oend = op + LZ4F_compressFrameBound(srcDataLength, NULL);
Yann Collet837551f2014-09-07 09:13:02 +0100413 unsigned maxBits = FUZ_highbit(srcSize);
Yann Collet5929de42014-09-07 12:57:09 +0100414 result = LZ4F_compressBegin(cCtx, op, oend-op, &prefs);
Yann Collet837551f2014-09-07 09:13:02 +0100415 CHECK(LZ4F_isError(result), "Compression header failed (error %i)", (int)result);
416 op += result;
417 while (ip < iend)
418 {
Yann Collet3d9d1782014-09-07 12:12:46 +0100419 unsigned nbBitsSeg = FUZ_rand(&randState) % maxBits;
420 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsSeg)-1)) + 1;
Yann Collet837551f2014-09-07 09:13:02 +0100421 size_t oSize = oend-op;
422 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
Yann Collet5929de42014-09-07 12:57:09 +0100423 result = LZ4F_compress(cCtx, op, oSize, ip, iSize, NULL);
Yann Collet837551f2014-09-07 09:13:02 +0100424 CHECK(LZ4F_isError(result), "Compression failed (error %i)", (int)result);
425 op += result;
426 ip += iSize;
427 }
Yann Collet5929de42014-09-07 12:57:09 +0100428 result = LZ4F_compressEnd(cCtx, op, oend-op, NULL);
Yann Collet837551f2014-09-07 09:13:02 +0100429 CHECK(LZ4F_isError(result), "Compression completion failed (error %i)", (int)result);
430 op += result;
Yann Colleta6af48e2014-09-07 11:04:29 +0100431 cSize = op-(BYTE*)compressedBuffer;
Yann Collet837551f2014-09-07 09:13:02 +0100432 }
Yann Colletb18d4092014-09-06 22:48:03 +0100433
434 {
435 const BYTE* ip = compressedBuffer;
436 const BYTE* const iend = ip + cSize;
437 BYTE* op = decodedBuffer;
438 BYTE* const oend = op + srcDataLength;
Yann Collet837551f2014-09-07 09:13:02 +0100439 unsigned maxBits = FUZ_highbit(cSize);
Yann Colletb18d4092014-09-06 22:48:03 +0100440 while (ip < iend)
441 {
Yann Collet3d9d1782014-09-07 12:12:46 +0100442 unsigned nbBitsI = (FUZ_rand(&randState) % (maxBits-1)) + 1;
443 unsigned nbBitsO = (FUZ_rand(&randState) % (maxBits-1)) + 1;
444 size_t iSize = (FUZ_rand(&randState) & ((1<<nbBitsI)-1)) + 1;
445 size_t oSize = (FUZ_rand(&randState) & ((1<<nbBitsO)-1)) + 1;
Yann Colletb18d4092014-09-06 22:48:03 +0100446 if (iSize > (size_t)(iend-ip)) iSize = iend-ip;
Yann Colleta6af48e2014-09-07 11:04:29 +0100447 if (oSize > (size_t)(oend-op)) oSize = oend-op;
Yann Colletb18d4092014-09-06 22:48:03 +0100448 result = LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL);
449 CHECK(LZ4F_isError(result), "Decompression failed (error %i)", (int)result);
450 op += oSize;
451 ip += iSize;
452 }
453 CHECK(result != OK_FrameEnd, "Frame decompression failed (error %i)", (int)result);
Yann Collet837551f2014-09-07 09:13:02 +0100454 crcDecoded = XXH64(decodedBuffer, op-(BYTE*)decodedBuffer, 1);
Yann Colletb18d4092014-09-06 22:48:03 +0100455 CHECK(crcDecoded != crcOrig, "Decompression corruption");
456 }
Yann Collet3d9d1782014-09-07 12:12:46 +0100457
458 (void)FUZ_rand(&coreRand); // update rand seed
Yann Collet1ffc02e2014-09-05 16:32:04 +0100459 }
460
Yann Collet837551f2014-09-07 09:13:02 +0100461 DISPLAYLEVEL(2, "\rAll tests completed \n");
Yann Collet1ffc02e2014-09-05 16:32:04 +0100462
463_end:
Yann Colletda1b0c12014-09-06 13:06:28 +0100464 LZ4F_freeDecompressionContext(dCtx);
Yann Collet5929de42014-09-07 12:57:09 +0100465 LZ4F_freeCompressionContext(cCtx);
Yann Collet1ffc02e2014-09-05 16:32:04 +0100466 free(srcBuffer);
467 free(compressedBuffer);
468 free(decodedBuffer);
469 return testResult;
470
471_output_error:
472 testResult = 1;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100473 goto _end;
474}
475
476
Yann Colletdb4c0122014-08-30 18:14:44 +0100477int FUZ_usage(void)
478{
479 DISPLAY( "Usage :\n");
480 DISPLAY( " %s [args]\n", programName);
481 DISPLAY( "\n");
482 DISPLAY( "Arguments :\n");
Yann Collet837551f2014-09-07 09:13:02 +0100483 DISPLAY( " -i# : Nb of tests (default:%i) \n", nbTestsDefault);
Yann Colletdb4c0122014-08-30 18:14:44 +0100484 DISPLAY( " -s# : Select seed (default:prompt user)\n");
485 DISPLAY( " -t# : Select starting test number (default:0)\n");
486 DISPLAY( " -p# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
487 DISPLAY( " -v : verbose\n");
488 DISPLAY( " -h : display help and exit\n");
489 return 0;
490}
491
492
Yann Colletfc8e3f52014-09-01 22:44:02 +0100493int main(int argc, char** argv)
494{
Yann Colletdb4c0122014-08-30 18:14:44 +0100495 U32 seed=0;
496 int seedset=0;
497 int argNb;
Yann Collet837551f2014-09-07 09:13:02 +0100498 int nbTests = nbTestsDefault;
Yann Colletdb4c0122014-08-30 18:14:44 +0100499 int testNb = 0;
500 int proba = FUZ_COMPRESSIBILITY_DEFAULT;
501
502 // Check command line
503 programName = argv[0];
504 for(argNb=1; argNb<argc; argNb++)
505 {
506 char* argument = argv[argNb];
507
508 if(!argument) continue; // Protection if argument empty
509
510 // Decode command (note : aggregated commands are allowed)
511 if (argument[0]=='-')
512 {
513 if (!strcmp(argument, "--no-prompt")) { no_prompt=1; seedset=1; displayLevel=1; continue; }
514
515 while (argument[1]!=0)
516 {
517 argument++;
518 switch(*argument)
519 {
520 case 'h':
521 return FUZ_usage();
522 case 'v':
523 argument++;
524 displayLevel=4;
525 break;
Yann Collet1ffc02e2014-09-05 16:32:04 +0100526 case 'q':
527 argument++;
528 displayLevel--;
529 break;
Yann Colletdb4c0122014-08-30 18:14:44 +0100530 case 'i':
531 argument++;
532 nbTests=0;
533 while ((*argument>='0') && (*argument<='9'))
534 {
535 nbTests *= 10;
536 nbTests += *argument - '0';
537 argument++;
538 }
539 break;
540 case 's':
541 argument++;
542 seed=0; seedset=1;
543 while ((*argument>='0') && (*argument<='9'))
544 {
545 seed *= 10;
546 seed += *argument - '0';
547 argument++;
548 }
549 break;
550 case 't':
551 argument++;
552 testNb=0;
553 while ((*argument>='0') && (*argument<='9'))
554 {
555 testNb *= 10;
556 testNb += *argument - '0';
557 argument++;
558 }
559 break;
560 case 'p':
561 argument++;
562 proba=0;
563 while ((*argument>='0') && (*argument<='9'))
564 {
565 proba *= 10;
566 proba += *argument - '0';
567 argument++;
568 }
569 if (proba<0) proba=0;
570 if (proba>100) proba=100;
571 break;
572 default: ;
573 }
574 }
575 }
576 }
577
578 // Get Seed
579 printf("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
580
Yann Colletfc8e3f52014-09-01 22:44:02 +0100581 if (!seedset) seed = FUZ_GetMilliStart() % 10000;
Yann Colletdb4c0122014-08-30 18:14:44 +0100582 printf("Seed = %u\n", seed);
583 if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba);
584
585 if (nbTests<=0) nbTests=1;
586
Yann Collet1ffc02e2014-09-05 16:32:04 +0100587 basicTests(seed, nbTests, testNb, ((double)proba) / 100);
588 return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
Yann Colletdb4c0122014-08-30 18:14:44 +0100589}