1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <cppunit/TestAssert.h> 21 #include <cppunit/TestFixture.h> 22 #include <cppunit/extensions/HelperMacros.h> 23 24 //#define TIMELOG for measuring performance 25 26 #include <bparr.hxx> 27 28 using namespace std; 29 30 namespace /* private */ 31 { 32 const sal_uLong NUM_ENTRIES = 10; 33 34 class BigPtrEntryMock : public BigPtrEntry 35 { 36 public: BigPtrEntryMock(sal_uLong count)37 explicit BigPtrEntryMock(sal_uLong count) : count_(count) 38 { 39 } 40 getCount() const41 sal_uLong getCount() const 42 { 43 return count_; 44 } 45 Position() const46 sal_uLong Position() const 47 { 48 return GetPos(); 49 } 50 51 private: 52 sal_uLong count_; 53 }; 54 fillBigPtrArray(BigPtrArray & bparr,sal_uLong numEntries)55 void fillBigPtrArray(BigPtrArray& bparr, sal_uLong numEntries) 56 { 57 for (sal_uLong i = 0; i < numEntries; i++) 58 bparr.Insert(new BigPtrEntryMock(i), bparr.Count()); 59 } 60 checkElementPositions(const BigPtrArray & bparr)61 bool checkElementPositions(const BigPtrArray& bparr) 62 { 63 for (sal_uLong i = 0; i < bparr.Count(); i++) 64 { 65 if (static_cast<BigPtrEntryMock*>(bparr[i])->Position() != i) 66 return false; 67 } 68 return true; 69 } 70 releaseBigPtrArrayContent(BigPtrArray const & bparr)71 void releaseBigPtrArrayContent(BigPtrArray const & bparr) 72 { 73 for (sal_uLong i = 0; i < bparr.Count(); i++) 74 delete bparr[i]; 75 } 76 } 77 78 class BigPtrArrayUnittest : public CppUnit::TestFixture 79 { 80 public: 81 BigPtrArrayUnittest()82 BigPtrArrayUnittest() 83 { 84 } 85 86 /** Test constructor/destructor 87 The size of the BigPtrArray 88 aka the 'Count' should be 0 89 initially. 90 */ test_ctor()91 void test_ctor() 92 { 93 BigPtrArray bparr; 94 95 CPPUNIT_ASSERT_EQUAL_MESSAGE 96 ( 97 "BigPtrArray ctor failed", 98 static_cast<sal_uLong>(0), bparr.Count() 99 ); 100 } 101 test_insert_entries_at_front()102 void test_insert_entries_at_front() 103 { 104 BigPtrArray bparr; 105 106 for (sal_uLong i = 0; i < NUM_ENTRIES; i++) 107 { 108 sal_uLong oldCount = bparr.Count(); 109 bparr.Insert(new BigPtrEntryMock(i), 0); 110 CPPUNIT_ASSERT_EQUAL_MESSAGE 111 ( 112 "test_insert_entries_at_front failed", 113 oldCount + 1, bparr.Count() 114 ); 115 } 116 117 for (sal_uLong i = 0, j = NUM_ENTRIES - 1; i < NUM_ENTRIES; i++, j--) 118 { 119 CPPUNIT_ASSERT_EQUAL_MESSAGE 120 ( 121 "test_insert_entries_at_front failed", 122 j, static_cast<BigPtrEntryMock*>(bparr[i])->getCount() 123 ); 124 } 125 126 CPPUNIT_ASSERT_MESSAGE 127 ( 128 "test_insert_entries_at_front failed", 129 checkElementPositions(bparr) 130 ); 131 132 releaseBigPtrArrayContent(bparr); 133 } 134 test_insert_entries_in_the_middle()135 void test_insert_entries_in_the_middle() 136 { 137 BigPtrArray bparr; 138 139 fillBigPtrArray(bparr, NUM_ENTRIES); 140 141 sal_uLong oldCount = bparr.Count(); 142 143 bparr.Insert(new BigPtrEntryMock(NUM_ENTRIES), bparr.Count() / 2); 144 145 CPPUNIT_ASSERT_MESSAGE 146 ( 147 "test_insert_entries_in_the_middle failed", 148 (oldCount + 1 == bparr.Count() && static_cast<BigPtrEntryMock*>(bparr[bparr.Count() / 2])->getCount() == NUM_ENTRIES) 149 ); 150 151 CPPUNIT_ASSERT_MESSAGE 152 ( 153 "test_insert_entries_in_the_middle failed", 154 checkElementPositions(bparr) 155 ); 156 157 releaseBigPtrArrayContent(bparr); 158 } 159 test_insert_at_already_used_index()160 void test_insert_at_already_used_index() 161 { 162 BigPtrArray bparr; 163 164 fillBigPtrArray(bparr, NUM_ENTRIES); 165 166 const sal_uLong oldCount = bparr.Count(); 167 168 // insert 5 elements 169 for (sal_uLong i = 0, j = 30; i < 5; i++, j++) 170 bparr.Insert(new BigPtrEntryMock(j), i); 171 172 CPPUNIT_ASSERT_EQUAL_MESSAGE 173 ( 174 "test_insert_at_already_used_index failed", 175 oldCount + 5, bparr.Count() 176 ); 177 178 // now, first 5 elements have counts: 30,31,..34 179 // next 10 elements have counts: 0,1,..9 180 for (sal_uLong i = 0, j = 30; i < bparr.Count(); i++, j++) 181 { 182 CPPUNIT_ASSERT_EQUAL_MESSAGE 183 ( 184 "test_insert_at_already_used_index failed", 185 (i < 5 ? j : i - 5), static_cast<BigPtrEntryMock*>(bparr[i])->getCount() 186 ); 187 } 188 189 CPPUNIT_ASSERT_MESSAGE 190 ( 191 "test_insert_at_already_used_index failed", 192 checkElementPositions(bparr) 193 ); 194 195 releaseBigPtrArrayContent(bparr); 196 } 197 test_insert_at_end()198 void test_insert_at_end() 199 { 200 BigPtrArray bparr; 201 202 fillBigPtrArray(bparr, NUM_ENTRIES); 203 204 sal_uLong oldCount = bparr.Count(); 205 bparr.Insert(new BigPtrEntryMock(NUM_ENTRIES), bparr.Count()); 206 207 CPPUNIT_ASSERT_MESSAGE 208 ( 209 "test_insert_at_end failed", 210 (oldCount + 1 == bparr.Count() && static_cast<BigPtrEntryMock*>(bparr[bparr.Count()-1])->getCount() == NUM_ENTRIES) 211 ); 212 213 CPPUNIT_ASSERT_MESSAGE 214 ( 215 "test_insert_at_end failed", 216 checkElementPositions(bparr) 217 ); 218 219 releaseBigPtrArrayContent(bparr); 220 } 221 test_remove_at_front()222 void test_remove_at_front() 223 { 224 BigPtrArray bparr; 225 226 fillBigPtrArray(bparr, NUM_ENTRIES); 227 228 for (sal_uLong i = 0; i < NUM_ENTRIES; i++) 229 { 230 sal_uLong oldCount = bparr.Count(); 231 232 delete bparr[0]; // release content 233 bparr.Remove(0); // remove item from container 234 235 CPPUNIT_ASSERT_EQUAL_MESSAGE 236 ( 237 "test_remove_at_front failed (wrong count)", 238 oldCount - 1, bparr.Count() 239 ); 240 241 for (sal_uLong j = 0, k = i + 1; j < bparr.Count(); j++, k++) 242 { 243 CPPUNIT_ASSERT_EQUAL_MESSAGE 244 ( 245 "test_remove_at_front failed", 246 k, static_cast<BigPtrEntryMock*>(bparr[j])->getCount() 247 ); 248 } 249 250 CPPUNIT_ASSERT_MESSAGE 251 ( 252 "test_remove_at_front failed", 253 checkElementPositions(bparr) 254 ); 255 } 256 } 257 test_remove_at_back()258 void test_remove_at_back() 259 { 260 BigPtrArray bparr; 261 262 fillBigPtrArray(bparr, NUM_ENTRIES); 263 264 for (int i = NUM_ENTRIES - 1; i >= 0; i--) 265 { 266 sal_uLong oldCount = bparr.Count(); 267 delete bparr[i]; 268 bparr.Remove(i); 269 270 CPPUNIT_ASSERT_EQUAL_MESSAGE 271 ( 272 "test_remove_at_back failed (wrong count)", 273 (oldCount - 1), bparr.Count() 274 ); 275 276 for (sal_uLong j = 0; j < bparr.Count(); j++) 277 { 278 CPPUNIT_ASSERT_EQUAL_MESSAGE 279 ( 280 "test_remove_at_back failed", 281 j, static_cast<BigPtrEntryMock*>(bparr[j])->getCount() 282 ); 283 } 284 285 CPPUNIT_ASSERT_MESSAGE 286 ( 287 "test_remove_at_back failed", 288 checkElementPositions(bparr) 289 ); 290 } 291 } 292 test_remove_in_the_middle()293 void test_remove_in_the_middle() 294 { 295 BigPtrArray bparr; 296 297 fillBigPtrArray(bparr, NUM_ENTRIES); 298 299 while (bparr.Count()) 300 { 301 sal_uLong oldCount = bparr.Count(); 302 sal_uLong oldElement = static_cast<BigPtrEntryMock*>(bparr[bparr.Count() / 2])->getCount(); 303 304 delete bparr[bparr.Count() / 2]; 305 bparr.Remove(bparr.Count() / 2); 306 307 CPPUNIT_ASSERT_EQUAL_MESSAGE 308 ( 309 "test_remove_in_the_middle failed (wrong count)", 310 oldCount - 1, bparr.Count() 311 ); 312 313 for (sal_uLong i = 0; i < bparr.Count(); i++) 314 { 315 CPPUNIT_ASSERT_MESSAGE 316 ( 317 "test_remove_in_the_middle failed", 318 static_cast<BigPtrEntryMock*>(bparr[i])->getCount() != oldElement 319 ); 320 } 321 322 CPPUNIT_ASSERT_MESSAGE 323 ( 324 "test_remove_in_the_middle failed", 325 checkElementPositions(bparr) 326 ); 327 } 328 } 329 test_remove_multiple_elements_at_once()330 void test_remove_multiple_elements_at_once() 331 { 332 BigPtrArray bparr; 333 334 fillBigPtrArray(bparr, NUM_ENTRIES); 335 336 while(bparr.Count()) 337 { 338 sal_uLong nRemove = std::min<sal_uLong>(bparr.Count(), 3); 339 sal_uLong oldCount = bparr.Count(); 340 341 for (sal_uLong i = 0; i < nRemove; i++) 342 delete bparr[i]; 343 344 bparr.Remove(0, nRemove); 345 346 CPPUNIT_ASSERT_EQUAL_MESSAGE 347 ( 348 "test_remove_multiple_elements_at_once failed", 349 oldCount - nRemove, bparr.Count() 350 ); 351 352 CPPUNIT_ASSERT_MESSAGE 353 ( 354 "test_remove_multiple_elements_at_once failed", 355 checkElementPositions(bparr) 356 ); 357 } 358 } 359 test_remove_all_elements_at_once()360 void test_remove_all_elements_at_once() 361 { 362 BigPtrArray bparr; 363 364 fillBigPtrArray(bparr, NUM_ENTRIES); 365 366 releaseBigPtrArrayContent(bparr); 367 bparr.Remove(0, bparr.Count()); 368 369 CPPUNIT_ASSERT_EQUAL_MESSAGE 370 ( 371 "test_remove_all_elements_at_once failed", 372 static_cast<sal_uLong>(0), bparr.Count() 373 ); 374 } 375 test_move_elements_from_lower_to_higher_pos()376 void test_move_elements_from_lower_to_higher_pos() 377 { 378 BigPtrArray bparr; 379 380 fillBigPtrArray(bparr, NUM_ENTRIES); 381 382 for (sal_uLong i = 0; i < NUM_ENTRIES - 1; i++) 383 { 384 bparr.Move(i, i + 2); 385 } 386 387 for (sal_uLong i = 0; i < (NUM_ENTRIES - 1); i++) 388 { 389 CPPUNIT_ASSERT_EQUAL_MESSAGE 390 ( 391 "test_move_elements_from_lower_to_higher_pos failed", 392 (i + 1), static_cast<BigPtrEntryMock*>(bparr[i])->getCount() 393 ); 394 } 395 396 CPPUNIT_ASSERT_EQUAL_MESSAGE 397 ( 398 "test_move_elements_from_lower_to_higher_pos failed", 399 static_cast<sal_uLong>(0), static_cast<BigPtrEntryMock*>(bparr[NUM_ENTRIES -1])->getCount() 400 ); 401 402 CPPUNIT_ASSERT_MESSAGE 403 ( 404 "test_move_elements_from_lower_to_higher_pos failed", 405 checkElementPositions(bparr) 406 ); 407 408 releaseBigPtrArrayContent(bparr); 409 } 410 test_move_elements_from_higher_to_lower_pos()411 void test_move_elements_from_higher_to_lower_pos() 412 { 413 BigPtrArray bparr; 414 415 fillBigPtrArray(bparr, NUM_ENTRIES); 416 417 for (int i = NUM_ENTRIES - 1; i >= 1; i--) 418 { 419 bparr.Move(i, i - 1); 420 } 421 422 CPPUNIT_ASSERT_EQUAL_MESSAGE 423 ( 424 "test_move_elements_from_higher_to_lower_pos failed", 425 (NUM_ENTRIES - 1), static_cast<BigPtrEntryMock*>(bparr[0])->getCount() 426 ); 427 428 for (sal_uLong i = 1; i < NUM_ENTRIES; i++) 429 { 430 CPPUNIT_ASSERT_EQUAL_MESSAGE 431 ( 432 "test_move_elements_from_higher_to_lower_pos failed", 433 (i - 1), static_cast<BigPtrEntryMock*>(bparr[i])->getCount() 434 ); 435 } 436 437 CPPUNIT_ASSERT_MESSAGE 438 ( 439 "test_move_elements_from_higher_to_lower_pos failed", 440 checkElementPositions(bparr) 441 ); 442 443 releaseBigPtrArrayContent(bparr); 444 } 445 test_move_to_same_position()446 void test_move_to_same_position() 447 { 448 BigPtrArray bparr; 449 450 fillBigPtrArray(bparr, NUM_ENTRIES); 451 452 for (sal_uLong i = 0; i < NUM_ENTRIES; i++) 453 { 454 bparr.Move(i, i); 455 } 456 457 for (sal_uLong i = 0; i < NUM_ENTRIES; i++) 458 { 459 CPPUNIT_ASSERT_EQUAL_MESSAGE 460 ( 461 "test_move_to_same_position failed", 462 i, static_cast<BigPtrEntryMock*>(bparr[i])->getCount() 463 ); 464 } 465 466 CPPUNIT_ASSERT_MESSAGE 467 ( 468 "test_move_to_same_position failed", 469 checkElementPositions(bparr) 470 ); 471 472 releaseBigPtrArrayContent(bparr); 473 } 474 test_replace_elements()475 void test_replace_elements() 476 { 477 BigPtrArray bparr; 478 479 fillBigPtrArray(bparr, NUM_ENTRIES); 480 481 for (sal_uLong i = 0, j = NUM_ENTRIES - 1; i < NUM_ENTRIES; i++, j--) 482 { 483 delete bparr[i]; 484 bparr.Replace(i, new BigPtrEntryMock(j)); 485 } 486 487 for (sal_uLong i = 0; i < NUM_ENTRIES; i++) 488 { 489 CPPUNIT_ASSERT_EQUAL_MESSAGE 490 ( 491 "test_replace_elements failed", 492 (NUM_ENTRIES - i - 1), static_cast<BigPtrEntryMock*>(bparr[i])->getCount() 493 ); 494 } 495 496 CPPUNIT_ASSERT_MESSAGE 497 ( 498 "test_replace_elements failed", 499 checkElementPositions(bparr) 500 ); 501 502 releaseBigPtrArrayContent(bparr); 503 } 504 505 CPPUNIT_TEST_SUITE(BigPtrArrayUnittest); 506 CPPUNIT_TEST(test_ctor); 507 CPPUNIT_TEST(test_insert_entries_at_front); 508 CPPUNIT_TEST(test_insert_entries_in_the_middle); 509 CPPUNIT_TEST(test_insert_at_already_used_index); 510 CPPUNIT_TEST(test_insert_at_end); 511 CPPUNIT_TEST(test_remove_at_front); 512 CPPUNIT_TEST(test_remove_at_back); 513 CPPUNIT_TEST(test_remove_in_the_middle); 514 CPPUNIT_TEST(test_remove_multiple_elements_at_once); 515 CPPUNIT_TEST(test_remove_all_elements_at_once); 516 CPPUNIT_TEST(test_move_elements_from_lower_to_higher_pos); 517 CPPUNIT_TEST(test_move_elements_from_higher_to_lower_pos); 518 CPPUNIT_TEST(test_move_to_same_position); 519 CPPUNIT_TEST(test_replace_elements); 520 CPPUNIT_TEST_SUITE_END(); 521 }; 522 523 #if defined TIMELOG 524 525 const char* const START = "START: "; 526 const char* const END = "END: "; 527 528 class PerformanceTracer 529 { 530 public: 531 532 public: PerformanceTracer(const string & methodName)533 explicit PerformanceTracer(const string& methodName) : 534 startString_(START), 535 endString_(END) 536 { 537 startString_ += methodName; 538 endString_ += methodName; 539 } 540 ~PerformanceTracer()541 ~PerformanceTracer() 542 { 543 } 544 545 private: 546 string startString_; 547 string endString_; 548 }; 549 550 class BigPtrArrayPerformanceTest : public CppUnit::TestFixture 551 { 552 public: BigPtrArrayPerformanceTest()553 BigPtrArrayPerformanceTest() 554 { 555 } 556 test_insert_at_end_1000()557 void test_insert_at_end_1000() 558 { test_insert_at_end("1000"); } 559 test_insert_at_end_10000()560 void test_insert_at_end_10000() 561 { test_insert_at_end("10000"); } 562 test_insert_at_end_100000()563 void test_insert_at_end_100000() 564 { test_insert_at_end("100000"); } 565 test_insert_at_end_1000000()566 void test_insert_at_end_1000000() 567 { test_insert_at_end("1000000"); } 568 test_insert_at_front_1000()569 void test_insert_at_front_1000() 570 { test_insert_at_front("1000"); } 571 test_insert_at_front_10000()572 void test_insert_at_front_10000() 573 { test_insert_at_front("10000"); } 574 test_insert_at_front_100000()575 void test_insert_at_front_100000() 576 { test_insert_at_front("100000"); } 577 test_insert_at_front_1000000()578 void test_insert_at_front_1000000() 579 { test_insert_at_front("1000000"); } 580 581 CPPUNIT_TEST_SUITE(BigPtrArrayPerformanceTest); 582 CPPUNIT_TEST(test_insert_at_end_1000); 583 CPPUNIT_TEST(test_insert_at_end_10000); 584 CPPUNIT_TEST(test_insert_at_end_100000); 585 CPPUNIT_TEST(test_insert_at_end_1000000); 586 CPPUNIT_TEST(test_insert_at_front_1000); 587 CPPUNIT_TEST(test_insert_at_front_10000); 588 CPPUNIT_TEST(test_insert_at_front_100000); 589 CPPUNIT_TEST(test_insert_at_front_1000000); 590 CPPUNIT_TEST_SUITE_END(); 591 592 private: test_insert_at_end(const char * numElements)593 void test_insert_at_end(const char* numElements) 594 { 595 OStringBuffer buff("test_insert_at_end "); 596 buff.append(numElements); 597 int n = atoi(numElements); 598 PerformanceTracer tracer(buff.getStr()); 599 BigPtrArray bparr; 600 for (int i = 0; i < n; i++) 601 bparr.Insert(new BigPtrEntryMock(i), bparr.Count()); 602 603 releaseBigPtrArrayContent(bparr); 604 } 605 test_insert_at_front(const char * numElements)606 void test_insert_at_front(const char* numElements) 607 { 608 OStringBuffer buff("test_insert_at_front "); 609 buff.append(numElements); 610 int n = atoi(numElements); 611 PerformanceTracer tracer(buff.getStr()); 612 BigPtrArray bparr; 613 for (int i = 0; i < n; i++) 614 bparr.Insert(new BigPtrEntryMock(i), 0); 615 616 releaseBigPtrArrayContent(bparr); 617 } 618 }; 619 620 #endif 621 622 // register test suites 623 CPPUNIT_TEST_SUITE_REGISTRATION(BigPtrArrayUnittest); 624 #ifdef TIMELOG 625 CPPUNIT_TEST_SUITE_REGISTRATION(BigPtrArrayPerformanceTest); 626 #endif 627 628 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 629