pak

pak.git
git clone git://git.lenczewski.org/pak.git
Log | Files | Refs | README | LICENSE

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"