23#include <freeradius-devel/util/test/acutest_common_init.h>
24#include <freeradius-devel/util/test/acutest_helpers.h>
26#include <freeradius-devel/bio/bio_priv.h>
27#include <freeradius-devel/bio/mem.h>
28#include <freeradius-devel/bio/null.h>
29#include <freeradius-devel/bio/pipe.h>
49 const void *
buffer,
size_t *size)
61 if (*size < (
size_t) p[0]) {
77 return source->
write(source, NULL,
data, size);
89 if (!source)
return NULL;
92 if (!mem)
return NULL;
96 if (source_p) *source_p = source;
116 TEST_CASE(
"one whole packet comes back");
119 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""abcd", 5) == 0);
121 TEST_CASE(
"there is nothing else to read");
142 TEST_CASE(
"half a packet is not a packet");
146 TEST_CASE(
"the rest of it completes the packet");
150 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""abcd", 5) == 0);
173 TEST_CASE(
"two packets arrive in one go");
176 TEST_CASE(
"a one-packet buffer gets the first packet, not an error");
180 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""abcd", 5) == 0);
182 TEST_CASE(
"and the second packet on the next read");
185 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""efgh", 5) == 0);
207 TEST_CASE(
"too small a buffer is reported as such");
210 TEST_CASE(
"and the packet is still there for a bigger one");
213 if (slen == 5)
TEST_CHECK(memcmp(big,
"\x05""abcd", 5) == 0);
235 TEST_CASE(
"a verify failure is reported as one");
263 TEST_CASE(
"a small read buffers the rest");
266 if (slen == 2)
TEST_CHECK(memcmp(buf,
"ab", 2) == 0);
268 TEST_CASE(
"asking for more than is left still returns what is left");
269 TEST_MSG(
"the source has nothing more, but three bytes are buffered");
272 if (slen == 3)
TEST_CHECK(memcmp(buf,
"cde", 3) == 0);
320 memcpy(
buffer,
"abcde", 5);
354 stub = talloc_zero(ctx,
stub_t);
355 if (!stub)
return NULL;
372 if (!stub)
goto done;
380 TEST_CASE(
"the write gets the error from the stub");
383 TEST_CASE(
"the memory bio does not shut the chain down");
386 TEST_CASE(
"the next write reaches the stub again");
403 if (!stub)
goto done;
411 TEST_CASE(
"a partial write leaves data in the write buffer");
415 TEST_CASE(
"the flush gets the error from the stub");
419 TEST_CASE(
"the memory bio does not shut the chain down");
422 TEST_CASE(
"a later flush sends the rest of the buffered data");
444 if (!stub)
goto done;
452 TEST_CASE(
"a small read buffers the rest");
456 TEST_CASE(
"the next read fails in the stub, which shuts the chain down");
457 ((
stub_t *) stub)->fatal =
true;
460 TEST_CASE(
"writes stop at once, but the teardown waits for the drain");
464 TEST_CASE(
"the application still gets the buffered data");
467 if (slen == 3)
TEST_CHECK(memcmp(buf,
"cde", 3) == 0);
469 TEST_CASE(
"an empty buffer completes the shutdown");
473 TEST_CASE(
"the chain reports SHUTDOWN once it is torn down");
491 if (!stub)
goto done;
493 ((
stub_t *) stub)->data_sent =
true;
502 TEST_CASE(
"the read gets the error from the stub");
505 TEST_CASE(
"the memory bio does not shut the chain down");
static int const char char buffer[256]
#define TEST_CHECK_RET(_got, _exp)
fr_bio_write_t _CONST write
write to the underlying bio
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
static ssize_t fr_bio_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read raw data from a bio.
fr_bio_io_t read_resume
"unblocked" is too similar to "blocked"
static int packet_ctx
the tests pass only the address of packet_ctx
static void test_verify_one_packet(void)
A complete packet is returned, and only one packet at a time.
static void test_recoverable_flush_passes_up(void)
The memory bio passes a recoverable flush error up to the application, and keeps the buffered data.
static void test_recoverable_read_datagram(void)
With the datagram verify reader, the memory bio passes a recoverable read error up to the application...
static void cb_noop_void(fr_bio_t *bio)
static ssize_t test_source_write(fr_bio_t *source, char const *data, size_t size)
Put bytes where the memory bio's reads will find them.
static fr_bio_cb_funcs_t test_cb
static fr_bio_t * test_mem_alloc(TALLOC_CTX *ctx, fr_bio_t **source_p, test_verify_ctx_t *tctx)
A memory bio in front of a pipe, which stands in for the network.
static ssize_t stub_read(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Return "abcde" once, and fail every read after that.
static ssize_t stub_write_one(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Accept one byte of each write, so the memory bio buffers the rest.
static ssize_t stub_write_all(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, size_t size)
Accept every write in full.
static void test_recoverable_write_passes_up(void)
The memory bio passes a recoverable write error up to the application, and keeps working.
static void test_verify_error_close(void)
A verify function which says "close" shuts the chain down.
static void test_buffered_read_drains(void)
Without a verify function the bio is a plain buffer, and hands back what it has.
static void test_fatal_read_drains(void)
After a fatal read error in the next bio, the application still gets the buffered data.
static void test_verify_pipelined(void)
Pipelined packets: a buffer holding more than one packet must still return the first.
static int cb_shutdown(fr_bio_t *bio)
static fr_bio_verify_action_t test_verify(UNUSED fr_bio_t *bio, void *verify_ctx, UNUSED void *packet_ctx, const void *buffer, size_t *size)
static fr_bio_t * stub_alloc(TALLOC_CTX *ctx)
static void test_verify_buffer_too_small(void)
A caller buffer smaller than the packet is an error, and loses nothing.
static ssize_t stub_write_fail(fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
static int shutdown_count
bool fail
return ERROR_CLOSE for the next packet
static int cb_noop(fr_bio_t *bio)
static fr_bio_cb_funcs_t stub_cb
static void test_verify_partial_packet(void)
A packet split across two reads is reassembled.
Framing for the tests: the first byte of a packet is its total length.
bool fatal
shut the chain down before failing
bool data_sent
the first read has returned "abcde"
A stub transport which fails recoverably or fatally, as each test chooses.
char const * fr_bio_strerror(ssize_t error)
void fr_bio_cb_set(fr_bio_t *bio, fr_bio_cb_funcs_t const *cb)
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
fr_bio_t * fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
Allocate a memory buffer bio.
int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, void *verify_ctx, bool datagram)
Set the verification function for memory bios.
fr_bio_verify_action_t
Status returned by the verification callback.
@ FR_BIO_VERIFY_ERROR_CLOSE
fatal error, the bio should be closed.
@ FR_BIO_VERIFY_OK
packet is OK
@ FR_BIO_VERIFY_WANT_MORE
not enough data for one packet
fr_bio_t * fr_bio_pipe_alloc(TALLOC_CTX *ctx, fr_bio_cb_funcs_t *cb, size_t buffer_size)
Allocate a thread-safe pipe which can be used for both reads and writes.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
#define fr_strerror_const(_msg)