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