/* SPDX-License-Identifier: BSD-2-Clause */ /* * Debugger test remote. * * Copyright (c) 2016 Chris Johns (chrisj@rtems.org) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tmacros.h" #include #include #include #include #include #include #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); }