summaryrefslogtreecommitdiffstats
path: root/testsuites
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-02-23 11:35:44 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-02-28 09:05:42 +0100
commit9fa0f543ecfcf6cdf79d60a3a9f5a0ed845c7046 (patch)
tree7b9f9ececc3099949067bf9b99afd6c0aa71d377 /testsuites
parenttermios: Change tty_rcvwakeup to bool (diff)
downloadrtems-9fa0f543ecfcf6cdf79d60a3a9f5a0ed845c7046.tar.bz2
termios: Change receive callback invocation
Call the receive callback in case a read will succeed without to block. This enables the use of the receive callback for a poll() and select() support. Increase raw input buffer size to allow buffering of one line. Close #2916.
Diffstat (limited to 'testsuites')
-rw-r--r--testsuites/libtests/termios09/init.c326
1 files changed, 325 insertions, 1 deletions
diff --git a/testsuites/libtests/termios09/init.c b/testsuites/libtests/termios09/init.c
index 6e651bfafa..a32ebdaec5 100644
--- a/testsuites/libtests/termios09/init.c
+++ b/testsuites/libtests/termios09/init.c
@@ -48,6 +48,7 @@ typedef struct {
size_t output_count;
char output_buf[OUTPUT_BUFFER_SIZE];
int input_char;
+ int callback_counter;
} device_context;
typedef struct {
@@ -146,7 +147,8 @@ static void init_term(test_context *ctx, size_t i)
ctx->term[i].c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
- ctx->term[i].c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ ctx->term[i].c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT
+ | ECHOCTL | ECHOKE | ICANON | ISIG | IEXTEN);
ctx->term[i].c_cflag &= ~(CSIZE | PARENB);
ctx->term[i].c_cflag |= CS8;
ctx->term[i].c_oflag &= ~(OPOST | ONLRET | ONLCR | OCRNL | ONLRET
@@ -207,6 +209,42 @@ static void clear_set_iflag(
set_term(ctx, i);
}
+static void clear_set_lflag(
+ test_context *ctx,
+ size_t i,
+ tcflag_t clear,
+ tcflag_t set
+)
+{
+ ctx->term[i].c_lflag &= ~clear;
+ ctx->term[i].c_lflag |= set;
+ set_term(ctx, i);
+}
+
+static void set_vmin_vtime(
+ test_context *ctx,
+ size_t i,
+ cc_t vmin,
+ cc_t vtime
+)
+{
+ ctx->term[i].c_cc[VMIN] = vmin;
+ ctx->term[i].c_cc[VTIME] = vtime;
+ set_term(ctx, i);
+}
+
+static void set_veol_veol2(
+ test_context *ctx,
+ size_t i,
+ cc_t veol,
+ cc_t veol2
+)
+{
+ ctx->term[i].c_cc[VEOL] = veol;
+ ctx->term[i].c_cc[VEOL2] = veol2;
+ set_term(ctx, i);
+}
+
static void test_igncr(test_context *ctx)
{
size_t i;
@@ -238,6 +276,286 @@ static void test_igncr(test_context *ctx)
}
}
+static void test_istrip(test_context *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < DEVICE_COUNT; ++i) {
+ ssize_t n;
+ char c;
+
+ c = 'x';
+
+ clear_set_iflag(ctx, i, 0, ISTRIP);
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 0);
+ rtems_test_assert(c == 'x');
+
+ input(ctx, i, '\376');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '~');
+
+ clear_set_iflag(ctx, i, ISTRIP, 0);
+ input(ctx, i, '\376');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '\376');
+ }
+}
+
+static void test_iuclc(test_context *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < DEVICE_COUNT; ++i) {
+ ssize_t n;
+ char c;
+
+ c = 'x';
+
+ clear_set_iflag(ctx, i, 0, IUCLC);
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 0);
+ rtems_test_assert(c == 'x');
+
+ input(ctx, i, 'A');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == 'a');
+
+ clear_set_iflag(ctx, i, IUCLC, 0);
+ input(ctx, i, 'A');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == 'A');
+ }
+}
+
+static void test_icrnl(test_context *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < DEVICE_COUNT; ++i) {
+ ssize_t n;
+ char c;
+
+ c = 'x';
+
+ clear_set_iflag(ctx, i, 0, ICRNL);
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 0);
+ rtems_test_assert(c == 'x');
+
+ input(ctx, i, '\r');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '\n');
+
+ clear_set_iflag(ctx, i, ICRNL, 0);
+ input(ctx, i, '\r');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '\r');
+ }
+}
+
+static void test_inlcr(test_context *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < DEVICE_COUNT; ++i) {
+ ssize_t n;
+ char c;
+
+ c = 'x';
+
+ clear_set_iflag(ctx, i, 0, INLCR);
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 0);
+ rtems_test_assert(c == 'x');
+
+ input(ctx, i, '\n');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '\r');
+
+ clear_set_iflag(ctx, i, INLCR, 0);
+ input(ctx, i, '\n');
+
+ n = read(ctx->fds[i], &c, sizeof(c));
+ rtems_test_assert(n == 1);
+ rtems_test_assert(c == '\n');
+ }
+}
+
+static void callback(struct termios *tty, void *arg)
+{
+ device_context *ctx = arg;
+
+ ++ctx->callback_counter;
+}
+
+static void test_rx_callback(test_context *ctx)
+{
+ size_t i = INTERRUPT;
+ device_context *dev = &ctx->devices[i];
+ ssize_t n;
+ char buf[3];
+
+ buf[0] = 'x';
+
+ dev->callback_counter = 0;
+ dev->tty->tty_rcv.sw_pfn = callback;
+ dev->tty->tty_rcv.sw_arg = dev;
+ clear_set_lflag(ctx, i, ICANON, 0);
+
+ set_vmin_vtime(ctx, i, 0, 0);
+
+ n = read(ctx->fds[i], buf, 1);
+ rtems_test_assert(n == 0);
+ rtems_test_assert(buf[0] == 'x');
+
+ input(ctx, i, 'a');
+ rtems_test_assert(dev->callback_counter == 1);
+
+ input(ctx, i, 'b');
+ rtems_test_assert(dev->callback_counter == 1);
+
+ n = read(ctx->fds[i], buf, 2);
+ rtems_test_assert(n == 2);
+ rtems_test_assert(buf[0] == 'a');
+ rtems_test_assert(buf[1] == 'b');
+
+ set_vmin_vtime(ctx, i, 2, 0);
+
+ input(ctx, i, 'd');
+ rtems_test_assert(dev->callback_counter == 1);
+
+ input(ctx, i, 'e');
+ rtems_test_assert(dev->callback_counter == 2);
+
+ input(ctx, i, 'f');
+ rtems_test_assert(dev->callback_counter == 2);
+
+ n = read(ctx->fds[i], buf, 3);
+ rtems_test_assert(n == 3);
+ rtems_test_assert(buf[0] == 'd');
+ rtems_test_assert(buf[1] == 'e');
+ rtems_test_assert(buf[2] == 'f');
+
+ dev->tty->tty_rcv.sw_pfn = NULL;
+ dev->tty->tty_rcv.sw_arg = NULL;
+}
+
+static void test_rx_callback_icanon(test_context *ctx)
+{
+ size_t i = INTERRUPT;
+ device_context *dev = &ctx->devices[i];
+ ssize_t n;
+ char buf[255];
+ size_t j;
+
+ buf[0] = 'x';
+
+ dev->callback_counter = 0;
+ dev->tty->tty_rcv.sw_pfn = callback;
+ dev->tty->tty_rcv.sw_arg = dev;
+
+ set_vmin_vtime(ctx, i, 0, 0);
+
+ n = read(ctx->fds[i], buf, 1);
+ rtems_test_assert(n == 0);
+ rtems_test_assert(buf[0] == 'x');
+
+ clear_set_lflag(ctx, i, 0, ICANON);
+ set_veol_veol2(ctx, i, '1', '2');
+
+ input(ctx, i, '\n');
+ rtems_test_assert(dev->callback_counter == 1);
+
+ input(ctx, i, 'a');
+ rtems_test_assert(dev->callback_counter == 1);
+
+ input(ctx, i, '\n');
+ rtems_test_assert(dev->callback_counter == 1);
+
+ n = read(ctx->fds[i], buf, 3);
+ rtems_test_assert(n == 3);
+ rtems_test_assert(buf[0] == '\n');
+ rtems_test_assert(buf[1] == 'a');
+ rtems_test_assert(buf[2] == '\n');
+
+ input(ctx, i, '\4');
+ rtems_test_assert(dev->callback_counter == 2);
+
+ input(ctx, i, 'b');
+ rtems_test_assert(dev->callback_counter == 2);
+
+ input(ctx, i, '\n');
+ rtems_test_assert(dev->callback_counter == 2);
+
+ n = read(ctx->fds[i], buf, 2);
+ rtems_test_assert(n == 2);
+ rtems_test_assert(buf[0] == 'b');
+ rtems_test_assert(buf[1] == '\n');
+
+ input(ctx, i, '1');
+ rtems_test_assert(dev->callback_counter == 3);
+
+ input(ctx, i, 'c');
+ rtems_test_assert(dev->callback_counter == 3);
+
+ input(ctx, i, '\n');
+ rtems_test_assert(dev->callback_counter == 3);
+
+ n = read(ctx->fds[i], buf, 3);
+ rtems_test_assert(n == 3);
+ rtems_test_assert(buf[0] == '1');
+ rtems_test_assert(buf[1] == 'c');
+ rtems_test_assert(buf[2] == '\n');
+
+ input(ctx, i, '2');
+ rtems_test_assert(dev->callback_counter == 4);
+
+ input(ctx, i, 'd');
+ rtems_test_assert(dev->callback_counter == 4);
+
+ input(ctx, i, '\n');
+ rtems_test_assert(dev->callback_counter == 4);
+
+ n = read(ctx->fds[i], buf, 3);
+ rtems_test_assert(n == 3);
+ rtems_test_assert(buf[0] == '2');
+ rtems_test_assert(buf[1] == 'd');
+ rtems_test_assert(buf[2] == '\n');
+
+ for (j = 0; j < 255; ++j) {
+ input(ctx, i, 'e');
+ rtems_test_assert(dev->callback_counter == 4);
+ }
+
+ /* Raw input buffer overflow */
+ input(ctx, i, 'e');
+ rtems_test_assert(dev->callback_counter == 5);
+
+ dev->tty->tty_rcv.sw_pfn = NULL;
+ dev->tty->tty_rcv.sw_arg = NULL;
+ set_veol_veol2(ctx, i, '\0', '\0');
+ clear_set_lflag(ctx, i, ICANON, 0);
+}
+
static void Init(rtems_task_argument arg)
{
test_context *ctx = &test_instance;
@@ -246,6 +564,12 @@ static void Init(rtems_task_argument arg)
setup(ctx);
test_igncr(ctx);
+ test_istrip(ctx);
+ test_iuclc(ctx);
+ test_icrnl(ctx);
+ test_inlcr(ctx);
+ test_rx_callback(ctx);
+ test_rx_callback_icanon(ctx);
TEST_END();
rtems_test_exit(0);