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