Как мне создать файловый дескриптор, подкрепленный простым массивом символов? - PullRequest
0 голосов
/ 24 августа 2018

У меня есть функция, которая получает дескриптор (вы знаете, одну из тех вещей, которые open() и socket() плюются), читает из нее и что-то делает с данные:

int do_something(int fd);

Я хочу проверить эту функцию. Предпочтительно входные данные должны располагаться рядом с тестовым утверждением для удобства отладки. (Поэтому следует избегать фактического чтения файлов.) На мой взгляд, идеальным было бы что-то вроде

unsigned char test_input[] = { 1, 2, 3 };
int fd = char_array_to_fd(test_input);
ck_assert(do_something(fd) == 1234);

(ck_assert из Check framework . Это просто типичное утверждение модульного теста.)

Есть ли способ реализовать char_array_to_fd()? Я не против, если мне нужно NULL-завершить массив или отправить длину в.

Я представляю, что могу открыть для себя сокет и написать на одном конце, чтобы тестовая функция получила данные на другом конце. Я просто не хочу писать что-то неловкое и узнавать, что Unix все время придумывал что-то менее хитрое. Решение должно быть удобным для Unix.

(В основном, я прошу C эквивалент ByteArrayInputStream.)

В качестве альтернативы: я должен думать каким-то другим способом, чтобы решить эту проблему?

Ответы [ 3 ]

0 голосов
/ 25 августа 2018

Вы можете использовать mkstemp для создания временного файла и записи в него или чтения из него:

int fd = mkstemp("tempXXXXXX");

Если вы хотите что-то более динамичное, вы можете использовать socketpair для создания пары соединенных сокетов.

int pair[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, pair);

Затем можно обработать процесс или поток для взаимодействия с тестируемой программой.

0 голосов
/ 25 августа 2018

@ Ответ ChrisDodd уже принят, но я хотел добавить решение для каналов, которое я разработал (благодаря комментарию @ Someprogrammerdude) для полноты:

struct writer_args {
    int fd;
    unsigned char *buffer;
    size_t size;
};

/* Pipe writer thread function */
void *write_buffer(void *_args)
{
    struct writer_args *args = _args;
    /*
     * error handling omitted.
     * Should probably also be thrown into a loop, in case it writes less
     * than args->size.
     */
    write(args->fd, args->buffer, args->size);
    close(args->fd);
    return NULL;
}

/*
 * Wrapper for quick & easy testing of the do_something() function.
 * Replaces the fd parameter for a char array and its size.
 */
static int __do_something(unsigned char *input, size_t size)
{
    pthread_t writer_thread;
    struct writer_args args;
    int fd[2];
    int result;

    pipe(fd); /* error handling omitted */
    /* fd[0] is for reading, fd[1] is for writing */

    /*
     * We want one thread for reading, another one for writing.
     * This is because pipes have a nonstandardized maximum buffer capacity.
     * If we write too much without reading, it will block forever.
     */
    args.fd = fd[1];
    args.buffer = input;
    args.size = size;
    /* error handling omitted */
    pthread_create(&writer_thread, NULL, write_buffer, &args);

    result = do_something(fd[0]);
    close(fd[0]);

    pthread_join(writer_thread, NULL); /* error handling omitted */

    return result;
}

Затем я могу продолжать тестировать do_something столько, сколько хочу:

ret = __do_something(input1, input1_size);
if (ret != 1234)
    fprintf(stderr, "Fail. Expected:1234 Actual:%d\n", ret);

ret = __do_something(input2, input2_size);
if (ret != 0)
    fprintf(stderr, "Fail. Expected:0 Actual:%d\n", ret);

ret = __do_something(input3, input3_size);
if (ret != 555)
    fprintf(stderr, "Fail. Expected:555 Actual:%d\n", ret);

...
0 голосов
/ 24 августа 2018

В Linux вы можете использовать memfd_create() для создания временного файла с поддержкой памяти:

unsigned char test_input[] = ...;

int fd = memfd_create( "test_input", 0 );

// write test data to the the "file"
write( fd, test_input, sizeof( test_input );

// reset file descriptor to the start of the "file"
lseek( fd, 0, SEEK_SET );

Обратите внимание, что в нем полностью отсутствует проверка ошибок.

...