1 #include <stddef.h>
2 #include <stdint.h>
3 #include <stdlib.h>  // malloc
4 #include <stdio.h>
5 #include <assert.h>
6 
7 #include "zstd_seekable.h"
8 
9 /* Basic unit tests for zstd seekable format */
main(int argc,const char ** argv)10 int main(int argc, const char** argv)
11 {
12     unsigned testNb = 1;
13     (void)argc; (void)argv;
14     printf("Beginning zstd seekable format tests...\n");
15 
16     printf("Test %u - simple round trip: ", testNb++);
17     {   size_t const inSize = 4000;
18         void* const inBuffer = malloc(inSize);
19         assert(inBuffer != NULL);
20 
21         size_t const seekCapacity = 5000;
22         void* const seekBuffer = malloc(seekCapacity);
23         assert(seekBuffer != NULL);
24         size_t seekSize;
25 
26         size_t const outCapacity = inSize;
27         void* const outBuffer = malloc(outCapacity);
28         assert(outBuffer != NULL);
29 
30         ZSTD_seekable_CStream* const zscs = ZSTD_seekable_createCStream();
31         assert(zscs != NULL);
32 
33         { size_t const initStatus = ZSTD_seekable_initCStream(zscs, 9, 0 /* checksumFlag */, (unsigned)inSize /* maxFrameSize */);
34           assert(!ZSTD_isError(initStatus));
35         }
36 
37         {   ZSTD_outBuffer outb = { .dst=seekBuffer, .pos=0, .size=seekCapacity };
38             ZSTD_inBuffer inb = { .src=inBuffer, .pos=0, .size=inSize };
39 
40             size_t const cStatus = ZSTD_seekable_compressStream(zscs, &outb, &inb);
41             assert(!ZSTD_isError(cStatus));
42             assert(inb.pos == inb.size);
43 
44             size_t const endStatus = ZSTD_seekable_endStream(zscs, &outb);
45             assert(!ZSTD_isError(endStatus));
46             seekSize = outb.pos;
47         }
48 
49         ZSTD_seekable* const stream = ZSTD_seekable_create();
50         assert(stream != NULL);
51         { size_t const initStatus = ZSTD_seekable_initBuff(stream, seekBuffer, seekSize);
52           assert(!ZSTD_isError(initStatus)); }
53 
54         { size_t const decStatus = ZSTD_seekable_decompress(stream, outBuffer, outCapacity, 0);
55           assert(decStatus == inSize); }
56 
57         /* unit test ZSTD_seekTable functions */
58         ZSTD_seekTable* const zst = ZSTD_seekTable_create_fromSeekable(stream);
59         assert(zst != NULL);
60 
61         unsigned const nbFrames = ZSTD_seekTable_getNumFrames(zst);
62         assert(nbFrames > 0);
63 
64         unsigned long long const frame0Offset = ZSTD_seekTable_getFrameCompressedOffset(zst, 0);
65         assert(frame0Offset == 0);
66 
67         unsigned long long const content0Offset = ZSTD_seekTable_getFrameDecompressedOffset(zst, 0);
68         assert(content0Offset == 0);
69 
70         size_t const cSize = ZSTD_seekTable_getFrameCompressedSize(zst, 0);
71         assert(!ZSTD_isError(cSize));
72         assert(cSize <= seekCapacity);
73 
74         size_t const origSize = ZSTD_seekTable_getFrameDecompressedSize(zst, 0);
75         assert(origSize == inSize);
76 
77         unsigned const fo1idx = ZSTD_seekTable_offsetToFrameIndex(zst, 1);
78         assert(fo1idx == 0);
79 
80         free(inBuffer);
81         free(seekBuffer);
82         free(outBuffer);
83         ZSTD_seekable_freeCStream(zscs);
84         ZSTD_seekTable_free(zst);
85         ZSTD_seekable_free(stream);
86     }
87     printf("Success!\n");
88 
89 
90     printf("Test %u - check that seekable decompress does not hang: ", testNb++);
91     {   /* Github issue #2335 */
92         const size_t compressed_size = 17;
93         const uint8_t compressed_data[17] = {
94             '^',
95             '*',
96             'M',
97             '\x18',
98             '\t',
99             '\x00',
100             '\x00',
101             '\x00',
102             '\x00',
103             '\x00',
104             '\x00',
105             '\x00',
106             (uint8_t)('\x03'),
107             (uint8_t)('\xb1'),
108             (uint8_t)('\xea'),
109             (uint8_t)('\x92'),
110             (uint8_t)('\x8f'),
111         };
112         const size_t uncompressed_size = 32;
113         uint8_t uncompressed_data[32];
114 
115         ZSTD_seekable* const stream = ZSTD_seekable_create();
116         assert(stream != NULL);
117         {   size_t const status = ZSTD_seekable_initBuff(stream, compressed_data, compressed_size);
118             if (ZSTD_isError(status)) {
119                 ZSTD_seekable_free(stream);
120                 goto _test_error;
121         }   }
122 
123         /* Should return an error, but not hang */
124         {   const size_t offset = 2;
125             size_t const status = ZSTD_seekable_decompress(stream, uncompressed_data, uncompressed_size, offset);
126             if (!ZSTD_isError(status)) {
127                 ZSTD_seekable_free(stream);
128                 goto _test_error;
129         }   }
130 
131         ZSTD_seekable_free(stream);
132     }
133     printf("Success!\n");
134 
135     printf("Test %u - check #2 that seekable decompress does not hang: ", testNb++);
136     {   /* Github issue #FIXME */
137         const size_t compressed_size = 27;
138         const uint8_t compressed_data[27] = {
139             (uint8_t)'\x28',
140             (uint8_t)'\xb5',
141             (uint8_t)'\x2f',
142             (uint8_t)'\xfd',
143             (uint8_t)'\x00',
144             (uint8_t)'\x32',
145             (uint8_t)'\x91',
146             (uint8_t)'\x00',
147             (uint8_t)'\x00',
148             (uint8_t)'\x00',
149             (uint8_t)'\x5e',
150             (uint8_t)'\x2a',
151             (uint8_t)'\x4d',
152             (uint8_t)'\x18',
153             (uint8_t)'\x09',
154             (uint8_t)'\x00',
155             (uint8_t)'\x00',
156             (uint8_t)'\x00',
157             (uint8_t)'\x00',
158             (uint8_t)'\x00',
159             (uint8_t)'\x00',
160             (uint8_t)'\x00',
161             (uint8_t)'\x00',
162             (uint8_t)'\xb1',
163             (uint8_t)'\xea',
164             (uint8_t)'\x92',
165             (uint8_t)'\x8f',
166         };
167         const size_t uncompressed_size = 400;
168         uint8_t uncompressed_data[400];
169 
170         ZSTD_seekable* stream = ZSTD_seekable_create();
171         size_t status = ZSTD_seekable_initBuff(stream, compressed_data, compressed_size);
172         if (ZSTD_isError(status)) {
173             ZSTD_seekable_free(stream);
174             goto _test_error;
175         }
176 
177         const size_t offset = 2;
178         /* Should return an error, but not hang */
179         status = ZSTD_seekable_decompress(stream, uncompressed_data, uncompressed_size, offset);
180         if (!ZSTD_isError(status)) {
181             ZSTD_seekable_free(stream);
182             goto _test_error;
183         }
184 
185         ZSTD_seekable_free(stream);
186     }
187     printf("Success!\n");
188 
189     /* TODO: Add more tests */
190     printf("Finished tests\n");
191     return 0;
192 
193 _test_error:
194     printf("test failed! Exiting..\n");
195     return 1;
196 }
197