test.c (7910B)
1 #define HEADER_IMPL 2 3 #include "pak.h" 4 5 #include <alloca.h> 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 12 #include <fcntl.h> 13 #include <sys/stat.h> 14 15 #define TEST_PAK_FROM_MEM 1 16 #define TEST_PAK_FROM_BUILDER 1 /* NOTE: TEST_PAK_FROM_MEM takes priority */ 17 #define TEST_PAK_READ_ALL 1 18 #define TEST_PAK_READ_SINGLE_ARCHIVE 1 19 20 #define TEST_RAW_FILE "/tmp/test.txt" 21 #define TEST_PAK_FILE_IN "/tmp/test.pak" 22 #define TEST_PAK_FILE_OUT "/tmp/test2.pak" 23 24 static char buf[8192]; 25 26 static void 27 print_bytes(void *buf, size_t len, int format) 28 { 29 uint8_t *ptr = buf; 30 31 for (size_t i = 0; i < len; i++) { 32 if (format == 16) 33 printf("0x%x,", *ptr++); 34 else if (format == 2) { 35 uint8_t val = *ptr++; 36 printf("0b%u%u%u%u%u%u%u%u,", 37 !!(val & 0x80), 38 !!(val & 0x40), 39 !!(val & 0x20), 40 !!(val & 0x10), 41 !!(val & 0x8), 42 !!(val & 0x4), 43 !!(val & 0x2), 44 !!(val & 0x1)); 45 } else 46 printf("0d%u,", *ptr++); 47 } 48 } 49 50 int 51 main(void) 52 { 53 struct arena arena = { .ptr = buf, .cap = sizeof buf, .len = 0, }; 54 arena_reset(&arena); 55 56 uint8_t test[] = { 57 /* header */ 58 'P', 'A', 'K', '0', /* magic */ 59 48, 0, 0, 0, /* header length */ 60 48, 0, 0, 0, 0, 0, 0, 0, /* index file offset */ 61 0, 0, 0, 0, /* index compression */ 62 80 + 44, 0, 0, 0, /* index compressed length */ 63 80 + 44, 0, 0, 0, /* index uncompressed length */ 64 0, 0, 0, 0, /* index uncompressed crc32c */ 65 48 + 80 + 44, 0, 0, 0, 0, 0, 0, 0, /* data file offset */ 66 64, 0, 0, 0, 0, 0, 0, 0, /* data compressed length */ 67 68 /* index */ 69 70 /* archive 0: 80 bytes + sizeof tag0 */ 71 'a','r','c','h','i','v','e','0', /* archive name */ 72 0,0,0,0,0,0,0,0, 73 0,0,0,0,0,0,0,0, 74 0,0,0,0,0,0,0,0, 75 76 0, 0, 0, 0, /* archive type */ 77 78 80 + 44, 0, 0, 0, /* archive header + tags length */ 79 80 0, 0, 0, 0, 0, 0, 0, 0, /* data compressed offset */ 81 64, 0, 0, 0, 0, 0, 0, 0, /* data compressed length */ 82 64, 0, 0, 0, 0, 0, 0, 0, /* data uncompressed length */ 83 0, 0, 0, 0, /* data uncompressed crc32c */ 84 0, 0, 0, 0, /* data compression */ 85 86 0, 0, 0, 0, /* reserved */ 87 1, 0, 0, 0, /* archive tag count */ 88 /* archive tags[] */ 89 90 /* archive 0: tag 0: 36 bytes + sizeof tag0.data */ 91 't','a','g','0',0,0,0,0, /* tag name */ 92 0,0,0,0,0,0,0,0, 93 0,0,0,0,0,0,0,0, 94 0,0,0,0,0,0,0,0, 95 96 0, 0, /* tag type */ 97 8, 0, /* tag length */ 98 /* tag data[] */ 99 0,0,0,0,0,0,0,0, 100 101 /* data */ 102 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 103 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 104 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 105 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 106 }; 107 108 struct pak test_pak; 109 110 #if TEST_PAK_FROM_MEM /* test pak deserialisation */ 111 112 if (pak_read_mem(test, sizeof test, &arena, &test_pak) < 0) { 113 fprintf(stderr, "error: failed to read test pak from memory buffer\n"); 114 return -1; 115 } 116 117 printf("in-memory test pak:\n"); 118 119 #elif TEST_PAK_FROM_BUILDER /* test pak_open(), pak_add_archive(), and pak_close() */ 120 121 pak_open(&test_pak); 122 123 char name[PAK_ARCHIVE_NAME_LEN] = "archive0"; 124 uint32_t type = 0; 125 126 uint8_t tag_data[] = { 127 0,0,0,0,0,0,0,0, 128 }; 129 130 struct pak_tag tag = { 131 .header = { .name = "tag0", .type = 0, .length = sizeof tag_data, }, 132 .data = tag_data, 133 }; 134 135 uint8_t archive_data[] = { 136 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 137 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 138 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 139 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7, 0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, 140 }; 141 142 struct pak_archive *archive = NULL; 143 if ((archive = pak_add_archive(&test_pak, &arena, name, type, 144 PAK_COMPRESSION_NONE, 145 &tag, 1, 146 archive_data, sizeof archive_data, 147 sizeof archive_data, 0)) == NULL) { 148 fprintf(stderr, "error: failed to add archive to pak file\n"); 149 return -1; 150 } 151 152 pak_close(&test_pak); 153 154 printf("builder test pak:\n"); 155 156 #endif 157 158 { 159 pak_debug_dump(&test_pak); 160 161 size_t test_file_size = pak_file_size(&test_pak); 162 printf("test pak file serialised size: %zu\n", test_file_size); 163 164 void *test_buf = alloca(test_file_size); 165 assert(test_buf); 166 167 if (pak_write_mem(test_buf, test_file_size, &test_pak) < 0) { 168 fprintf(stderr, "error: failed to serialise pak file\n"); 169 return -1; 170 } 171 172 assert(sizeof test == test_file_size); 173 assert(memcmp(test, test_buf, test_file_size) == 0); 174 175 int fd = open(TEST_PAK_FILE_IN, O_WRONLY | O_CREAT, 0644); 176 if (fd < 0) { 177 fprintf(stderr, "error: failed to open test pak file: %s\n", TEST_PAK_FILE_IN); 178 return -1; 179 } 180 181 size_t written = write(fd, test_buf, test_file_size); 182 assert(written == test_file_size); 183 } 184 185 #if TEST_PAK_READ_ALL /* test whole-pak reading */ 186 187 { 188 arena_reset(&arena); 189 190 int in = open(TEST_PAK_FILE_IN, O_RDONLY); 191 if (in < 0) { 192 fprintf(stderr, "error: failed to open input pak file: %s\n", TEST_PAK_FILE_IN); 193 return -1; 194 } 195 196 struct pak pak; 197 if (pak_read_header(in, &pak.header) < 0) { 198 fprintf(stderr, "error: failed to read pak file header: %s\n", TEST_PAK_FILE_IN); 199 return -1; 200 } 201 202 size_t len = pak.header.index_uncompressed_length; 203 uint8_t *data = alloca(len); 204 205 pak.index = LIST_INIT(pak.index); 206 if (pak_read_index(in, &arena, &pak.header, data, len, &pak.index) < 0) { 207 fprintf(stderr, "error: failed to read pak file index: %s\n", TEST_PAK_FILE_IN); 208 return -1; 209 } 210 211 struct pak_archive *it; 212 LIST_ENTRY_ITER(&pak.index, it, list_node) { 213 size_t archive_len = it->header.data_uncompressed_length; 214 uint8_t *archive_data = arena_alloc(&arena, archive_len, 1); 215 assert(archive_data); 216 217 if (pak_read_archive_data(in, &pak.header, &it->header, archive_data, archive_len) < 0) { 218 fprintf(stderr, "error: failed to read archive \"%.*s\" data from pak file: %s\n", 219 (int) sizeof it->header.name, it->header.name, TEST_PAK_FILE_IN); 220 return -1; 221 } 222 223 it->data = archive_data; 224 } 225 226 printf("read pak:\n"); 227 pak_debug_dump(&pak); 228 229 int out = open(TEST_PAK_FILE_OUT, O_WRONLY | O_CREAT, 0644); 230 if (out < 0) { 231 fprintf(stderr, "error: failed to open output pak file: %s\n", TEST_PAK_FILE_OUT); 232 return -1; 233 } 234 235 if (pak_write(out, &pak) < 0) { 236 fprintf(stderr, "error: failed to write pak file: %s\n", TEST_PAK_FILE_OUT); 237 return -1; 238 } 239 } 240 241 #endif 242 243 #if TEST_PAK_READ_SINGLE_ARCHIVE /* test pak single-archive reading */ 244 245 { 246 int single = open(TEST_PAK_FILE_OUT, O_RDONLY); 247 assert(single >= 0); 248 249 arena_reset(&arena); 250 251 struct pakfmt_header header; 252 if (pak_read_header(single, &header) < 0) { 253 fprintf(stderr, "error: failed to read pak header from file: %s\n", 254 TEST_PAK_FILE_OUT); 255 return -1; 256 } 257 258 struct pak_archive *archive; 259 char name[PAK_ARCHIVE_NAME_LEN] = "archive0"; 260 uint32_t type = 0; 261 262 if (pak_read_archive(single, &arena, &header, name, type, &archive) < 0) { 263 fprintf(stderr, "error: failed to read archive \"%s\" from file: %s\n", 264 name, TEST_PAK_FILE_OUT); 265 return -1; 266 } 267 268 size_t len = archive->header.data_uncompressed_length; 269 uint8_t *data = alloca(len); 270 if (pak_read_archive_data(single, &header, &archive->header, data, len) < 0) { 271 fprintf(stderr, "error: failed to read archive \"%s\" data from file: %s\n", 272 name, TEST_PAK_FILE_OUT); 273 return -1; 274 } 275 276 printf("Archive data: %zu bytes\n", archive->header.data_uncompressed_length); 277 print_bytes(data, archive->header.data_uncompressed_length, 16); 278 printf("\n"); 279 280 printf("Archive tags:\n"); 281 282 struct pak_tag *it; 283 LIST_ENTRY_ITER(&archive->tags, it, list_node) { 284 printf("\ttag: \"%.*s\", type: %u\n", 285 (int) sizeof it->header.name, it->header.name, it->header.type); 286 print_bytes(it->data, it->header.length, 16); 287 printf("\n"); 288 } 289 } 290 #endif 291 292 return 0; 293 } 294 295 #include "pak.c"