add unit tests for write_<xnn>_le() functions

This commit is contained in:
Rupert
2025-05-07 17:54:32 +02:00
parent 1bba98e395
commit 668cc352e3
4 changed files with 332 additions and 0 deletions

View File

@@ -93,6 +93,17 @@ test_read_io = executable('test_read_io',
dependencies: m_dep,
)
test_write_io = executable('test_write_io',
'test-write-io.c',
'bmp-common.c',
'bmp-read.c',
'huffman.c',
'logging.c',
'test-fileio-pipes.c',
huff_codes[0],
dependencies: m_dep,
)
test('read - s_s2_13_to_float', test_read_conversions, args : ['s_s2_13_to_float'])
test('read - s_convert64', test_read_conversions, args : ['s_convert64'])
test('read - s_float_to_s2_13', test_read_conversions, args : ['s_float_to_s2_13'])
@@ -108,3 +119,7 @@ test('read - read_u16_le', test_read_io, args : ['read_u16_le'
test('read - read_s16_le', test_read_io, args : ['read_s16_le'])
test('read - read_u32_le', test_read_io, args : ['read_u32_le'])
test('read - read_s32_le', test_read_io, args : ['read_s32_le'])
test('write - write_u32_le', test_write_io, args : ['write_u32_le'])
test('write - write_s32_le', test_write_io, args : ['write_s32_le'])
test('write - write_u16_le', test_write_io, args : ['write_u16_le'])
test('write - write_s16_le', test_write_io, args : ['write_s16_le'])

View File

@@ -69,3 +69,77 @@ abort:
return NULL;
}
FILE* open_write_pipe(struct WritePipe **hwp)
{
int fd[2] = { -1, -1 };
FILE *file_read = NULL, *file_write = NULL;
struct WritePipe *wp = NULL;
if (!hwp)
return NULL;
*hwp = NULL;
if (!(wp = malloc(sizeof *wp))) {
perror(__func__);
goto abort;
}
memset(wp, 0, sizeof *wp);
if (pipe(fd)) {
perror("pipe");
goto abort;
}
if (!(file_read = fdopen(fd[0], "rb"))) {
perror("fdopen read pipe");
goto abort;
}
if (!(file_write = fdopen(fd[1], "w"))) {
perror("fdopen write pipe");
goto abort;
}
wp->file_read = file_read;
*hwp = wp;
return file_write;
abort:
if (file_write)
fclose(file_write);
else if (fd[1] != -1)
close(fd[1]);
if (file_read)
fclose(file_read);
else if (fd[0] != -1)
close(fd[0]);
if (wp)
free(wp);
return NULL;
}
int data_from_write_pipe(struct WritePipe *wp, unsigned char *buffer, int size)
{
int nread;
if (!(wp && buffer)) {
fprintf(stderr, "%s(): invalid NULL argument(s)\n", __func__);
exit(3);
}
if (!wp->file_read) {
fprintf(stderr, "%s(): FILE* is NULL\n", __func__);
exit(3);
}
nread = fread(buffer, 1, size, wp->file_read);
fclose(wp->file_read);
free(wp);
return nread;
}

View File

@@ -18,4 +18,12 @@
* If not, see <https://www.gnu.org/licenses/>
*/
struct WritePipe {
FILE *file_read;
};
FILE* provide_as_file(const unsigned char *data, size_t size);
FILE* open_write_pipe(struct WritePipe **hwp);
int data_from_write_pipe(struct WritePipe *wp, unsigned char *buffer, int size);

235
test-write-io.c Normal file
View File

@@ -0,0 +1,235 @@
/* bmplib - test-read-io.c
*
* Copyright (c) 2025, Rupert Weber.
*
* This file is part of bmplib.
* bmplib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* If not, see <https://www.gnu.org/licenses/>
*/
#include "bmp-write.c"
#include "test-fileio-pipes.h"
#define ARRAY_LEN(a) ((int)(sizeof (a) / sizeof ((a)[0])))
int main(int argc, const char **argv)
{
const char *func /*, *subtest =""*/;
if (argc < 2) {
fprintf(stderr, "Invalid invocation\n");
return 2;
}
func = argv[1];
/*if (argc >= 3)
subtest = argv[2];*/
if (!strcmp(func, "write_u32_le")) {
const int expected_len = 4;
struct {
uint32_t value;
unsigned char *expected;
} data[] = {
{ .expected = (unsigned char[]){0x00,0x00,0x00,0x00}, .value = 0 },
{ .expected = (unsigned char[]){0x01,0x00,0x00,0x00}, .value = 1 },
{ .expected = (unsigned char[]){0xfe,0xff,0xff,0xff}, .value = 0xfffffffeUL },
{ .expected = (unsigned char[]){0xff,0xff,0xff,0xff}, .value = 0xffffffffUL },
{ .expected = (unsigned char[]){0x12,0x34,0x56,0x78}, .value = 0x78563412UL },
};
for (int i = 0; i < ARRAY_LEN(data); i++) {
struct WritePipe *wp = NULL;
unsigned char buf[expected_len];
FILE *file = open_write_pipe(&wp);
if (!file)
return 2;
if (!write_u32_le(file, data[i].value)) {
perror(func);
return 3;
}
fflush(file); /* important, otherwise read will get stuck */
int nbytes = data_from_write_pipe(wp, buf, (int) sizeof buf);
fclose(file);
if (nbytes != expected_len) {
printf("%s() failed on dataset %d (%lu):\n", func, i, (unsigned long)data[i].value);
printf("expected to read %d bytes, got %d bytes\n", expected_len, nbytes);
return 1;
}
if (memcmp(data[i].expected, buf, expected_len) != 0) {
printf("%s() failed on dataset %d (%lu):\n", func, i, (unsigned long)data[i].value);
printf("expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x\n",
(unsigned)data[i].expected[0], (unsigned)data[i].expected[1],
(unsigned)data[i].expected[2], (unsigned)data[i].expected[3],
(unsigned)buf[0], (unsigned)buf[1], (unsigned)buf[2], (unsigned)buf[3]);
return 1;
}
}
return 0;
}
if (!strcmp(func, "write_s32_le")) {
const int expected_len = 4;
struct {
int32_t value;
unsigned char *expected;
} data[] = {
{ .expected = (unsigned char[]){0x00,0x00,0x00,0x00}, .value = 0 },
{ .expected = (unsigned char[]){0x01,0x00,0x00,0x00}, .value = 1 },
{ .expected = (unsigned char[]){0xff,0xff,0xff,0xff}, .value = -1 },
{ .expected = (unsigned char[]){0x00,0x00,0x00,0x80}, .value = -2147483648L },
{ .expected = (unsigned char[]){0x01,0x00,0x00,0x80}, .value = -2147483647L },
{ .expected = (unsigned char[]){0xfe,0xff,0xff,0x7f}, .value = 2147483646L },
{ .expected = (unsigned char[]){0xff,0xff,0xff,0x7f}, .value = 2147483647L },
{ .expected = (unsigned char[]){0x12,0x34,0x56,0x78}, .value = 2018915346L },
};
for (int i = 0; i < ARRAY_LEN(data); i++) {
struct WritePipe *wp = NULL;
unsigned char buf[expected_len];
FILE *file = open_write_pipe(&wp);
if (!file)
return 2;
if (!write_s32_le(file, data[i].value)) {
perror(func);
return 3;
}
fflush(file); /* important, otherwise read will get stuck */
int nbytes = data_from_write_pipe(wp, buf, (int) sizeof buf);
fclose(file);
if (nbytes != expected_len) {
printf("%s() failed on dataset %d (%ld):\n", func, i, (long)data[i].value);
printf("expected to read %d bytes, got %d bytes\n", expected_len, nbytes);
return 1;
}
if (memcmp(data[i].expected, buf, expected_len) != 0) {
printf("%s() failed on dataset %d (%ld):\n", func, i, (long)data[i].value);
printf("expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x\n",
(unsigned)data[i].expected[0], (unsigned)data[i].expected[1],
(unsigned)data[i].expected[2], (unsigned)data[i].expected[3],
(unsigned)buf[0], (unsigned)buf[1], (unsigned)buf[2], (unsigned)buf[3]);
return 1;
}
}
return 0;
}
if (!strcmp(func, "write_u16_le")) {
const int expected_len = 2;
struct {
uint16_t value;
unsigned char *expected;
} data[] = {
{ .expected = (unsigned char[]){0x00,0x00}, .value = 0 },
{ .expected = (unsigned char[]){0x01,0x00}, .value = 1 },
{ .expected = (unsigned char[]){0xfe,0xff}, .value = 65534 },
{ .expected = (unsigned char[]){0xff,0xff}, .value = 65535 },
};
for (int i = 0; i < ARRAY_LEN(data); i++) {
struct WritePipe *wp = NULL;
unsigned char buf[expected_len];
FILE *file = open_write_pipe(&wp);
if (!file)
return 2;
if (!write_u16_le(file, data[i].value)) {
perror(func);
return 3;
}
fflush(file); /* important, otherwise read will get stuck */
int nbytes = data_from_write_pipe(wp, buf, (int) sizeof buf);
fclose(file);
if (nbytes != expected_len) {
printf("%s() failed on dataset %d (%u):\n", func, i, (unsigned)data[i].value);
printf("expected to read %d bytes, got %d bytes\n", expected_len, nbytes);
return 1;
}
if (memcmp(data[i].expected, buf, expected_len) != 0) {
printf("%s() failed on dataset %d (%u):\n", func, i, (unsigned)data[i].value);
printf("expected 0x%02x%02x, got 0x%02x%02x\n",
(unsigned)data[i].expected[0], (unsigned)data[i].expected[1],
(unsigned)buf[0], (unsigned)buf[1]);
return 1;
}
}
return 0;
}
if (!strcmp(func, "write_s16_le")) {
const int expected_len = 2;
struct {
int16_t value;
unsigned char *expected;
} data[] = {
{ .expected = (unsigned char[]){0x00,0x00}, .value = 0 },
{ .expected = (unsigned char[]){0x01,0x00}, .value = 1 },
{ .expected = (unsigned char[]){0x00,0x80}, .value = -32768 },
{ .expected = (unsigned char[]){0x01,0x80}, .value = -32767 },
{ .expected = (unsigned char[]){0xfe,0x7f}, .value = 32766 },
{ .expected = (unsigned char[]){0xff,0x7f}, .value = 32767 },
};
for (int i = 0; i < ARRAY_LEN(data); i++) {
struct WritePipe *wp = NULL;
unsigned char buf[expected_len];
FILE *file = open_write_pipe(&wp);
if (!file)
return 2;
if (!write_s16_le(file, data[i].value)) {
perror(func);
return 3;
}
fflush(file); /* important, otherwise read will get stuck */
int nbytes = data_from_write_pipe(wp, buf, (int) sizeof buf);
fclose(file);
if (nbytes != expected_len) {
printf("%s() failed on dataset %d (%d):\n", func, i, (int)data[i].value);
printf("expected to read %d bytes, got %d bytes\n", expected_len, nbytes);
return 1;
}
if (memcmp(data[i].expected, buf, expected_len) != 0) {
printf("%s() failed on dataset %d (%d):\n", func, i, (int)data[i].value);
printf("expected 0x%02x%02x, got 0x%02x%02x\n",
(unsigned)data[i].expected[0], (unsigned)data[i].expected[1],
(unsigned)buf[0], (unsigned)buf[1]);
return 1;
}
}
return 0;
}
fprintf(stderr, "Invalid test '%s'\n", func);
return 2;
}