MOAB: Mesh Oriented datABase  (version 5.3.1)
TestTypeSequenceManager.cpp
Go to the documentation of this file.
00001 #include <thread>
00002 #include <set>
00003 
00004 #include "TypeSequenceManager.hpp"
00005 #include "EntitySequence.hpp"
00006 #include "SequenceData.hpp"
00007 #include "TestUtil.hpp"
00008 #include "moab/Error.hpp"
00009 
00010 using namespace moab;
00011 
00012 void test_basic();
00013 void test_lower_bound();
00014 void test_upper_bound();
00015 void test_find();
00016 void test_get_entities();
00017 void test_insert_sequence_merge();
00018 void test_insert_sequence_nomerge();
00019 void test_remove_sequence();
00020 void test_replace_subsequence();
00021 void test_erase();
00022 void test_find_free_handle();
00023 void test_find_free_sequence();
00024 void test_is_free_sequence();
00025 void test_is_free_handle();
00026 #ifndef MOAB_FORCE_32_BIT_HANDLES
00027 void test_threaded_access( int n_threads );
00028 void test_single_thread_access();
00029 #endif
00030 void test_multi_thread_access();
00031 
00032 void regression_svn1952();
00033 void regression_svn1958();
00034 void regression_svn1960();
00035 
00036 /* Construct sequence of vertex handles containing
00037    the ID ranges: { [3,7], [100,111], [1001] }
00038    referencing a SequnceData with the range [1,22000]
00039  */
00040 void make_basic_sequence( TypeSequenceManager& seq );
00041 void make_basic_sequence( TypeSequenceManager& seq, EntitySequence*& seq3to7, EntitySequence*& seq100to111,
00042                           EntitySequence*& seq1001 );
00043 
00044 /* Compare expected sequence contents to actual contents.
00045  * Also does some consistency checks.
00046  */
00047 bool seqman_equal( const EntityHandle pair_array[][2], unsigned num_pairs, const TypeSequenceManager& seqman );
00048 
00049 /*
00050  * Insert a sequence into a sequence manager.  Delete passed
00051  * sequence (and optionally SequenceData) if insertion fails.
00052  */
00053 ErrorCode insert_seq( TypeSequenceManager& seqman, EntityHandle start_handle, EntityID count, SequenceData* data,
00054                       bool del_data = false );
00055 
00056 int main()
00057 {
00058     if( RUN_TEST( test_basic ) )
00059     {
00060         printf( "BASIC USE TEST FAILED\nCANNOT TEST FURTHER\n" );
00061         return 1;
00062     }
00063 
00064     int error_count = 0;
00065     error_count += RUN_TEST( test_lower_bound );
00066     error_count += RUN_TEST( test_upper_bound );
00067     error_count += RUN_TEST( test_find );
00068     error_count += RUN_TEST( test_get_entities );
00069     error_count += RUN_TEST( test_insert_sequence_merge );
00070     error_count += RUN_TEST( test_insert_sequence_nomerge );
00071     error_count += RUN_TEST( test_remove_sequence );
00072     error_count += RUN_TEST( test_replace_subsequence );
00073     error_count += RUN_TEST( test_erase );
00074     error_count += RUN_TEST( test_find_free_handle );
00075     error_count += RUN_TEST( test_find_free_sequence );
00076     error_count += RUN_TEST( test_is_free_sequence );
00077 #ifndef MOAB_FORCE_32_BIT_HANDLES
00078     error_count += RUN_TEST( test_single_thread_access );
00079     error_count += RUN_TEST( test_multi_thread_access );
00080 #endif
00081     error_count += RUN_TEST( regression_svn1952 );
00082     error_count += RUN_TEST( regression_svn1958 );
00083     error_count += RUN_TEST( regression_svn1960 );
00084 
00085     if( !error_count )
00086         printf( "ALL TESTS PASSED\n" );
00087     else
00088         printf( "%d TESTS FAILED\n", error_count );
00089 
00090     return error_count;
00091 }
00092 
00093 class DumSeq : public EntitySequence
00094 {
00095   private:
00096     int valsPerEnt;
00097 
00098   public:
00099     DumSeq( EntityHandle start, EntityID count, SequenceData* data2, int vals_per_ent = 0 )
00100         : EntitySequence( start, count, data2 ), valsPerEnt( vals_per_ent )
00101     {
00102     }
00103     DumSeq( SequenceData* data2, int vals_per_ent = 0 )
00104         : EntitySequence( data2->start_handle(), data2->size(), data2 ), valsPerEnt( vals_per_ent )
00105     {
00106     }
00107 
00108     DumSeq( DumSeq& split_from, EntityHandle here )
00109         : EntitySequence( split_from, here ), valsPerEnt( split_from.valsPerEnt )
00110     {
00111     }
00112 
00113     virtual ~DumSeq() {}
00114 
00115     EntitySequence* split( EntityHandle here )
00116     {
00117         return new DumSeq( *this, here );
00118     }
00119 
00120     SequenceData* create_data_subset( EntityHandle a, EntityHandle b ) const
00121     {
00122         return data()->subset( a, b, 0 );
00123     }
00124 
00125     void get_const_memory_use( unsigned long& a, unsigned long& b ) const
00126     {
00127         a = b = 0;
00128     }
00129     unsigned long get_per_entity_memory_use( EntityHandle, EntityHandle ) const
00130     {
00131         return 0;
00132     }
00133 
00134     int values_per_entity() const
00135     {
00136         return valsPerEnt;
00137     }
00138 };
00139 
00140 void make_basic_sequence( TypeSequenceManager& seqman )
00141 {
00142     EntitySequence *s, *t, *u;
00143     make_basic_sequence( seqman, s, t, u );
00144 }
00145 
00146 ErrorCode insert_seq( TypeSequenceManager& seqman, EntityHandle start_handle, EntityID count, SequenceData* data,
00147                       bool del_data )
00148 {
00149     EntitySequence* seq = new DumSeq( start_handle, count, data );
00150     ErrorCode rval      = seqman.insert_sequence( seq );
00151     if( MB_SUCCESS != rval )
00152     {
00153         delete seq;
00154         if( del_data ) delete data;
00155     }
00156     else
00157     {
00158         CHECK( start_handle >= seq->start_handle() );
00159         CHECK( start_handle + count - 1 <= seq->end_handle() );
00160     }
00161     return rval;
00162 }
00163 
00164 void make_basic_sequence( TypeSequenceManager& seqman, EntitySequence*& seq1, EntitySequence*& seq2,
00165                           EntitySequence*& seq3 )
00166 {
00167     CHECK( seqman.empty() );
00168     CHECK_EQUAL( (EntityID)0, seqman.get_number_entities() );
00169 
00170     SequenceData* data = new SequenceData( 0, 1, 22000 );CHECK_ERR( insert_seq( seqman, 3, 5, data ) );CHECK_ERR( insert_seq( seqman, 100, 12, data ) );CHECK_ERR( insert_seq( seqman, 1001, 1, data ) );
00171 
00172     CHECK( !seqman.empty() );
00173     CHECK_EQUAL( (EntityID)18, seqman.get_number_entities() );
00174 
00175     TypeSequenceManager::iterator iter = seqman.begin();
00176     CHECK( iter != seqman.end() );
00177     seq1 = *iter;
00178     CHECK_EQUAL( (EntityHandle)3, seq1->start_handle() );
00179     CHECK_EQUAL( (EntityHandle)7, seq1->end_handle() );
00180     CHECK_EQUAL( data, seq1->data() );
00181     CHECK_EQUAL( (EntityID)5, seq1->size() );
00182 
00183     ++iter;
00184     CHECK( iter != seqman.end() );
00185     seq2 = *iter;
00186     CHECK_EQUAL( (EntityHandle)100, seq2->start_handle() );
00187     CHECK_EQUAL( (EntityHandle)111, seq2->end_handle() );
00188     CHECK_EQUAL( data, seq2->data() );
00189     CHECK_EQUAL( (EntityID)12, seq2->size() );
00190 
00191     ++iter;
00192     seq3 = *iter;
00193     CHECK( iter != seqman.end() );
00194     CHECK_EQUAL( (EntityHandle)1001, seq3->start_handle() );
00195     CHECK_EQUAL( (EntityHandle)1001, seq3->end_handle() );
00196     CHECK_EQUAL( data, seq3->data() );
00197     CHECK_EQUAL( (EntityID)1, seq3->size() );
00198 
00199     ++iter;
00200     CHECK( iter == seqman.end() );
00201 }
00202 
00203 void test_basic()
00204 {
00205     TypeSequenceManager seqman;
00206     make_basic_sequence( seqman );
00207 }
00208 
00209 void test_lower_bound()
00210 {
00211     TypeSequenceManager::const_iterator i;
00212     TypeSequenceManager seqman;
00213     EntitySequence *seq1,  // 3 to 7
00214         *seq2,             // 100 to 111
00215         *seq3;             // 1001
00216     make_basic_sequence( seqman, seq1, seq2, seq3 );
00217 
00218     i = seqman.lower_bound( 2 );
00219     CHECK_EQUAL( seq1, *i );
00220     i = seqman.lower_bound( 3 );
00221     CHECK_EQUAL( seq1, *i );
00222     i = seqman.lower_bound( 4 );
00223     CHECK_EQUAL( seq1, *i );
00224     i = seqman.lower_bound( 7 );
00225     CHECK_EQUAL( seq1, *i );
00226 
00227     i = seqman.lower_bound( 8 );
00228     CHECK_EQUAL( seq2, *i );
00229     i = seqman.lower_bound( 99 );
00230     CHECK_EQUAL( seq2, *i );
00231     i = seqman.lower_bound( 100 );
00232     CHECK_EQUAL( seq2, *i );
00233     i = seqman.lower_bound( 110 );
00234     CHECK_EQUAL( seq2, *i );
00235     i = seqman.lower_bound( 111 );
00236     CHECK_EQUAL( seq2, *i );
00237 
00238     i = seqman.lower_bound( 112 );
00239     CHECK_EQUAL( seq3, *i );
00240     i = seqman.lower_bound( 1000 );
00241     CHECK_EQUAL( seq3, *i );
00242     i = seqman.lower_bound( 1001 );
00243     CHECK_EQUAL( seq3, *i );
00244 
00245     i = seqman.lower_bound( 1002 );
00246     CHECK( i == seqman.end() );
00247 }
00248 
00249 void test_upper_bound()
00250 {
00251     TypeSequenceManager::const_iterator i;
00252     TypeSequenceManager seqman;
00253     EntitySequence *seq1,  // 3 to 7
00254         *seq2,             // 100 to 111
00255         *seq3;             // 1001
00256     make_basic_sequence( seqman, seq1, seq2, seq3 );
00257 
00258     i = seqman.upper_bound( 2 );
00259     CHECK_EQUAL( seq1, *i );
00260 
00261     i = seqman.upper_bound( 3 );
00262     CHECK_EQUAL( seq2, *i );
00263     i = seqman.upper_bound( 4 );
00264     CHECK_EQUAL( seq2, *i );
00265     i = seqman.upper_bound( 7 );
00266     CHECK_EQUAL( seq2, *i );
00267     i = seqman.upper_bound( 8 );
00268     CHECK_EQUAL( seq2, *i );
00269     i = seqman.upper_bound( 99 );
00270     CHECK_EQUAL( seq2, *i );
00271 
00272     i = seqman.upper_bound( 100 );
00273     CHECK_EQUAL( seq3, *i );
00274     i = seqman.upper_bound( 110 );
00275     CHECK_EQUAL( seq3, *i );
00276     i = seqman.upper_bound( 111 );
00277     CHECK_EQUAL( seq3, *i );
00278     i = seqman.upper_bound( 112 );
00279     CHECK_EQUAL( seq3, *i );
00280     i = seqman.upper_bound( 1000 );
00281     CHECK_EQUAL( seq3, *i );
00282 
00283     i = seqman.upper_bound( 1001 );
00284     CHECK( i == seqman.end() );
00285 }
00286 
00287 void test_find()
00288 {
00289     TypeSequenceManager seqman;
00290     EntitySequence *seq1,  // 3 to 7
00291         *seq2,             // 100 to 111
00292         *seq3,             // 1001
00293         *seq;
00294     make_basic_sequence( seqman, seq1, seq2, seq3 );
00295 
00296     seq = seqman.find( 2 );
00297     CHECK_EQUAL( NULL, seq );
00298     seq = seqman.find( 3 );
00299     CHECK_EQUAL( seq1, seq );
00300     seq = seqman.find( 4 );
00301     CHECK_EQUAL( seq1, seq );
00302     seq = seqman.find( 7 );
00303     CHECK_EQUAL( seq1, seq );
00304     seq = seqman.find( 8 );
00305     CHECK_EQUAL( NULL, seq );
00306 
00307     seq = seqman.find( 99 );
00308     CHECK_EQUAL( NULL, seq );
00309     seq = seqman.find( 100 );
00310     CHECK_EQUAL( seq2, seq );
00311     seq = seqman.find( 110 );
00312     CHECK_EQUAL( seq2, seq );
00313     seq = seqman.find( 111 );
00314     CHECK_EQUAL( seq2, seq );
00315     seq = seqman.find( 112 );
00316     CHECK_EQUAL( NULL, seq );
00317 
00318     seq = seqman.find( 1000 );
00319     CHECK_EQUAL( NULL, seq );
00320     seq = seqman.find( 1001 );
00321     CHECK_EQUAL( seq3, seq );
00322     seq = seqman.find( 1002 );
00323     CHECK_EQUAL( NULL, seq );
00324 }
00325 
00326 bool seqman_equal( const EntityHandle pair_array[][2], unsigned num_pairs, const TypeSequenceManager& seqman )
00327 {
00328     unsigned i;
00329     TypeSequenceManager::const_iterator j = seqman.begin();
00330     EntitySequence* seq                   = 0;
00331     for( i = 0; i < num_pairs; ++i, ++j )
00332     {
00333         if( j == seqman.end() ) break;
00334 
00335         if( seq && seq->end_handle() >= ( *j )->start_handle() )
00336         {
00337             printf( "Sequence [%lu,%lu] overlaps sequence [%lu,%lu]\n",
00338                     (unsigned long)ID_FROM_HANDLE( seq->start_handle() ),
00339                     (unsigned long)ID_FROM_HANDLE( seq->end_handle() ),
00340                     (unsigned long)ID_FROM_HANDLE( ( *j )->start_handle() ),
00341                     (unsigned long)ID_FROM_HANDLE( ( *j )->end_handle() ) );
00342             return false;
00343         }
00344 
00345         if( seq && seq->data() != ( *j )->data() && seq->data()->end_handle() >= ( *j )->data()->start_handle() )
00346         {
00347             printf( "SequenceData [%lu,%lu] overlaps SequenceData [%lu,%lu]\n",
00348                     (unsigned long)ID_FROM_HANDLE( seq->data()->start_handle() ),
00349                     (unsigned long)ID_FROM_HANDLE( seq->data()->end_handle() ),
00350                     (unsigned long)ID_FROM_HANDLE( ( *j )->data()->start_handle() ),
00351                     (unsigned long)ID_FROM_HANDLE( ( *j )->data()->end_handle() ) );
00352             return false;
00353         }
00354 
00355         seq = *j;
00356         if( seq->start_handle() > seq->end_handle() )
00357         {
00358             printf( "Inverted sequence [%lu,%lu]\n", (unsigned long)ID_FROM_HANDLE( seq->start_handle() ),
00359                     (unsigned long)ID_FROM_HANDLE( seq->end_handle() ) );
00360             return false;
00361         }
00362 
00363         if( pair_array[i][0] != seq->start_handle() || pair_array[i][1] != seq->end_handle() ) break;
00364 
00365         if( seq->data()->start_handle() > seq->start_handle() || seq->data()->end_handle() < seq->end_handle() )
00366         {
00367             printf( "Sequence [%lu,%lu] has data [%lu,%lu]\n", (unsigned long)ID_FROM_HANDLE( seq->start_handle() ),
00368                     (unsigned long)ID_FROM_HANDLE( seq->end_handle() ),
00369                     (unsigned long)ID_FROM_HANDLE( seq->data()->start_handle() ),
00370                     (unsigned long)ID_FROM_HANDLE( seq->data()->end_handle() ) );
00371             return false;
00372         }
00373     }
00374 
00375     if( i == num_pairs && j == seqman.end() ) return true;
00376 
00377     if( i < num_pairs )
00378         printf( "Sequence Mismatch: Expected: [%lu,%lu], got ", (unsigned long)ID_FROM_HANDLE( pair_array[i][0] ),
00379                 (unsigned long)ID_FROM_HANDLE( pair_array[i][1] ) );
00380     else
00381         printf( "Sequence Mismatch: Expected END, got " );
00382 
00383     if( j == seqman.end() )
00384         printf( "END.\n" );
00385     else
00386         printf( "[%lu,%lu]\n", (unsigned long)ID_FROM_HANDLE( ( *j )->start_handle() ),
00387                 (unsigned long)ID_FROM_HANDLE( ( *j )->end_handle() ) );
00388 
00389     return false;
00390 }
00391 
00392 void test_get_entities()
00393 {
00394     TypeSequenceManager seqman;
00395     make_basic_sequence( seqman );
00396 
00397     CHECK( !seqman.empty() );
00398     CHECK_EQUAL( (EntityID)18, seqman.get_number_entities() );
00399 
00400     Range entities;
00401     seqman.get_entities( entities );
00402     CHECK_EQUAL( (size_t)18, entities.size() );
00403 
00404     EntityHandle pairs[][2] = { { 3, 7 }, { 100, 111 }, { 1001, 1001 } };
00405     CHECK( seqman_equal( pairs, 3, seqman ) );
00406 }
00407 
00408 void test_insert_sequence_merge()
00409 {
00410     TypeSequenceManager seqman;
00411     make_basic_sequence( seqman );
00412     SequenceData* data = ( *seqman.begin() )->data();
00413 
00414     // append a sequence
00415     CHECK_ERR( insert_seq( seqman, 1003, 1, data ) );
00416     EntityHandle exp1[][2] = { { 3, 7 }, { 100, 111 }, { 1001, 1001 }, { 1003, 1003 } };
00417     CHECK( seqman_equal( exp1, 4, seqman ) );
00418 
00419     // prepend a sequence
00420     CHECK_ERR( insert_seq( seqman, 1, 1, data ) );
00421     EntityHandle exp2[][2] = { { 1, 1 }, { 3, 7 }, { 100, 111 }, { 1001, 1001 }, { 1003, 1003 } };
00422     CHECK( seqman_equal( exp2, 5, seqman ) );
00423 
00424     // insert sequence in middle
00425     CHECK_ERR( insert_seq( seqman, 150, 11, data ) );
00426     EntityHandle exp3[][2] = { { 1, 1 }, { 3, 7 }, { 100, 111 }, { 150, 160 }, { 1001, 1001 }, { 1003, 1003 } };
00427     CHECK( seqman_equal( exp3, 6, seqman ) );
00428 
00429     // merge sequence with predecessor
00430     CHECK_ERR( insert_seq( seqman, 8, 13, data ) );
00431     EntityHandle exp4[][2] = { { 1, 1 }, { 3, 20 }, { 100, 111 }, { 150, 160 }, { 1001, 1001 }, { 1003, 1003 } };
00432     CHECK( seqman_equal( exp4, 6, seqman ) );
00433 
00434     // merge sequence with following one
00435     CHECK_ERR( insert_seq( seqman, 87, 13, data ) );
00436     EntityHandle exp5[][2] = { { 1, 1 }, { 3, 20 }, { 87, 111 }, { 150, 160 }, { 1001, 1001 }, { 1003, 1003 } };
00437     CHECK( seqman_equal( exp5, 6, seqman ) );
00438 
00439     // merge sequence with two adjacent ones
00440     CHECK_ERR( insert_seq( seqman, 2, 1, data ) );
00441     EntityHandle exp6[][2] = { { 1, 20 }, { 87, 111 }, { 150, 160 }, { 1001, 1001 }, { 1003, 1003 } };
00442     CHECK( seqman_equal( exp6, 5, seqman ) );
00443 
00444     // try to insert a sequence that overlaps on the end
00445     CHECK_EQUAL( MB_ALREADY_ALLOCATED, insert_seq( seqman, 900, 1001, data ) );
00446 
00447     // try to insert a sequence that overlaps at the start
00448     CHECK_EQUAL( MB_ALREADY_ALLOCATED, insert_seq( seqman, 111, 140, data ) );
00449 }
00450 
00451 void test_insert_sequence_nomerge()
00452 {
00453     TypeSequenceManager seqman;
00454 
00455     // make sure inserting a sequence w/out a SequenceData fails
00456     CHECK_EQUAL( MB_FAILURE, insert_seq( seqman, 1, 5, NULL ) );
00457     CHECK( seqman.empty() );
00458 
00459     // Now set up a TypeSequenceManager for testing
00460 
00461     // Insert an EntitySequence for which the corresponding SequenceData
00462     // is exactly the same size.
00463     SequenceData* data1 = new SequenceData( 0, 3, 7 );
00464     DumSeq* seq         = new DumSeq( data1 );
00465     ErrorCode rval      = seqman.insert_sequence( seq );CHECK_ERR( rval );
00466     if( MB_SUCCESS != rval )
00467     {
00468         delete seq;
00469         delete data1;
00470         return;
00471     }
00472 
00473     // Insert an EntitySequence with additional room on both ends of
00474     // the SequenceData
00475     SequenceData* data2 = new SequenceData( 0, 100, 999 );
00476     seq                 = new DumSeq( 200, 100, data2 );
00477     rval                = seqman.insert_sequence( seq );CHECK_ERR( rval );
00478     if( MB_SUCCESS != rval )
00479     {
00480         delete seq;
00481         delete data2;
00482         return;
00483     }
00484 
00485     // Insert another EntitySequence sharing the previous SequenceData
00486     seq  = new DumSeq( 400, 100, data2 );
00487     rval = seqman.insert_sequence( seq );CHECK_ERR( rval );
00488     if( MB_SUCCESS != rval )
00489     {
00490         delete seq;
00491         return;
00492     }
00493 
00494     // Setup complete, begin tests
00495 
00496     // Test inserting sequence that appends an existing sequence
00497     // but overlaps underling SequenceData boundary
00498     SequenceData* data = new SequenceData( 0, 999, 1000 );
00499     seq                = new DumSeq( data );
00500     rval               = seqman.insert_sequence( seq );
00501     CHECK_EQUAL( MB_ALREADY_ALLOCATED, rval );
00502     delete seq;
00503     delete data;
00504 
00505     // Test inserting sequence that prepends an existing sequence
00506     // but overlaps underling SequenceData boundary
00507     data = new SequenceData( 0, 50, 199 );
00508     seq  = new DumSeq( data );
00509     rval = seqman.insert_sequence( seq );
00510     CHECK_EQUAL( MB_ALREADY_ALLOCATED, rval );
00511     delete seq;
00512     delete data;
00513 
00514     // Test fits within existing, but has different SequenceData
00515     data = new SequenceData( 0, 500, 599 );
00516     seq  = new DumSeq( data );
00517     rval = seqman.insert_sequence( seq );
00518     CHECK_EQUAL( MB_ALREADY_ALLOCATED, rval );
00519     delete seq;
00520     delete data;
00521 
00522     // Make sure we're starting out with what we expect
00523     EntityHandle exp1[][2] = { { 3, 7 }, { 200, 299 }, { 400, 499 } };
00524     CHECK( seqman_equal( exp1, 3, seqman ) );
00525 
00526     // Test fits within existing, and has same data
00527     CHECK_ERR( insert_seq( seqman, 600, 100, data2 ) );
00528     EntityHandle exp2[][2] = { { 3, 7 }, { 200, 299 }, { 400, 499 }, { 600, 699 } };
00529     CHECK( seqman_equal( exp2, 4, seqman ) );
00530 
00531     // Test is entirely outside existing data
00532     CHECK_ERR( insert_seq( seqman, 2000, 2, new SequenceData( 0, 2000, 2001 ), true ) );
00533     EntityHandle exp3[][2] = { { 3, 7 }, { 200, 299 }, { 400, 499 }, { 600, 699 }, { 2000, 2001 } };
00534     CHECK( seqman_equal( exp3, 5, seqman ) );
00535 
00536     // Test abutts end of existing data
00537     CHECK_ERR( insert_seq( seqman, 1000, 6, new SequenceData( 0, 1000, 1005 ), true ) );
00538     EntityHandle exp4[][2] = { { 3, 7 }, { 200, 299 }, { 400, 499 }, { 600, 699 }, { 1000, 1005 }, { 2000, 2001 } };
00539     CHECK( seqman_equal( exp4, 6, seqman ) );
00540 
00541     // Test abutts beginning of existing data
00542     CHECK_ERR( insert_seq( seqman, 50, 50, new SequenceData( 0, 50, 99 ), true ) );
00543     EntityHandle exp5[][2] = { { 3, 7 },     { 50, 99 },     { 200, 299 },  { 400, 499 },
00544                                { 600, 699 }, { 1000, 1005 }, { 2000, 2001 } };
00545     CHECK( seqman_equal( exp5, 7, seqman ) );
00546 }
00547 
00548 void test_remove_sequence()
00549 {
00550     TypeSequenceManager seqman;
00551     EntitySequence *seq1,  // 3 to 7
00552         *seq2,             // 100 to 111
00553         *seq3;             // 1001
00554     make_basic_sequence( seqman, seq1, seq2, seq3 );
00555 
00556     // test removing something that hasn't been inserted
00557     bool last;
00558     DumSeq junk( 3, 5, NULL );
00559     CHECK_EQUAL( MB_ENTITY_NOT_FOUND, seqman.remove_sequence( &junk, last ) );
00560     EntityHandle exp1[][2] = { { 3, 7 }, { 100, 111 }, { 1001, 1001 } };
00561     CHECK( seqman_equal( exp1, 3, seqman ) );
00562 
00563     // remove the middle sequence
00564     CHECK_ERR( seqman.remove_sequence( seq2, last ) );
00565     CHECK( !last );
00566     delete seq2;
00567 
00568     // remove the first sequence
00569     CHECK_ERR( seqman.remove_sequence( seq1, last ) );
00570     CHECK( !last );
00571     delete seq1;
00572 
00573     // remove the last sequence
00574     CHECK_ERR( seqman.remove_sequence( seq3, last ) );
00575     CHECK( last );
00576     SequenceData* data = seq3->data();
00577     delete seq3;
00578     delete data;
00579 }
00580 
00581 void test_replace_subsequence()
00582 {
00583     ErrorCode rval;
00584     TypeSequenceManager seqman;
00585 
00586     // create an initial set
00587     SequenceData* data1 = new SequenceData( 0, 51, 950 );
00588     rval                = insert_seq( seqman, 101, 100, data1, true );CHECK_ERR( rval );
00589     if( MB_SUCCESS != rval )
00590     {
00591         // data1 has been deleted by insert_seq call above
00592         return;
00593     }
00594     rval = insert_seq( seqman, 301, 300, data1 );CHECK_ERR( rval );
00595     rval = insert_seq( seqman, 701, 100, data1 );CHECK_ERR( rval );
00596 
00597     // try a sequence that is outside all existing data
00598     SequenceData* data = new SequenceData( 0, 10, 20 );
00599     DumSeq* seq        = new DumSeq( data );
00600     rval               = seqman.replace_subsequence( seq, 0, 0 );
00601     CHECK_EQUAL( MB_FAILURE, rval );
00602     delete seq;
00603     delete data;
00604 
00605     // try a sequence that overlaps the start of the data
00606     data = new SequenceData( 0, 40, 60 );
00607     seq  = new DumSeq( data );
00608     rval = seqman.replace_subsequence( seq, 0, 0 );
00609     CHECK_EQUAL( MB_FAILURE, rval );
00610     delete seq;
00611     delete data;
00612 
00613     // try a sequence that is within the data but not within any sequence
00614     data = new SequenceData( 0, 60, 70 );
00615     seq  = new DumSeq( data );
00616     rval = seqman.replace_subsequence( seq, 0, 0 );
00617     CHECK_EQUAL( MB_FAILURE, rval );
00618     delete seq;
00619     delete data;
00620 
00621     // try a sequence that overlaps an existing sequence
00622     data = new SequenceData( 0, 60, 101 );
00623     seq  = new DumSeq( data );
00624     rval = seqman.replace_subsequence( seq, 0, 0 );
00625     CHECK_EQUAL( MB_FAILURE, rval );
00626     delete seq;
00627     delete data;
00628 
00629     // try a sequence that should work, but with a SequenceData that
00630     // overlaps an existing sequence
00631     data = new SequenceData( 0, 150, 200 );
00632     seq  = new DumSeq( 190, 200, data );
00633     rval = seqman.replace_subsequence( seq, 0, 0 );
00634     CHECK_EQUAL( MB_FAILURE, rval );
00635     delete seq;
00636     delete data;
00637 
00638     // check that we're starting with what we expect
00639     EntityHandle exp1[][2] = { { 101, 200 }, { 301, 600 }, { 701, 800 } };
00640     CHECK( seqman_equal( exp1, 3, seqman ) );
00641 
00642     // split at start of sequence
00643     data = new SequenceData( 0, 101, 105 );
00644     seq  = new DumSeq( data );
00645     rval = seqman.replace_subsequence( seq, 0, 0 );CHECK_ERR( rval );
00646     if( MB_SUCCESS != rval )
00647     {
00648         delete seq;
00649         delete data;
00650         return;
00651     }
00652     EntityHandle exp2[][2] = { { 101, 105 }, { 106, 200 }, { 301, 600 }, { 701, 800 } };
00653     CHECK( seqman_equal( exp2, 4, seqman ) );
00654 
00655     // split at end of sequence
00656     data = new SequenceData( 0, 750, 800 );
00657     seq  = new DumSeq( data );
00658     rval = seqman.replace_subsequence( seq, 0, 0 );CHECK_ERR( rval );
00659     if( MB_SUCCESS != rval )
00660     {
00661         delete seq;
00662         delete data;
00663         return;
00664     }
00665     EntityHandle exp3[][2] = { { 101, 105 }, { 106, 200 }, { 301, 600 }, { 701, 749 }, { 750, 800 } };
00666     CHECK( seqman_equal( exp3, 5, seqman ) );
00667 
00668     // split at middle of sequence
00669     data = new SequenceData( 0, 400, 499 );
00670     seq  = new DumSeq( data );
00671     rval = seqman.replace_subsequence( seq, 0, 0 );CHECK_ERR( rval );
00672     if( MB_SUCCESS != rval )
00673     {
00674         delete seq;
00675         delete data;
00676         return;
00677     }
00678     EntityHandle exp4[][2] = { { 101, 105 }, { 106, 200 }, { 301, 399 }, { 400, 499 },
00679                                { 500, 600 }, { 701, 749 }, { 750, 800 } };
00680     CHECK( seqman_equal( exp4, 7, seqman ) );
00681 }
00682 
00683 void test_erase()
00684 {
00685     TypeSequenceManager seqman;
00686     make_basic_sequence( seqman );
00687     Error eh;
00688 
00689     // verify initial state
00690     EntityHandle exp1[][2] = { { 3, 7 }, { 100, 111 }, { 1001, 1001 } };
00691     CHECK( seqman_equal( exp1, 3, seqman ) );
00692 
00693     // try erasing invalid handles at start of existing sequence
00694     CHECK_EQUAL( MB_ENTITY_NOT_FOUND, seqman.erase( &eh, 1000, 1001 ) );
00695     // try erasing invalid entities at end of existing sequence
00696     CHECK_EQUAL( MB_ENTITY_NOT_FOUND, seqman.erase( &eh, 3, 8 ) );
00697     // verify initial state
00698     CHECK( seqman_equal( exp1, 3, seqman ) );
00699 
00700     // erase from front of sequence
00701     CHECK_ERR( seqman.erase( &eh, 3, 6 ) );
00702     EntityHandle exp2[][2] = { { 7, 7 }, { 100, 111 }, { 1001, 1001 } };
00703     CHECK( seqman_equal( exp2, 3, seqman ) );
00704 
00705     // erase from end of sequence
00706     CHECK_ERR( seqman.erase( &eh, 110, 111 ) );
00707     EntityHandle exp3[][2] = { { 7, 7 }, { 100, 109 }, { 1001, 1001 } };
00708     CHECK( seqman_equal( exp3, 3, seqman ) );
00709 
00710     // erase from middle of sequence
00711     CHECK_ERR( seqman.erase( &eh, 105, 107 ) );
00712     EntityHandle exp4[][2] = { { 7, 7 }, { 100, 104 }, { 108, 109 }, { 1001, 1001 } };
00713     CHECK( seqman_equal( exp4, 4, seqman ) );
00714 
00715     // erase sequence
00716     CHECK_ERR( seqman.erase( &eh, 7, 7 ) );
00717     EntityHandle exp5[][2] = { { 100, 104 }, { 108, 109 }, { 1001, 1001 } };
00718     CHECK( seqman_equal( exp5, 3, seqman ) );
00719 
00720     // erase sequence
00721     CHECK_ERR( seqman.erase( &eh, 108, 109 ) );
00722     EntityHandle exp6[][2] = { { 100, 104 }, { 1001, 1001 } };
00723     CHECK( seqman_equal( exp6, 2, seqman ) );
00724 
00725     // erase sequence
00726     CHECK_ERR( seqman.erase( &eh, 100, 104 ) );
00727     EntityHandle exp7[][2] = { { 1001, 1001 } };
00728     CHECK( seqman_equal( exp7, 1, seqman ) );
00729 
00730     // erase sequence
00731     CHECK_ERR( seqman.erase( &eh, 1001, 1001 ) );
00732     CHECK( seqman.empty() );
00733 }
00734 
00735 void test_find_free_handle()
00736 {
00737     bool append;
00738     TypeSequenceManager::iterator seq;
00739     TypeSequenceManager seqman;
00740     make_basic_sequence( seqman );  // { [3,7], [100,111], [1001] }
00741 
00742     seq = seqman.find_free_handle( 0, MB_END_ID, append );
00743     CHECK( seq != seqman.end() );
00744     // expect the first available handle (2).
00745     CHECK_EQUAL( (EntityHandle)3, ( *seq )->start_handle() );
00746     CHECK_EQUAL( (EntityHandle)7, ( *seq )->end_handle() );
00747     CHECK( !append );
00748 
00749     // Expect end() if no adjacent sequence
00750     seq = seqman.find_free_handle( 9, 98, append );
00751     CHECK( seq == seqman.end() );
00752 
00753     // Try a limited handle range
00754     seq = seqman.find_free_handle( 8, 99, append );
00755     CHECK( seq != seqman.end() );
00756     // expect the first available handle (8).
00757     CHECK_EQUAL( (EntityHandle)3, ( *seq )->start_handle() );
00758     CHECK_EQUAL( (EntityHandle)7, ( *seq )->end_handle() );
00759     CHECK( append );
00760 
00761     // Try an unambigious case (above tests have multiple
00762     // possible answers, were we assume the first available
00763     // handle).
00764     seq = seqman.find_free_handle( 8, 98, append );
00765     CHECK( seq != seqman.end() );
00766     CHECK_EQUAL( (EntityHandle)3, ( *seq )->start_handle() );
00767     CHECK_EQUAL( (EntityHandle)7, ( *seq )->end_handle() );
00768     CHECK( append );
00769 
00770     // Try an unambigious case (above tests have multiple
00771     // possible answers, were we assume the first available
00772     // handle).
00773     seq = seqman.find_free_handle( 9, 99, append );
00774     CHECK( seq != seqman.end() );
00775     CHECK_EQUAL( (EntityHandle)100, ( *seq )->start_handle() );
00776     CHECK_EQUAL( (EntityHandle)111, ( *seq )->end_handle() );
00777     CHECK( !append );
00778 
00779     // Try a case where the expected result handle
00780     // is in the middle of the input range.
00781     seq = seqman.find_free_handle( 900, 1100, append );
00782     CHECK( seq != seqman.end() );
00783     CHECK_EQUAL( (EntityHandle)1001, ( *seq )->start_handle() );
00784     CHECK_EQUAL( (EntityHandle)1001, ( *seq )->end_handle() );
00785     // Expect first available handle
00786     CHECK( !append );
00787 }
00788 
00789 void test_find_free_sequence()
00790 {
00791     EntityHandle start;
00792     SequenceData* data = 0;
00793     EntityID data_size = 0;
00794     TypeSequenceManager seqman;
00795     make_basic_sequence( seqman );  // { [3,7], [100,111], [1001] }
00796     SequenceData* expdata = ( *seqman.begin() )->data();
00797 
00798     start = seqman.find_free_sequence( 2, 1, 3, data, data_size );
00799     CHECK_EQUAL( expdata, data );
00800     CHECK_EQUAL( (EntityHandle)1, start );
00801 
00802     start = seqman.find_free_sequence( 3, 1, 7, data, data_size );
00803     CHECK_EQUAL( (EntityHandle)0, start );
00804     CHECK_EQUAL( NULL, data );
00805 
00806     start = seqman.find_free_sequence( 30, 1, 120, data, data_size );
00807     CHECK_EQUAL( expdata, data );
00808     CHECK( start == 8 || start == 70 );
00809 
00810     start = seqman.find_free_sequence( 10, 92, 999, data, data_size );
00811     CHECK_EQUAL( expdata, data );
00812     CHECK_EQUAL( (EntityHandle)112, start );
00813 
00814     start = seqman.find_free_sequence( 100, 1, 600, data, data_size );
00815     CHECK_EQUAL( expdata, data );
00816     CHECK_EQUAL( (EntityHandle)112, start );
00817 
00818     start = seqman.find_free_sequence( 1000, 1, MB_END_ID, data, data_size );
00819     CHECK_EQUAL( expdata, data );
00820     CHECK_EQUAL( (EntityHandle)1002, start );
00821 
00822     start = seqman.find_free_sequence( 980, 1, 1800, data, data_size );
00823     CHECK_EQUAL( (EntityHandle)0, start );
00824     CHECK_EQUAL( NULL, data );
00825 }
00826 
00827 void test_is_free_sequence()
00828 {
00829     SequenceData* data = 0;
00830     TypeSequenceManager seqman;
00831     make_basic_sequence( seqman );  // { [3,7], [100,111], [1001] }
00832     SequenceData* expdata = ( *seqman.begin() )->data();
00833 
00834     CHECK( !seqman.is_free_sequence( 1, 3, data ) );
00835     CHECK( seqman.is_free_sequence( 1, 2, data ) );
00836     CHECK_EQUAL( expdata, data );
00837     CHECK( !seqman.is_free_sequence( 7, 93, data ) );
00838     CHECK( !seqman.is_free_sequence( 8, 93, data ) );
00839     CHECK( seqman.is_free_sequence( 8, 92, data ) );
00840     CHECK_EQUAL( expdata, data );
00841     CHECK( !seqman.is_free_sequence( 111, 890, data ) );
00842     CHECK( !seqman.is_free_sequence( 112, 890, data ) );
00843     CHECK( seqman.is_free_sequence( 112, 879, data ) );
00844     CHECK_EQUAL( expdata, data );
00845     CHECK( seqman.is_free_sequence( 1002, 1, data ) );
00846     CHECK_EQUAL( expdata, data );
00847     CHECK( seqman.is_free_sequence( 2000, 20000, data ) );
00848     CHECK_EQUAL( expdata, data );
00849 }
00850 
00851 void test_is_free_handle()
00852 {
00853     // Construct a TypeSequenceManager with the following data:
00854     // EntitySequence: |[1,500]|   |[601,1000]|       |[2500,2599]|    |[2800,2999]|
00855     // SequenceData:   |       [1,1000]       |    |         [2001,3000]            |
00856     ErrorCode rval;
00857     TypeSequenceManager seqman;
00858     SequenceData* data1 = new SequenceData( 0, 1, 1000 );
00859     SequenceData* data2 = new SequenceData( 0, 2001, 3000 );
00860     rval                = insert_seq( seqman, 1, 500, data1, true );CHECK_ERR( rval );
00861     if( MB_SUCCESS != rval )
00862     {
00863         // data1 has been deleted by insert_seq call above
00864         return;
00865     }
00866     rval = insert_seq( seqman, 601, 400, data1, false );CHECK_ERR( rval );
00867     rval = insert_seq( seqman, 2500, 100, data2, true );CHECK_ERR( rval );
00868     if( MB_SUCCESS != rval )
00869     {
00870         // data2 has been deleted by insert_seq call above
00871         return;
00872     }
00873     rval = insert_seq( seqman, 2800, 200, data2, false );CHECK_ERR( rval );
00874 
00875     // Begin tests
00876     TypeSequenceManager::iterator seq;
00877     SequenceData* data;
00878     EntityHandle first, last;
00879 
00880     // Test handle in use
00881 
00882     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 1, seq, data, first, last ) );
00883     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 300, seq, data, first, last ) );
00884     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 500, seq, data, first, last ) );
00885     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 601, seq, data, first, last ) );
00886     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 2500, seq, data, first, last ) );
00887     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 2599, seq, data, first, last ) );
00888     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 2800, seq, data, first, last ) );
00889     CHECK_EQUAL( MB_ALREADY_ALLOCATED, seqman.is_free_handle( 2999, seq, data, first, last ) );
00890 
00891     // Test prepend to sequence
00892 
00893     seq   = seqman.end();
00894     data  = 0;
00895     first = last = 0;
00896     CHECK( seqman.is_free_handle( 600, seq, data, first, last ) );
00897     CHECK( seq != seqman.end() );
00898     CHECK_EQUAL( (EntityHandle)601, ( *seq )->start_handle() );
00899     CHECK_EQUAL( data1, data );
00900     CHECK_EQUAL( (EntityHandle)600, first );
00901     CHECK_EQUAL( (EntityHandle)600, last );
00902 
00903     seq   = seqman.end();
00904     data  = 0;
00905     first = last = 0;
00906     CHECK( seqman.is_free_handle( 2499, seq, data, first, last ) );
00907     CHECK( seq != seqman.end() );
00908     CHECK_EQUAL( (EntityHandle)2500, ( *seq )->start_handle() );
00909     CHECK_EQUAL( data2, data );
00910     CHECK_EQUAL( (EntityHandle)2499, first );
00911     CHECK_EQUAL( (EntityHandle)2499, last );
00912 
00913     seq   = seqman.end();
00914     data  = 0;
00915     first = last = 0;
00916     CHECK( seqman.is_free_handle( 2799, seq, data, first, last ) );
00917     CHECK( seq != seqman.end() );
00918     CHECK_EQUAL( (EntityHandle)2800, ( *seq )->start_handle() );
00919     CHECK_EQUAL( data2, data );
00920     CHECK_EQUAL( (EntityHandle)2799, first );
00921     CHECK_EQUAL( (EntityHandle)2799, last );
00922 
00923     // Test append to sequence
00924 
00925     seq   = seqman.end();
00926     data  = 0;
00927     first = last = 0;
00928     CHECK( seqman.is_free_handle( 501, seq, data, first, last ) );
00929     CHECK( seq != seqman.end() );
00930     CHECK_EQUAL( (EntityHandle)1, ( *seq )->start_handle() );
00931     CHECK_EQUAL( data1, data );
00932     CHECK_EQUAL( (EntityHandle)501, first );
00933     CHECK_EQUAL( (EntityHandle)501, last );
00934 
00935     seq   = seqman.end();
00936     data  = 0;
00937     first = last = 0;
00938     CHECK( seqman.is_free_handle( 2600, seq, data, first, last ) );
00939     CHECK( seq != seqman.end() );
00940     CHECK_EQUAL( (EntityHandle)2500, ( *seq )->start_handle() );
00941     CHECK_EQUAL( data2, data );
00942     CHECK_EQUAL( (EntityHandle)2600, first );
00943     CHECK_EQUAL( (EntityHandle)2600, last );
00944 
00945     seq   = seqman.end();
00946     data  = 0;
00947     first = last = 0;
00948     CHECK( seqman.is_free_handle( 3000, seq, data, first, last ) );
00949     CHECK( seq != seqman.end() );
00950     CHECK_EQUAL( (EntityHandle)2800, ( *seq )->start_handle() );
00951     CHECK_EQUAL( data2, data );
00952     CHECK_EQUAL( (EntityHandle)3000, first );
00953     CHECK_EQUAL( (EntityHandle)3000, last );
00954 
00955     // Test new sequence in existing SequenceData
00956 
00957     seq   = seqman.end();
00958     data  = 0;
00959     first = last = 0;
00960     CHECK( seqman.is_free_handle( 502, seq, data, first, last ) );
00961     CHECK( seqman.end() == seq );
00962     CHECK_EQUAL( data1, data );
00963     CHECK_EQUAL( (EntityHandle)501, first );
00964     CHECK_EQUAL( (EntityHandle)600, last );
00965 
00966     seq   = seqman.end();
00967     data  = 0;
00968     first = last = 0;
00969     CHECK( seqman.is_free_handle( 599, seq, data, first, last ) );
00970     CHECK( seqman.end() == seq );
00971     CHECK_EQUAL( data1, data );
00972     CHECK_EQUAL( (EntityHandle)501, first );
00973     CHECK_EQUAL( (EntityHandle)600, last );
00974 
00975     seq   = seqman.end();
00976     data  = 0;
00977     first = last = 0;
00978     CHECK( seqman.is_free_handle( 2001, seq, data, first, last ) );
00979     CHECK( seqman.end() == seq );
00980     CHECK_EQUAL( data2, data );
00981     CHECK_EQUAL( (EntityHandle)2001, first );
00982     CHECK_EQUAL( (EntityHandle)2499, last );
00983 
00984     seq   = seqman.end();
00985     data  = 0;
00986     first = last = 0;
00987     CHECK( seqman.is_free_handle( 2498, seq, data, first, last ) );
00988     CHECK( seqman.end() == seq );
00989     CHECK_EQUAL( data2, data );
00990     CHECK_EQUAL( (EntityHandle)2001, first );
00991     CHECK_EQUAL( (EntityHandle)2499, last );
00992 
00993     // Test new SequenceData
00994 
00995     seq   = seqman.end();
00996     data  = 0;
00997     first = last = 0;
00998     CHECK( seqman.is_free_handle( 1001, seq, data, first, last ) );
00999     CHECK( seqman.end() == seq );
01000     CHECK_EQUAL( (SequenceData*)0, data );
01001     CHECK_EQUAL( (EntityHandle)1001, first );
01002     CHECK_EQUAL( (EntityHandle)2000, last );
01003 
01004     seq   = seqman.end();
01005     data  = 0;
01006     first = last = 0;
01007     CHECK( seqman.is_free_handle( 1500, seq, data, first, last ) );
01008     CHECK( seqman.end() == seq );
01009     CHECK_EQUAL( (SequenceData*)0, data );
01010     CHECK_EQUAL( (EntityHandle)1001, first );
01011     CHECK_EQUAL( (EntityHandle)2000, last );
01012 
01013     seq   = seqman.end();
01014     data  = 0;
01015     first = last = 0;
01016     CHECK( seqman.is_free_handle( 2000, seq, data, first, last ) );
01017     CHECK( seqman.end() == seq );
01018     CHECK_EQUAL( (SequenceData*)0, data );
01019     CHECK_EQUAL( (EntityHandle)1001, first );
01020     CHECK_EQUAL( (EntityHandle)2000, last );
01021 
01022     seq   = seqman.end();
01023     data  = 0;
01024     first = last = 0;
01025     CHECK( seqman.is_free_handle( 3001, seq, data, first, last ) );
01026     CHECK( seqman.end() == seq );
01027     CHECK_EQUAL( (SequenceData*)0, data );
01028     CHECK_EQUAL( (EntityHandle)3001, first );
01029     CHECK_EQUAL( (EntityHandle)MB_END_ID, last );
01030 
01031     seq   = seqman.end();
01032     data  = 0;
01033     first = last = 0;
01034     CHECK( seqman.is_free_handle( 10000, seq, data, first, last ) );
01035     CHECK( seqman.end() == seq );
01036     CHECK_EQUAL( (SequenceData*)0, data );
01037     CHECK_EQUAL( (EntityHandle)3001, first );
01038     CHECK_EQUAL( (EntityHandle)MB_END_ID, last );
01039 }
01040 
01041 void call_find( TypeSequenceManager* seqman, const std::set< int >& removed, int num_orig_entities, int& n_failures )
01042 {
01043     ErrorCode rval = MB_SUCCESS;
01044 
01045     const EntitySequence* seq;
01046     int n_queries = 10000;
01047     for( int i = 0; i < n_queries; i++ )
01048     {
01049         int idx = ( (double)rand() / RAND_MAX * num_orig_entities ) + 1;
01050 
01051         // do not check for entities we've removed
01052         if( removed.count( idx ) != 0 ) continue;
01053         // search for this entity in the sequence manager
01054         rval = seqman->find( idx, seq );
01055         CHECK_EQUAL( MB_SUCCESS, rval );
01056         // check that the returned sequence actually contains this entity
01057         // (this is where threaded access used to fail)
01058         if( idx < seq->start_handle() || idx > seq->end_handle() ) { n_failures += 1; }
01059     }
01060 }
01061 #ifndef MOAB_FORCE_32_BIT_HANDLES
01062 void test_threaded_access( int n_threads )
01063 {
01064     TypeSequenceManager seqman;
01065     std::set< int > removed_indices;
01066 
01067     // create a sequence from start to end
01068     EntityHandle start = 1, end = 200000;
01069     int i_end          = end;
01070     SequenceData* data = new SequenceData( 0, start, end );CHECK_ERR( insert_seq( seqman, start, end, data ) );
01071 
01072     // erase one hundred random entities from the sequence
01073     // to ensure a lot of switching of TypeSequenceManager::lastReferenced
01074     Error e;
01075     for( int i = 0; i < 100; i++ )
01076     {
01077         int idx = ( (double)rand() / RAND_MAX * i_end ) + 1;
01078         removed_indices.insert( idx );
01079         seqman.erase( &e, idx );
01080     }
01081     // create a set of quereies per thread
01082     std::vector< std::thread > threads;
01083     std::vector< int > failures( n_threads, 0 );
01084     for( int i = 0; i < n_threads; i++ )
01085     {
01086         threads.push_back( std::thread( call_find, &seqman, removed_indices, i_end, std::ref< int >( failures[i] ) ) );
01087     }
01088     // wait for threads to finish
01089     for( size_t i = 0; i < threads.size(); i++ )
01090     {
01091         threads[i].join();
01092     }
01093 
01094     int n_failures = 0;
01095     for( size_t i = 0; i < failures.size(); i++ )
01096         n_failures += failures[i];
01097 
01098     if( n_failures > 0 ) { std::cout << n_failures << " invalid sequences found." << std::endl; }
01099 
01100     CHECK_EQUAL( 0, n_failures );
01101 }
01102 
01103 void test_single_thread_access()
01104 {
01105     test_threaded_access( 1 );
01106 }
01107 
01108 void test_multi_thread_access()
01109 {
01110     test_threaded_access( 2 );
01111 }
01112 #endif
01113 // Regression test for bug fixed in SVN revision 1952.
01114 // SVN checkin message:
01115 //  Fixing a bug in allocation of sequences.  Before this commit, when:
01116 //  - Existing sequence starts at one place, e.g. 41686, but its
01117 //  sequenceData starts earlier, e.g. 41673, and
01118 //  - You try to allocate a new sequence at a lower handle but with a
01119 //  range which is more than the room available in the sequenceData,
01120 //
01121 //  then
01122 //  - the code wants to allocate right up against the lower end of the
01123 //  existing sequence, and sizes the new sequenceData accordingly
01124 //  (i.e. with a max of 41685).
01125 //
01126 //  In this case, that new sequenceData will overlap the existing
01127 //  sequenceData (which starts at 41673, even though it has an empty chunk
01128 //  in front).
01129 //
01130 //  So, this change passes back a sequence data size from the code which
01131 //  computes where to put the start handle when allocating the new
01132 //  sequence.
01133 void regression_svn1952()
01134 {
01135     const EntityHandle last_handle = 50000;
01136     TypeSequenceManager seqman;
01137     SequenceData* data = new SequenceData( 0, 41673, last_handle );CHECK_ERR( insert_seq( seqman, 41686, 1000, data, true ) );
01138 
01139     SequenceData* result_data;
01140     EntityID result_size;
01141     EntityHandle result_handle;
01142     result_handle = seqman.find_free_sequence( 1686, 4000, 2 * last_handle, result_data, result_size );
01143     CHECK( result_handle > last_handle || result_handle + result_size <= 41673 );
01144     CHECK( result_handle + result_size <= 2 * last_handle );
01145 }
01146 
01147 // Regression test for bug fixed in SVN revision 1958.
01148 // SVN checkin message:
01149 //  Another fix to SequenceManager.  This time:
01150 //  - there was no sequence data allocated for the target range
01151 //  - there was exactly enough room in unallocated sequence data for the target range
01152 //  - the next data sequence up had a couple of empty slots, so the first occupied handle was a
01153 //  couple spaces from the start of the sequence data
01154 //  - the upper end of the range of the allocated sequence data was computed based on the first
01155 //  handle in the next sequence data
01156 //
01157 //  Fixed by setting the size using the parameter I added before.
01158 void regression_svn1958()
01159 {
01160     const int data_size           = 100;
01161     const EntityHandle data_start = 100;
01162     const EntityHandle data_end   = data_start + data_size - 1;
01163     const int seq_offset          = 2;
01164 
01165     TypeSequenceManager seqman;
01166     SequenceData* data = new SequenceData( 0, data_start, data_end );CHECK_ERR( insert_seq( seqman, data_start + seq_offset, data_size - seq_offset, data, true ) );
01167 
01168     SequenceData* result_data;
01169     EntityID result_size;
01170     EntityHandle result_handle;
01171     result_handle = seqman.find_free_sequence( data_start - 1, 1, 100000, result_data, result_size );
01172     CHECK( result_handle > data_end || result_handle + result_size <= data_start );
01173 }
01174 
01175 // Regression test for bug fixed in SVN revision 1960.
01176 // SVN checkin message:
01177 //  Third time pays for all.  This time, in TSM::is_free_sequence was true,
01178 //  so there was a free sequence; SM::create_entity_sequence then called
01179 //  SM::new_sequence_size, which used the first handle of the next higher
01180 //  sequence to compute the size, when the start handle of the data on
01181 //  which that first handle was allocated was smaller.  Sigh.
01182 void regression_svn1960()
01183 {
01184     const int data_size           = 6000;
01185     const EntityHandle data_start = 4000;
01186     const EntityHandle data_end   = data_start + data_size - 1;
01187     const int seq_offset          = 1000;
01188 
01189     TypeSequenceManager seqman;
01190     SequenceData* data = new SequenceData( 0, data_start, data_end );CHECK_ERR( insert_seq( seqman, data_start + seq_offset, data_size - seq_offset, data, true ) );
01191 
01192     SequenceData* result_data;
01193     EntityID result_size;
01194     EntityHandle result_handle;
01195     result_handle = seqman.find_free_sequence( data_start - 2, 1, 100000, result_data, result_size );
01196     CHECK( result_handle + result_size <= data_start );
01197 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines