list01.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 702 行 · 第 1/2 页

CPP
702
字号
    int ans = *it;
    for( int i = 0; i < 20 ; i++ ){
        if( INSANE( l ) || ans != i || *it != i ) FAIL
        if( i%2 ) ans = (*(it++)) + 1;
        else ans = *(++it);
    }
    //and again with const iterator
    cit = l.begin();
    ans = *cit;
    for( int i = 0; i < 20 ; i++ ){
        if( INSANE( l ) || ans != i || *cit != i ) FAIL
        if( i%2 ) ans = *(cit++) + 1;
        else ans = *(++cit);
    }
    //test decrement
    it = l.end();
    for( int i = 19; i > 0 ; i-- ){
        int ans;
        if( i%2 ) ans = *(--it);
        else ans = *(it--) - 1;
        if( INSANE( l ) || ans != i || *it != i ) FAIL
    }
    //and again with const iterator
    cit = l.end();
    for( int i = 19; i > 0 ; i-- ){
        int ans;
        if( i%2 ) ans = *(--cit);
        else ans = *(cit--) - 1;
        if( INSANE( l ) || ans != i || *cit != i ) FAIL
    }
    
    return( true );
}

/* ------------------------------------------------------------------
 * reverse_iterator_test
 * make sure reverse iterators do something reasonable
 */
bool reverse_iterator_test( )
{
    std::list< int > lst;
    for( int i = 1; i <= 10; ++i ) lst.push_back( i );

    std::list< int >::reverse_iterator rit = lst.rbegin( );
    for( int i = 10; i >= 1; --i ) {
      if( *rit != i ) FAIL
      ++rit;
    }
    if( rit != lst.rend( ) ) FAIL
    return( true );
}

/* ------------------------------------------------------------------
 * copy_test
 * test copy constructor
 */
bool copy_test()
{
    std::list<int> lst1;
    for( int i = 0; i < 20; i++ ){
        lst1.push_front( -i );
    }
    std::list<int> lst2(lst1);
    if( INSANE( lst1 ) || lst1.size() != 20 ) FAIL
    if( INSANE( lst2 ) || lst2.size() != 20 ) FAIL
    for( int i = 0; i < 20; i++ ){
        if( lst2.back() != -i ) FAIL
        lst2.pop_back();
    }
    return( true );
}

/* ------------------------------------------------------------------
 * splice_test
 * test list splicing operations
 */
bool splice_test( )
{
    std::list< int > lst1, lst2;
    //two trivial (empty) lists
    lst1.splice( lst1.begin( ), lst2 );
    if( INSANE( lst1 )    || INSANE( lst2 )    ||
        lst1.size( ) != 0 || lst2.size( ) != 0 ) FAIL
    //non-trival list spliced into empty list
    for( int i = 1; i <= 10; ++i ) lst2.push_back( i );
    lst1.splice( lst1.begin( ), lst2 );
    if( INSANE( lst1 )     || INSANE( lst2 )    ||
        lst1.size( ) != 10 || lst2.size( ) != 0 ) FAIL
    //two non-trivial lists
    for( int i = 11; i <= 20; ++i ) lst2.push_back( i );
    std::list< int >::iterator it = lst1.begin( );
    ++it; ++it; ++it; ++it; ++it;
    lst1.splice( it, lst2 );
    if( INSANE( lst1 )     || INSANE( lst2 )    ||
        lst1.size( ) != 20 || lst2.size( ) != 0 ) FAIL
    it = lst1.begin( );
    //check final list contents
    for( int i = 1; i <= 5; ++i ) {
        if( *it != i ) FAIL
        ++it;
    }
    for( int i = 11; i <= 20; ++i ) {
        if( *it != i ) FAIL
        ++it;
    }
    for( int i = 6; i <= 10; ++i ) {
        if( *it != i ) FAIL
        ++it;
    }

    std::list< int > lst3, lst4;
    for( int i = 1; i <= 5; ++i ) lst4.push_back( i );
    it = lst4.begin( ); ++it; ++it;
    lst3.splice( lst3.begin( ), lst4, it );
    if( INSANE( lst3 )    || INSANE( lst4 )    ||
        lst3.size( ) != 1 || lst4.size( ) != 4 ) FAIL
    lst3.splice( lst3.end( ), lst4, lst4.begin( ) );
    if( INSANE( lst3 )    || INSANE( lst4 )    ||
        lst3.size( ) != 2 || lst4.size( ) != 3 ) FAIL
    it = lst4.end( ); --it;
    lst3.splice( ++lst3.begin( ), lst4, it );
    if( INSANE( lst3 )    || INSANE( lst4 )    ||
        lst3.size( ) != 3 || lst4.size( ) != 2 ) FAIL
    lst3.splice( lst3.begin( ), lst3, --lst3.end( ) );
    if( INSANE( lst3 ) || lst3.size( ) != 3 ) FAIL
    //check final list contents
    it = lst3.begin( );
    if( *it != 1 ) FAIL; ++it;
    if( *it != 3 ) FAIL; ++it;
    if( *it != 5 ) FAIL;

    std::list< int > lst5, lst6;
    for( int i = 1; i <= 10; ++i ) lst6.push_back( i );
    lst5.splice( lst5.begin( ), lst6, lst6.begin( ), lst6.end( ) );
    if( INSANE( lst5 )     || INSANE( lst6 )    ||
        lst5.size( ) != 10 || lst6.size( ) != 0 ) FAIL
    //check final list contents
    it = lst5.begin( );
    for( int i = 1; i <= 10; ++i ) {
        if( *it != i ) FAIL
        ++it;
    }

    return( true );
}

