xref: /aosp_15_r20/external/lz4/tests/abiTest.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker /*
2*27162e4eSAndroid Build Coastguard Worker  * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3*27162e4eSAndroid Build Coastguard Worker  * All rights reserved.
4*27162e4eSAndroid Build Coastguard Worker  *
5*27162e4eSAndroid Build Coastguard Worker  * This source code is licensed under both the BSD-style license (found in the
6*27162e4eSAndroid Build Coastguard Worker  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*27162e4eSAndroid Build Coastguard Worker  * in the COPYING file in the root directory of this source tree),
8*27162e4eSAndroid Build Coastguard Worker  * meaning you may select, at your option, one of the above-listed licenses.
9*27162e4eSAndroid Build Coastguard Worker  */
10*27162e4eSAndroid Build Coastguard Worker 
11*27162e4eSAndroid Build Coastguard Worker /*
12*27162e4eSAndroid Build Coastguard Worker  * abiTest :
13*27162e4eSAndroid Build Coastguard Worker  * ensure ABI stability expectations are not broken by a new version
14*27162e4eSAndroid Build Coastguard Worker **/
15*27162e4eSAndroid Build Coastguard Worker 
16*27162e4eSAndroid Build Coastguard Worker 
17*27162e4eSAndroid Build Coastguard Worker /*===========================================
18*27162e4eSAndroid Build Coastguard Worker *   Dependencies
19*27162e4eSAndroid Build Coastguard Worker *==========================================*/
20*27162e4eSAndroid Build Coastguard Worker #include <stddef.h>     /* size_t */
21*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h>     /* malloc, free, exit */
22*27162e4eSAndroid Build Coastguard Worker #include <stdio.h>      /* fprintf */
23*27162e4eSAndroid Build Coastguard Worker #include <string.h>     /* strcmp */
24*27162e4eSAndroid Build Coastguard Worker #include <assert.h>
25*27162e4eSAndroid Build Coastguard Worker #include <sys/types.h>  /* stat */
26*27162e4eSAndroid Build Coastguard Worker #include <sys/stat.h>   /* stat */
27*27162e4eSAndroid Build Coastguard Worker #include "xxhash.h"
28*27162e4eSAndroid Build Coastguard Worker 
29*27162e4eSAndroid Build Coastguard Worker #include "lz4.h"
30*27162e4eSAndroid Build Coastguard Worker #include "lz4frame.h"
31*27162e4eSAndroid Build Coastguard Worker 
32*27162e4eSAndroid Build Coastguard Worker 
33*27162e4eSAndroid Build Coastguard Worker /*===========================================
34*27162e4eSAndroid Build Coastguard Worker *   Macros
35*27162e4eSAndroid Build Coastguard Worker *==========================================*/
36*27162e4eSAndroid Build Coastguard Worker #define MIN(a,b)  ( (a) < (b) ? (a) : (b) )
37*27162e4eSAndroid Build Coastguard Worker 
38*27162e4eSAndroid Build Coastguard Worker #define MSG(...)    fprintf(stderr, __VA_ARGS__)
39*27162e4eSAndroid Build Coastguard Worker 
40*27162e4eSAndroid Build Coastguard Worker #define CONTROL_MSG(c, ...) {   \
41*27162e4eSAndroid Build Coastguard Worker     if ((c)) {                  \
42*27162e4eSAndroid Build Coastguard Worker         MSG(__VA_ARGS__);       \
43*27162e4eSAndroid Build Coastguard Worker         MSG(" \n");             \
44*27162e4eSAndroid Build Coastguard Worker         abort();                \
45*27162e4eSAndroid Build Coastguard Worker     }                           \
46*27162e4eSAndroid Build Coastguard Worker }
47*27162e4eSAndroid Build Coastguard Worker 
48*27162e4eSAndroid Build Coastguard Worker 
checkBuffers(const void * buff1,const void * buff2,size_t buffSize)49*27162e4eSAndroid Build Coastguard Worker static size_t checkBuffers(const void* buff1, const void* buff2, size_t buffSize)
50*27162e4eSAndroid Build Coastguard Worker {
51*27162e4eSAndroid Build Coastguard Worker     const char* const ip1 = (const char*)buff1;
52*27162e4eSAndroid Build Coastguard Worker     const char* const ip2 = (const char*)buff2;
53*27162e4eSAndroid Build Coastguard Worker     size_t pos;
54*27162e4eSAndroid Build Coastguard Worker 
55*27162e4eSAndroid Build Coastguard Worker     for (pos=0; pos<buffSize; pos++)
56*27162e4eSAndroid Build Coastguard Worker         if (ip1[pos]!=ip2[pos])
57*27162e4eSAndroid Build Coastguard Worker             break;
58*27162e4eSAndroid Build Coastguard Worker 
59*27162e4eSAndroid Build Coastguard Worker     return pos;
60*27162e4eSAndroid Build Coastguard Worker }
61*27162e4eSAndroid Build Coastguard Worker 
62*27162e4eSAndroid Build Coastguard Worker 
63*27162e4eSAndroid Build Coastguard Worker LZ4_stream_t LZ4_cState;
64*27162e4eSAndroid Build Coastguard Worker LZ4_streamDecode_t LZ4_dState;
65*27162e4eSAndroid Build Coastguard Worker 
66*27162e4eSAndroid Build Coastguard Worker /** roundTripTest() :
67*27162e4eSAndroid Build Coastguard Worker  *  Compresses `srcBuff` into `compressedBuff`,
68*27162e4eSAndroid Build Coastguard Worker  *  then decompresses `compressedBuff` into `resultBuff`.
69*27162e4eSAndroid Build Coastguard Worker  *  If clevel==0, compression level is derived from srcBuff's content head bytes.
70*27162e4eSAndroid Build Coastguard Worker  *  This function abort() if it detects any round-trip error.
71*27162e4eSAndroid Build Coastguard Worker  *  Therefore, if it returns, round trip is considered successfully validated.
72*27162e4eSAndroid Build Coastguard Worker  *  Note : `compressedBuffCapacity` should be `>= LZ4_compressBound(srcSize)`
73*27162e4eSAndroid Build Coastguard Worker  *         for compression to be guaranteed to work */
roundTripTest(void * resultBuff,size_t resultBuffCapacity,void * compressedBuff,size_t compressedBuffCapacity,const void * srcBuff,size_t srcSize)74*27162e4eSAndroid Build Coastguard Worker static void roundTripTest(void* resultBuff, size_t resultBuffCapacity,
75*27162e4eSAndroid Build Coastguard Worker                           void* compressedBuff, size_t compressedBuffCapacity,
76*27162e4eSAndroid Build Coastguard Worker                     const void* srcBuff, size_t srcSize)
77*27162e4eSAndroid Build Coastguard Worker {
78*27162e4eSAndroid Build Coastguard Worker     int const acceleration = 1;
79*27162e4eSAndroid Build Coastguard Worker     // Note : can't use LZ4_initStream(), because it's only present since v1.9.0
80*27162e4eSAndroid Build Coastguard Worker     memset(&LZ4_cState, 0, sizeof(LZ4_cState));
81*27162e4eSAndroid Build Coastguard Worker     {   int const cSize = LZ4_compress_fast_continue(&LZ4_cState, (const char*)srcBuff, (char*)compressedBuff, (int)srcSize, (int)compressedBuffCapacity, acceleration);
82*27162e4eSAndroid Build Coastguard Worker         CONTROL_MSG(cSize == 0, "Compression error !");
83*27162e4eSAndroid Build Coastguard Worker         {   int const dInit = LZ4_setStreamDecode(&LZ4_dState, NULL, 0);
84*27162e4eSAndroid Build Coastguard Worker             CONTROL_MSG(dInit == 0, "LZ4_setStreamDecode error !");
85*27162e4eSAndroid Build Coastguard Worker         }
86*27162e4eSAndroid Build Coastguard Worker         {   int const dSize = LZ4_decompress_safe_continue (&LZ4_dState, (const char*)compressedBuff, (char*)resultBuff, cSize, (int)resultBuffCapacity);
87*27162e4eSAndroid Build Coastguard Worker             CONTROL_MSG(dSize < 0, "Decompression detected an error !");
88*27162e4eSAndroid Build Coastguard Worker             CONTROL_MSG(dSize != (int)srcSize, "Decompression corruption error : wrong decompressed size !");
89*27162e4eSAndroid Build Coastguard Worker     }   }
90*27162e4eSAndroid Build Coastguard Worker 
91*27162e4eSAndroid Build Coastguard Worker     /* check potential content corruption error */
92*27162e4eSAndroid Build Coastguard Worker     assert(resultBuffCapacity >= srcSize);
93*27162e4eSAndroid Build Coastguard Worker     {   size_t const errorPos = checkBuffers(srcBuff, resultBuff, srcSize);
94*27162e4eSAndroid Build Coastguard Worker         CONTROL_MSG(errorPos != srcSize,
95*27162e4eSAndroid Build Coastguard Worker                     "Silent decoding corruption, at pos %u !!!",
96*27162e4eSAndroid Build Coastguard Worker                     (unsigned)errorPos);
97*27162e4eSAndroid Build Coastguard Worker     }
98*27162e4eSAndroid Build Coastguard Worker }
99*27162e4eSAndroid Build Coastguard Worker 
roundTripCheck(const void * srcBuff,size_t srcSize)100*27162e4eSAndroid Build Coastguard Worker static void roundTripCheck(const void* srcBuff, size_t srcSize)
101*27162e4eSAndroid Build Coastguard Worker {
102*27162e4eSAndroid Build Coastguard Worker     size_t const cBuffSize = LZ4_COMPRESSBOUND(srcSize);
103*27162e4eSAndroid Build Coastguard Worker     void* const cBuff = malloc(cBuffSize);
104*27162e4eSAndroid Build Coastguard Worker     void* const rBuff = malloc(cBuffSize);
105*27162e4eSAndroid Build Coastguard Worker 
106*27162e4eSAndroid Build Coastguard Worker     if (!cBuff || !rBuff) {
107*27162e4eSAndroid Build Coastguard Worker         fprintf(stderr, "not enough memory ! \n");
108*27162e4eSAndroid Build Coastguard Worker         exit(1);
109*27162e4eSAndroid Build Coastguard Worker     }
110*27162e4eSAndroid Build Coastguard Worker 
111*27162e4eSAndroid Build Coastguard Worker     roundTripTest(rBuff, cBuffSize,
112*27162e4eSAndroid Build Coastguard Worker                   cBuff, cBuffSize,
113*27162e4eSAndroid Build Coastguard Worker                   srcBuff, srcSize);
114*27162e4eSAndroid Build Coastguard Worker 
115*27162e4eSAndroid Build Coastguard Worker     free(rBuff);
116*27162e4eSAndroid Build Coastguard Worker     free(cBuff);
117*27162e4eSAndroid Build Coastguard Worker }
118*27162e4eSAndroid Build Coastguard Worker 
119*27162e4eSAndroid Build Coastguard Worker 
getFileSize(const char * infilename)120*27162e4eSAndroid Build Coastguard Worker static size_t getFileSize(const char* infilename)
121*27162e4eSAndroid Build Coastguard Worker {
122*27162e4eSAndroid Build Coastguard Worker     int r;
123*27162e4eSAndroid Build Coastguard Worker #if defined(_MSC_VER)
124*27162e4eSAndroid Build Coastguard Worker     struct _stat64 statbuf;
125*27162e4eSAndroid Build Coastguard Worker     r = _stat64(infilename, &statbuf);
126*27162e4eSAndroid Build Coastguard Worker     if (r || !(statbuf.st_mode & S_IFREG)) return 0;   /* No good... */
127*27162e4eSAndroid Build Coastguard Worker #else
128*27162e4eSAndroid Build Coastguard Worker     struct stat statbuf;
129*27162e4eSAndroid Build Coastguard Worker     r = stat(infilename, &statbuf);
130*27162e4eSAndroid Build Coastguard Worker     if (r || !S_ISREG(statbuf.st_mode)) return 0;   /* No good... */
131*27162e4eSAndroid Build Coastguard Worker #endif
132*27162e4eSAndroid Build Coastguard Worker     return (size_t)statbuf.st_size;
133*27162e4eSAndroid Build Coastguard Worker }
134*27162e4eSAndroid Build Coastguard Worker 
135*27162e4eSAndroid Build Coastguard Worker 
isDirectory(const char * infilename)136*27162e4eSAndroid Build Coastguard Worker static int isDirectory(const char* infilename)
137*27162e4eSAndroid Build Coastguard Worker {
138*27162e4eSAndroid Build Coastguard Worker     int r;
139*27162e4eSAndroid Build Coastguard Worker #if defined(_MSC_VER)
140*27162e4eSAndroid Build Coastguard Worker     struct _stat64 statbuf;
141*27162e4eSAndroid Build Coastguard Worker     r = _stat64(infilename, &statbuf);
142*27162e4eSAndroid Build Coastguard Worker     if (!r && (statbuf.st_mode & _S_IFDIR)) return 1;
143*27162e4eSAndroid Build Coastguard Worker #else
144*27162e4eSAndroid Build Coastguard Worker     struct stat statbuf;
145*27162e4eSAndroid Build Coastguard Worker     r = stat(infilename, &statbuf);
146*27162e4eSAndroid Build Coastguard Worker     if (!r && S_ISDIR(statbuf.st_mode)) return 1;
147*27162e4eSAndroid Build Coastguard Worker #endif
148*27162e4eSAndroid Build Coastguard Worker     return 0;
149*27162e4eSAndroid Build Coastguard Worker }
150*27162e4eSAndroid Build Coastguard Worker 
151*27162e4eSAndroid Build Coastguard Worker 
152*27162e4eSAndroid Build Coastguard Worker /** loadFile() :
153*27162e4eSAndroid Build Coastguard Worker  *  requirement : `buffer` size >= `fileSize` */
loadFile(void * buffer,const char * fileName,size_t fileSize)154*27162e4eSAndroid Build Coastguard Worker static void loadFile(void* buffer, const char* fileName, size_t fileSize)
155*27162e4eSAndroid Build Coastguard Worker {
156*27162e4eSAndroid Build Coastguard Worker     FILE* const f = fopen(fileName, "rb");
157*27162e4eSAndroid Build Coastguard Worker     if (isDirectory(fileName)) {
158*27162e4eSAndroid Build Coastguard Worker         MSG("Ignoring %s directory \n", fileName);
159*27162e4eSAndroid Build Coastguard Worker         exit(2);
160*27162e4eSAndroid Build Coastguard Worker     }
161*27162e4eSAndroid Build Coastguard Worker     if (f==NULL) {
162*27162e4eSAndroid Build Coastguard Worker         MSG("Impossible to open %s \n", fileName);
163*27162e4eSAndroid Build Coastguard Worker         exit(3);
164*27162e4eSAndroid Build Coastguard Worker     }
165*27162e4eSAndroid Build Coastguard Worker     {   size_t const readSize = fread(buffer, 1, fileSize, f);
166*27162e4eSAndroid Build Coastguard Worker         if (readSize != fileSize) {
167*27162e4eSAndroid Build Coastguard Worker             MSG("Error reading %s \n", fileName);
168*27162e4eSAndroid Build Coastguard Worker             exit(5);
169*27162e4eSAndroid Build Coastguard Worker     }   }
170*27162e4eSAndroid Build Coastguard Worker     fclose(f);
171*27162e4eSAndroid Build Coastguard Worker }
172*27162e4eSAndroid Build Coastguard Worker 
173*27162e4eSAndroid Build Coastguard Worker 
fileCheck(const char * fileName)174*27162e4eSAndroid Build Coastguard Worker static void fileCheck(const char* fileName)
175*27162e4eSAndroid Build Coastguard Worker {
176*27162e4eSAndroid Build Coastguard Worker     size_t const fileSize = getFileSize(fileName);
177*27162e4eSAndroid Build Coastguard Worker     void* const buffer = malloc(fileSize + !fileSize /* avoid 0 */);
178*27162e4eSAndroid Build Coastguard Worker     if (!buffer) {
179*27162e4eSAndroid Build Coastguard Worker         MSG("not enough memory \n");
180*27162e4eSAndroid Build Coastguard Worker         exit(4);
181*27162e4eSAndroid Build Coastguard Worker     }
182*27162e4eSAndroid Build Coastguard Worker     loadFile(buffer, fileName, fileSize);
183*27162e4eSAndroid Build Coastguard Worker     roundTripCheck(buffer, fileSize);
184*27162e4eSAndroid Build Coastguard Worker     free (buffer);
185*27162e4eSAndroid Build Coastguard Worker }
186*27162e4eSAndroid Build Coastguard Worker 
187*27162e4eSAndroid Build Coastguard Worker 
bad_usage(const char * exeName)188*27162e4eSAndroid Build Coastguard Worker int bad_usage(const char* exeName)
189*27162e4eSAndroid Build Coastguard Worker {
190*27162e4eSAndroid Build Coastguard Worker     MSG(" \n");
191*27162e4eSAndroid Build Coastguard Worker     MSG("bad usage: \n");
192*27162e4eSAndroid Build Coastguard Worker     MSG(" \n");
193*27162e4eSAndroid Build Coastguard Worker     MSG("%s [Options] fileName \n", exeName);
194*27162e4eSAndroid Build Coastguard Worker     MSG(" \n");
195*27162e4eSAndroid Build Coastguard Worker     MSG("Options: \n");
196*27162e4eSAndroid Build Coastguard Worker     MSG("-#     : use #=[0-9] compression level (default:0 == random) \n");
197*27162e4eSAndroid Build Coastguard Worker     return 1;
198*27162e4eSAndroid Build Coastguard Worker }
199*27162e4eSAndroid Build Coastguard Worker 
200*27162e4eSAndroid Build Coastguard Worker 
main(int argCount,const char ** argv)201*27162e4eSAndroid Build Coastguard Worker int main(int argCount, const char** argv)
202*27162e4eSAndroid Build Coastguard Worker {
203*27162e4eSAndroid Build Coastguard Worker     const char* const exeName = argv[0];
204*27162e4eSAndroid Build Coastguard Worker     int argNb = 1;
205*27162e4eSAndroid Build Coastguard Worker     // Note : LZ4_VERSION_STRING requires >= v1.7.3+
206*27162e4eSAndroid Build Coastguard Worker     MSG("abiTest, built binary based on API %s \n", LZ4_VERSION_STRING);
207*27162e4eSAndroid Build Coastguard Worker     // Note : LZ4_versionString() requires >= v1.7.5+
208*27162e4eSAndroid Build Coastguard Worker     MSG("currently linked to dll %s \n", LZ4_versionString());
209*27162e4eSAndroid Build Coastguard Worker 
210*27162e4eSAndroid Build Coastguard Worker     assert(argCount >= 1);
211*27162e4eSAndroid Build Coastguard Worker     if (argCount < 2) return bad_usage(exeName);
212*27162e4eSAndroid Build Coastguard Worker 
213*27162e4eSAndroid Build Coastguard Worker     if (argNb >= argCount) return bad_usage(exeName);
214*27162e4eSAndroid Build Coastguard Worker 
215*27162e4eSAndroid Build Coastguard Worker     fileCheck(argv[argNb]);
216*27162e4eSAndroid Build Coastguard Worker     MSG("no pb detected \n");
217*27162e4eSAndroid Build Coastguard Worker     return 0;
218*27162e4eSAndroid Build Coastguard Worker }
219