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