+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+#include <string.h>
+
+#define MEMTEST( ptr, size ) ( ( ptr = malloc( size ) ) != NULL ) && ( memset( ptr, 0, size ) == ptr )
+#define PAGETEST( x ) ( pages_start + x * _PDCLIB_PAGESIZE ) == sbrk( 0 )
+#define EFFECTIVE _PDCLIB_PAGESIZE - sizeof( struct _PDCLIB_memnode_t )
+
+/* Note that this test driver heavily tests *internals* of the implementation
+ above (and of free() and realloc(), too). That means that changes in the
+ implementation must be accompanied with appropriate changes of the test
+ driver. It does *not* make a good regression tester for the implementation,
+ I am afraid, and thus there is no REGTEST equivalent.
+*/
+
+#include <unistd.h>
+
+int main( int argc, char * argv[] )
+{
+ BEGIN_TESTS;
+#ifndef REGTEST
+ {
+ void * ptr1, * ptr2, * ptr3, * ptr4, * ptr5, * ptr6, * ptr7, * ptr8;
+ char * pages_start = _PDCLIB_allocpages( 0 );
+ /* allocating 10 byte; expected: 1 page allocation, node split */
+ TESTCASE( MEMTEST( ptr1, 10 ) );
+ TESTCASE( PAGETEST( 1 ) );
+ /* allocating EFFECTIVE - 10 byte; expected: no page allocation, receiving split node */
+ TESTCASE( MEMTEST( ptr2, EFFECTIVE - 10 - sizeof( struct _PDCLIB_memnode_t ) ) );
+ TESTCASE( PAGETEST( 1 ) );
+ /* allocating EFFECTIVE; expected: 1 page allocation, no node split */
+ TESTCASE( MEMTEST( ptr3, EFFECTIVE ) );
+ TESTCASE( PAGETEST( 2 ) );
+ /* allocating EFFECTIVE - 4; expected: 1 page allocation, no node split */
+ TESTCASE( MEMTEST( ptr4, EFFECTIVE - 4 ) );
+ TESTCASE( PAGETEST( 3 ) );
+ /* freeing and re-allocating EFFECTIVE - 4; expected: no page allocation, no node split */
+ free( ptr4 );
+ TESTCASE( MEMTEST( ptr5, EFFECTIVE - 4 ) );
+ TESTCASE( ptr4 == ptr5 );
+ TESTCASE( PAGETEST( 3 ) );
+ /* releasing EFFECTIVE; expected: no page release */
+ free( ptr3 );
+ TESTCASE( PAGETEST( 3 ) );
+ /* allocating EFFECTIVE + _PDCLIB_PAGESIZE; expected: 2 page allocation, no node split */
+ TESTCASE( MEMTEST( ptr3, EFFECTIVE + _PDCLIB_PAGESIZE ) );
+ TESTCASE( PAGETEST( 5 ) );
+ /* reallocating to 10 byte; expected: no page allocation, no node split */
+ TESTCASE( realloc( ptr3, 10 ) == ptr3 );
+ TESTCASE( PAGETEST( 5 ) );
+ /* reallocating to EFFECTIVE + _PDCLIB_PAGESIZE; expected: no page allocation, no node split */
+ TESTCASE( realloc( ptr3, EFFECTIVE + _PDCLIB_PAGESIZE ) == ptr3 );
+ TESTCASE( PAGETEST( 5 ) );
+ /* reallocating to EFFECTIVE + _PDCLIB_PAGESIZE * 2; expected: 3 page allocations, no node split */
+ TESTCASE( realloc( ptr3, EFFECTIVE + _PDCLIB_PAGESIZE * 2 ) != ptr3 );
+ TESTCASE( PAGETEST( 8 ) );
+ /* allocating EFFECTIVE + _PDCLIB_PAGESIZE; expected: no page allocation, no node split */
+ TESTCASE( MEMTEST( ptr4, EFFECTIVE + _PDCLIB_PAGESIZE ) );
+ TESTCASE( PAGETEST( 8 ) );
+ /* allocating zero size; expected: no page allocation, no node split */
+ TESTCASE( ! MEMTEST( ptr6, 0 ) );
+ TESTCASE( PAGETEST( 8 ) );
+ /* allocating 4 byte; expected: no page allocation, upsizing of size, node split */
+ TESTCASE( MEMTEST( ptr7, 4 ) );
+ TESTCASE( PAGETEST( 8 ) );
+ /* allocating rest of page; expected: no page allocation, no node split */
+ TESTCASE( MEMTEST( ptr8, EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ) ) );
+ TESTCASE( PAGETEST( 8 ) );
+ /* freeing, and allocating one byte more; expected: 1 page allocation, node split */
+ free( ptr8 );
+ TESTCASE( MEMTEST( ptr8, EFFECTIVE + 1 - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ) ) );
+ TESTCASE( PAGETEST( 9 ) );
+ }
+#endif
+ return TEST_RESULTS;
+}
+
+#endif