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