bluez/unit/util.c
Archie Pusaka 10400c77c6 unit/gobex: remove timer only when it's not removed yet
There are instances where timer is removed because timeout has
occurred, yet we still remove it again by the end of the test. This
causes double removal and prints ugly messages which obscures the
real culprit.

Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
2021-05-06 12:57:45 -07:00

195 lines
4.1 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
*
* OBEX library with GLib integration
*
* Copyright (C) 2011 Intel Corporation. All rights reserved.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include "gobex/gobex.h"
#include "util.h"
GQuark test_error_quark(void)
{
return g_quark_from_static_string("test-error-quark");
}
static void dump_bytes(const uint8_t *buf, size_t buf_len)
{
size_t i;
for (i = 0; i < buf_len; i++)
g_printerr("%02x ", buf[i]);
g_printerr("\n");
}
void dump_bufs(const void *mem1, size_t len1, const void *mem2, size_t len2)
{
g_printerr("\nExpected: ");
dump_bytes(mem1, len1);
g_printerr("Got: ");
dump_bytes(mem2, len2);
}
void assert_memequal(const void *mem1, size_t len1,
const void *mem2, size_t len2)
{
if (len1 == len2 && memcmp(mem1, mem2, len1) == 0)
return;
dump_bufs(mem1, len1, mem2, len2);
g_assert(0);
}
GObex *create_gobex(int fd, GObexTransportType transport_type,
gboolean close_on_unref)
{
GIOChannel *io;
GObex *obex;
io = g_io_channel_unix_new(fd);
g_assert(io != NULL);
g_io_channel_set_close_on_unref(io, close_on_unref);
obex = g_obex_new(io, transport_type, -1, -1);
g_io_channel_unref(io);
return obex;
}
void create_endpoints(GObex **obex, GIOChannel **io, int sock_type)
{
GObexTransportType transport_type;
int sv[2];
if (socketpair(AF_UNIX, sock_type | SOCK_NONBLOCK, 0, sv) < 0) {
g_printerr("socketpair: %s", strerror(errno));
abort();
}
if (sock_type == SOCK_STREAM)
transport_type = G_OBEX_TRANSPORT_STREAM;
else
transport_type = G_OBEX_TRANSPORT_PACKET;
*obex = create_gobex(sv[0], transport_type, TRUE);
g_assert(*obex != NULL);
if (io == NULL) {
close(sv[1]);
return;
}
*io = g_io_channel_unix_new(sv[1]);
g_assert(*io != NULL);
g_io_channel_set_encoding(*io, NULL, NULL);
g_io_channel_set_buffered(*io, FALSE);
g_io_channel_set_close_on_unref(*io, TRUE);
}
gboolean test_timeout(gpointer user_data)
{
struct test_data *d = user_data;
if (!g_main_loop_is_running(d->mainloop))
return FALSE;
d->err = g_error_new(TEST_ERROR, TEST_ERROR_TIMEOUT, "Timed out");
d->timer_id = 0;
g_main_loop_quit(d->mainloop);
return FALSE;
}
gboolean test_io_cb(GIOChannel *io, GIOCondition cond, gpointer user_data)
{
struct test_data *d = user_data;
GIOStatus status;
gsize bytes_written, rbytes, send_buf_len, expect_len;
char buf[65535];
const char *send_buf, *expect;
expect = d->recv[d->count].data;
expect_len = d->recv[d->count].len;
send_buf = d->send[d->count].data;
send_buf_len = d->send[d->count].len;
d->count++;
if (!(cond & G_IO_IN))
goto send;
status = g_io_channel_read_chars(io, buf, sizeof(buf), &rbytes, NULL);
if (status != G_IO_STATUS_NORMAL) {
g_print("io_cb count %u\n", d->count);
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
"Reading data failed with status %d", status);
goto failed;
}
if (rbytes < expect_len) {
g_print("io_cb count %u\n", d->count);
dump_bufs(expect, expect_len, buf, rbytes);
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
"Not enough data from socket");
goto failed;
}
if (memcmp(buf, expect, expect_len) != 0) {
g_print("io_cb count %u\n", d->count);
dump_bufs(expect, expect_len, buf, rbytes);
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
"Received data is not correct");
goto failed;
}
send:
if ((gssize) send_buf_len < 0)
goto failed;
g_io_channel_write_chars(io, send_buf, send_buf_len, &bytes_written,
NULL);
if (bytes_written != send_buf_len) {
g_print("io_cb count %u\n", d->count);
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
"Unable to write to socket");
goto failed;
}
if (d->count >= TEST_BUF_MAX) {
g_print("io_cb count %u\n", d->count);
goto failed;
}
if (d->recv[d->count].len < 0 || (gssize) expect_len < 0)
return test_io_cb(io, G_IO_OUT, user_data);
return TRUE;
failed:
d->io_id = 0;
g_main_loop_quit(d->mainloop);
return FALSE;
}