libcruft-util/test/buffer/paged.cpp

106 lines
3.0 KiB
C++
Raw Normal View History

#include <cruft/util/std.hpp>
#include <cruft/util/tap.hpp>
#include <cruft/util/buffer/paged.hpp>
#include <cruft/util/debug/assert.hpp>
#include <cruft/util/except.hpp>
#include <cruft/util/posix/except.hpp>
2015-11-11 16:56:35 +11:00
#include <signal.h>
#include <setjmp.h>
///////////////////////////////////////////////////////////////////////////////
sigjmp_buf fault_jmp;
__attribute__((no_sanitize_address))
2015-11-11 16:56:35 +11:00
bool
has_fault
(const volatile char* addr)
2015-11-11 16:56:35 +11:00
{
if (sigsetjmp (fault_jmp, 1) == 0) {
*addr;
return false;
} else {
return true;
}
}
//-----------------------------------------------------------------------------
static bool fault_seen;
static void *fault_address;
__attribute__((no_sanitize_address))
2015-11-11 16:56:35 +11:00
void
segv_handler (int num, siginfo_t *info, void *cookie)
{
CHECK_EQ (num, SIGSEGV);
(void)num;
(void)cookie;
fault_seen = true;
fault_address = info->si_addr;
siglongjmp (fault_jmp, SIGSEGV);
}
///////////////////////////////////////////////////////////////////////////////
int
main (void)
{
cruft::TAP::logger tap;
2015-11-11 16:56:35 +11:00
#if 0
2015-11-11 16:56:35 +11:00
// setup a trap to record SEGV events
struct sigaction newhandler {};
newhandler.sa_sigaction = segv_handler;
newhandler.sa_flags = SA_SIGINFO;
cruft::posix::error::try_call (
sigaction, SIGSEGV, &newhandler, nullptr
);
2015-11-11 16:56:35 +11:00
// initialise a partially unmapped buffer. the tests assume that the
// window is substantially less than half the capacity (so that probing
// the centre doesn't trigger a mapping overlapping the end).
constexpr size_t CAPACITY = 16 * 1024 * 1024;
cruft::buffer::paged buffer (CAPACITY);
2015-11-11 16:56:35 +11:00
typedef decltype(buffer)::value_type value_type;
const value_type *first = buffer.begin ();
const value_type *last = buffer.end () - 1;
const value_type *centre = buffer.begin () + buffer.capacity () / 2;
const value_type *window = centre + buffer.window () - 1;
// ensure correct initial mappings
tap.expect (!has_fault (first), "first is initially valid");
tap.expect ( has_fault (last), "last is intially invalid");
// allocate half the buffer and check mappings
buffer.commit ({ first, last });
2015-11-11 16:56:35 +11:00
tap.expect (!has_fault (first), "first remains valid after commit");
tap.expect (!has_fault (centre), "centre is valid after partial commit");
tap.expect (!has_fault (window), "centre window is valid after partial commit");
tap.expect ( has_fault (last), "last is invalid after partial commit");
// allocate the entire buffer and check the last address
buffer.access (const_cast<value_type*> (last));
tap.expect (!has_fault (last), "last is valid after total commit");
// unmap the buffer and check centre and last are invalid
buffer.access (const_cast<value_type*> (first));
tap.expect (!has_fault (first), "first value remains valid after release");
tap.expect ( has_fault (centre), "centre is invalid after release");
tap.expect ( has_fault (last), "last is invalid after release");
#endif
2015-11-11 16:56:35 +11:00
return tap.status ();
}