Skip to content

Commit

Permalink
Added unit tests to test private functions
Browse files Browse the repository at this point in the history
These functions implement the RSP protocol and deal with the string buffer.
  • Loading branch information
shivmgg committed Jul 6, 2018
1 parent b65770f commit acc9d98
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 60 deletions.
46 changes: 46 additions & 0 deletions src/libosd/gdbserver-private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* Copyright 2018 The Open SoC Debug Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef OSD_GDBSERVER_PRIVATE_H
#define OSD_GDBSERVER_PRIVATE_H

#include <osd/hostmod.h>
#include <osd/osd.h>

#include <stdlib.h>

/**
* Return packet-data from the received data buffer by validating the checksum
*
* @param buf_p the pointer to the received packet buffer data
* @param ver_checksum '1' indicates valid checksum
* @param len the length of the packet-data
* @param buffer the packet-data received
*
*/
osd_result validate_rsp_packet(char *buf_p, bool *ver_checksum, int *len,
char *buffer);


/**
* Set packet-data into the RSP format: $packet-data#checksum
*
* @param buffer the packet-data buffer
* @param len the length of the packet-data
* @param packet_buffer the packet buffer in RSP format
*/
osd_result configure_rsp_packet(char *buffer, int len, char *packet_buffer);

#endif // OSD_GDBSERVER_PRIVATE_H
124 changes: 68 additions & 56 deletions src/libosd/gdbserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

#include <osd/gdbserver.h>
#include "gdbserver-private.h"
#include <osd/module.h>
#include <osd/osd.h>
#include <osd/reg.h>
Expand Down Expand Up @@ -128,33 +129,6 @@ osd_result osd_gdbserver_connect(struct osd_gdbserver_ctx *ctx, char *name,
return OSD_ERROR_CONNECTION_FAILED;
}

struct sockaddr_in addr_in;
addr_in.sin_port = 0;
socklen_t addr_in_size = sizeof(addr_in);

getsockname(ctx->fd, (struct sockaddr *)&addr_in, &addr_in_size);
printf("server started on %s, listening on port %d\n", name,
ntohs(addr_in.sin_port));

while (1) {
ctx->client_fd =
accept(ctx->fd, (struct sockaddr *)&addr_in, &addr_in_size);
if (OSD_FAILED(ctx->client_fd)) {
rv = close(ctx->client_fd);
if (OSD_SUCCEEDED(rv)) {
break;
}
}
printf("Server got connection from client %s\n",
inet_ntoa(addr_in.sin_addr));

if (OSD_SUCCEEDED(close(ctx->client_fd))) {
break;
}
}

close(ctx->fd);

return OSD_OK;
}

Expand Down Expand Up @@ -185,6 +159,47 @@ void osd_gdbserver_free(struct osd_gdbserver_ctx **ctx_p)
*ctx_p = NULL;
}

API_EXPORT
osd_result osd_gdbserver_start(struct osd_gdbserver_ctx *ctx)
{
osd_result rv;

struct sockaddr_in addr_in;
addr_in.sin_port = 0;
socklen_t addr_in_size = sizeof(addr_in);

getsockname(ctx->fd, (struct sockaddr *)&addr_in, &addr_in_size);
printf("server started listening on port %d\n", ntohs(addr_in.sin_port));

while (1) {
ctx->client_fd =
accept(ctx->fd, (struct sockaddr *)&addr_in, &addr_in_size);
if (OSD_FAILED(ctx->client_fd)) {
rv = close(ctx->client_fd);
if (OSD_SUCCEEDED(rv)) {
break;
}
}

// At this point, connection is established between GDB client
// and gdbserver, and they are ready to transfer data.
// More functions to be added
printf("Server got connection from client %s\n",
inet_ntoa(addr_in.sin_addr));

if (OSD_SUCCEEDED(close(ctx->client_fd))) {
break;
}
}
return OSD_OK;
}

API_EXPORT
osd_result osd_gdbserver_stop(struct osd_gdbserver_ctx *ctx)
{
return close(ctx->fd);
}

