Yann Collet | 32fb407 | 2017-08-18 16:52:05 -0700 | [diff] [blame] | 1 | /* |
Nick Terrell | a494308 | 2021-03-29 14:23:36 -0700 | [diff] [blame] | 2 | * Copyright (c) Yann Collet, Facebook, Inc. |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 3 | * All rights reserved. |
| 4 | * |
Yann Collet | 32fb407 | 2017-08-18 16:52:05 -0700 | [diff] [blame] | 5 | * This source code is licensed under both the BSD-style license (found in the |
| 6 | * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| 7 | * in the COPYING file in the root directory of this source tree). |
Yann Collet | 3128e03 | 2017-09-08 00:09:23 -0700 | [diff] [blame] | 8 | * You may select, at your option, one of the above-listed licenses. |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 9 | */ |
| 10 | |
| 11 | /* |
| 12 | This program uses hard-coded data compressed with Zstd legacy versions |
| 13 | and tests that the API decompresses them correctly |
| 14 | */ |
| 15 | |
| 16 | /*=========================================== |
| 17 | * Dependencies |
| 18 | *==========================================*/ |
shakeelrao | 4c0540d | 2019-03-15 05:13:55 -0700 | [diff] [blame] | 19 | #include <stddef.h> /* size_t */ |
| 20 | #include <stdlib.h> /* malloc, free */ |
| 21 | #include <stdio.h> /* fprintf */ |
| 22 | #include <string.h> /* strlen */ |
| 23 | #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_decompressBound */ |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 24 | #include "zstd.h" |
| 25 | #include "zstd_errors.h" |
| 26 | |
| 27 | /*=========================================== |
| 28 | * Macros |
| 29 | *==========================================*/ |
| 30 | #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) |
| 31 | |
| 32 | /*=========================================== |
| 33 | * Precompressed frames |
| 34 | *==========================================*/ |
| 35 | const char* const COMPRESSED; /* content is at end of file */ |
| 36 | size_t const COMPRESSED_SIZE = 917; |
| 37 | const char* const EXPECTED; /* content is at end of file */ |
| 38 | |
| 39 | |
Yann Collet | 73773c6 | 2018-09-27 18:15:14 -0700 | [diff] [blame] | 40 | static int testSimpleAPI(void) |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 41 | { |
| 42 | size_t const size = strlen(EXPECTED); |
| 43 | char* const output = malloc(size); |
| 44 | |
| 45 | if (!output) { |
| 46 | DISPLAY("ERROR: Not enough memory!\n"); |
| 47 | return 1; |
| 48 | } |
| 49 | |
| 50 | { |
| 51 | size_t const ret = ZSTD_decompress(output, size, COMPRESSED, COMPRESSED_SIZE); |
| 52 | if (ZSTD_isError(ret)) { |
| 53 | if (ret == ZSTD_error_prefix_unknown) { |
| 54 | DISPLAY("ERROR: Invalid frame magic number, was this compiled " |
| 55 | "without legacy support?\n"); |
| 56 | } else { |
| 57 | DISPLAY("ERROR: %s\n", ZSTD_getErrorName(ret)); |
| 58 | } |
| 59 | return 1; |
| 60 | } |
| 61 | if (ret != size) { |
| 62 | DISPLAY("ERROR: Wrong decoded size\n"); |
| 63 | } |
| 64 | } |
| 65 | if (memcmp(EXPECTED, output, size) != 0) { |
| 66 | DISPLAY("ERROR: Wrong decoded output produced\n"); |
| 67 | return 1; |
| 68 | } |
| 69 | |
Przemyslaw Skibinski | 346ce32 | 2017-02-21 20:10:21 +0100 | [diff] [blame] | 70 | free(output); |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 71 | DISPLAY("Simple API OK\n"); |
| 72 | return 0; |
| 73 | } |
| 74 | |
Yann Collet | 73773c6 | 2018-09-27 18:15:14 -0700 | [diff] [blame] | 75 | |
| 76 | static int testStreamingAPI(void) |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 77 | { |
Lzu Tao | 260ff2f | 2019-01-06 23:42:24 +0700 | [diff] [blame] | 78 | int error_code = 0; |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 79 | size_t const outBuffSize = ZSTD_DStreamOutSize(); |
| 80 | char* const outBuff = malloc(outBuffSize); |
| 81 | ZSTD_DStream* const stream = ZSTD_createDStream(); |
| 82 | ZSTD_inBuffer input = { COMPRESSED, COMPRESSED_SIZE, 0 }; |
| 83 | size_t outputPos = 0; |
| 84 | int needsInit = 1; |
| 85 | |
| 86 | if (outBuff == NULL) { |
| 87 | DISPLAY("ERROR: Could not allocate memory\n"); |
| 88 | return 1; |
| 89 | } |
| 90 | if (stream == NULL) { |
| 91 | DISPLAY("ERROR: Could not create dstream\n"); |
Lzu Tao | de7e3be | 2019-01-06 23:28:38 +0700 | [diff] [blame] | 92 | free(outBuff); |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 93 | return 1; |
| 94 | } |
| 95 | |
| 96 | while (1) { |
| 97 | ZSTD_outBuffer output = {outBuff, outBuffSize, 0}; |
| 98 | if (needsInit) { |
| 99 | size_t const ret = ZSTD_initDStream(stream); |
| 100 | if (ZSTD_isError(ret)) { |
Yann Collet | e0cb8d1 | 2018-03-20 17:48:22 -0700 | [diff] [blame] | 101 | DISPLAY("ERROR: ZSTD_initDStream: %s\n", ZSTD_getErrorName(ret)); |
Lzu Tao | 260ff2f | 2019-01-06 23:42:24 +0700 | [diff] [blame] | 102 | error_code = 1; |
| 103 | break; |
Yann Collet | e0cb8d1 | 2018-03-20 17:48:22 -0700 | [diff] [blame] | 104 | } } |
| 105 | |
Yann Collet | e0cb8d1 | 2018-03-20 17:48:22 -0700 | [diff] [blame] | 106 | { size_t const ret = ZSTD_decompressStream(stream, &output, &input); |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 107 | if (ZSTD_isError(ret)) { |
Yann Collet | e0cb8d1 | 2018-03-20 17:48:22 -0700 | [diff] [blame] | 108 | DISPLAY("ERROR: ZSTD_decompressStream: %s\n", ZSTD_getErrorName(ret)); |
Lzu Tao | 260ff2f | 2019-01-06 23:42:24 +0700 | [diff] [blame] | 109 | error_code = 1; |
| 110 | break; |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | if (ret == 0) { |
| 114 | needsInit = 1; |
Yann Collet | e0cb8d1 | 2018-03-20 17:48:22 -0700 | [diff] [blame] | 115 | } } |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 116 | |
| 117 | if (memcmp(outBuff, EXPECTED + outputPos, output.pos) != 0) { |
| 118 | DISPLAY("ERROR: Wrong decoded output produced\n"); |
Lzu Tao | 260ff2f | 2019-01-06 23:42:24 +0700 | [diff] [blame] | 119 | error_code = 1; |
| 120 | break; |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 121 | } |
| 122 | outputPos += output.pos; |
| 123 | if (input.pos == input.size && output.pos < output.size) { |
| 124 | break; |
| 125 | } |
| 126 | } |
| 127 | |
Przemyslaw Skibinski | 346ce32 | 2017-02-21 20:10:21 +0100 | [diff] [blame] | 128 | free(outBuff); |
| 129 | ZSTD_freeDStream(stream); |
Lzu Tao | 260ff2f | 2019-01-06 23:42:24 +0700 | [diff] [blame] | 130 | if (error_code == 0) DISPLAY("Streaming API OK\n"); |
| 131 | return error_code; |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 132 | } |
| 133 | |
shakeelrao | 91ffc8d | 2019-03-15 03:59:03 -0700 | [diff] [blame] | 134 | static int testFrameDecoding(void) |
| 135 | { |
shakeelrao | 60796e7 | 2019-03-15 16:10:37 -0700 | [diff] [blame] | 136 | if (strlen(EXPECTED) > ZSTD_decompressBound(COMPRESSED, COMPRESSED_SIZE)) { |
| 137 | DISPLAY("ERROR: ZSTD_decompressBound: decompressed bound too small\n"); |
shakeelrao | 91ffc8d | 2019-03-15 03:59:03 -0700 | [diff] [blame] | 138 | return 1; |
| 139 | } |
shakeelrao | 19b75b6 | 2019-03-15 18:04:19 -0700 | [diff] [blame] | 140 | { const char* ip = COMPRESSED; |
| 141 | size_t remainingSize = COMPRESSED_SIZE; |
| 142 | while (1) { |
| 143 | size_t frameSize = ZSTD_findFrameCompressedSize(ip, remainingSize); |
| 144 | if (ZSTD_isError(frameSize)) { |
| 145 | DISPLAY("ERROR: ZSTD_findFrameCompressedSize: %s\n", ZSTD_getErrorName(frameSize)); |
| 146 | return 1; |
| 147 | } |
| 148 | if (frameSize > remainingSize) { |
| 149 | DISPLAY("ERROR: ZSTD_findFrameCompressedSize: expected frameSize to align with src buffer"); |
| 150 | return 1; |
| 151 | } |
| 152 | ip += frameSize; |
| 153 | remainingSize -= frameSize; |
| 154 | if (remainingSize == 0) break; |
| 155 | } |
| 156 | } |
shakeelrao | 91ffc8d | 2019-03-15 03:59:03 -0700 | [diff] [blame] | 157 | DISPLAY("Frame Decoding OK\n"); |
| 158 | return 0; |
| 159 | } |
| 160 | |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 161 | int main(void) |
| 162 | { |
Yann Collet | e0cb8d1 | 2018-03-20 17:48:22 -0700 | [diff] [blame] | 163 | { int const ret = testSimpleAPI(); |
| 164 | if (ret) return ret; } |
| 165 | { int const ret = testStreamingAPI(); |
| 166 | if (ret) return ret; } |
shakeelrao | 91ffc8d | 2019-03-15 03:59:03 -0700 | [diff] [blame] | 167 | { int const ret = testFrameDecoding(); |
| 168 | if (ret) return ret; } |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 169 | |
| 170 | DISPLAY("OK\n"); |
Sean Purcell | f07ddf8 | 2017-02-08 13:56:32 -0800 | [diff] [blame] | 171 | return 0; |
| 172 | } |
| 173 | |
| 174 | /* Consists of the "EXPECTED" string compressed with default settings on |
| 175 | - v0.4.3 |
| 176 | - v0.5.0 |
| 177 | - v0.6.0 |
| 178 | - v0.7.0 |
| 179 | - v0.8.0 |
| 180 | */ |
| 181 | const char* const COMPRESSED = |
| 182 | "\x24\xB5\x2F\xFD\x00\x00\x00\xBB\xB0\x02\xC0\x10\x00\x1E\xB0\x01" |
| 183 | "\x02\x00\x00\x80\x00\xE8\x92\x34\x12\x97\xC8\xDF\xE9\xF3\xEF\x53" |
| 184 | "\xEA\x1D\x27\x4F\x0C\x44\x90\x0C\x8D\xF1\xB4\x89\x17\x00\x18\x00" |
| 185 | "\x18\x00\x3F\xE6\xE2\xE3\x74\xD6\xEC\xC9\x4A\xE0\x71\x71\x42\x3E" |
| 186 | "\x64\x4F\x6A\x45\x4E\x78\xEC\x49\x03\x3F\xC6\x80\xAB\x8F\x75\x5E" |
| 187 | "\x6F\x2E\x3E\x7E\xC6\xDC\x45\x69\x6C\xC5\xFD\xC7\x40\xB8\x84\x8A" |
| 188 | "\x01\xEB\xA8\xD1\x40\x39\x90\x4C\x64\xF8\xEB\x53\xE6\x18\x0B\x67" |
| 189 | "\x12\xAD\xB8\x99\xB3\x5A\x6F\x8A\x19\x03\x01\x50\x67\x56\xF5\x9F" |
| 190 | "\x35\x84\x60\xA0\x60\x91\xC9\x0A\xDC\xAB\xAB\xE0\xE2\x81\xFA\xCF" |
| 191 | "\xC6\xBA\x01\x0E\x00\x54\x00\x00\x19\x00\x00\x54\x14\x00\x24\x24" |
| 192 | "\x04\xFE\x04\x84\x4E\x41\x00\x27\xE2\x02\xC4\xB1\x00\xD2\x51\x00" |
| 193 | "\x79\x58\x41\x28\x00\xE0\x0C\x01\x68\x65\x00\x04\x13\x0C\xDA\x0C" |
| 194 | "\x80\x22\x06\xC0\x00\x00\x25\xB5\x2F\xFD\x00\x00\x00\xAD\x12\xB0" |
| 195 | "\x7D\x1E\xB0\x01\x02\x00\x00\x80\x00\xE8\x92\x34\x12\x97\xC8\xDF" |
| 196 | "\xE9\xF3\xEF\x53\xEA\x1D\x27\x4F\x0C\x44\x90\x0C\x8D\xF1\xB4\x89" |
| 197 | "\x03\x01\x50\x67\x56\xF5\x9F\x35\x84\x60\xA0\x60\x91\xC9\x0A\xDC" |
| 198 | "\xAB\xAB\xE0\xE2\x81\xFA\xCF\xC6\xBA\xEB\xA8\xD1\x40\x39\x90\x4C" |
| 199 | "\x64\xF8\xEB\x53\xE6\x18\x0B\x67\x12\xAD\xB8\x99\xB3\x5A\x6F\x8A" |
| 200 | "\xF9\x63\x0C\xB8\xFA\x58\xE7\xF5\xE6\xE2\xE3\x67\xCC\x5D\x94\xC6" |
| 201 | "\x56\xDC\x7F\x0C\x84\x4B\xA8\xF8\x63\x2E\x3E\x4E\x67\xCD\x9E\xAC" |
| 202 | "\x04\x1E\x17\x27\xE4\x43\xF6\xA4\x56\xE4\x84\xC7\x9E\x34\x0E\x00" |
| 203 | "\x00\x32\x40\x80\xA8\x00\x01\x49\x81\xE0\x3C\x01\x29\x1D\x00\x87" |
| 204 | "\xCE\x80\x75\x08\x80\x72\x24\x00\x7B\x52\x00\x94\x00\x20\xCC\x01" |
| 205 | "\x86\xD2\x00\x81\x09\x83\xC1\x34\xA0\x88\x01\xC0\x00\x00\x26\xB5" |
| 206 | "\x2F\xFD\x42\xEF\x00\x00\xA6\x12\xB0\x7D\x1E\xB0\x01\x02\x00\x00" |
| 207 | "\x54\xA0\xBA\x24\x8D\xC4\x25\xF2\x77\xFA\xFC\xFB\x94\x7A\xC7\xC9" |
| 208 | "\x13\x03\x11\x24\x43\x63\x3C\x6D\x22\x03\x01\x50\x67\x56\xF5\x9F" |
| 209 | "\x35\x84\x60\xA0\x60\x91\xC9\x0A\xDC\xAB\xAB\xE0\xE2\x81\xFA\xCF" |
| 210 | "\xC6\xBA\xEB\xA8\xD1\x40\x39\x90\x4C\x64\xF8\xEB\x53\xE6\x18\x0B" |
| 211 | "\x67\x12\xAD\xB8\x99\xB3\x5A\x6F\x8A\xF9\x63\x0C\xB8\xFA\x58\xE7" |
| 212 | "\xF5\xE6\xE2\xE3\x67\xCC\x5D\x94\xC6\x56\xDC\x7F\x0C\x84\x4B\xA8" |
| 213 | "\xF8\x63\x2E\x3E\x4E\x67\xCD\x9E\xAC\x04\x1E\x17\x27\xE4\x43\xF6" |
| 214 | "\xA4\x56\xE4\x84\xC7\x9E\x34\x0E\x00\x35\x0B\x71\xB5\xC0\x2A\x5C" |
| 215 | "\x26\x94\x22\x20\x8B\x4C\x8D\x13\x47\x58\x67\x15\x6C\xF1\x1C\x4B" |
| 216 | "\x54\x10\x9D\x31\x50\x85\x4B\x54\x0E\x01\x4B\x3D\x01\xC0\x00\x00" |
| 217 | "\x27\xB5\x2F\xFD\x20\xEF\x00\x00\xA6\x12\xE4\x84\x1F\xB0\x01\x10" |
| 218 | "\x00\x00\x00\x35\x59\xA6\xE7\xA1\xEF\x7C\xFC\xBD\x3F\xFF\x9F\xEF" |
| 219 | "\xEE\xEF\x61\xC3\xAA\x31\x1D\x34\x38\x22\x22\x04\x44\x21\x80\x32" |
| 220 | "\xAD\x28\xF3\xD6\x28\x0C\x0A\x0E\xD6\x5C\xAC\x19\x8D\x20\x5F\x45" |
| 221 | "\x02\x2E\x17\x50\x66\x6D\xAC\x8B\x9C\x6E\x07\x73\x46\xBB\x44\x14" |
| 222 | "\xE7\x98\xC3\xB9\x17\x32\x6E\x33\x7C\x0E\x21\xB1\xDB\xCB\x89\x51" |
| 223 | "\x23\x34\xAB\x9D\xBC\x6D\x20\xF5\x03\xA9\x91\x4C\x2E\x1F\x59\xDB" |
| 224 | "\xD9\x35\x67\x4B\x0C\x95\x79\x10\x00\x85\xA6\x96\x95\x2E\xDF\x78" |
| 225 | "\x7B\x4A\x5C\x09\x76\x97\xD1\x5C\x96\x12\x75\x35\xA3\x55\x4A\xD4" |
| 226 | "\x0B\x00\x35\x0B\x71\xB5\xC0\x2A\x5C\xE6\x08\x45\xF1\x39\x43\xF1" |
| 227 | "\x1C\x4B\x54\x10\x9D\x31\x50\x85\x4B\x54\x0E\x01\x4B\x3D\x01\xC0" |
| 228 | "\x00\x00\x28\xB5\x2F\xFD\x24\xEF\x35\x05\x00\x92\x0B\x21\x1F\xB0" |
| 229 | "\x01\x10\x00\x00\x00\x35\x59\xA6\xE7\xA1\xEF\x7C\xFC\xBD\x3F\xFF" |
| 230 | "\x9F\xEF\xEE\xEF\x61\xC3\xAA\x31\x1D\x34\x38\x22\x22\x04\x44\x21" |
| 231 | "\x80\x32\xAD\x28\xF3\xD6\x28\x0C\x0A\x0E\xD6\x5C\xAC\x19\x8D\x20" |
| 232 | "\x5F\x45\x02\x2E\x17\x50\x66\x6D\xAC\x8B\x9C\x6E\x07\x73\x46\xBB" |
| 233 | "\x44\x14\xE7\x98\xC3\xB9\x17\x32\x6E\x33\x7C\x0E\x21\xB1\xDB\xCB" |
| 234 | "\x89\x51\x23\x34\xAB\x9D\xBC\x6D\x20\xF5\x03\xA9\x91\x4C\x2E\x1F" |
| 235 | "\x59\xDB\xD9\x35\x67\x4B\x0C\x95\x79\x10\x00\x85\xA6\x96\x95\x2E" |
| 236 | "\xDF\x78\x7B\x4A\x5C\x09\x76\x97\xD1\x5C\x96\x12\x75\x35\xA3\x55" |
| 237 | "\x4A\xD4\x0B\x00\x35\x0B\x71\xB5\xC0\x2A\x5C\xE6\x08\x45\xF1\x39" |
| 238 | "\x43\xF1\x1C\x4B\x54\x10\x9D\x31\x50\x85\x4B\x54\x0E\x01\x4B\x3D" |
| 239 | "\x01\xD2\x2F\x21\x80"; |
| 240 | |
| 241 | const char* const EXPECTED = |
| 242 | "snowden is snowed in / he's now then in his snow den / when does the snow end?\n" |
| 243 | "goodbye little dog / you dug some holes in your day / they'll be hard to fill.\n" |
| 244 | "when life shuts a door, / just open it. it’s a door. / that is how doors work.\n" |
| 245 | |
| 246 | "snowden is snowed in / he's now then in his snow den / when does the snow end?\n" |
| 247 | "goodbye little dog / you dug some holes in your day / they'll be hard to fill.\n" |
| 248 | "when life shuts a door, / just open it. it’s a door. / that is how doors work.\n" |
| 249 | |
| 250 | "snowden is snowed in / he's now then in his snow den / when does the snow end?\n" |
| 251 | "goodbye little dog / you dug some holes in your day / they'll be hard to fill.\n" |
| 252 | "when life shuts a door, / just open it. it’s a door. / that is how doors work.\n" |
| 253 | |
| 254 | "snowden is snowed in / he's now then in his snow den / when does the snow end?\n" |
| 255 | "goodbye little dog / you dug some holes in your day / they'll be hard to fill.\n" |
| 256 | "when life shuts a door, / just open it. it’s a door. / that is how doors work.\n" |
| 257 | |
| 258 | "snowden is snowed in / he's now then in his snow den / when does the snow end?\n" |
| 259 | "goodbye little dog / you dug some holes in your day / they'll be hard to fill.\n" |
| 260 | "when life shuts a door, / just open it. it’s a door. / that is how doors work.\n"; |