blob: 4366c203579570990214d9e48c4b175317cfca1f [file] [log] [blame]
/* The reader part of a test program for non-blocking communication.
Copyright (C) 2011-2020 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* This program implements 4 tests:
test == 0:
Test blocking write() with blocking read().
Timeline Main process Child process
0 s Start Start, read(10000)
1 s write(20000) Return from read(10000)
2 s Next read(10000)
2 s Return from write(20000) Return from read(10000)
test == 1:
Test non-blocking write() with blocking read().
Timeline Main process Child process
0 s Start Start, read(10000)
1 s write(20000) Return from read(10000)
Return with at least 10000,
Repeatedly continue
write() of the rest
2 s Next read(10000)
2 s Return from write(10000) Return from read(10000)
test == 2:
Test blocking write() with non-blocking read().
Timeline Main process Child process
0 s Start Start, read(10000)
repeatedly polling
1 s write(20000) Return from read(10000)
2 s Next read(10000)
2 s Return from write(20000) Return from read(10000)
test == 3:
Test non-blocking write() with non-blocking read().
*/
#include "test-nonblocking-misc.h"
static ssize_t
full_read (size_t fd, void *buf, size_t count)
{
size_t bytes_read;
bytes_read = 0;
while (bytes_read < count)
{
TIMING_DECLS
ssize_t ret;
int saved_errno;
dbgfprintf (stderr, "%s: >> read (%lu)\n", PROG_ROLE,
(unsigned long) (count - bytes_read));
START_TIMING
ret = read (fd, (char *) buf + bytes_read, count - bytes_read);
saved_errno = errno;
END_TIMING
dbgfprintf (stderr, "%s: << read -> %ld%s\n", PROG_ROLE,
(long) ret, dbgstrerror (ret < 0, saved_errno));
if (ret < 0)
return -1;
else
{
ASSERT (ret > 0);
bytes_read += ret;
}
}
return bytes_read;
}
static ssize_t
full_read_from_nonblocking_fd (size_t fd, void *buf, size_t count)
{
size_t bytes_read;
bytes_read = 0;
while (bytes_read < count)
{
TIMING_DECLS
ssize_t ret;
int saved_errno;
dbgfprintf (stderr, "%s: >> read (%lu)\n", PROG_ROLE,
(unsigned long) (count - bytes_read));
START_TIMING
ret = read (fd, (char *) buf + bytes_read, count - bytes_read);
saved_errno = errno;
END_TIMING
dbgfprintf (stderr, "%s: << read -> %ld%s\n", PROG_ROLE,
(long) ret, dbgstrerror (ret < 0, saved_errno));
/* This assertion fails if the non-blocking flag is effectively not set
on fd. */
ASSERT (spent_time < 0.5);
if (ret < 0)
{
ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK);
usleep (SMALL_DELAY);
}
else
{
ASSERT (ret > 0);
bytes_read += ret;
}
}
return bytes_read;
}
/* Execute the reader loop. */
static void
main_reader_loop (int test, size_t data_block_size, int fd)
{
unsigned char *expected;
unsigned char *data;
/* Set up the expected data. */
expected = init_data (data_block_size);
data = (unsigned char *) malloc (2 * data_block_size);
ASSERT (data != NULL);
switch (test)
{
TIMING_DECLS
ssize_t ret;
case 0: /* Test blocking write() with blocking read(). */
case 1: /* Test non-blocking write() with blocking read(). */
START_TIMING
ret = full_read (fd, data, data_block_size);
END_TIMING
ASSERT (ret == data_block_size);
ASSERT (memcmp (data, expected, data_block_size) == 0);
ASSERT (spent_time > 0.5);
/* This assertion fails if data_block_size is very large and
ENABLE_DEBUGGING is 1. */
ASSERT (spent_time < 1.5);
usleep (1000000);
START_TIMING
ret = full_read (fd, data, data_block_size);
END_TIMING
ASSERT (ret == data_block_size);
ASSERT (memcmp (data, expected + data_block_size, data_block_size) == 0);
/* This assertion fails if data_block_size is much larger than needed
and SMALL_DELAY is too large. */
ASSERT (spent_time < 0.5);
break;
case 2: /* Test blocking write() with non-blocking read(). */
case 3: /* Test non-blocking write() with non-blocking read(). */
START_TIMING
ret = full_read_from_nonblocking_fd (fd, data, data_block_size);
END_TIMING
ASSERT (ret == data_block_size);
ASSERT (memcmp (data, expected, data_block_size) == 0);
ASSERT (spent_time > 0.5);
/* This assertion fails if data_block_size is much larger than needed
and SMALL_DELAY is too large, or if data_block_size is very large and
ENABLE_DEBUGGING is 1. */
ASSERT (spent_time < 1.5);
usleep (1000000);
START_TIMING
ret = full_read_from_nonblocking_fd (fd, data, data_block_size);
END_TIMING
ASSERT (ret == data_block_size);
ASSERT (memcmp (data, expected + data_block_size, data_block_size) == 0);
/* This assertion fails if data_block_size is much larger than needed
and SMALL_DELAY is too large. */
ASSERT (spent_time < 0.5);
break;
default:
abort ();
}
free (data);
free (expected);
}