/* ------------------------------------------------------------------
 * reverse_test
 * test list reverse method
 */
bool reverse_test( )
{
    std::list< int > lst;
    //try a zero sized list
    lst.reverse( );
    if( INSANE( lst ) || lst.size( ) != 0 ) FAIL
    //try a non-trivial list
    for( int i = 1; i <= 10; ++i ) lst.push_back( i );
    lst.reverse( );
    if( INSANE( lst ) || lst.size( ) != 10 ) FAIL
    //check final list contents
    std::list< int >::iterator it( lst.begin( ) );
    for( int i = 10; i >= 1; --i ) {
        if( *it != i ) FAIL
        ++it;
    }
    //let's try a reverse iteration too to check out the reverse links
    std::list< int >::reverse_iterator rit( lst.rbegin( ) );
    for( int i = 1; i <= 10; ++i ) {
        if( *rit != i ) FAIL
        ++rit;
    }
    return( true );
}

/* ------------------------------------------------------------------
 * merge_test
 * test list merging methods
 */

struct merge_data {
  int A[11];
  int B[11];
  int R[11];
};
struct merge_data merge_tests[] = {
  { { 0, 2, 4, -1 },
    { 1, 3, 5, -1 },
    { 0, 1, 2, 3, 4, 5, -1 } },

  { { 0, 2, 4, -1 },
    { -1 },
    { 0, 2, 4, -1 } },

  { { -1 },
    { 0, 2, 4, -1 },
    { 0, 2, 4, -1 } },

  { { 1, 3, 5, -1 },
    { 1, 2, -1 },
    { 1, 1, 2, 3, 5, -1 } },

  { { 1, 2, -1 },
    { 1, 3, 5, -1 },
    { 1, 1, 2, 3, 5, -1 } },

  { { 1, 2, -1 },
    { 3, 4, 5, -1 },
    { 1, 2, 3, 4, 5, -1 } },

  { { 3, 4, 5, -1 },
    { 1, 2, -1 },
    { 1, 2, 3, 4, 5, -1 } }
};
const int merge_test_count = sizeof(merge_tests)/sizeof(merge_data);

bool merge_test( )
{
  int *p;

  for( int test_no = 0; test_no < merge_test_count; ++test_no ) {
    std::list< int > lst_1, lst_2;

    //prepare the two lists and merge them.
    p = merge_tests[test_no].A;
    while( *p != -1 ) { lst_1.push_back( *p ); ++p; }
    p = merge_tests[test_no].B;
    while( *p != -1 ) { lst_2.push_back( *p ); ++p; }
    lst_1.merge( lst_2 );

    //did it work?
    if( INSANE( lst_1 ) || INSANE( lst_2 ) ) FAIL;
    p = merge_tests[test_no].R;
    while( *p != -1 ) {
      if( lst_1.front( ) != *p ) FAIL;
      lst_1.pop_front( );
      ++p;
    }
  }

  return( true );
}

