+
+#endif
+
+/* 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.
+*/
+
+int main( void )
+{
+#ifndef REGTEST
+ void * ptr1, * ptr2, * ptr3, * ptr4, * ptr5, * ptr6, * ptr7, * ptr8, * ptr9, * ptrA, * ptrB, * ptrC;
+
+ pages_start = _PDCLIB_allocpages( 0 );
+ PRINT( "\nEffective is: %#.4x\nsizeof( memnode ) is: %#.2x\n\n", EFFECTIVE, sizeof( struct _PDCLIB_memnode_t ) );
+
+ /* Allocating 10 bytes; expecting one page allocation and a node split */
+ TESTCASE( MEMTEST( ptr1, 10 ) );
+ TESTCASE( test_nodes( "Allocating 10 bytes.", 1,
+ sizeof( struct _PDCLIB_memnode_t ) + 10, EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - 10,
+ 0 ) );
+
+ /* Allocating the rest of the page; expecting no page allocation and assignment of the remaining node */
+ TESTCASE( MEMTEST( ptr2, EFFECTIVE - 10 - sizeof( struct _PDCLIB_memnode_t ) ) );
+ TESTCASE( test_nodes( "Allocating the rest of the page.", 1,
+ 0 ) );
+
+ /* Allocating a full page; expecting one page allocation, no node split */
+ TESTCASE( MEMTEST( ptr3, EFFECTIVE ) );
+ TESTCASE( test_nodes( "Allocating a full page.", 2,
+ 0 ) );
+
+ /* Allocating *almost* a full page; expecting one page allocation, no node split */
+ TESTCASE( MEMTEST( ptr4, EFFECTIVE - 4 ) );
+ TESTCASE( test_nodes( "Allocating *almost* a full page.", 3,
+ 0 ) );
+
+ /* Freeing and re-allocating the "almost" full page; expecting no page allocation, no node split */
+ free( ptr4 );
+ TESTCASE( MEMTEST( ptr5, EFFECTIVE - 4 ) );
+ TESTCASE( ptr4 == ptr5 );
+ TESTCASE( test_nodes( "Freeing and re-allocating the \"almost\" full page.", 3 ) );
+
+ /* Freeing the full page from test #3; expecting a full-sized free node. */
+ free( ptr3 );
+ TESTCASE( test_nodes( "Freeing the full page from test #3.", 3,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ 0 ) );
+
+ /* Allocating two full pages; expecting two page allocations, no node split */
+ TESTCASE( MEMTEST( ptr3, EFFECTIVE + _PDCLIB_PAGESIZE ) );
+ TESTCASE( test_nodes( "Allocating two full pages.", 5,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ 0 ) );
+
+ /* Re-allocating to size of 10 bytes; expecting no page allocation, no node split */
+ /* TODO: Shouldn't realloc() split the now much-too-large node? */
+ TESTCASE( realloc( ptr3, 10 ) == ptr3 );
+ TESTCASE( test_nodes( "Re-allocating to size of 10 bytes.", 5,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ 0 ) );
+
+ /* Re-allocating to size of two full pages; expecting no page allocation, no node split */
+ TESTCASE( realloc( ptr3, EFFECTIVE + _PDCLIB_PAGESIZE ) == ptr3 );
+ TESTCASE( test_nodes( "Re-allocating to size of two full pages.", 5,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ 0 ) );
+
+ /* Re-allocating to size of three full pages; expecting three page allocation, freeing of two-page node */
+ TESTCASE( realloc( ptr3, EFFECTIVE + _PDCLIB_PAGESIZE * 2 ) != ptr3 );
+ TESTCASE( test_nodes( "Re-allocating to size of three full pages.", 8,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ _PDCLIB_PAGESIZE * 3, EFFECTIVE + _PDCLIB_PAGESIZE,
+ 0 ) );
+
+ /* Allocating two full pages; expecting allocation of the available two-page node */
+ TESTCASE( MEMTEST( ptr4, EFFECTIVE + _PDCLIB_PAGESIZE ) );
+ TESTCASE( test_nodes( "Allocating two full pages.", 8,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ 0 ) );
+
+ /* Allocating zero bytes; expecting no change */
+ TESTCASE( ! MEMTEST( ptr6, 0 ) );
+ TESTCASE( test_nodes( "Allocating zero bytes.", 8,
+ _PDCLIB_PAGESIZE * 1, EFFECTIVE,
+ 0 ) );
+
+ /* Allocating 4 bytes; expecting upsizing of requestupsizing of size, node split */
+ TESTCASE( MEMTEST( ptr7, 4 ) );
+ TESTCASE( test_nodes( "Allocating 4 bytes.", 8,
+ _PDCLIB_PAGESIZE * 1 + _PDCLIB_MINALLOC + sizeof( struct _PDCLIB_memnode_t ),
+ EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ),
+ 0 ) );
+
+ /* Allocating the rest of the page; expecting no page allocation and assignment of the remaining node */
+ TESTCASE( MEMTEST( ptr8, EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ) ) );
+ TESTCASE( test_nodes( "Allocating the rest of the page.", 8, 0 ) );
+
+ /* Freeing the node from the previous test; expecting node to re-appear in free list */
+ free( ptr8 );
+ TESTCASE( test_nodes( "Freeing the node from the previous test.", 8,
+ _PDCLIB_PAGESIZE * 1 + _PDCLIB_MINALLOC + sizeof( struct _PDCLIB_memnode_t ),
+ EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ),
+ 0 ) );
+
+ /* Allocating one byte more than available in free node; expecting page allocation */
+ TESTCASE( MEMTEST( ptr8, EFFECTIVE + 1 - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ) ) );
+ TESTCASE( test_nodes( "Allocating one byte more than available in free node.", 9,
+ _PDCLIB_PAGESIZE * 1 + _PDCLIB_MINALLOC + sizeof( struct _PDCLIB_memnode_t ),
+ EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ),
+ 0 ) );
+
+ /* Re-allocating with NULL pointer; expecting no page allocation, no node split */
+ ptr9 = realloc( NULL, EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ) );
+ TESTCASE( ptr9 != NULL );
+ TESTCASE( memset( ptr9, 0, EFFECTIVE - _PDCLIB_MINALLOC - sizeof( struct _PDCLIB_memnode_t ) ) == ptr9 );
+ TESTCASE( test_nodes( "Re-allocating with NULL pointer.", 9, 0 ) );
+
+ /* Allocating a bit more than half a page; expecting page allocation, node split */
+#define TESTSIZE 3000
+ TESTCASE( MEMTEST( ptrA, TESTSIZE ) );
+ TESTCASE( test_nodes( "Allocating a bit more than half a page.", 10,
+ _PDCLIB_PAGESIZE * 9 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ 0 ) );
+
+ /* Allocating a bit more than half a page; expecting page allocation, node split */
+ TESTCASE( MEMTEST( ptrB, TESTSIZE ) );
+ TESTCASE( test_nodes( "Allocating a bit more than half a page.", 11,
+ _PDCLIB_PAGESIZE * 9 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ _PDCLIB_PAGESIZE * 10 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ 0 ) );
+
+ /* Allocating a bit more than half a page; expecting page allocation, node split */
+ TESTCASE( MEMTEST( ptrC, TESTSIZE ) );
+ TESTCASE( test_nodes( "Allocating a bit more than half a page.", 12,
+ _PDCLIB_PAGESIZE * 9 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ _PDCLIB_PAGESIZE * 10 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ _PDCLIB_PAGESIZE * 11 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ 0 ) );
+
+ /* Freeing the middle node */
+ free( ptrB );
+ TESTCASE( test_nodes( "Freeing the middle node.", 12,
+ _PDCLIB_PAGESIZE * 9 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ _PDCLIB_PAGESIZE * 10 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ _PDCLIB_PAGESIZE * 11 + sizeof( struct _PDCLIB_memnode_t ) + TESTSIZE,
+ EFFECTIVE - sizeof( struct _PDCLIB_memnode_t ) - TESTSIZE,
+ _PDCLIB_PAGESIZE * 10,
+ TESTSIZE,
+ 0 ) );
+
+#else
+ puts( " NOTEST malloc() test driver is PDCLib-specific." );
+#endif
+ return TEST_RESULTS;
+}
+
+#endif