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