/*
* Debugger test remote.
*
* Copyright (c) 2016 Chris Johns (chrisj@rtems.org)
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tmacros.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <rtems/rtems-debugger.h>
#include <rtems/debugger/rtems-debugger-server.h>
#include <rtems/debugger/rtems-debugger-remote.h>
#include "system.h"
/**
* Remote data.
*/
typedef struct
{
int connect_count;
bool connected;
size_t out;
size_t in;
} rtems_debugger_remote_test;
static const char* out[] =
{
"+",
"xxxxx",
"$x#aa",
"$qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;"
"vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+#df",
"$vMustReplyEmpty#3a",
"+",
"$Hgp0.0#ad",
"+",
"$qTStatus#49",
"+",
"$?#3f",
"+",
"$qfThreadInfo#bb",
"+",
"$qsThreadInfo#c8",
"-",
"+",
"$qAttached:1#fa",
"+",
"$Hc-1#09",
"+",
"$qOffsets#4b",
"+",
"$g#67"
"+",
"$D;1#b0",
"+"
};
static const char* in[] =
{
/* 0 */
"-",
/* 1 */
"+",
"$qSupported:PacketSize=4096;QNonStop-;multiprocess+;swbreak+;hwbreak-;"
"qRelocInsn-;fork-events-;vfork-events-;exec-events-;vContSupported+;"
"QThreadEvents-;no-resumed+#b3",
/* 3 */
"+",
"$#00",
/* 5 */
"+",
"$OK#9a",
/* 7 */
"+",
"$#00",
/* 9 */
"+",
"$T00thread:p1.0a010001;#23",
/* 11 */
"+",
"**",
/* 13 */
"+",
"$l#6c",
"$l#6c",
/* 16 */
"+",
"$1#31",
/* 18 */
"+",
"$OK#9a",
/* 20 */
"+",
"$#00",
/* 22 */
"+",
"**",
"+",
"$OK#9a"
};
static int
test_remote_begin(rtems_debugger_remote* remote, const char* device)
{
rtems_debugger_remote_test* test;
rtems_debugger_printf("error: rtems-db: test remote: begin\n");
rtems_debugger_lock();
/*
* Check the device.
*/
rtems_test_assert(strcmp(device, "something") == 0);
test = malloc(sizeof(rtems_debugger_remote_test));
rtems_test_assert(test != NULL);
remote->data = test;
test->connect_count = 0;
test->connected = false;
test->out = 0;
test->in = 0;
rtems_debugger_unlock();
return 0;
}
static int
test_remote_end(rtems_debugger_remote* remote)
{
rtems_debugger_remote_test* test;
rtems_debugger_printf("error: rtems-db: test remote: end\n");
rtems_debugger_lock();
rtems_test_assert(remote != NULL);
rtems_test_assert(remote->data != NULL);
test = (rtems_debugger_remote_test*) remote->data;
test->connected = false;
free(test);
rtems_debugger_unlock();
return 0;
}
static int
test_remote_connect(rtems_debugger_remote* remote)
{
rtems_debugger_remote_test* test;
rtems_test_assert(remote != NULL);
rtems_test_assert(remote->data != NULL);
test = (rtems_debugger_remote_test*) remote->data;
if (test->connect_count > 0) {
rtems_event_set out = 0;
rtems_test_assert(rtems_event_receive(RTEMS_EVENT_1,
RTEMS_EVENT_ALL | RTEMS_WAIT,
RTEMS_NO_TIMEOUT,
&out) == RTEMS_SUCCESSFUL);
}
rtems_debugger_printf("error: rtems-db: test remote: connect\n");
++test->connect_count;
test->connected = true;
test->out = 0;
test->in = 0;
return 0;
}
static int
test_remote_disconnect(rtems_debugger_remote* remote)
{
rtems_debugger_remote_test* test;
rtems_test_assert(remote != NULL);
rtems_test_assert(remote->data != NULL);
test = (rtems_debugger_remote_test*) remote->data;
rtems_debugger_printf("rtems-db: test remote: disconnect host\n");
rtems_debugger_lock();
rtems_test_assert(test->connected == true);
test->connected = false;
rtems_debugger_unlock();
return 0;
}
static bool
test_remote_isconnected(rtems_debugger_remote* remote)
{
rtems_debugger_remote_test* test;
bool isconnected;
rtems_test_assert(remote != NULL);
rtems_test_assert(remote->data != NULL);
test = (rtems_debugger_remote_test*) remote->data;
isconnected = test != NULL && test->connected;
rtems_debugger_printf("rtems-db: test remote: isconnected: %s\n",
isconnected ? "connected" : "not-connected");
return isconnected;
}
static void
test_remote_print(const char* label, const char* buf, size_t size)
{
printf(" remote: %s: ", label);
while (size-- > 0) {
printf("%c", *buf++);
}
printf("\n");
}
static ssize_t
test_remote_receive(rtems_debugger_remote* remote,
void* buf,
size_t nbytes)
{
rtems_debugger_remote_test* test;
size_t len;
rtems_test_assert(remote != NULL);
rtems_test_assert(remote->data != NULL);
test = (rtems_debugger_remote_test*) remote->data;
rtems_test_assert(test->out < RTEMS_DEBUGGER_NUMOF(out));
len = strlen(out[test->out]);
printf(" remote: rx: message=%zu length=%zu\n", test->out, len);
test_remote_print("rx", out[test->out], len);
rtems_test_assert(len < nbytes);
memcpy(buf, out[test->out++], len);
return len;
}
static ssize_t
test_remote_send(rtems_debugger_remote* remote,
const void* buf,
size_t nbytes)
{
rtems_debugger_remote_test* test;
size_t len;
bool no_match;
rtems_test_assert(remote != NULL);
rtems_test_assert(remote->data != NULL);
test = (rtems_debugger_remote_test*) remote->data;
rtems_test_assert(test->in < RTEMS_DEBUGGER_NUMOF(in));
len = strlen(in[test->in]);
no_match = len == 2 && strcmp(in[test->in], "**") == 0;
printf(" remote: tx: message=%zu length=%zu\n", test->in, len);
if (!no_match)
rtems_test_assert(len == nbytes);
test_remote_print("tx", buf, nbytes);
if (!no_match)
rtems_test_assert(memcmp(buf, in[test->in], nbytes) == 0);
test->in++;
return nbytes;
}
static rtems_debugger_remote remote_test =
{
.name = "test",
.begin = test_remote_begin,
.end = test_remote_end,
.connect = test_remote_connect,
.disconnect = test_remote_disconnect,
.isconnected = test_remote_isconnected,
.read = test_remote_receive,
.write = test_remote_send
};
int
rtems_debugger_register_test_remote(void)
{
return rtems_debugger_remote_register(&remote_test);
}