23#include <freeradius-devel/util/test/acutest_common_init.h>
24#include <freeradius-devel/util/test/acutest_helpers.h>
27#include <freeradius-devel/bio/bio_priv.h>
28#include <freeradius-devel/bio/mem.h>
29#include <freeradius-devel/bio/null.h>
30#include <freeradius-devel/bio/pipe.h>
50 const void *
buffer,
size_t *size)
62 if (*size < (
size_t) p[0]) {
78 return source->
write(source, NULL,
data, size);
90 if (!source)
return NULL;
93 if (!mem)
return NULL;
97 if (source_p) *source_p = source;
117 TEST_CASE(
"one whole packet comes back");
120 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""abcd", 5) == 0);
122 TEST_CASE(
"there is nothing else to read");
143 TEST_CASE(
"half a packet is not a packet");
147 TEST_CASE(
"the rest of it completes the packet");
151 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""abcd", 5) == 0);
174 TEST_CASE(
"two packets arrive in one go");
177 TEST_CASE(
"a one-packet buffer gets the first packet, not an error");
181 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""abcd", 5) == 0);
183 TEST_CASE(
"and the second packet on the next read");
186 if (slen == 5)
TEST_CHECK(memcmp(buf,
"\x05""efgh", 5) == 0);
208 TEST_CASE(
"too small a buffer is reported as such");
211 TEST_CASE(
"and the packet is still there for a bigger one");
214 if (slen == 5)
TEST_CHECK(memcmp(big,
"\x05""abcd", 5) == 0);
236 TEST_CASE(
"a verify failure is reported as one");
264 TEST_CASE(
"a small read buffers the rest");
267 if (slen == 2)
TEST_CHECK(memcmp(buf,
"ab", 2) == 0);
269 TEST_CASE(
"asking for more than is left still returns what is left");
270 TEST_MSG(
"the source has nothing more, but three bytes are buffered");
273 if (slen == 3)
TEST_CHECK(memcmp(buf,
"cde", 3) == 0);
321 memcpy(
buffer,
"abcde", 5);
355 stub = talloc_zero(ctx,
stub_t);
356 if (!stub)
return NULL;
373 if (!stub)
goto done;
381 TEST_CASE(
"the write gets the error from the stub");
384 TEST_CASE(
"the memory bio does not shut the chain down");
387 TEST_CASE(
"the next write reaches the stub again");
404 if (!stub)
goto done;
412 TEST_CASE(
"a partial write leaves data in the write buffer");
416 TEST_CASE(
"the flush gets the error from the stub");
420 TEST_CASE(
"the memory bio does not shut the chain down");
423 TEST_CASE(
"a later flush sends the rest of the buffered data");
445 if (!stub)
goto done;
453 TEST_CASE(
"a small read buffers the rest");
457 TEST_CASE(
"the next read fails in the stub, which shuts the chain down");
458 ((
stub_t *) stub)->fatal =
true;
461 TEST_CASE(
"writes stop at once, but the teardown waits for the drain");
465 TEST_CASE(
"the application still gets the buffered data");
468 if (slen == 3)
TEST_CHECK(memcmp(buf,
"cde", 3) == 0);
470 TEST_CASE(
"an empty buffer completes the shutdown");
474 TEST_CASE(
"the chain reports SHUTDOWN once it is torn down");
492 if (!stub)
goto done;
494 ((
stub_t *) stub)->data_sent =
true;
503 TEST_CASE(
"the read gets the error from the stub");
506 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)