mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2025-12-30 14:10:08 +01:00
246 lines
7 KiB
C
246 lines
7 KiB
C
/*
|
|
* Copyright © 2020 Red Hat, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
|
|
#include "util-io.h"
|
|
#include "util-munit.h"
|
|
|
|
MUNIT_TEST(test_iobuf_new)
|
|
{
|
|
/* test allocation and freeing a buffer */
|
|
struct iobuf *buf = iobuf_new(10);
|
|
munit_assert_size(buf->sz, ==, 10);
|
|
|
|
munit_assert_size(buf->len, ==, 0);
|
|
munit_assert_size(iobuf_len(buf), ==, 0);
|
|
|
|
buf = iobuf_free(buf);
|
|
munit_assert_null(buf);
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
MUNIT_TEST(test_iobuf_cleanup)
|
|
{
|
|
/* Test the attribute(cleanup) define. This test needs to run in
|
|
* valgrind --leak-check=full to be really useful */
|
|
_cleanup_iobuf_ struct iobuf *buf = iobuf_new(10);
|
|
_cleanup_iobuf_ struct iobuf *nullbuf = NULL;
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
MUNIT_TEST(test_iobuf_append)
|
|
{
|
|
/* Test appending data */
|
|
_cleanup_iobuf_ struct iobuf *buf = iobuf_new(10);
|
|
|
|
/* append data without a resize */
|
|
const char data[] = "foo";
|
|
iobuf_append(buf, data, 3);
|
|
|
|
munit_assert_size(buf->len, ==, 3);
|
|
munit_assert_size(iobuf_len(buf), ==, 3);
|
|
munit_assert_size(buf->sz, ==, 10);
|
|
|
|
/* we don't have a trailing \0 */
|
|
const char *bufdata = iobuf_data(buf);
|
|
munit_assert_char(bufdata[0], ==, 'f');
|
|
munit_assert_char(bufdata[1], ==, 'o');
|
|
munit_assert_char(bufdata[2], ==, 'o');
|
|
|
|
/* Now append enough data to force a buffer resize */
|
|
|
|
const char data2[] = "data forcing resize";
|
|
iobuf_append(buf, data2, sizeof(data2)); /* includes \0 */
|
|
|
|
size_t expected = strlen(data) + strlen(data2) + 1;
|
|
munit_assert_size(iobuf_len(buf), ==, expected);
|
|
munit_assert_size(buf->sz, ==, expected);
|
|
/* now we have a trailing \0 */
|
|
munit_assert_string_equal(iobuf_data(buf), "foodata forcing resize");
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
MUNIT_TEST(test_iobuf_append_short)
|
|
{
|
|
_cleanup_iobuf_ struct iobuf *buf = iobuf_new(10);
|
|
|
|
/* Append only the first few bytes out of a larger data field, i.e.
|
|
* make sure we honor the lenght parameter */
|
|
const char data[] = "foobar";
|
|
const char nullbyte = '\0';
|
|
iobuf_append(buf, data, 3);
|
|
iobuf_append(buf, &nullbyte, 1);
|
|
|
|
munit_assert_size(buf->len, ==, 4);
|
|
munit_assert_size(iobuf_len(buf), ==, 4);
|
|
munit_assert_size(buf->sz, ==, 10);
|
|
munit_assert_string_equal(iobuf_data(buf),
|
|
"foo");
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
MUNIT_TEST(test_iobuf_append_fd)
|
|
{
|
|
_cleanup_iobuf_ struct iobuf *buf = iobuf_new(10);
|
|
int fds[2];
|
|
|
|
int rc = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, fds);
|
|
munit_assert_int(rc, ==, 0);
|
|
|
|
int wr = fds[0],
|
|
rd = fds[1];
|
|
|
|
/* write some data */
|
|
const char data[] = "foobar";
|
|
int wlen = xwrite(wr, data, 4);
|
|
munit_assert_int(wlen, ==, 4);
|
|
|
|
/* read that data */
|
|
int rlen = iobuf_append_from_fd(buf, rd);
|
|
munit_assert_int(rlen, ==, 4);
|
|
|
|
munit_assert_size(iobuf_len(buf), ==, 4);
|
|
|
|
/* so we can do strcmp */
|
|
const char nullbyte = '\0';
|
|
iobuf_append(buf, &nullbyte, 1);
|
|
munit_assert_string_equal(iobuf_data(buf), "foob");
|
|
|
|
/* read when there's nothing waiting */
|
|
int blocking_read = iobuf_append_from_fd(buf, rd);
|
|
munit_assert_int(blocking_read, ==, -EAGAIN);
|
|
|
|
const char largebuffer[2048] = {0xaa};
|
|
|
|
/* read data exactly our internal buffer size */
|
|
wlen = xwrite(wr, largebuffer, 1024);
|
|
munit_assert_int(wlen, ==, 1024);
|
|
int read_1024 = iobuf_append_from_fd(buf, rd);
|
|
munit_assert_int(read_1024, ==, 1024);
|
|
|
|
/* read data exactly our internal buffer size + 1*/
|
|
wlen = xwrite(wr, largebuffer, 1025);
|
|
munit_assert_int(wlen, ==, 1025);
|
|
int read_1025 = iobuf_append_from_fd(buf, rd);
|
|
munit_assert_int(read_1025, ==, 1025);
|
|
|
|
/* close write side, read nothing */
|
|
xclose(wr);
|
|
int read_none = iobuf_append_from_fd(buf, rd);
|
|
munit_assert_int(read_none, ==, 0);
|
|
|
|
/* close read side, expect error */
|
|
xclose(rd);
|
|
int read_fail = iobuf_append_from_fd(buf, rd);
|
|
munit_assert_int(read_fail, ==, -EBADF);
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
MUNIT_TEST(test_iobuf_recv_fd)
|
|
{
|
|
int fds[2];
|
|
int rc = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, fds);
|
|
munit_assert_int(rc, ==, 0);
|
|
|
|
_cleanup_close_ int left = fds[0];
|
|
_cleanup_close_ int right = fds[1];
|
|
_cleanup_fclose_ FILE *fp = tmpfile();
|
|
|
|
/* actual message data to be sent */
|
|
char data[] = "some data\n";
|
|
|
|
/* Send the fd from left to right */
|
|
int sendfds[2] = { fileno(fp), -1 };
|
|
int sendrc = xsend_with_fd(left, data, sizeof(data), sendfds);
|
|
munit_assert_int(sendrc, ==, sizeof(data));
|
|
|
|
_cleanup_iobuf_ struct iobuf *buf = iobuf_new(64);
|
|
rc = iobuf_recv_from_fd(buf, right);
|
|
munit_assert_int(rc, ==, sizeof(data));
|
|
|
|
_cleanup_close_ int fd = iobuf_take_fd(buf);
|
|
munit_assert_int(fd, !=, -1);
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
MUNIT_TEST(test_pass_fd)
|
|
{
|
|
int fds[2];
|
|
int rc = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, fds);
|
|
munit_assert_int(rc, ==, 0);
|
|
|
|
_cleanup_close_ int left = fds[0];
|
|
_cleanup_close_ int right = fds[1];
|
|
_cleanup_fclose_ FILE *fp = tmpfile();
|
|
|
|
/* actual message data to be sent */
|
|
char data[] = "some data\n";
|
|
|
|
/* Send the fd from left to right */
|
|
int sendfds[2] = { fileno(fp), -1 };
|
|
int sendrc = xsend_with_fd(left, data, sizeof(data), sendfds);
|
|
munit_assert_int(sendrc, ==, sizeof(data));
|
|
|
|
/* Write some data to the file on it's real fd */
|
|
char buf[] = "foo\n";
|
|
fwrite(buf, sizeof(buf), 1, fp);
|
|
fflush(fp);
|
|
|
|
/* Receive the fd on the right */
|
|
_cleanup_free_ int *recvfds = NULL;
|
|
char recvbuf[sizeof(data)];
|
|
int recvrc = xread_with_fds(right, recvbuf, sizeof(recvbuf), &recvfds);
|
|
munit_assert_int(recvrc, ==, sizeof(data));
|
|
munit_assert_string_equal(recvbuf, data);
|
|
munit_assert_ptr_not_null(recvfds);
|
|
munit_assert_int(recvfds[0], !=, -1);
|
|
munit_assert_int(recvfds[1], ==, -1);
|
|
|
|
/* Now check that we can read "foo" from the passed fd */
|
|
_cleanup_close_ int passed_fd = recvfds[0];
|
|
off_t off = lseek(passed_fd, 0, SEEK_SET);
|
|
munit_assert_int(off, ==, 0);
|
|
char readbuf[64];
|
|
int readrc = xread(passed_fd, readbuf, sizeof(readbuf));
|
|
munit_assert_int(readrc, ==, sizeof(buf));
|
|
munit_assert_string_equal(readbuf, buf);
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
|
|
int
|
|
main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)])
|
|
{
|
|
return munit_tests_run(argc, argv);
|
|
}
|