/* ------------------------------------------------------------------
 * allocator_test
 * test stateful allocators and exception handling
 */
bool allocator_test( )
{
    typedef std::list< int, LowMemAllocator<int> > list_t;
    LowMemAllocator<int> mem(100);
    mem.SetTripOnAlloc();
    list_t lst( mem );
    bool thrown = false;
    
    //LowMemAllocator is set to trip after 100 allocations
    try{
        for( int i=0; i<101; i++ ){
            lst.push_front( i );
        }
    }catch( std::bad_alloc const & ){
        mem = lst.get_allocator();
        if( mem.GetNumAllocs() != 101 ) FAIL       //should fail on 101st
        if( INSANE(lst) || lst.size() != 99 ) FAIL //one alloc for sentinel
        thrown = true;
    }
    if( !thrown ) FAIL  //exception should have been thrown
    
    lst.clear();
    mem.Reset(100);
    mem.SetTripOnConstruct();
    thrown = false;
    //LowMemAllocator is set to trip after 100 allocations
    try{
        for( int i=0; i<101; i++ ){
            lst.push_back( i );
        }
    }catch( std::bad_alloc const & ){
        mem = lst.get_allocator();
        if( mem.GetNumConstructs() != 101 ) FAIL
        //should have cleaned up last one and left only 100 allocated items
        if( mem.GetNumAllocs() != 101 || mem.GetNumDeallocs() != 1 ) FAIL    
        if( INSANE(lst) || lst.size() != 100 ) FAIL
        thrown = true;
    }
    if( !thrown ) FAIL  //exception should have been thrown
    //if container didn't deal with the exception and clean up the allocated 
    //memory then the leak detector will also trip later
    
    lst.clear();
    mem.Reset(100);
    thrown = false;
    for( int i = 0; i < 70; i++ ){
        lst.push_back( i );
    }
    //now reset the allocator so it trips at a lower threshold
    //and test the copy mechanism works right
    mem.Reset( 50 );
    mem.SetTripOnAlloc();
    try{
        list_t lst2( lst );
    }catch( std::bad_alloc ){
        if( mem.GetNumConstructs() != 49 ) FAIL  //sentinel not constructed
        if( mem.GetNumAllocs()     != 51 ) FAIL
        if( mem.GetNumDestroys()   != 49 ) FAIL  //sentinel not destroyed
        if( mem.GetNumDeallocs()   != 50 ) FAIL
        if( INSANE( lst ) || lst.size() != 70 ) FAIL
        thrown = true;
    }
    if( !thrown ) FAIL
    
    return( true );
}

int main( )
{
    int rc = 0;
    int original_count = heap_count( );
    //heap_dump();

    try {
        if( !construct_test( )        || !heap_ok( "t01" ) ) rc = 1;
        if( !access_test( )           || !heap_ok( "t02" ) ) rc = 1;
        //if( !string_test( )           || !heap_ok( "t03" ) ) rc = 1;
        //if( !torture_test( )          || !heap_ok( "t04" ) ) rc = 1;
        if( !assign_test( )           || !heap_ok( "t05" ) ) rc = 1;
        if( !clear_test( )            || !heap_ok( "t06" ) ) rc = 1;
        if( !erase_test( )            || !heap_ok( "t07" ) ) rc = 1;
        if( !swap_test( )             || !heap_ok( "t08" ) ) rc = 1;
        if( !remove_test( )           || !heap_ok( "t09" ) ) rc = 1;
        if( !iterator_test( )         || !heap_ok( "t10" ) ) rc = 1;
        if( !reverse_iterator_test( ) || !heap_ok( "t11" ) ) rc = 1;
        if( !copy_test( )             || !heap_ok( "t12" ) ) rc = 1;
        if( !splice_test( )           || !heap_ok( "t13" ) ) rc = 1;
        if( !reverse_test( )          || !heap_ok( "t14" ) ) rc = 1;
        if( !merge_test( )            || !heap_ok( "t15" ) ) rc = 1;
        if( !allocator_test( )        || !heap_ok( "t16" ) ) rc = 1;
    }
    catch( ... ) {
        std::cout << "Unexpected exception of unexpected type.\n";
        rc = 1;
    }

    if( heap_count( ) != original_count ) {
        std::cout << "Possible memory leak!\n";
        heap_dump();
        rc = 1;
    }
    return( rc );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?