| OLD | NEW |
| 1 // Copyright (c) 2010, Google Inc. | 1 // Copyright (c) 2010, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 using google_breakpad::MinidumpModule; | 56 using google_breakpad::MinidumpModule; |
| 57 using google_breakpad::MinidumpModuleList; | 57 using google_breakpad::MinidumpModuleList; |
| 58 using google_breakpad::MinidumpSystemInfo; | 58 using google_breakpad::MinidumpSystemInfo; |
| 59 using google_breakpad::MinidumpThread; | 59 using google_breakpad::MinidumpThread; |
| 60 using google_breakpad::MinidumpThreadList; | 60 using google_breakpad::MinidumpThreadList; |
| 61 using google_breakpad::SynthMinidump::Context; | 61 using google_breakpad::SynthMinidump::Context; |
| 62 using google_breakpad::SynthMinidump::Dump; | 62 using google_breakpad::SynthMinidump::Dump; |
| 63 using google_breakpad::SynthMinidump::Exception; | 63 using google_breakpad::SynthMinidump::Exception; |
| 64 using google_breakpad::SynthMinidump::Memory; | 64 using google_breakpad::SynthMinidump::Memory; |
| 65 using google_breakpad::SynthMinidump::Module; | 65 using google_breakpad::SynthMinidump::Module; |
| 66 using google_breakpad::SynthMinidump::Section; |
| 66 using google_breakpad::SynthMinidump::Stream; | 67 using google_breakpad::SynthMinidump::Stream; |
| 67 using google_breakpad::SynthMinidump::String; | 68 using google_breakpad::SynthMinidump::String; |
| 68 using google_breakpad::SynthMinidump::SystemInfo; | 69 using google_breakpad::SynthMinidump::SystemInfo; |
| 69 using google_breakpad::SynthMinidump::Thread; | 70 using google_breakpad::SynthMinidump::Thread; |
| 70 using google_breakpad::test_assembler::kBigEndian; | 71 using google_breakpad::test_assembler::kBigEndian; |
| 71 using google_breakpad::test_assembler::kLittleEndian; | 72 using google_breakpad::test_assembler::kLittleEndian; |
| 72 using std::ifstream; | 73 using std::ifstream; |
| 73 using std::istringstream; | 74 using std::istringstream; |
| 74 using std::vector; | 75 using std::vector; |
| 75 using ::testing::Return; | 76 using ::testing::Return; |
| 76 | 77 |
| 77 class MinidumpTest : public ::testing::Test { | 78 class MinidumpTest : public ::testing::Test { |
| 78 public: | 79 public: |
| 79 void SetUp() { | 80 void SetUp() { |
| 80 minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + | 81 minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + |
| 81 "/src/processor/testdata/minidump2.dmp"; | 82 "/src/processor/testdata/minidump2.dmp"; |
| 82 } | 83 } |
| 83 string minidump_file_; | 84 string minidump_file_; |
| 84 }; | 85 }; |
| 85 | 86 |
| 86 TEST_F(MinidumpTest, TestMinidumpFromFile) { | 87 TEST_F(MinidumpTest, TestMinidumpFromFile) { |
| 87 Minidump minidump(minidump_file_); | 88 Minidump minidump(minidump_file_); |
| 88 ASSERT_EQ(minidump.path(), minidump_file_); | 89 ASSERT_EQ(minidump.path(), minidump_file_); |
| 89 ASSERT_TRUE(minidump.Read()); | 90 ASSERT_TRUE(minidump.Read()); |
| 90 const MDRawHeader* header = minidump.header(); | 91 const MDRawHeader* header = minidump.header(); |
| 91 ASSERT_NE(header, (MDRawHeader*)NULL); | 92 ASSERT_NE(header, (MDRawHeader*)NULL); |
| 92 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); | 93 ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); |
| 93 //TODO: add more checks here | 94 |
| 95 MinidumpModuleList *md_module_list = minidump.GetModuleList(); |
| 96 ASSERT_TRUE(md_module_list != NULL); |
| 97 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); |
| 98 ASSERT_TRUE(md_module != NULL); |
| 99 ASSERT_EQ("c:\\test_app.exe", md_module->code_file()); |
| 100 ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file()); |
| 101 ASSERT_EQ("45D35F6C2d000", md_module->code_identifier()); |
| 102 ASSERT_EQ("5A9832E5287241C1838ED98914E9B7FF1", md_module->debug_identifier()); |
| 94 } | 103 } |
| 95 | 104 |
| 96 TEST_F(MinidumpTest, TestMinidumpFromStream) { | 105 TEST_F(MinidumpTest, TestMinidumpFromStream) { |
| 97 // read minidump contents into memory, construct a stringstream around them | 106 // read minidump contents into memory, construct a stringstream around them |
| 98 ifstream file_stream(minidump_file_.c_str(), std::ios::in); | 107 ifstream file_stream(minidump_file_.c_str(), std::ios::in); |
| 99 ASSERT_TRUE(file_stream.good()); | 108 ASSERT_TRUE(file_stream.good()); |
| 100 vector<char> bytes; | 109 vector<char> bytes; |
| 101 file_stream.seekg(0, std::ios_base::end); | 110 file_stream.seekg(0, std::ios_base::end); |
| 102 ASSERT_TRUE(file_stream.good()); | 111 ASSERT_TRUE(file_stream.good()); |
| 103 bytes.resize(file_stream.tellg()); | 112 bytes.resize(file_stream.tellg()); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 uint32_t thread_id; | 387 uint32_t thread_id; |
| 379 ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); | 388 ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); |
| 380 ASSERT_EQ(0xa898f11bU, thread_id); | 389 ASSERT_EQ(0xa898f11bU, thread_id); |
| 381 MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); | 390 MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); |
| 382 ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); | 391 ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); |
| 383 | 392 |
| 384 MinidumpContext* md_context = md_thread->GetContext(); | 393 MinidumpContext* md_context = md_thread->GetContext(); |
| 385 ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context); | 394 ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context); |
| 386 } | 395 } |
| 387 | 396 |
| 397 static const MDVSFixedFileInfo fixed_file_info = { |
| 398 0xb2fba33a, // signature |
| 399 0x33d7a728, // struct_version |
| 400 0x31afcb20, // file_version_hi |
| 401 0xe51cdab1, // file_version_lo |
| 402 0xd1ea6907, // product_version_hi |
| 403 0x03032857, // product_version_lo |
| 404 0x11bf71d7, // file_flags_mask |
| 405 0x5fb8cdbf, // file_flags |
| 406 0xe45d0d5d, // file_os |
| 407 0x107d9562, // file_type |
| 408 0x5a8844d4, // file_subtype |
| 409 0xa8d30b20, // file_date_hi |
| 410 0x651c3e4e // file_date_lo |
| 411 }; |
| 412 |
| 388 TEST(Dump, OneModule) { | 413 TEST(Dump, OneModule) { |
| 389 static const MDVSFixedFileInfo fixed_file_info = { | |
| 390 0xb2fba33a, // signature | |
| 391 0x33d7a728, // struct_version | |
| 392 0x31afcb20, // file_version_hi | |
| 393 0xe51cdab1, // file_version_lo | |
| 394 0xd1ea6907, // product_version_hi | |
| 395 0x03032857, // product_version_lo | |
| 396 0x11bf71d7, // file_flags_mask | |
| 397 0x5fb8cdbf, // file_flags | |
| 398 0xe45d0d5d, // file_os | |
| 399 0x107d9562, // file_type | |
| 400 0x5a8844d4, // file_subtype | |
| 401 0xa8d30b20, // file_date_hi | |
| 402 0x651c3e4e // file_date_lo | |
| 403 }; | |
| 404 | |
| 405 Dump dump(0, kBigEndian); | 414 Dump dump(0, kBigEndian); |
| 406 String module_name(dump, "single module"); | 415 String module_name(dump, "single module"); |
| 416 Section cv_info(dump); |
| 417 cv_info |
| 418 .D32(MD_CVINFOPDB70_SIGNATURE) // signature |
| 419 // signature, a MDGUID |
| 420 .D32(0xabcd1234) |
| 421 .D16(0xf00d) |
| 422 .D16(0xbeef) |
| 423 .Append("\x01\x02\x03\x04\x05\x06\x07\x08") |
| 424 .D32(1) // age |
| 425 .AppendCString("c:\\foo\\file.pdb"); // pdb_file_name |
| 426 |
| 427 String csd_version(dump, "Windows 9000"); |
| 428 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); |
| 429 |
| 407 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, | 430 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, |
| 408 module_name, | 431 module_name, |
| 409 0xb1054d2a, | 432 0xb1054d2a, |
| 410 0x34571371, | 433 0x34571371, |
| 411 fixed_file_info, // from synth_minidump_unittest_data.h | 434 fixed_file_info, // from synth_minidump_unittest_data.h |
| 412 NULL, NULL); | 435 &cv_info, nullptr); |
| 413 | 436 |
| 414 dump.Add(&module); | 437 dump.Add(&module); |
| 415 dump.Add(&module_name); | 438 dump.Add(&module_name); |
| 439 dump.Add(&cv_info); |
| 440 dump.Add(&system_info); |
| 441 dump.Add(&csd_version); |
| 416 dump.Finish(); | 442 dump.Finish(); |
| 417 | 443 |
| 418 string contents; | 444 string contents; |
| 419 ASSERT_TRUE(dump.GetContents(&contents)); | 445 ASSERT_TRUE(dump.GetContents(&contents)); |
| 420 istringstream minidump_stream(contents); | 446 istringstream minidump_stream(contents); |
| 421 Minidump minidump(minidump_stream); | 447 Minidump minidump(minidump_stream); |
| 422 ASSERT_TRUE(minidump.Read()); | 448 ASSERT_TRUE(minidump.Read()); |
| 423 ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); | 449 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); |
| 424 | 450 |
| 425 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); | 451 const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(1); |
| 426 ASSERT_TRUE(dir != NULL); | 452 ASSERT_TRUE(dir != NULL); |
| 427 EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type); | 453 EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type); |
| 428 | 454 |
| 429 MinidumpModuleList *md_module_list = minidump.GetModuleList(); | 455 MinidumpModuleList *md_module_list = minidump.GetModuleList(); |
| 430 ASSERT_TRUE(md_module_list != NULL); | 456 ASSERT_TRUE(md_module_list != NULL); |
| 431 ASSERT_EQ(1U, md_module_list->module_count()); | 457 ASSERT_EQ(1U, md_module_list->module_count()); |
| 432 | 458 |
| 433 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); | 459 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); |
| 434 ASSERT_TRUE(md_module != NULL); | 460 ASSERT_TRUE(md_module != NULL); |
| 435 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); | 461 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); |
| 436 ASSERT_EQ(0xada542bd, md_module->size()); | 462 ASSERT_EQ(0xada542bd, md_module->size()); |
| 437 ASSERT_EQ("single module", md_module->code_file()); | 463 ASSERT_EQ("single module", md_module->code_file()); |
| 464 ASSERT_EQ("c:\\foo\\file.pdb", md_module->debug_file()); |
| 465 // time_date_stamp and size_of_image concatenated |
| 466 ASSERT_EQ("B1054D2Aada542bd", md_module->code_identifier()); |
| 467 ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier()); |
| 438 | 468 |
| 439 const MDRawModule *md_raw_module = md_module->module(); | 469 const MDRawModule *md_raw_module = md_module->module(); |
| 440 ASSERT_TRUE(md_raw_module != NULL); | 470 ASSERT_TRUE(md_raw_module != NULL); |
| 441 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); | 471 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); |
| 442 ASSERT_EQ(0x34571371U, md_raw_module->checksum); | 472 ASSERT_EQ(0x34571371U, md_raw_module->checksum); |
| 443 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, | 473 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, |
| 444 sizeof(fixed_file_info)) == 0); | 474 sizeof(fixed_file_info)) == 0); |
| 445 } | 475 } |
| 446 | 476 |
| 477 // Test that a module with a MDCVInfoELF CV record is handled properly. |
| 478 TEST(Dump, OneModuleCVELF) { |
| 479 Dump dump(0, kLittleEndian); |
| 480 String module_name(dump, "elf module"); |
| 481 Section cv_info(dump); |
| 482 cv_info |
| 483 .D32(MD_CVINFOELF_SIGNATURE) // signature |
| 484 // build_id |
| 485 .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf" |
| 486 "\x37\x38\xce\xa3\x4a\x87"); |
| 487 |
| 488 const MDRawSystemInfo linux_x86 = { |
| 489 MD_CPU_ARCHITECTURE_X86, // processor_architecture |
| 490 6, // processor_level |
| 491 0xd08, // processor_revision |
| 492 1, // number_of_processors |
| 493 0, // product_type |
| 494 0, // major_version |
| 495 0, // minor_version |
| 496 0, // build_number |
| 497 MD_OS_LINUX, // platform_id |
| 498 0xdeadbeef, // csd_version_rva |
| 499 0x100, // suite_mask |
| 500 0, // reserved2 |
| 501 { // cpu |
| 502 { // x86_cpu_info |
| 503 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id |
| 504 0x6d8, // version_information |
| 505 0xafe9fbff, // feature_information |
| 506 0xffffffff // amd_extended_cpu_features |
| 507 } |
| 508 } |
| 509 }; |
| 510 String csd_version(dump, "Literally Linux"); |
| 511 SystemInfo system_info(dump, linux_x86, csd_version); |
| 512 |
| 513 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, |
| 514 module_name, |
| 515 0xb1054d2a, |
| 516 0x34571371, |
| 517 fixed_file_info, // from synth_minidump_unittest_data.h |
| 518 &cv_info, nullptr); |
| 519 |
| 520 dump.Add(&module); |
| 521 dump.Add(&module_name); |
| 522 dump.Add(&cv_info); |
| 523 dump.Add(&system_info); |
| 524 dump.Add(&csd_version); |
| 525 dump.Finish(); |
| 526 |
| 527 string contents; |
| 528 ASSERT_TRUE(dump.GetContents(&contents)); |
| 529 istringstream minidump_stream(contents); |
| 530 Minidump minidump(minidump_stream); |
| 531 ASSERT_TRUE(minidump.Read()); |
| 532 |
| 533 MinidumpModuleList *md_module_list = minidump.GetModuleList(); |
| 534 ASSERT_TRUE(md_module_list != NULL); |
| 535 ASSERT_EQ(1U, md_module_list->module_count()); |
| 536 |
| 537 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); |
| 538 ASSERT_TRUE(md_module != NULL); |
| 539 ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); |
| 540 ASSERT_EQ(0xada542bd, md_module->size()); |
| 541 ASSERT_EQ("elf module", md_module->code_file()); |
| 542 // debug_file == code_file |
| 543 ASSERT_EQ("elf module", md_module->debug_file()); |
| 544 // just the build_id, directly |
| 545 ASSERT_EQ("5fa9cdb41053df1b86fab733b4df3738cea34a87", |
| 546 md_module->code_identifier()); |
| 547 // build_id truncted to GUID length and treated as such, with zero |
| 548 // age appended |
| 549 ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier()); |
| 550 |
| 551 const MDRawModule *md_raw_module = md_module->module(); |
| 552 ASSERT_TRUE(md_raw_module != NULL); |
| 553 ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); |
| 554 ASSERT_EQ(0x34571371U, md_raw_module->checksum); |
| 555 ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, |
| 556 sizeof(fixed_file_info)) == 0); |
| 557 } |
| 558 |
| 559 // Test that a build_id that's shorter than a GUID is handled properly. |
| 560 TEST(Dump, CVELFShort) { |
| 561 Dump dump(0, kLittleEndian); |
| 562 String module_name(dump, "elf module"); |
| 563 Section cv_info(dump); |
| 564 cv_info |
| 565 .D32(MD_CVINFOELF_SIGNATURE) // signature |
| 566 // build_id, shorter than a GUID |
| 567 .Append("\x5f\xa9\xcd\xb4"); |
| 568 |
| 569 const MDRawSystemInfo linux_x86 = { |
| 570 MD_CPU_ARCHITECTURE_X86, // processor_architecture |
| 571 6, // processor_level |
| 572 0xd08, // processor_revision |
| 573 1, // number_of_processors |
| 574 0, // product_type |
| 575 0, // major_version |
| 576 0, // minor_version |
| 577 0, // build_number |
| 578 MD_OS_LINUX, // platform_id |
| 579 0xdeadbeef, // csd_version_rva |
| 580 0x100, // suite_mask |
| 581 0, // reserved2 |
| 582 { // cpu |
| 583 { // x86_cpu_info |
| 584 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id |
| 585 0x6d8, // version_information |
| 586 0xafe9fbff, // feature_information |
| 587 0xffffffff // amd_extended_cpu_features |
| 588 } |
| 589 } |
| 590 }; |
| 591 String csd_version(dump, "Literally Linux"); |
| 592 SystemInfo system_info(dump, linux_x86, csd_version); |
| 593 |
| 594 Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, |
| 595 module_name, |
| 596 0xb1054d2a, |
| 597 0x34571371, |
| 598 fixed_file_info, // from synth_minidump_unittest_data.h |
| 599 &cv_info, nullptr); |
| 600 |
| 601 dump.Add(&module); |
| 602 dump.Add(&module_name); |
| 603 dump.Add(&cv_info); |
| 604 dump.Add(&system_info); |
| 605 dump.Add(&csd_version); |
| 606 dump.Finish(); |
| 607 |
| 608 string contents; |
| 609 ASSERT_TRUE(dump.GetContents(&contents)); |
| 610 istringstream minidump_stream(contents); |
| 611 Minidump minidump(minidump_stream); |
| 612 ASSERT_TRUE(minidump.Read()); |
| 613 ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); |
| 614 |
| 615 MinidumpModuleList *md_module_list = minidump.GetModuleList(); |
| 616 ASSERT_TRUE(md_module_list != NULL); |
| 617 ASSERT_EQ(1U, md_module_list->module_count()); |
| 618 |
| 619 const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); |
| 620 ASSERT_TRUE(md_module != NULL); |
| 621 // just the build_id, directly |
| 622 ASSERT_EQ("5fa9cdb4", md_module->code_identifier()); |
| 623 // build_id expanded to GUID length and treated as such, with zero |
| 624 // age appended |
| 625 ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier()); |
| 626 } |
| 627 |
| 447 TEST(Dump, OneSystemInfo) { | 628 TEST(Dump, OneSystemInfo) { |
| 448 Dump dump(0, kLittleEndian); | 629 Dump dump(0, kLittleEndian); |
| 449 String csd_version(dump, "Petulant Pierogi"); | 630 String csd_version(dump, "Petulant Pierogi"); |
| 450 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); | 631 SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); |
| 451 | 632 |
| 452 dump.Add(&system_info); | 633 dump.Add(&system_info); |
| 453 dump.Add(&csd_version); | 634 dump.Add(&csd_version); |
| 454 dump.Finish(); | 635 dump.Finish(); |
| 455 | 636 |
| 456 string contents; | 637 string contents; |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]); | 1438 EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]); |
| 1258 EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]); | 1439 EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]); |
| 1259 EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]); | 1440 EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]); |
| 1260 EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]); | 1441 EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]); |
| 1261 EXPECT_EQ(0x56781234U, raw_context.iregs[29]); | 1442 EXPECT_EQ(0x56781234U, raw_context.iregs[29]); |
| 1262 EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]); | 1443 EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]); |
| 1263 EXPECT_EQ(0x30401020U, raw_context.iregs[31]); | 1444 EXPECT_EQ(0x30401020U, raw_context.iregs[31]); |
| 1264 } | 1445 } |
| 1265 | 1446 |
| 1266 } // namespace | 1447 } // namespace |
| OLD | NEW |