MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 }