1 // ResourcesTest.cpp 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 7 #include <string> 8 using std::string; 9 #include <vector> 10 using std::vector; 11 12 #include <ByteOrder.h> 13 #include <File.h> 14 #include <Mime.h> 15 #include <Resources.h> 16 #include <String.h> 17 #include <TypeConstants.h> 18 #include <TestShell.h> 19 20 #include "ResourcesTest.h" 21 22 static const char *testDir = "/tmp/testDir"; 23 static const char *x86ResFile = "/tmp/testDir/x86.rsrc"; 24 static const char *ppcResFile = "/tmp/testDir/ppc.rsrc"; 25 static const char *elfFile = "/tmp/testDir/elf"; 26 static const char *elfNoResFile = "/tmp/testDir/elf-no-res"; 27 static const char *pefFile = "/tmp/testDir/pef"; 28 static const char *pefNoResFile = "/tmp/testDir/pef-no-res"; 29 static const char *emptyFile = "/tmp/testDir/empty-file"; 30 static const char *noResFile = "/tmp/testDir/no-res-file"; 31 static const char *testFile1 = "/tmp/testDir/testFile1"; 32 static const char *testFile2 = "/tmp/testDir/testFile2"; 33 static const char *noSuchFile = "/tmp/testDir/no-such-file"; 34 static const char *x86ResName = "x86.rsrc"; 35 static const char *ppcResName = "ppc.rsrc"; 36 static const char *elfName = "elf"; 37 static const char *elfNoResName = "elf-no-res"; 38 static const char *pefName = "pef"; 39 static const char *pefNoResName = "pef-no-res"; 40 41 static const int32 kEmptyResourceFileSize = 1984; 42 43 struct ResourceInfo { 44 ResourceInfo(type_code type, int32 id, const void *data, size_t size, 45 const char *name = NULL) 46 : type(type), 47 id(id), 48 name(NULL), 49 data(NULL), 50 size(size) 51 { 52 if (data) { 53 this->data = new char[size]; 54 memcpy(this->data, data, size); 55 } 56 if (name) { 57 int32 len = strlen(name); 58 this->name = new char[len + 1]; 59 strcpy(this->name, name); 60 } 61 } 62 63 ~ResourceInfo() 64 { 65 delete[] name; 66 delete[] data; 67 } 68 69 type_code type; 70 int32 id; 71 char *name; 72 char *data; 73 size_t size; 74 }; 75 76 static const char *testResData1 = "I like strings, especially cellos."; 77 static const int32 testResSize1 = strlen(testResData1) + 1; 78 static const int32 testResData2 = 42; 79 static const int32 testResSize2 = sizeof(int32); 80 static const char *testResData3 = "application/bread-roll-counter"; 81 static const int32 testResSize3 = strlen(testResData3) + 1; 82 static const char *testResData4 = "This is a long string. At least longer " 83 "than the first one"; 84 static const int32 testResSize4 = strlen(testResData1) + 1; 85 static const char *testResData6 = "Short, but true."; 86 static const int32 testResSize6 = strlen(testResData6) + 1; 87 88 static const ResourceInfo testResource1(B_STRING_TYPE, 74, testResData1, 89 testResSize1, "a string resource"); 90 static const ResourceInfo testResource2(B_INT32_TYPE, 17, &testResData2, 91 testResSize2, "just a resource"); 92 static const ResourceInfo testResource3(B_MIME_STRING_TYPE, 29, testResData3, 93 testResSize3, "another resource"); 94 static const ResourceInfo testResource4(B_STRING_TYPE, 75, &testResData4, 95 testResSize4, 96 "a second string resource"); 97 static const ResourceInfo testResource5(B_MIME_STRING_TYPE, 74, &testResData1, 98 testResSize1, "a string resource"); 99 static const ResourceInfo testResource6(B_STRING_TYPE, 74, &testResData6, 100 testResSize6, 101 "a third string resource"); 102 103 // helper class: maintains a ResourceInfo set 104 struct ResourceSet { 105 typedef vector<const ResourceInfo*> ResInfoSet; 106 107 ResourceSet() : fResources() { } 108 109 ResourceSet(const ResourceSet &resourceSet) 110 : fResources() 111 { 112 fResources = resourceSet.fResources; 113 } 114 115 void add(const ResourceInfo *info) 116 { 117 if (info) { 118 remove(info->type, info->id); 119 fResources.insert(fResources.end(), info); 120 } 121 } 122 123 void remove(const ResourceInfo *info) 124 { 125 if (info) 126 remove(info->type, info->id); 127 } 128 129 void remove(type_code type, int32 id) 130 { 131 for (ResInfoSet::iterator it = fResources.begin(); 132 it != fResources.end(); 133 it++) { 134 const ResourceInfo *info = *it; 135 if (info->type == type && info->id == id) { 136 fResources.erase(it); 137 break; 138 } 139 } 140 } 141 142 int32 size() const 143 { 144 return fResources.size(); 145 } 146 147 const ResourceInfo *infoAt(int32 index) const 148 { 149 const ResourceInfo *info = NULL; 150 if (index >= 0 && index < size()) 151 info = fResources[index]; 152 return info; 153 } 154 155 const ResourceInfo *find(type_code type, int32 id) const 156 { 157 const ResourceInfo *result = NULL; 158 for (ResInfoSet::const_iterator it = fResources.begin(); 159 result == NULL && it != fResources.end(); 160 it++) { 161 const ResourceInfo *info = *it; 162 if (info->type == type && info->id == id) 163 result = info; 164 } 165 return result; 166 } 167 168 ResInfoSet fResources; 169 }; 170 171 172 // Suite 173 CppUnit::Test* 174 ResourcesTest::Suite() { 175 CppUnit::TestSuite *suite = new CppUnit::TestSuite(); 176 typedef CppUnit::TestCaller<ResourcesTest> TC; 177 178 suite->addTest( new TC("BResources::Init Test", 179 &ResourcesTest::InitTest) ); 180 suite->addTest( new TC("BResources::Read Test", 181 &ResourcesTest::ReadTest) ); 182 suite->addTest( new TC("BResources::Sync Test", 183 &ResourcesTest::SyncTest) ); 184 suite->addTest( new TC("BResources::Merge Test", 185 &ResourcesTest::MergeTest) ); 186 suite->addTest( new TC("BResources::WriteTo Test", 187 &ResourcesTest::WriteToTest) ); 188 suite->addTest( new TC("BResources::AddRemove Test", 189 &ResourcesTest::AddRemoveTest) ); 190 suite->addTest( new TC("BResources::ReadWrite Test", 191 &ResourcesTest::ReadWriteTest) ); 192 193 return suite; 194 } 195 196 // setUp 197 void 198 ResourcesTest::setUp() 199 { 200 BasicTest::setUp(); 201 BString unescapedTestDir(BTestShell::GlobalTestDir()); 202 unescapedTestDir.CharacterEscape(" \t\n!\"'`$&()?*+{}[]<>|", '\\'); 203 string resourcesTestDir(unescapedTestDir.String()); 204 resourcesTestDir += "/resources"; 205 execCommand(string("mkdir ") + testDir 206 + " ; cp " + resourcesTestDir + "/" + x86ResName + " " 207 + resourcesTestDir + "/" + ppcResName + " " 208 + resourcesTestDir + "/" + elfName + " " 209 + resourcesTestDir + "/" + elfNoResName + " " 210 + resourcesTestDir + "/" + pefName + " " 211 + resourcesTestDir + "/" + pefNoResName + " " 212 + testDir 213 + " ; touch " + emptyFile 214 + " ; echo \"That's not a resource file.\" > " + noResFile 215 ); 216 } 217 218 // tearDown 219 void 220 ResourcesTest::tearDown() 221 { 222 execCommand(string("rm -rf ") + testDir); 223 BasicTest::tearDown(); 224 } 225 226 // InitTest 227 void 228 ResourcesTest::InitTest() 229 { 230 // 1. existing files, read only 231 // x86 resource file 232 NextSubTest(); 233 { 234 BResources resources; 235 BFile file(x86ResFile, B_READ_ONLY); 236 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 237 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 238 } 239 // ppc resource file 240 NextSubTest(); 241 { 242 BResources resources; 243 BFile file(ppcResFile, B_READ_ONLY); 244 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 245 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 246 } 247 // ELF binary containing resources 248 NextSubTest(); 249 { 250 BResources resources; 251 BFile file(elfFile, B_READ_ONLY); 252 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 253 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 254 } 255 // ELF binary not containing resources 256 NextSubTest(); 257 { 258 BResources resources; 259 BFile file(elfNoResFile, B_READ_ONLY); 260 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 261 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 262 } 263 // PEF binary containing resources 264 NextSubTest(); 265 { 266 BResources resources; 267 BFile file(pefFile, B_READ_ONLY); 268 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 269 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 270 } 271 // PEF binary not containing resources 272 NextSubTest(); 273 { 274 BResources resources; 275 BFile file(pefNoResFile, B_READ_ONLY); 276 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 277 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 278 } 279 // empty file 280 NextSubTest(); 281 { 282 BResources resources; 283 BFile file(emptyFile, B_READ_ONLY); 284 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 285 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 286 } 287 // non-resource file 288 NextSubTest(); 289 { 290 BResources resources; 291 BFile file(noResFile, B_READ_ONLY); 292 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 293 CPPUNIT_ASSERT( equals(resources.SetTo(&file, false), B_ERROR, 294 B_IO_ERROR) ); 295 } 296 297 // 2. existing files, read only, clobber 298 // x86 resource file 299 NextSubTest(); 300 { 301 BResources resources; 302 BFile file(x86ResFile, B_READ_ONLY); 303 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 304 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 305 } 306 // ppc resource file 307 NextSubTest(); 308 { 309 BResources resources; 310 BFile file(ppcResFile, B_READ_ONLY); 311 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 312 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 313 } 314 // ELF binary containing resources 315 NextSubTest(); 316 { 317 BResources resources; 318 BFile file(elfFile, B_READ_ONLY); 319 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 320 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 321 } 322 // ELF binary not containing resources 323 NextSubTest(); 324 { 325 BResources resources; 326 BFile file(elfNoResFile, B_READ_ONLY); 327 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 328 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 329 } 330 // PEF binary containing resources 331 NextSubTest(); 332 { 333 BResources resources; 334 BFile file(pefFile, B_READ_ONLY); 335 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 336 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 337 } 338 // PEF binary not containing resources 339 NextSubTest(); 340 { 341 BResources resources; 342 BFile file(pefNoResFile, B_READ_ONLY); 343 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 344 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 345 } 346 // empty file 347 NextSubTest(); 348 { 349 BResources resources; 350 BFile file(emptyFile, B_READ_ONLY); 351 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 352 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 353 } 354 // non-resource file 355 NextSubTest(); 356 { 357 BResources resources; 358 BFile file(noResFile, B_READ_ONLY); 359 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 360 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 361 } 362 363 // 3. existing files, read/write 364 // x86 resource file 365 NextSubTest(); 366 { 367 BResources resources; 368 BFile file(x86ResFile, B_READ_WRITE); 369 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 370 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 371 } 372 // ppc resource file 373 NextSubTest(); 374 { 375 BResources resources; 376 BFile file(ppcResFile, B_READ_WRITE); 377 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 378 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 379 } 380 // ELF binary containing resources 381 NextSubTest(); 382 { 383 BResources resources; 384 BFile file(elfFile, B_READ_WRITE); 385 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 386 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 387 } 388 // ELF binary not containing resources 389 NextSubTest(); 390 { 391 BResources resources; 392 BFile file(elfNoResFile, B_READ_WRITE); 393 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 394 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 395 } 396 // PEF binary containing resources 397 NextSubTest(); 398 { 399 BResources resources; 400 BFile file(pefFile, B_READ_WRITE); 401 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 402 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 403 } 404 // PEF binary not containing resources 405 NextSubTest(); 406 { 407 BResources resources; 408 BFile file(pefNoResFile, B_READ_WRITE); 409 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 410 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 411 } 412 // empty file 413 NextSubTest(); 414 { 415 BResources resources; 416 BFile file(emptyFile, B_READ_WRITE); 417 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 418 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 419 } 420 // non-resource file 421 NextSubTest(); 422 { 423 BResources resources; 424 BFile file(noResFile, B_READ_WRITE); 425 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 426 CPPUNIT_ASSERT( equals(resources.SetTo(&file, false), B_ERROR, 427 B_IO_ERROR) ); 428 } 429 430 // 4. existing files, read/write, clobber 431 // x86 resource file 432 NextSubTest(); 433 { 434 BResources resources; 435 BFile file(x86ResFile, B_READ_WRITE); 436 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 437 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 438 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 439 } 440 // ppc resource file 441 NextSubTest(); 442 { 443 BResources resources; 444 BFile file(ppcResFile, B_READ_WRITE); 445 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 446 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 447 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 448 } 449 // ELF binary containing resources 450 NextSubTest(); 451 { 452 BResources resources; 453 BFile file(elfFile, B_READ_WRITE); 454 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 455 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 456 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 457 } 458 // ELF binary not containing resources 459 NextSubTest(); 460 { 461 BResources resources; 462 BFile file(elfNoResFile, B_READ_WRITE); 463 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 464 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 465 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 466 } 467 // PEF binary containing resources 468 NextSubTest(); 469 { 470 BResources resources; 471 BFile file(pefFile, B_READ_WRITE); 472 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 473 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 474 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 475 } 476 // PEF binary not containing resources 477 NextSubTest(); 478 { 479 BResources resources; 480 BFile file(pefNoResFile, B_READ_WRITE); 481 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 482 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 483 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 484 } 485 // empty file 486 NextSubTest(); 487 { 488 BResources resources; 489 BFile file(emptyFile, B_READ_WRITE); 490 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 491 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 492 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 493 } 494 // non-resource file 495 NextSubTest(); 496 { 497 BResources resources; 498 BFile file(noResFile, B_READ_WRITE); 499 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 500 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 501 } 502 503 // 5. bad args 504 // uninitialized file 505 NextSubTest(); 506 { 507 BResources resources; 508 BFile file; 509 CPPUNIT_ASSERT( file.InitCheck() == B_NO_INIT ); 510 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_NO_INIT ); 511 } 512 // badly initialized file 513 NextSubTest(); 514 { 515 BResources resources; 516 BFile file(noSuchFile, B_READ_ONLY); 517 CPPUNIT_ASSERT( file.InitCheck() == B_ENTRY_NOT_FOUND ); 518 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_ENTRY_NOT_FOUND ); 519 } 520 // NULL file 521 NextSubTest(); 522 { 523 BResources resources; 524 // R5: A NULL file is B_OK! 525 // CPPUNIT_ASSERT( resources.SetTo(NULL, false) == B_BAD_VALUE ); 526 CPPUNIT_ASSERT( resources.SetTo((BFile*)NULL, false) == B_OK ); 527 } 528 } 529 530 // ReadResTest 531 static 532 void 533 ReadResTest(BResources& resources, const ResourceInfo& info, bool exists) 534 { 535 if (exists) { 536 // test an existing resource 537 // HasResource() 538 CPPUNIT_ASSERT( resources.HasResource(info.type, info.id) == true ); 539 CPPUNIT_ASSERT( resources.HasResource(info.type, info.name) 540 == true ); 541 // GetResourceInfo() 542 const char *name; 543 size_t length; 544 int32 id; 545 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.id, 546 &name, &length) == true ); 547 CPPUNIT_ASSERT( name == NULL && info.name == NULL 548 || name != NULL && info.name != NULL 549 && !strcmp(name, info.name) ); 550 CPPUNIT_ASSERT( length == info.size ); 551 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.name, 552 &id, &length) == true ); 553 CPPUNIT_ASSERT( id == info.id ); 554 CPPUNIT_ASSERT( length == info.size ); 555 // LoadResource 556 size_t length1; 557 size_t length2; 558 const void *data1 559 = resources.LoadResource(info.type, info.id, &length1); 560 const void *data2 561 = resources.LoadResource(info.type, info.name, &length2); 562 CPPUNIT_ASSERT( length1 == info.size && length2 == info.size ); 563 CPPUNIT_ASSERT( data1 != NULL && data1 == data2 ); 564 CPPUNIT_ASSERT( !memcmp(data1, info.data, info.size) ); 565 // GetResourceInfo() 566 type_code type = 0; 567 id = 0; 568 length = 0; 569 name = NULL; 570 CPPUNIT_ASSERT( resources.GetResourceInfo(data1, &type, &id, &length, 571 &name) == true ); 572 CPPUNIT_ASSERT( type == info.type ); 573 CPPUNIT_ASSERT( id == info.id ); 574 CPPUNIT_ASSERT( length == info.size ); 575 CPPUNIT_ASSERT( name == NULL && info.name == NULL 576 || name != NULL && info.name != NULL 577 && !strcmp(name, info.name) ); 578 // ReadResource() 579 const int32 bufferSize = 1024; 580 char buffer[bufferSize]; 581 memset(buffer, 0x0f, bufferSize); 582 // read past the end 583 status_t error = resources.ReadResource(info.type, info.id, buffer, 584 info.size + 2, bufferSize); 585 CPPUNIT_ASSERT( error == B_OK ); 586 for (int32 i = 0; i < bufferSize; i++) 587 CPPUNIT_ASSERT( buffer[i] == 0x0f ); 588 // read 2 bytes from the middle 589 int32 offset = (info.size - 2) / 2; 590 error = resources.ReadResource(info.type, info.id, buffer, offset, 2); 591 CPPUNIT_ASSERT( error == B_OK ); 592 CPPUNIT_ASSERT( !memcmp(buffer, (const char*)info.data + offset, 2) ); 593 for (int32 i = 2; i < bufferSize; i++) 594 CPPUNIT_ASSERT( buffer[i] == 0x0f ); 595 // read the whole chunk 596 error = resources.ReadResource(info.type, info.id, buffer, 0, 597 bufferSize); 598 CPPUNIT_ASSERT( error == B_OK ); 599 CPPUNIT_ASSERT( !memcmp(buffer, info.data, info.size) ); 600 // FindResource() 601 size_t lengthFound1; 602 size_t lengthFound2; 603 void *dataFound1 604 = resources.FindResource(info.type, info.id, &lengthFound1); 605 void *dataFound2 606 = resources.FindResource(info.type, info.name, &lengthFound2); 607 CPPUNIT_ASSERT( dataFound1 != NULL && dataFound2 != NULL ); 608 CPPUNIT_ASSERT( lengthFound1 == info.size 609 && lengthFound2 == info.size ); 610 CPPUNIT_ASSERT( !memcmp(dataFound1, info.data, info.size) ); 611 CPPUNIT_ASSERT( !memcmp(dataFound2, info.data, info.size) ); 612 free(dataFound1); 613 free(dataFound2); 614 } else { 615 // test a non-existing resource 616 // HasResource() 617 CPPUNIT_ASSERT( resources.HasResource(info.type, info.id) == false ); 618 CPPUNIT_ASSERT( resources.HasResource(info.type, info.name) 619 == false ); 620 // GetResourceInfo() 621 const char *name; 622 size_t length; 623 int32 id; 624 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.id, 625 &name, &length) == false ); 626 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.name, 627 &id, &length) == false ); 628 // LoadResource 629 size_t length1; 630 size_t length2; 631 const void *data1 632 = resources.LoadResource(info.type, info.id, &length1); 633 const void *data2 634 = resources.LoadResource(info.type, info.name, &length2); 635 CPPUNIT_ASSERT( data1 == NULL && data2 == NULL ); 636 // ReadResource() 637 const int32 bufferSize = 1024; 638 char buffer[bufferSize]; 639 status_t error = resources.ReadResource(info.type, info.id, buffer, 640 0, bufferSize); 641 CPPUNIT_ASSERT( error == B_BAD_VALUE ); 642 // FindResource() 643 size_t lengthFound1; 644 size_t lengthFound2; 645 void *dataFound1 646 = resources.FindResource(info.type, info.id, &lengthFound1); 647 void *dataFound2 648 = resources.FindResource(info.type, info.name, &lengthFound2); 649 CPPUNIT_ASSERT( dataFound1 == NULL && dataFound2 == NULL ); 650 } 651 } 652 653 // ReadBadResTest 654 static 655 void 656 ReadBadResTest(BResources& resources, const ResourceInfo& info) 657 { 658 // HasResource() 659 CPPUNIT_ASSERT( resources.HasResource(info.type, info.id) == false ); 660 CPPUNIT_ASSERT( resources.HasResource(info.type, info.name) 661 == false ); 662 // GetResourceInfo() 663 type_code type; 664 const char *name; 665 size_t length; 666 int32 id; 667 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.id, 668 &name, &length) == false ); 669 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.name, 670 &id, &length) == false ); 671 CPPUNIT_ASSERT( resources.GetResourceInfo(0, &type, &id, 672 &name, &length) == false ); 673 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, 0, &id, 674 &name, &length) == false ); 675 // LoadResource 676 size_t length1; 677 size_t length2; 678 const void *data1 679 = resources.LoadResource(info.type, info.id, &length1); 680 const void *data2 681 = resources.LoadResource(info.type, info.name, &length2); 682 CPPUNIT_ASSERT( data1 == NULL && data2 == NULL ); 683 // ReadResource() 684 const int32 bufferSize = 1024; 685 char buffer[bufferSize]; 686 status_t error = resources.ReadResource(info.type, info.id, buffer, 687 0, bufferSize); 688 CPPUNIT_ASSERT( error == B_BAD_VALUE ); 689 // FindResource() 690 size_t lengthFound1; 691 size_t lengthFound2; 692 void *dataFound1 693 = resources.FindResource(info.type, info.id, &lengthFound1); 694 void *dataFound2 695 = resources.FindResource(info.type, info.name, &lengthFound2); 696 CPPUNIT_ASSERT( dataFound1 == NULL && dataFound2 == NULL ); 697 } 698 699 // ReadTest 700 void 701 ResourcesTest::ReadTest() 702 { 703 // tests: 704 // * HasResource() 705 // * GetResourceInfo() 706 // * LoadResource() 707 // * ReadResource() 708 // * FindResource() 709 // * PreloadResource() 710 711 // 1. basic tests 712 // x86 resource file 713 NextSubTest(); 714 { 715 BFile file(x86ResFile, B_READ_ONLY); 716 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 717 BResources resources; 718 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 719 ReadResTest(resources, testResource1, true); 720 ReadResTest(resources, testResource2, true); 721 ReadResTest(resources, testResource3, true); 722 ReadResTest(resources, testResource4, false); 723 ReadResTest(resources, testResource5, false); 724 } 725 // ppc resource file 726 NextSubTest(); 727 { 728 BFile file(ppcResFile, B_READ_ONLY); 729 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 730 BResources resources; 731 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 732 ReadResTest(resources, testResource1, true); 733 ReadResTest(resources, testResource2, true); 734 ReadResTest(resources, testResource3, true); 735 ReadResTest(resources, testResource4, false); 736 ReadResTest(resources, testResource5, false); 737 } 738 // ELF binary containing resources 739 NextSubTest(); 740 { 741 BFile file(elfFile, B_READ_ONLY); 742 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 743 BResources resources; 744 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 745 ReadResTest(resources, testResource1, true); 746 ReadResTest(resources, testResource2, true); 747 ReadResTest(resources, testResource3, true); 748 ReadResTest(resources, testResource4, false); 749 ReadResTest(resources, testResource5, false); 750 } 751 // ELF binary not containing resources 752 NextSubTest(); 753 { 754 BFile file(elfNoResFile, B_READ_ONLY); 755 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 756 BResources resources; 757 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 758 ReadResTest(resources, testResource1, false); 759 ReadResTest(resources, testResource2, false); 760 ReadResTest(resources, testResource3, false); 761 ReadResTest(resources, testResource4, false); 762 ReadResTest(resources, testResource5, false); 763 } 764 // PEF binary containing resources 765 NextSubTest(); 766 { 767 BFile file(pefFile, B_READ_ONLY); 768 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 769 BResources resources; 770 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 771 ReadResTest(resources, testResource1, true); 772 ReadResTest(resources, testResource2, true); 773 ReadResTest(resources, testResource3, true); 774 ReadResTest(resources, testResource4, false); 775 ReadResTest(resources, testResource5, false); 776 } 777 // PEF binary not containing resources 778 NextSubTest(); 779 { 780 BFile file(pefNoResFile, B_READ_ONLY); 781 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 782 BResources resources; 783 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 784 ReadResTest(resources, testResource1, false); 785 ReadResTest(resources, testResource2, false); 786 ReadResTest(resources, testResource3, false); 787 ReadResTest(resources, testResource4, false); 788 ReadResTest(resources, testResource5, false); 789 } 790 791 // 2. PreloadResource() 792 // Hard to test: just preload all and check, if it still works. 793 NextSubTest(); 794 { 795 BFile file(x86ResFile, B_READ_ONLY); 796 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 797 BResources resources; 798 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 799 // non existing type 800 CPPUNIT_ASSERT( resources.PreloadResourceType(B_MESSENGER_TYPE) 801 == B_OK ); 802 // int32 type 803 CPPUNIT_ASSERT( resources.PreloadResourceType(B_INT32_TYPE) == B_OK ); 804 // all types 805 CPPUNIT_ASSERT( resources.PreloadResourceType() == B_OK ); 806 ReadResTest(resources, testResource1, true); 807 ReadResTest(resources, testResource2, true); 808 ReadResTest(resources, testResource3, true); 809 ReadResTest(resources, testResource4, false); 810 ReadResTest(resources, testResource5, false); 811 } 812 // uninitialized BResources 813 NextSubTest(); 814 { 815 BResources resources; 816 // int32 type 817 CPPUNIT_ASSERT( resources.PreloadResourceType(B_INT32_TYPE) == B_OK ); 818 // all types 819 CPPUNIT_ASSERT( resources.PreloadResourceType() == B_OK ); 820 } 821 822 // 3. the index versions of GetResourceInfo() 823 // index only 824 NextSubTest(); 825 { 826 BFile file(x86ResFile, B_READ_ONLY); 827 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 828 BResources resources; 829 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 830 const ResourceInfo *resourceInfos[] = { 831 &testResource1, &testResource2, &testResource3 832 }; 833 int32 resourceCount = sizeof(resourceInfos) / sizeof(ResourceInfo*); 834 for (int32 i = 0; i < resourceCount; i++) { 835 const ResourceInfo &info = *resourceInfos[i]; 836 type_code type; 837 int32 id; 838 const char *name; 839 size_t length; 840 CPPUNIT_ASSERT( resources.GetResourceInfo(i, &type, &id, &name, 841 &length) == true ); 842 CPPUNIT_ASSERT( id == info.id ); 843 CPPUNIT_ASSERT( type == info.type ); 844 CPPUNIT_ASSERT( name == NULL && info.name == NULL 845 || name != NULL && info.name != NULL 846 && !strcmp(name, info.name) ); 847 CPPUNIT_ASSERT( length == info.size ); 848 } 849 type_code type; 850 int32 id; 851 const char *name; 852 size_t length; 853 CPPUNIT_ASSERT( resources.GetResourceInfo(resourceCount, &type, &id, 854 &name, &length) == false ); 855 } 856 // type and index 857 NextSubTest(); 858 { 859 BFile file(x86ResFile, B_READ_WRITE); 860 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 861 BResources resources; 862 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 863 CPPUNIT_ASSERT( resources.AddResource(testResource4.type, 864 testResource4.id, 865 testResource4.data, 866 testResource4.size, 867 testResource4.name) == B_OK ); 868 869 const ResourceInfo *resourceInfos[] = { 870 &testResource1, &testResource4 871 }; 872 int32 resourceCount = sizeof(resourceInfos) / sizeof(ResourceInfo*); 873 type_code type = resourceInfos[0]->type; 874 for (int32 i = 0; i < resourceCount; i++) { 875 const ResourceInfo &info = *resourceInfos[i]; 876 int32 id; 877 const char *name; 878 size_t length; 879 CPPUNIT_ASSERT( resources.GetResourceInfo(type, i, &id, &name, 880 &length) == true ); 881 CPPUNIT_ASSERT( id == info.id ); 882 CPPUNIT_ASSERT( type == info.type ); 883 CPPUNIT_ASSERT( name == NULL && info.name == NULL 884 || name != NULL && info.name != NULL 885 && !strcmp(name, info.name) ); 886 CPPUNIT_ASSERT( length == info.size ); 887 } 888 int32 id; 889 const char *name; 890 size_t length; 891 CPPUNIT_ASSERT( resources.GetResourceInfo(type, resourceCount, &id, 892 &name, &length) == false ); 893 } 894 895 // 4. error cases 896 // non-resource file 897 NextSubTest(); 898 { 899 BResources resources; 900 BFile file(noResFile, B_READ_ONLY); 901 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 902 CPPUNIT_ASSERT( equals(resources.SetTo(&file, false), B_ERROR, 903 B_IO_ERROR) ); 904 ReadBadResTest(resources, testResource1); 905 } 906 // uninitialized file 907 NextSubTest(); 908 { 909 BResources resources; 910 BFile file; 911 CPPUNIT_ASSERT( file.InitCheck() == B_NO_INIT ); 912 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_NO_INIT ); 913 ReadBadResTest(resources, testResource1); 914 } 915 // badly initialized file 916 NextSubTest(); 917 { 918 BResources resources; 919 BFile file(noSuchFile, B_READ_ONLY); 920 CPPUNIT_ASSERT( file.InitCheck() == B_ENTRY_NOT_FOUND ); 921 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_ENTRY_NOT_FOUND ); 922 ReadBadResTest(resources, testResource1); 923 } 924 // NULL file 925 NextSubTest(); 926 { 927 BResources resources; 928 // R5: A NULL file is B_OK! 929 // CPPUNIT_ASSERT( resources.SetTo(NULL, false) == B_BAD_VALUE ); 930 CPPUNIT_ASSERT( resources.SetTo((BFile*)NULL, false) == B_OK ); 931 ReadBadResTest(resources, testResource1); 932 } 933 // bad args 934 NextSubTest(); 935 { 936 BFile file(x86ResFile, B_READ_ONLY); 937 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 938 BResources resources; 939 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 940 const ResourceInfo &info = testResource1; 941 // GetResourceInfo() 942 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.id, 943 NULL, NULL) == true ); 944 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.name, 945 NULL, NULL) == true ); 946 CPPUNIT_ASSERT( resources.GetResourceInfo(0L, (type_code*)NULL, NULL, 947 NULL, NULL) == true ); 948 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, 0, NULL, 949 NULL, NULL) == true ); 950 // LoadResource 951 const void *data1 952 = resources.LoadResource(info.type, info.id, NULL); 953 const void *data2 954 = resources.LoadResource(info.type, info.name, NULL); 955 CPPUNIT_ASSERT( data1 != NULL && data2 != NULL ); 956 // ReadResource() 957 const int32 bufferSize = 1024; 958 status_t error = resources.ReadResource(info.type, info.id, NULL, 959 0, bufferSize); 960 CPPUNIT_ASSERT( error == B_BAD_VALUE ); 961 // FindResource() 962 void *dataFound1 963 = resources.FindResource(info.type, info.id, NULL); 964 void *dataFound2 965 = resources.FindResource(info.type, info.name, NULL); 966 CPPUNIT_ASSERT( dataFound1 != NULL && dataFound2 != NULL ); 967 free(dataFound1); 968 free(dataFound2); 969 } 970 } 971 972 // AddResources 973 static 974 void 975 AddResources(BResources &resources, const ResourceInfo *resourceInfos[], 976 int32 count) 977 { 978 for (int32 i = 0; i < count; i++) { 979 const ResourceInfo &info = *resourceInfos[i]; 980 CPPUNIT_ASSERT( resources.AddResource(info.type, info.id, info.data, 981 info.size, info.name) == B_OK ); 982 } 983 } 984 985 // CompareFiles 986 static 987 void 988 CompareFiles(BFile &file1, BFile &file2) 989 { 990 off_t size1 = 0; 991 off_t size2 = 0; 992 CPPUNIT_ASSERT( file1.GetSize(&size1) == B_OK ); 993 CPPUNIT_ASSERT( file2.GetSize(&size2) == B_OK ); 994 CPPUNIT_ASSERT( size1 == size2 ); 995 char *buffer1 = new char[size1]; 996 char *buffer2 = new char[size2]; 997 CPPUNIT_ASSERT( file1.ReadAt(0, buffer1, size1) == size1 ); 998 CPPUNIT_ASSERT( file2.ReadAt(0, buffer2, size2) == size2 ); 999 for (int32 i = 0; i < size1; i++) 1000 CPPUNIT_ASSERT( buffer1[i] == buffer2[i] ); 1001 delete[] buffer1; 1002 delete[] buffer2; 1003 } 1004 1005 // CompareResources 1006 static 1007 void 1008 CompareResources(BResources &resources, const ResourceSet &resourceSet) 1009 { 1010 // compare the count 1011 int32 count = resourceSet.size(); 1012 { 1013 type_code type; 1014 int32 id; 1015 const char *name; 1016 size_t length; 1017 CPPUNIT_ASSERT( resources.GetResourceInfo(count, &type, &id, 1018 &name, &length) == false ); 1019 } 1020 // => resources contains at most count resources. If it contains all the 1021 // resources that are in resourceSet, then the sets are equal. 1022 for (int32 i = 0; i < count; i++) { 1023 const ResourceInfo &info = *resourceSet.infoAt(i); 1024 const char *name; 1025 size_t length; 1026 CPPUNIT_ASSERT( resources.GetResourceInfo(info.type, info.id, &name, 1027 &length) == true ); 1028 CPPUNIT_ASSERT( name == NULL && info.name == NULL 1029 || name != NULL && info.name != NULL 1030 && !strcmp(name, info.name) ); 1031 CPPUNIT_ASSERT( length == info.size ); 1032 const void *data = resources.LoadResource(info.type, info.id, &length); 1033 CPPUNIT_ASSERT( data != NULL && length == info.size ); 1034 CPPUNIT_ASSERT( !memcmp(data, info.data, info.size) ); 1035 } 1036 } 1037 1038 // AddResource 1039 static 1040 void 1041 AddResource(BResources &resources, ResourceSet &resourceSet, 1042 const ResourceInfo &info) 1043 { 1044 resourceSet.add(&info); 1045 CPPUNIT_ASSERT( resources.AddResource(info.type, info.id, info.data, 1046 info.size, info.name) == B_OK ); 1047 CompareResources(resources, resourceSet); 1048 } 1049 1050 // RemoveResource 1051 static 1052 void 1053 RemoveResource(BResources &resources, ResourceSet &resourceSet, 1054 const ResourceInfo &info, bool firstVersion) 1055 { 1056 resourceSet.remove(&info); 1057 if (firstVersion) { 1058 CPPUNIT_ASSERT( resources.RemoveResource(info.type, info.id) == B_OK ); 1059 } else { 1060 size_t size; 1061 const void *data = resources.LoadResource(info.type, info.id, &size); 1062 CPPUNIT_ASSERT( data != NULL ); 1063 CPPUNIT_ASSERT( resources.RemoveResource(data) == B_OK ); 1064 } 1065 CompareResources(resources, resourceSet); 1066 } 1067 1068 // ListResources 1069 /*static 1070 void 1071 ListResources(BResources &resources) 1072 { 1073 printf("Resources:\n"); 1074 type_code type; 1075 int32 id; 1076 const char *name; 1077 size_t size; 1078 for (int32 i = 0; 1079 resources.GetResourceInfo(i, &type, &id, &name, &size); 1080 i++) { 1081 type_code bigType = htonl(type); 1082 printf("resource %2ld: type: `%.4s', id: %3ld, size: %5lu\n", i, 1083 (char*)&bigType, id, size); 1084 } 1085 }*/ 1086 1087 // SyncTest 1088 void 1089 ResourcesTest::SyncTest() 1090 { 1091 // Sync() is not easy to test. We just check its return value for now. 1092 NextSubTest(); 1093 execCommand(string("cp ") + x86ResFile + " " + testFile1); 1094 { 1095 BFile file(testFile1, B_READ_WRITE); 1096 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1097 BResources resources; 1098 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1099 // add a resource and Sync() 1100 CPPUNIT_ASSERT( resources.AddResource(testResource4.type, 1101 testResource4.id, 1102 testResource4.data, 1103 testResource4.size, 1104 testResource4.name) == B_OK ); 1105 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 1106 // remove a resource and Sync() 1107 CPPUNIT_ASSERT( resources.RemoveResource(testResource1.type, 1108 testResource1.id) == B_OK ); 1109 CPPUNIT_ASSERT( resources.Sync() == B_OK ); 1110 } 1111 // error cases 1112 // read only file 1113 NextSubTest(); 1114 { 1115 BFile file(testFile1, B_READ_ONLY); 1116 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1117 BResources resources; 1118 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1119 CPPUNIT_ASSERT( resources.Sync() == B_NOT_ALLOWED ); 1120 } 1121 // uninitialized BResources 1122 NextSubTest(); 1123 { 1124 BResources resources; 1125 CPPUNIT_ASSERT( resources.Sync() == B_NO_INIT ); 1126 } 1127 // badly initialized BResources 1128 NextSubTest(); 1129 { 1130 BFile file(noSuchFile, B_READ_ONLY); 1131 CPPUNIT_ASSERT( file.InitCheck() == B_ENTRY_NOT_FOUND ); 1132 BResources resources; 1133 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_ENTRY_NOT_FOUND ); 1134 CPPUNIT_ASSERT( resources.Sync() == B_NO_INIT ); 1135 } 1136 } 1137 1138 // MergeTest 1139 void 1140 ResourcesTest::MergeTest() 1141 { 1142 // empty file, merge with resources from another file 1143 NextSubTest(); 1144 { 1145 BFile file(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1146 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1147 BResources resources; 1148 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 1149 BFile file2(x86ResFile, B_READ_ONLY); 1150 CPPUNIT_ASSERT( resources.MergeFrom(&file2) == B_OK ); 1151 ResourceSet resourceSet; 1152 resourceSet.add(&testResource1); 1153 resourceSet.add(&testResource2); 1154 resourceSet.add(&testResource3); 1155 CompareResources(resources, resourceSet); 1156 } 1157 // empty file, add some resources first and then merge with resources 1158 // from another file 1159 NextSubTest(); 1160 { 1161 BFile file(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1162 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1163 BResources resources; 1164 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 1165 // add some resources 1166 ResourceSet resourceSet; 1167 AddResource(resources, resourceSet, testResource4); 1168 AddResource(resources, resourceSet, testResource5); 1169 AddResource(resources, resourceSet, testResource6); 1170 // merge 1171 BFile file2(x86ResFile, B_READ_ONLY); 1172 CPPUNIT_ASSERT( resources.MergeFrom(&file2) == B_OK ); 1173 resourceSet.add(&testResource1); // replaces testResource6 1174 resourceSet.add(&testResource2); 1175 resourceSet.add(&testResource3); 1176 CompareResources(resources, resourceSet); 1177 } 1178 // error cases 1179 // bad args 1180 NextSubTest(); 1181 { 1182 BFile file(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1183 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1184 BResources resources; 1185 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 1186 BFile file2(noResFile, B_READ_ONLY); 1187 // non-resource file 1188 CPPUNIT_ASSERT( resources.MergeFrom(&file2) == B_IO_ERROR ); 1189 // NULL file 1190 // R5: crashs 1191 #if !TEST_R5 1192 CPPUNIT_ASSERT( resources.MergeFrom(NULL) == B_BAD_VALUE ); 1193 #endif 1194 } 1195 // uninitialized BResources 1196 // R5: returns B_OK! 1197 NextSubTest(); 1198 { 1199 BResources resources; 1200 BFile file2(x86ResFile, B_READ_ONLY); 1201 CPPUNIT_ASSERT( resources.MergeFrom(&file2) == B_OK ); 1202 } 1203 // badly initialized BResources 1204 // R5: returns B_OK! 1205 NextSubTest(); 1206 { 1207 BFile file(noSuchFile, B_READ_ONLY); 1208 CPPUNIT_ASSERT( file.InitCheck() == B_ENTRY_NOT_FOUND ); 1209 BResources resources; 1210 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_ENTRY_NOT_FOUND ); 1211 BFile file2(x86ResFile, B_READ_ONLY); 1212 CPPUNIT_ASSERT( resources.MergeFrom(&file2) == B_OK ); 1213 } 1214 } 1215 1216 // WriteToTest 1217 void 1218 ResourcesTest::WriteToTest() 1219 { 1220 // take a file with resources and write them to an empty file 1221 NextSubTest(); 1222 { 1223 BFile file(x86ResFile, B_READ_ONLY); 1224 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1225 BResources resources; 1226 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1227 BFile file2(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1228 CPPUNIT_ASSERT( file2.InitCheck() == B_OK ); 1229 CPPUNIT_ASSERT( resources.WriteTo(&file2) == B_OK); 1230 CPPUNIT_ASSERT( resources.File() == file2 ); 1231 } 1232 // take a file with resources and write them to an non-empty non-resource 1233 // file 1234 NextSubTest(); 1235 { 1236 BFile file(x86ResFile, B_READ_ONLY); 1237 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1238 BResources resources; 1239 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1240 BFile file2(noResFile, B_READ_WRITE); 1241 CPPUNIT_ASSERT( file2.InitCheck() == B_OK ); 1242 CPPUNIT_ASSERT( resources.WriteTo(&file2) == B_IO_ERROR); 1243 CPPUNIT_ASSERT( resources.File() == file2 ); 1244 } 1245 // take a file with resources and write them to an ELF file 1246 NextSubTest(); 1247 execCommand(string("cp ") + elfNoResFile + " " + testFile1); 1248 { 1249 BFile file(x86ResFile, B_READ_ONLY); 1250 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1251 BResources resources; 1252 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1253 BFile file2(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1254 CPPUNIT_ASSERT( file2.InitCheck() == B_OK ); 1255 CPPUNIT_ASSERT( resources.WriteTo(&file2) == B_OK); 1256 CPPUNIT_ASSERT( resources.File() == file2 ); 1257 } 1258 // empty file, add a resource, write it to another file 1259 NextSubTest(); 1260 { 1261 BFile file(testFile2, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1262 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1263 BResources resources; 1264 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1265 // add a resource 1266 ResourceSet resourceSet; 1267 AddResource(resources, resourceSet, testResource1); 1268 // write to another file 1269 BFile file2(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1270 CPPUNIT_ASSERT( file2.InitCheck() == B_OK ); 1271 CPPUNIT_ASSERT( resources.WriteTo(&file2) == B_OK); 1272 CPPUNIT_ASSERT( resources.File() == file2 ); 1273 // check, whether the first file has been modified -- it shouldn't be 1274 off_t fileSize = 0; 1275 CPPUNIT_ASSERT( file.GetSize(&fileSize) == B_OK ); 1276 CPPUNIT_ASSERT( fileSize == 0 ); 1277 } 1278 // uninitialized BResources 1279 NextSubTest(); 1280 execCommand(string("cp ") + elfNoResFile + " " + testFile1); 1281 { 1282 BResources resources; 1283 BFile file2(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1284 CPPUNIT_ASSERT( file2.InitCheck() == B_OK ); 1285 CPPUNIT_ASSERT( resources.WriteTo(&file2) == B_OK); 1286 CPPUNIT_ASSERT( resources.File() == file2 ); 1287 } 1288 // bad args: NULL file 1289 // R5: crashs 1290 NextSubTest(); 1291 { 1292 BFile file(testFile2, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1293 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1294 BResources resources; 1295 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1296 #if !TEST_R5 1297 CPPUNIT_ASSERT( resources.WriteTo(NULL) == B_BAD_VALUE); 1298 #endif 1299 } 1300 } 1301 1302 // AddRemoveTest 1303 void 1304 ResourcesTest::AddRemoveTest() 1305 { 1306 // tests: 1307 // * AddResource() 1308 // * RemoveResource() 1309 // * WriteResource() 1310 1311 // Start with an empty file, add all the resources of our x86 resource 1312 // file and compare the two bytewise. 1313 // This does of course only work on x86 machines. 1314 NextSubTest(); 1315 { 1316 BFile file(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1317 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1318 BResources resources; 1319 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 1320 const ResourceInfo *resourceInfos[] = { 1321 &testResource1, &testResource2, &testResource3 1322 }; 1323 int32 resourceCount = sizeof(resourceInfos) / sizeof(ResourceInfo*); 1324 AddResources(resources, resourceInfos, resourceCount); 1325 } 1326 { 1327 BFile file1(testFile1, B_READ_ONLY); 1328 BFile file2(x86ResFile, B_READ_ONLY); 1329 CompareFiles(file1, file2); 1330 } 1331 // Now remove all resources and compare the file with an empty resource 1332 // file. 1333 NextSubTest(); 1334 { 1335 BFile file(testFile1, B_READ_WRITE); 1336 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1337 BResources resources; 1338 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1339 const ResourceInfo *resourceInfos[] = { 1340 &testResource1, &testResource2, &testResource3 1341 }; 1342 int32 resourceCount = sizeof(resourceInfos) / sizeof(ResourceInfo*); 1343 for (int32 i = 0; i < resourceCount; i++) { 1344 const ResourceInfo &info = *resourceInfos[i]; 1345 CPPUNIT_ASSERT( resources.RemoveResource(info.type, info.id) 1346 == B_OK ); 1347 } 1348 BFile file2(testFile2, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1349 BResources resources2; 1350 CPPUNIT_ASSERT( resources2.SetTo(&file2, true) == B_OK ); 1351 } 1352 { 1353 BFile file1(testFile1, B_READ_ONLY); 1354 BFile file2(testFile2, B_READ_ONLY); 1355 CompareFiles(file1, file2); 1356 } 1357 // Same file, use the other remove version. 1358 NextSubTest(); 1359 execCommand(string("cp ") + x86ResFile + " " + testFile1); 1360 { 1361 BFile file(testFile1, B_READ_WRITE); 1362 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1363 BResources resources; 1364 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1365 const ResourceInfo *resourceInfos[] = { 1366 &testResource1, &testResource2, &testResource3 1367 }; 1368 int32 resourceCount = sizeof(resourceInfos) / sizeof(ResourceInfo*); 1369 for (int32 i = 0; i < resourceCount; i++) { 1370 const ResourceInfo &info = *resourceInfos[i]; 1371 size_t size; 1372 const void *data = resources.LoadResource(info.type, info.id, 1373 &size); 1374 CPPUNIT_ASSERT( data != NULL ); 1375 CPPUNIT_ASSERT( resources.RemoveResource(data) == B_OK ); 1376 } 1377 } 1378 { 1379 BFile file1(testFile1, B_READ_ONLY); 1380 BFile file2(testFile2, B_READ_ONLY); 1381 CompareFiles(file1, file2); 1382 } 1383 // some arbitrary adding and removing... 1384 NextSubTest(); 1385 { 1386 BFile file(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1387 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1388 BResources resources; 1389 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 1390 ResourceSet resourceSet; 1391 AddResource(resources, resourceSet, testResource1); 1392 AddResource(resources, resourceSet, testResource2); 1393 RemoveResource(resources, resourceSet, testResource1, true); 1394 AddResource(resources, resourceSet, testResource3); 1395 AddResource(resources, resourceSet, testResource4); 1396 RemoveResource(resources, resourceSet, testResource3, false); 1397 AddResource(resources, resourceSet, testResource5); 1398 AddResource(resources, resourceSet, testResource1); 1399 AddResource(resources, resourceSet, testResource6); // replaces 1 1400 RemoveResource(resources, resourceSet, testResource2, true); 1401 RemoveResource(resources, resourceSet, testResource5, false); 1402 RemoveResource(resources, resourceSet, testResource6, true); 1403 RemoveResource(resources, resourceSet, testResource4, false); 1404 } 1405 // bad args 1406 NextSubTest(); 1407 { 1408 BFile file(testFile1, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 1409 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1410 BResources resources; 1411 CPPUNIT_ASSERT( resources.SetTo(&file, true) == B_OK ); 1412 CPPUNIT_ASSERT( resources.RemoveResource(NULL) == B_BAD_VALUE ); 1413 CPPUNIT_ASSERT( resources.RemoveResource(B_INT32_TYPE, 0) 1414 == B_BAD_VALUE ); 1415 CPPUNIT_ASSERT( resources.AddResource(B_INT32_TYPE, 0, NULL, 7, 1416 "Hey!") == B_BAD_VALUE ); 1417 } 1418 // uninitialized BResources 1419 NextSubTest(); 1420 { 1421 BResources resources; 1422 const ResourceInfo &info = testResource1; 1423 CPPUNIT_ASSERT( resources.AddResource(info.type, info.id, info.data, 1424 info.size, info.name) 1425 == B_OK ); 1426 } 1427 } 1428 1429 // ReadWriteTest 1430 void 1431 ResourcesTest::ReadWriteTest() 1432 { 1433 // ReadResource() has already been tested in ReadTest(). Thus we focus on 1434 // WriteResource(). 1435 // Open a file and write a little bit into one of its resources. 1436 NextSubTest(); 1437 execCommand(string("cp ") + x86ResFile + " " + testFile1); 1438 { 1439 BFile file(testFile1, B_READ_WRITE); 1440 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1441 BResources resources; 1442 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1443 const ResourceInfo &info = testResource1; 1444 type_code type = info.type; 1445 int32 id = info.id; 1446 // write at the beginning of the resource 1447 char writeBuffer[1024]; 1448 for (int32 i = 0; i < 1024; i++) 1449 writeBuffer[i] = i & 0xff; 1450 char readBuffer[1024]; 1451 memset(readBuffer, 0, 1024); 1452 CPPUNIT_ASSERT( resources.WriteResource(type, id, writeBuffer, 0, 10) 1453 == B_OK ); 1454 size_t length; 1455 const void *data = resources.LoadResource(type, id, &length); 1456 CPPUNIT_ASSERT( data != NULL && length == info.size ); 1457 CPPUNIT_ASSERT( !memcmp(data, writeBuffer, 10) ); 1458 CPPUNIT_ASSERT( !memcmp((const char*)data + 10, info.data + 10, 1459 info.size - 10) ); 1460 // completely overwrite the resource with the former data 1461 CPPUNIT_ASSERT( resources.WriteResource(type, id, info.data, 0, 1462 info.size) == B_OK ); 1463 data = resources.LoadResource(type, id, &length); 1464 CPPUNIT_ASSERT( data != NULL && length == info.size ); 1465 CPPUNIT_ASSERT( !memcmp(data, info.data, info.size) ); 1466 // write something in the middle 1467 size_t offset = (info.size - 2) / 2; 1468 CPPUNIT_ASSERT( resources.WriteResource(type, id, writeBuffer, offset, 1469 2) == B_OK ); 1470 data = resources.LoadResource(type, id, &length); 1471 CPPUNIT_ASSERT( data != NULL && length == info.size ); 1472 CPPUNIT_ASSERT( !memcmp(data, info.data, offset) ); 1473 CPPUNIT_ASSERT( !memcmp((const char*)data + offset, writeBuffer, 2) ); 1474 CPPUNIT_ASSERT( !memcmp((const char*)data + offset + 2, 1475 info.data + offset + 2, 1476 info.size - offset - 2) ); 1477 // write starting inside the resource, but extending it 1478 size_t writeSize = info.size + 3; 1479 CPPUNIT_ASSERT( resources.WriteResource(type, id, writeBuffer, offset, 1480 writeSize) == B_OK ); 1481 data = resources.LoadResource(type, id, &length); 1482 CPPUNIT_ASSERT( data != NULL && length == (size_t)offset + writeSize ); 1483 CPPUNIT_ASSERT( !memcmp(data, info.data, offset) ); 1484 CPPUNIT_ASSERT( !memcmp((const char*)data + offset, writeBuffer, 1485 writeSize) ); 1486 // write past the end of the resource 1487 size_t newOffset = length + 30; 1488 size_t newWriteSize = 17; 1489 CPPUNIT_ASSERT( resources.WriteResource(type, id, writeBuffer, 1490 newOffset, newWriteSize) 1491 == B_OK ); 1492 data = resources.LoadResource(type, id, &length); 1493 CPPUNIT_ASSERT( data != NULL && length == newOffset + newWriteSize ); 1494 CPPUNIT_ASSERT( !memcmp(data, info.data, offset) ); 1495 CPPUNIT_ASSERT( !memcmp((const char*)data + offset, writeBuffer, 1496 writeSize) ); 1497 // [offset + writeSize, newOffset) unspecified 1498 CPPUNIT_ASSERT( !memcmp((const char*)data + newOffset, writeBuffer, 1499 newWriteSize) ); 1500 } 1501 // error cases 1502 // bad args 1503 NextSubTest(); 1504 { 1505 BFile file(testFile1, B_READ_WRITE); 1506 CPPUNIT_ASSERT( file.InitCheck() == B_OK ); 1507 BResources resources; 1508 CPPUNIT_ASSERT( resources.SetTo(&file, false) == B_OK ); 1509 const ResourceInfo &info = testResource1; 1510 type_code type = info.type; 1511 int32 id = info.id; 1512 // NULL buffer 1513 CPPUNIT_ASSERT( resources.WriteResource(type, id, NULL, 0, 10) 1514 == B_BAD_VALUE ); 1515 // non existing resource 1516 char writeBuffer[1024]; 1517 CPPUNIT_ASSERT( resources.WriteResource(B_MESSENGER_TYPE, 0, 1518 writeBuffer, 0, 10) 1519 == B_BAD_VALUE ); 1520 } 1521 // uninitialized BResources 1522 NextSubTest(); 1523 { 1524 BResources resources; 1525 const ResourceInfo &info = testResource1; 1526 type_code type = info.type; 1527 int32 id = info.id; 1528 char writeBuffer[1024]; 1529 CPPUNIT_ASSERT( resources.WriteResource(type, id, writeBuffer, 0, 10) 1530 == B_BAD_VALUE ); 1531 } 1532 } 1533 1534 1535 1536 1537 1538