mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-16 08:44:38 +08:00
10400c77c6
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>
1362 lines
32 KiB
C
1362 lines
32 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
*
|
|
* OBEX library with GLib integration
|
|
*
|
|
* Copyright (C) 2011 Intel Corporation. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
#include "gobex/gobex.h"
|
|
|
|
#include "util.h"
|
|
|
|
#define FINAL_BIT 0x80
|
|
|
|
static GMainLoop *mainloop = NULL;
|
|
|
|
static uint8_t pkt_connect_req[] = { G_OBEX_OP_CONNECT | FINAL_BIT,
|
|
0x00, 0x07, 0x10, 0x00, 0x10, 0x00 };
|
|
static uint8_t pkt_connect_rsp[] = { 0x20 | FINAL_BIT, 0x00, 0x07,
|
|
0x10, 0x00, 0x10, 0x00 };
|
|
|
|
static uint8_t pkt_disconnect_req[] = { G_OBEX_OP_DISCONNECT | FINAL_BIT,
|
|
0x00, 0x03 };
|
|
static uint8_t pkt_disconnect_rsp[] = { 0x20 | FINAL_BIT, 0x00, 0x03 };
|
|
|
|
static uint8_t pkt_unauth_rsp[] = { 0x41 | FINAL_BIT, 0x00, 0x1c,
|
|
0x10, 0x00, 0x10, 0x00, 0x4d, 0x00,
|
|
0x15, 0x00, 0x10, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00 };
|
|
static uint8_t pkt_auth_req[] = { G_OBEX_OP_CONNECT | FINAL_BIT, 0x00, 0x1c,
|
|
0x10, 0x00, 0x10, 0x00, 0x4e, 0x00,
|
|
0x15, 0x00, 0x10, 0x5a, 0xd4, 0x93,
|
|
0x93, 0xba, 0x4a, 0xf8, 0xac, 0xce,
|
|
0x7f, 0x5b, 0x1a, 0x05, 0x38, 0x74,
|
|
0x24 };
|
|
static uint8_t pkt_auth_rsp[] = { 0x20 | FINAL_BIT, 0x00, 0x07,
|
|
0x10, 0x00, 0x10, 0x00 };
|
|
|
|
static uint8_t pkt_setpath_req[] = { G_OBEX_OP_SETPATH | FINAL_BIT, 0x00, 0x10,
|
|
0x02, 0x00,
|
|
G_OBEX_HDR_NAME, 0x00, 0x0b,
|
|
0, 'd', 0, 'i', 0, 'r', 0, 0 };
|
|
static uint8_t pkt_setpath_up_req[] = { G_OBEX_OP_SETPATH | FINAL_BIT,
|
|
0x00, 0x05, 0x03, 0x00 };
|
|
static uint8_t pkt_setpath_up_down_req[] = { G_OBEX_OP_SETPATH | FINAL_BIT,
|
|
0x00, 0x10, 0x03, 0x00,
|
|
G_OBEX_HDR_NAME, 0x00, 0x0b,
|
|
0, 'd', 0, 'i', 0, 'r', 0, 0 };
|
|
static uint8_t pkt_success_rsp[] = { 0x20 | FINAL_BIT, 0x00, 0x03 };
|
|
|
|
static uint8_t pkt_mkdir_req[] = { G_OBEX_OP_SETPATH | FINAL_BIT, 0x00, 0x10,
|
|
0x00, 0x00,
|
|
G_OBEX_HDR_NAME, 0x00, 0x0b,
|
|
0, 'd', 0, 'i', 0, 'r', 0, 0 };
|
|
|
|
static uint8_t pkt_delete_req[] = { G_OBEX_OP_PUT | FINAL_BIT, 0x00, 0x16,
|
|
G_OBEX_HDR_NAME, 0x00, 0x13,
|
|
0, 'f', 0, 'o', 0, 'o', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0 };
|
|
|
|
static uint8_t pkt_copy_req[] = { G_OBEX_OP_ACTION | FINAL_BIT, 0x00, 0x1b,
|
|
G_OBEX_HDR_ACTION, 0x00,
|
|
G_OBEX_HDR_NAME, 0x00, 0x0b,
|
|
0, 'f', 0, 'o', 0, 'o', 0, 0,
|
|
G_OBEX_HDR_DESTNAME, 0x00, 0x0b,
|
|
0, 'b', 0, 'a', 0, 'r', 0, 0 };
|
|
static uint8_t pkt_move_req[] = { G_OBEX_OP_ACTION | FINAL_BIT, 0x00, 0x1b,
|
|
G_OBEX_HDR_ACTION, 0x01,
|
|
G_OBEX_HDR_NAME, 0x00, 0x0b,
|
|
0, 'f', 0, 'o', 0, 'o', 0, 0,
|
|
G_OBEX_HDR_DESTNAME, 0x00, 0x0b,
|
|
0, 'b', 0, 'a', 0, 'r', 0, 0 };
|
|
|
|
static uint8_t pkt_nval_connect_rsp[] = { 0x10 | FINAL_BIT, 0x00, 0x05,
|
|
0x10, 0x00, };
|
|
static uint8_t pkt_abort_rsp[] = { 0x90, 0x00, 0x03 };
|
|
static uint8_t pkt_nval_short_rsp[] = { 0x10 | FINAL_BIT, 0x12 };
|
|
static uint8_t pkt_put_body[] = { G_OBEX_OP_PUT, 0x00, 0x0a,
|
|
G_OBEX_HDR_BODY, 0x00, 0x07,
|
|
1, 2, 3, 4 };
|
|
|
|
static gboolean timeout(gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (!g_main_loop_is_running(mainloop))
|
|
return FALSE;
|
|
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_TIMEOUT, "Timed out");
|
|
d->timer_id = 0;
|
|
|
|
g_main_loop_quit(mainloop);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void connect_rsp(GObex *obex, GError *err, GObexPacket *rsp,
|
|
gpointer user_data)
|
|
{
|
|
guint8 rsp_code;
|
|
gboolean final;
|
|
GError **test_err = user_data;
|
|
|
|
if (err != NULL) {
|
|
g_assert(*test_err == NULL);
|
|
*test_err = g_error_copy(err);
|
|
goto done;
|
|
}
|
|
|
|
rsp_code = g_obex_packet_get_operation(rsp, &final);
|
|
if (rsp_code != 0x20) {
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Unexpected response 0x%02x", rsp_code);
|
|
goto done;
|
|
}
|
|
|
|
if (!final) {
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Connect response didn't have final bit");
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
g_main_loop_quit(mainloop);
|
|
}
|
|
|
|
static void nval_connect_rsp(GObex *obex, GError *err, GObexPacket *rsp,
|
|
gpointer user_data)
|
|
{
|
|
GError **test_err = user_data;
|
|
|
|
if (!g_error_matches(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR))
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Did not get expected parse error");
|
|
|
|
g_main_loop_quit(mainloop);
|
|
}
|
|
|
|
static void timeout_rsp(GObex *obex, GError *err, GObexPacket *rsp,
|
|
gpointer user_data)
|
|
{
|
|
GError **test_err = user_data;
|
|
|
|
if (!g_error_matches(err, G_OBEX_ERROR, G_OBEX_ERROR_TIMEOUT))
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Did not get expected timeout error");
|
|
|
|
g_main_loop_quit(mainloop);
|
|
}
|
|
|
|
static gboolean recv_and_send(GIOChannel *io, void *data, gsize len,
|
|
GError **err)
|
|
{
|
|
gsize bytes_written, rbytes;
|
|
char buf[255];
|
|
GIOStatus status;
|
|
|
|
status = g_io_channel_read_chars(io, buf, sizeof(buf), &rbytes, NULL);
|
|
if (status != G_IO_STATUS_NORMAL) {
|
|
g_set_error(err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"read failed with status %d", status);
|
|
return FALSE;
|
|
}
|
|
|
|
if (data == NULL)
|
|
return TRUE;
|
|
|
|
g_io_channel_write_chars(io, data, len, &bytes_written, NULL);
|
|
if (bytes_written != len) {
|
|
g_set_error(err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Unable to write to socket");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean send_connect_rsp(GIOChannel *io, GIOCondition cond,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (!recv_and_send(io, pkt_connect_rsp, sizeof(pkt_connect_rsp),
|
|
&d->err))
|
|
g_main_loop_quit(mainloop);
|
|
|
|
d->io_id = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean send_nval_connect_rsp(GIOChannel *io, GIOCondition cond,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (!recv_and_send(io, pkt_nval_connect_rsp,
|
|
sizeof(pkt_nval_connect_rsp), &d->err))
|
|
g_main_loop_quit(mainloop);
|
|
|
|
d->io_id = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean send_nval_short_rsp(GIOChannel *io, GIOCondition cond,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (!recv_and_send(io, pkt_nval_short_rsp,
|
|
sizeof(pkt_nval_short_rsp), &d->err))
|
|
g_main_loop_quit(mainloop);
|
|
|
|
d->io_id = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean send_nothing(GIOChannel *io, GIOCondition cond,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (!recv_and_send(io, NULL, 0, &d->err))
|
|
g_main_loop_quit(mainloop);
|
|
|
|
d->io_id = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
static void send_req(GObexPacket *req, GObexResponseFunc rsp_func,
|
|
GIOFunc send_rsp_func, int req_timeout,
|
|
int transport_type)
|
|
{
|
|
struct test_data d;
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
int test_time;
|
|
GObex *obex;
|
|
|
|
create_endpoints(&obex, &io, transport_type);
|
|
|
|
d.err = NULL;
|
|
g_obex_send_req(obex, req, req_timeout, rsp_func, &d.err, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, send_rsp_func, &d);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
if (req_timeout > 0)
|
|
test_time = req_timeout + 1;
|
|
else
|
|
test_time = 1;
|
|
|
|
d.timer_id = g_timeout_add_seconds(test_time, timeout, &d);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_main_loop_unref(mainloop);
|
|
mainloop = NULL;
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void send_connect(GObexResponseFunc rsp_func, GIOFunc send_rsp_func,
|
|
int req_timeout, int transport_type)
|
|
{
|
|
GObexPacket *req;
|
|
guint8 connect_data[] = { 0x10, 0x00, 0x10, 0x00 };
|
|
|
|
req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, G_OBEX_HDR_INVALID);
|
|
g_assert(req != NULL);
|
|
|
|
g_obex_packet_set_data(req, connect_data, sizeof(connect_data),
|
|
G_OBEX_DATA_REF);
|
|
|
|
send_req(req, rsp_func, send_rsp_func, req_timeout, transport_type);
|
|
}
|
|
|
|
static void test_send_connect_req_stream(void)
|
|
{
|
|
send_connect(connect_rsp, send_connect_rsp, -1, SOCK_STREAM);
|
|
}
|
|
|
|
static void test_send_connect_req_pkt(void)
|
|
{
|
|
send_connect(connect_rsp, send_connect_rsp, -1, SOCK_SEQPACKET);
|
|
}
|
|
|
|
static void test_send_nval_connect_req_stream(void)
|
|
{
|
|
send_connect(nval_connect_rsp, send_nval_connect_rsp, -1, SOCK_STREAM);
|
|
}
|
|
|
|
static void test_send_nval_connect_req_pkt(void)
|
|
{
|
|
send_connect(nval_connect_rsp, send_nval_connect_rsp, -1,
|
|
SOCK_SEQPACKET);
|
|
}
|
|
|
|
static void test_send_nval_connect_req_short_pkt(void)
|
|
{
|
|
send_connect(nval_connect_rsp, send_nval_short_rsp, -1,
|
|
SOCK_SEQPACKET);
|
|
}
|
|
|
|
static void test_send_connect_req_timeout_stream(void)
|
|
{
|
|
send_connect(timeout_rsp, send_nothing, 0, SOCK_STREAM);
|
|
}
|
|
|
|
static void test_send_connect_req_timeout_pkt(void)
|
|
{
|
|
send_connect(timeout_rsp, send_nothing, 0, SOCK_SEQPACKET);
|
|
}
|
|
|
|
static void req_done(GObex *obex, GError *err, GObexPacket *rsp,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (!g_error_matches(err, G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED))
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Did not get expected cancelled error");
|
|
|
|
g_main_loop_quit(mainloop);
|
|
}
|
|
|
|
static void test_cancel_req_immediate(void)
|
|
{
|
|
GObexPacket *req;
|
|
struct test_data d;
|
|
gboolean ret;
|
|
|
|
create_endpoints(&d.obex, NULL, SOCK_STREAM);
|
|
|
|
d.err = NULL;
|
|
|
|
req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_INVALID);
|
|
d.id = g_obex_send_req(d.obex, req, -1, req_done, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
g_assert(d.id != 0);
|
|
|
|
ret = g_obex_cancel_req(d.obex, d.id, FALSE);
|
|
g_assert(ret == TRUE);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_assert_no_error(d.err);
|
|
|
|
g_obex_unref(d.obex);
|
|
g_main_loop_unref(mainloop);
|
|
}
|
|
|
|
static gboolean cancel_server(GIOChannel *io, GIOCondition cond,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
GIOStatus status;
|
|
gsize bytes_written, rbytes;
|
|
char buf[255];
|
|
|
|
status = g_io_channel_read_chars(io, buf, sizeof(buf), &rbytes, NULL);
|
|
if (status != G_IO_STATUS_NORMAL) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Reading data failed with status %d", status);
|
|
goto failed;
|
|
}
|
|
|
|
if (rbytes < 3) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Not enough data from socket");
|
|
goto failed;
|
|
}
|
|
|
|
if ((uint8_t) buf[0] == (G_OBEX_OP_PUT | FINAL_BIT)) {
|
|
if (!g_obex_cancel_req(d->obex, d->id, FALSE)) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Cancelling request failed");
|
|
goto failed;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
if ((uint8_t) buf[0] != (G_OBEX_OP_ABORT | FINAL_BIT)) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Neither Put nor Abort packet received");
|
|
goto failed;
|
|
}
|
|
|
|
g_io_channel_write_chars(io, (char *) pkt_abort_rsp,
|
|
sizeof(pkt_abort_rsp), &bytes_written, NULL);
|
|
if (bytes_written != sizeof(pkt_abort_rsp)) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Unable to write to socket");
|
|
goto failed;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
failed:
|
|
d->io_id = 0;
|
|
g_main_loop_quit(mainloop);
|
|
return FALSE;
|
|
}
|
|
|
|
static void test_cancel_req_delay(int transport_type)
|
|
{
|
|
GIOChannel *io;
|
|
struct test_data d;
|
|
GObexPacket *req;
|
|
GIOCondition cond;
|
|
|
|
create_endpoints(&d.obex, &io, transport_type);
|
|
|
|
d.err = NULL;
|
|
|
|
req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_INVALID);
|
|
d.id = g_obex_send_req(d.obex, req, -1, req_done, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
g_assert(d.id != 0);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, cancel_server, &d);
|
|
|
|
d.timer_id = g_timeout_add_seconds(2, timeout, &d);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_assert_no_error(d.err);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(d.obex);
|
|
g_main_loop_unref(mainloop);
|
|
}
|
|
|
|
static void test_cancel_req_delay_stream(void)
|
|
{
|
|
test_cancel_req_delay(SOCK_STREAM);
|
|
}
|
|
|
|
static void test_cancel_req_delay_pkt(void)
|
|
{
|
|
test_cancel_req_delay(SOCK_SEQPACKET);
|
|
}
|
|
|
|
static gboolean rcv_data(GIOChannel *io, GIOCondition cond, gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
struct test_buf *b = d->recv;
|
|
GIOStatus status;
|
|
gsize rbytes;
|
|
char buf[255];
|
|
|
|
if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Unexpected condition %d on socket", cond);
|
|
goto done;
|
|
}
|
|
|
|
status = g_io_channel_read_chars(io, buf, sizeof(buf), &rbytes, NULL);
|
|
if (status != G_IO_STATUS_NORMAL) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Reading data failed with status %d", status);
|
|
goto done;
|
|
}
|
|
|
|
if ((gssize) rbytes != b->len) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Got %zu bytes instead of %zu",
|
|
rbytes, sizeof(pkt_connect_req));
|
|
dump_bufs(b->data, b->len, buf, rbytes);
|
|
goto done;
|
|
}
|
|
|
|
if (memcmp(buf, b->data, rbytes) != 0) {
|
|
g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Mismatch with received data");
|
|
dump_bufs(b->data, b->len, buf, rbytes);
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
d->io_id = 0;
|
|
g_main_loop_quit(mainloop);
|
|
return FALSE;
|
|
}
|
|
|
|
static void test_send_connect(int transport_type)
|
|
{
|
|
guint8 connect_data[] = { 0x10, 0x00, 0x10, 0x00 };
|
|
struct test_data d;
|
|
struct test_buf *b = d.recv;
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObexPacket *req;
|
|
GObex *obex;
|
|
|
|
create_endpoints(&obex, &io, transport_type);
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
b->data = pkt_connect_req;
|
|
b->len = sizeof(pkt_connect_req);
|
|
|
|
req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, G_OBEX_HDR_INVALID);
|
|
g_assert(req != NULL);
|
|
|
|
g_obex_packet_set_data(req, connect_data, sizeof(connect_data),
|
|
G_OBEX_DATA_REF);
|
|
g_obex_send(obex, req, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, rcv_data, &d);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, timeout, &d);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_main_loop_unref(mainloop);
|
|
mainloop = NULL;
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_send_connect_stream(void)
|
|
{
|
|
test_send_connect(SOCK_STREAM);
|
|
}
|
|
|
|
static void test_send_connect_pkt(void)
|
|
{
|
|
test_send_connect(SOCK_SEQPACKET);
|
|
}
|
|
|
|
static void unexpected_disconn(GObex *obex, GError *err, gpointer user_data)
|
|
{
|
|
GError **test_err = user_data;
|
|
|
|
if (!g_error_matches(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR))
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Didn't get parse error as expected");
|
|
|
|
g_main_loop_quit(mainloop);
|
|
}
|
|
|
|
static void test_recv_unexpected(void)
|
|
{
|
|
struct test_data d;
|
|
GObexPacket *req;
|
|
GIOChannel *io;
|
|
GObex *obex;
|
|
guint8 buf[255];
|
|
gssize len;
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
d.err = NULL;
|
|
g_obex_set_disconnect_function(obex, unexpected_disconn, &d.err);
|
|
|
|
req = g_obex_packet_new(G_OBEX_RSP_CONTINUE, TRUE, G_OBEX_HDR_INVALID);
|
|
len = g_obex_packet_encode(req, buf, sizeof(buf));
|
|
g_obex_packet_free(req);
|
|
g_assert_cmpint(len, >=, 0);
|
|
|
|
g_io_channel_write_chars(io, (char *) buf, len, NULL, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, timeout, &d);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_main_loop_unref(mainloop);
|
|
mainloop = NULL;
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static gssize get_body_data(void *buf, gsize len, gpointer user_data)
|
|
{
|
|
uint8_t data[] = { 1, 2, 3, 4 };
|
|
|
|
memcpy(buf, data, sizeof(data));
|
|
|
|
return sizeof(data);
|
|
}
|
|
|
|
static gssize get_body_data_fail(void *buf, gsize len, gpointer user_data)
|
|
{
|
|
g_main_loop_quit(mainloop);
|
|
return -1;
|
|
}
|
|
|
|
static void test_send_on_demand(int transport_type, GObexDataProducer func)
|
|
{
|
|
struct test_data d;
|
|
struct test_buf *b = d.recv;
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObexPacket *req;
|
|
GObex *obex;
|
|
|
|
create_endpoints(&obex, &io, transport_type);
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
b->data = pkt_put_body;
|
|
b->len = sizeof(pkt_put_body);
|
|
|
|
req = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_INVALID);
|
|
g_obex_packet_add_body(req, func, &d);
|
|
|
|
g_obex_send(obex, req, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, rcv_data, &d);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, timeout, &d);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_main_loop_unref(mainloop);
|
|
mainloop = NULL;
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_send_on_demand_stream(void)
|
|
{
|
|
test_send_on_demand(SOCK_STREAM, get_body_data);
|
|
}
|
|
|
|
static void test_send_on_demand_pkt(void)
|
|
{
|
|
test_send_on_demand(SOCK_SEQPACKET, get_body_data);
|
|
}
|
|
|
|
static void test_send_on_demand_fail_stream(void)
|
|
{
|
|
test_send_on_demand(SOCK_STREAM, get_body_data_fail);
|
|
}
|
|
|
|
static void test_send_on_demand_fail_pkt(void)
|
|
{
|
|
test_send_on_demand(SOCK_SEQPACKET, get_body_data_fail);
|
|
}
|
|
|
|
static void handle_connect_req(GObex *obex, GObexPacket *req,
|
|
gpointer user_data)
|
|
{
|
|
GError **test_err = user_data;
|
|
|
|
if (g_obex_packet_get_operation(req, NULL) != G_OBEX_OP_CONNECT)
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Unexpected operation");
|
|
g_main_loop_quit(mainloop);
|
|
|
|
}
|
|
|
|
static void handle_connect_err(GObex *obex, GError *err, gpointer user_data)
|
|
{
|
|
GError **test_err = user_data;
|
|
|
|
g_main_loop_quit(mainloop);
|
|
|
|
if (err != NULL)
|
|
*test_err = g_error_copy(err);
|
|
else
|
|
*test_err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Disconnected");
|
|
}
|
|
|
|
static void recv_connect(int transport_type)
|
|
{
|
|
struct test_data d;
|
|
GObex *obex;
|
|
GIOChannel *io;
|
|
GIOStatus status;
|
|
gsize bytes_written;
|
|
|
|
create_endpoints(&obex, &io, transport_type);
|
|
|
|
d.err = NULL;
|
|
g_obex_add_request_function(obex, G_OBEX_OP_CONNECT,
|
|
handle_connect_req, &d.err);
|
|
g_obex_set_disconnect_function(obex, handle_connect_err, &d.err);
|
|
|
|
status = g_io_channel_write_chars(io, (char *) pkt_connect_req,
|
|
sizeof(pkt_connect_req),
|
|
&bytes_written, NULL);
|
|
g_assert_cmpint(status, ==, G_IO_STATUS_NORMAL);
|
|
g_assert_cmpuint(bytes_written, ==, sizeof(pkt_connect_req));
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, timeout, &d);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
|
|
g_obex_unref(obex);
|
|
g_io_channel_unref(io);
|
|
|
|
g_main_loop_unref(mainloop);
|
|
mainloop = NULL;
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_recv_connect_stream(void)
|
|
{
|
|
recv_connect(SOCK_STREAM);
|
|
}
|
|
|
|
static void test_recv_connect_pkt(void)
|
|
{
|
|
recv_connect(SOCK_SEQPACKET);
|
|
}
|
|
|
|
static void disconn_ev(GObex *obex, GError *err, gpointer user_data)
|
|
{
|
|
GError **test_err = user_data;
|
|
|
|
if (!g_error_matches(err, G_OBEX_ERROR, G_OBEX_ERROR_DISCONNECTED))
|
|
g_set_error(test_err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
|
|
"Did not get expected disconnect error");
|
|
|
|
g_main_loop_quit(mainloop);
|
|
}
|
|
|
|
static void test_disconnect(void)
|
|
{
|
|
struct test_data d;
|
|
GObex *obex;
|
|
GIOChannel *io;
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
d.err = NULL;
|
|
g_obex_set_disconnect_function(obex, disconn_ev, &d.err);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, timeout, &d);
|
|
|
|
mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
g_io_channel_shutdown(io, FALSE, NULL);
|
|
|
|
g_main_loop_run(mainloop);
|
|
|
|
g_assert_no_error(d.err);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_main_loop_unref(mainloop);
|
|
mainloop = NULL;
|
|
}
|
|
|
|
static void test_ref_unref(void)
|
|
{
|
|
GObex *obex;
|
|
|
|
obex = create_gobex(STDIN_FILENO, G_OBEX_TRANSPORT_STREAM, FALSE);
|
|
|
|
g_assert(obex != NULL);
|
|
|
|
obex = g_obex_ref(obex);
|
|
|
|
g_obex_unref(obex);
|
|
g_obex_unref(obex);
|
|
}
|
|
|
|
static void test_basic(void)
|
|
{
|
|
GObex *obex;
|
|
|
|
obex = create_gobex(STDIN_FILENO, G_OBEX_TRANSPORT_STREAM, FALSE);
|
|
|
|
g_assert(obex != NULL);
|
|
|
|
g_obex_unref(obex);
|
|
}
|
|
|
|
static void test_null_io(void)
|
|
{
|
|
GObex *obex;
|
|
|
|
obex = g_obex_new(NULL, 0, -1, -1);
|
|
|
|
g_assert(obex == NULL);
|
|
}
|
|
|
|
static void req_complete(GObex *obex, GError *err, GObexPacket *rsp,
|
|
gpointer user_data)
|
|
{
|
|
struct test_data *d = user_data;
|
|
|
|
if (err != NULL)
|
|
d->err = g_error_copy(err);
|
|
|
|
g_main_loop_quit(d->mainloop);
|
|
}
|
|
|
|
static void test_connect(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_connect_req, sizeof(pkt_connect_req) } }, {
|
|
{ pkt_connect_rsp, sizeof(pkt_connect_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_connect(obex, req_complete, &d, &d.err, G_OBEX_HDR_INVALID);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_obex_disconnect(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_disconnect_req, sizeof(pkt_disconnect_req) } }, {
|
|
{ pkt_disconnect_rsp, sizeof(pkt_disconnect_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_disconnect(obex, req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_auth(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_connect_req, sizeof(pkt_connect_req) },
|
|
{ pkt_auth_req, sizeof(pkt_auth_req) } }, {
|
|
{ pkt_unauth_rsp, sizeof(pkt_unauth_rsp) },
|
|
{ pkt_auth_rsp, sizeof(pkt_auth_rsp) } },
|
|
};
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_connect(obex, req_complete, &d, &d.err, G_OBEX_HDR_INVALID);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 2);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_auth_fail(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_connect_req, sizeof(pkt_connect_req) },
|
|
{ pkt_auth_req, sizeof(pkt_auth_req) } }, {
|
|
{ pkt_unauth_rsp, sizeof(pkt_unauth_rsp) },
|
|
{ pkt_unauth_rsp, sizeof(pkt_unauth_rsp) } },
|
|
};
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_connect(obex, req_complete, &d, &d.err, G_OBEX_HDR_INVALID);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 2);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_setpath(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_setpath_req, sizeof(pkt_setpath_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_setpath(obex, "dir", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_setpath_up(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_setpath_up_req, sizeof(pkt_setpath_up_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_setpath(obex, "..", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_setpath_up_down(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_setpath_up_down_req,
|
|
sizeof(pkt_setpath_up_down_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_setpath(obex, "../dir", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_mkdir(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_mkdir_req, sizeof(pkt_mkdir_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_mkdir(obex, "dir", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_delete(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_delete_req, sizeof(pkt_delete_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_delete(obex, "foo.txt", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_copy(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_copy_req, sizeof(pkt_copy_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_copy(obex, "foo", "bar", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
static void test_move(void)
|
|
{
|
|
GIOChannel *io;
|
|
GIOCondition cond;
|
|
GObex *obex;
|
|
struct test_data d = { 0, NULL, {
|
|
{ pkt_move_req, sizeof(pkt_move_req) } }, {
|
|
{ pkt_success_rsp, sizeof(pkt_success_rsp) } } };
|
|
|
|
create_endpoints(&obex, &io, SOCK_STREAM);
|
|
|
|
cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
|
|
d.io_id = g_io_add_watch(io, cond, test_io_cb, &d);
|
|
|
|
d.mainloop = g_main_loop_new(NULL, FALSE);
|
|
|
|
d.timer_id = g_timeout_add_seconds(1, test_timeout, &d);
|
|
|
|
g_obex_move(obex, "foo", "bar", req_complete, &d, &d.err);
|
|
g_assert_no_error(d.err);
|
|
|
|
g_main_loop_run(d.mainloop);
|
|
|
|
g_assert_cmpuint(d.count, ==, 1);
|
|
|
|
g_main_loop_unref(d.mainloop);
|
|
|
|
if (d.timer_id > 0)
|
|
g_source_remove(d.timer_id);
|
|
if (d.io_id > 0)
|
|
g_source_remove(d.io_id);
|
|
|
|
g_io_channel_unref(io);
|
|
g_obex_unref(obex);
|
|
|
|
g_assert_no_error(d.err);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
g_test_init(&argc, &argv, NULL);
|
|
|
|
g_test_add_func("/gobex/null_io", test_null_io);
|
|
g_test_add_func("/gobex/basic", test_basic);
|
|
g_test_add_func("/gobex/ref_unref", test_ref_unref);
|
|
|
|
g_test_add_func("/gobex/test_disconnect", test_disconnect);
|
|
|
|
g_test_add_func("/gobex/test_recv_connect_stream",
|
|
test_recv_connect_stream);
|
|
g_test_add_func("/gobex/test_recv_connect_pkt",
|
|
test_recv_connect_pkt);
|
|
g_test_add_func("/gobex/test_send_connect_stream",
|
|
test_send_connect_stream);
|
|
g_test_add_func("/gobex/test_send_connect_pkt",
|
|
test_send_connect_pkt);
|
|
g_test_add_func("/gobex/test_recv_unexpected",
|
|
test_recv_unexpected);
|
|
g_test_add_func("/gobex/test_send_on_demand_stream",
|
|
test_send_on_demand_stream);
|
|
g_test_add_func("/gobex/test_send_on_demand_pkt",
|
|
test_send_on_demand_pkt);
|
|
g_test_add_func("/gobex/test_send_on_demand_fail_stream",
|
|
test_send_on_demand_fail_stream);
|
|
g_test_add_func("/gobex/test_send_on_demand_fail_pkt",
|
|
test_send_on_demand_fail_pkt);
|
|
g_test_add_func("/gobex/test_send_connect_req_stream",
|
|
test_send_connect_req_stream);
|
|
g_test_add_func("/gobex/test_send_connect_req_pkt",
|
|
test_send_connect_req_pkt);
|
|
g_test_add_func("/gobex/test_send_nval_connect_req_stream",
|
|
test_send_nval_connect_req_stream);
|
|
g_test_add_func("/gobex/test_send_nval_connect_req_pkt",
|
|
test_send_nval_connect_req_pkt);
|
|
g_test_add_func("/gobex/test_send_nval_connect_req_short_pkt",
|
|
test_send_nval_connect_req_short_pkt);
|
|
g_test_add_func("/gobex/test_send_connect_req_timeout_stream",
|
|
test_send_connect_req_timeout_stream);
|
|
g_test_add_func("/gobex/test_send_connect_req_timeout_pkt",
|
|
test_send_connect_req_timeout_pkt);
|
|
|
|
|
|
g_test_add_func("/gobex/test_cancel_req_immediate",
|
|
test_cancel_req_immediate);
|
|
g_test_add_func("/gobex/test_cancel_req_delay_stream",
|
|
test_cancel_req_delay_stream);
|
|
g_test_add_func("/gobex/test_cancel_req_delay_pkt",
|
|
test_cancel_req_delay_pkt);
|
|
|
|
g_test_add_func("/gobex/test_connect", test_connect);
|
|
g_test_add_func("/gobex/test_obex_disconnect", test_obex_disconnect);
|
|
g_test_add_func("/gobex/test_auth", test_auth);
|
|
g_test_add_func("/gobex/test_auth_fail", test_auth_fail);
|
|
|
|
g_test_add_func("/gobex/test_setpath", test_setpath);
|
|
g_test_add_func("/gobex/test_setpath_up", test_setpath_up);
|
|
g_test_add_func("/gobex/test_setpath_up_down", test_setpath_up_down);
|
|
|
|
g_test_add_func("/gobex/test_mkdir", test_mkdir);
|
|
|
|
g_test_add_func("/gobex/test_delete", test_delete);
|
|
|
|
g_test_add_func("/gobex/test_copy", test_copy);
|
|
g_test_add_func("/gobex/test_move", test_move);
|
|
|
|
return g_test_run();
|
|
}
|