API_EXPORT
osd_result osd_gdbserver_read_data(struct osd_gdbserver_ctx *ctx)
{
Expand Down Expand Up @@ -225,8 +240,6 @@ osd_result osd_gdbserver_write_data(struct osd_gdbserver_ctx *ctx, char *data,

static osd_result get_char(struct osd_gdbserver_ctx *ctx, int *ch)
{
osd_result rv;

ctx->buf_p = ctx->buffer;
ctx->buf_cnt--;
if (OSD_FAILED(ctx->buf_cnt)) {
Expand All @@ -237,30 +250,22 @@ static osd_result get_char(struct osd_gdbserver_ctx *ctx, int *ch)
return OSD_OK;
}

static osd_result validate_rsp_packet(struct osd_gdbserver_ctx *ctx,
bool *ver_checksum, int *len,
char *buffer)
//API_EXPORT
osd_result validate_rsp_packet(char *buf_p, bool *ver_checksum, int *len,
char *buffer)
{
unsigned char val_checksum = 0;
char packet_checksum[3];
int packet_char;
int cnt = 0;
osd_result rv;

char *buf_p = ctx->buf_p;
int buf_cnt = ctx->buf_cnt;
char *buf = buf_p;

// packet-format: $packet-data#checksum
int i = 0;
char *buf = buf_p;
int done = 0;
// traversing through the obtained packet till we obtained '#'
while (1) {
packet_char = *buf++;
i++;

if (packet_char == '#') {
done = 1;
break;
}
/*Any escaped byte (here, '}') is transmitted as the escape
Expand All @@ -269,7 +274,6 @@ static osd_result validate_rsp_packet(struct osd_gdbserver_ctx *ctx,
if (packet_char == '}') {
val_checksum += packet_char & 0xff;
packet_char = *buf++;
i++;
val_checksum += packet_char & 0xff;
buffer[cnt++] = (packet_char ^ 0x20) & 0xff;
} else {
Expand All @@ -278,6 +282,7 @@ static osd_result validate_rsp_packet(struct osd_gdbserver_ctx *ctx,
}
}

buffer[cnt] = '\0';
*len = cnt;
packet_char = *buf++;
packet_checksum[0] = packet_char;
Expand All @@ -303,7 +308,7 @@ static osd_result receive_rsp_packet(struct osd_gdbserver_ctx *ctx,
} while (packet_char != '$');

bool ver_checksum = 0;
rv = validate_rsp_packet(ctx, &ver_checksum, len, buffer);
rv = validate_rsp_packet(ctx->buf_p, &ver_checksum, len, buffer);

if (OSD_FAILED(rv)) {
return rv;
Expand All @@ -320,23 +325,32 @@ static osd_result receive_rsp_packet(struct osd_gdbserver_ctx *ctx,
return OSD_OK;
}

API_EXPORT
osd_result configure_rsp_packet(char *buffer, int len, char *packet_buffer)
{
int packet_checksum = 0;
packet_buffer[0] = '$';
memcpy(packet_buffer + 1, buffer, len);
int j = len + 1;
packet_buffer[j++] = '#';
for (int i = 0; i < len; i++) {
packet_checksum += buffer[i];
}
packet_buffer[j++] = dectohex((packet_checksum >> 4) & 0xf);
packet_buffer[j++] = dectohex(packet_checksum & 0xf);
packet_buffer[j] = '\0';

return OSD_OK;
}

static osd_result send_rsp_packet(struct osd_gdbserver_ctx *ctx, char *buffer,
int len)
{
char packet_buffer[len + 3];
int packet_checksum = 0;
char packet_buffer[len + 5];
osd_result rv;

while (1) {
packet_buffer[0] = '$';
memcpy(packet_buffer + 1, buffer, len);
int j = len + 1;
packet_buffer[j++] = '#';
for (int i = 0; i < len; i++) {
packet_checksum += buffer[i];
}
packet_buffer[j++] = dectohex((packet_checksum >> 4) & 0xf);
packet_buffer[j] = dectohex(packet_checksum & 0xf);
configure_rsp_packet(buffer, len, packet_buffer);

rv = osd_gdbserver_write_data(ctx, packet_buffer, len + 4);
if (OSD_FAILED(rv)) {
Expand All @@ -355,6 +369,4 @@ static osd_result send_rsp_packet(struct osd_gdbserver_ctx *ctx, char *buffer,
return OSD_ERROR_FAILURE;
}
}

return OSD_OK;
}
23 changes: 20 additions & 3 deletions src/libosd/include/osd/gdbserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
#ifndef OSD_GDBSERVER_H
#define OSD_GDBSERVER_H

#define OSD_GDBSERVER_PORT 5555
#define OSD_GDBSERVER_BUFF_SIZE 1024

#include <osd/hostmod.h>
#include <osd/osd.h>

Expand All @@ -37,6 +34,16 @@ extern "C" {

struct osd_gdbserver_ctx;

/**
* Indicates the port for connecting to GDB
*/
#define OSD_GDBSERVER_PORT 5555

/**
* Indicates the size of the buffer
*/
#define OSD_GDBSERVER_BUFF_SIZE 1024

/**
* Create a new context object
*/
Expand Down Expand Up @@ -67,6 +74,16 @@ bool osd_gdbserver_is_connected(struct osd_gdbserver_ctx *ctx);
*/
void osd_gdbserver_free(struct osd_gdbserver_ctx **ctx_p);

/**
* Start the connection with GDB client
*/
osd_result osd_gdbserver_start(struct osd_gdbserver_ctx *ctx);

/**
* Close the connection with GDB client
*/
osd_result osd_gdbserver_stop(struct osd_gdbserver_ctx *ctx);

/**
* Read data from the GDB client
*
Expand Down
7 changes: 6 additions & 1 deletion tests/unit/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ check_PROGRAMS = \
check_cl_cdm \
check_memaccess \
check_systracelogger \
check_coretracelogger
check_coretracelogger \
check_gdbserver

check_hostmod_SOURCES = \
check_hostmod.c \
Expand Down Expand Up @@ -54,6 +55,10 @@ check_coretracelogger_SOURCES = \
check_coretracelogger.c \
mock_host_controller.c

check_gdbserver_SOURCE = \
check_gdbserver.c \
mock_host_controller.c

TESTS = $(check_PROGRAMS)

AM_CFLAGS = \
Expand Down
75 changes: 75 additions & 0 deletions tests/unit/check_gdbserver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* Copyright 2018 The Open SoC Debug Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#define TEST_SUITE_NAME "check_gdbserver"

#include "testutil.h"

#include <../../src/libosd/gdbserver-private.h>
#include <osd/osd.h>
#include <osd/reg.h>

#include "mock_host_controller.h"

struct osd_gdbserver_ctx *gdbserver_ctx;
struct osd_log_ctx *log_ctx;

const unsigned int target_subnet_addr = 0;
unsigned int mock_hostmod_diaddr;
unsigned int mock_scm_diaddr;

START_TEST(test_validate_rsp_packet)
{
osd_result rv;
char packet_buffer[12] = "swbreak#ef";
char *buf_p = "swbreak#ef";
bool ver_checksum;
int len;
char buffer[1024];

rv = validate_rsp_packet(buf_p, &ver_checksum, &len, buffer);
ck_assert(OSD_SUCCEEDED(rv));
ck_assert_uint_eq(len, 7);
ck_assert_str_eq(buffer, "swbreak");
}
END_TEST

START_TEST(test_configure_rsp_packet)
{
char buffer[8] = "swbreak";
int packet_checksum;
int len = 7;
char packet_buffer[len + 5];

configure_rsp_packet(buffer, len, packet_buffer);
ck_assert_str_eq(packet_buffer, "$swbreak#ef");
}
END_TEST

Suite *suite(void)
{
Suite *s;
TCase *tc_testing;

s = suite_create(TEST_SUITE_NAME);

tc_testing = tcase_create("Testing");

tcase_add_test(tc_testing, test_validate_rsp_packet);
tcase_add_test(tc_testing, test_configure_rsp_packet);
suite_add_tcase(s, tc_testing);

return s;
}

0 comments on commit acc9d98

Please sign in to comment.