1 /*- 2 * Copyright (c) 2012, 2013, 2014 Spectra Logic Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * Authors: Alan Somers (Spectra Logic Corporation) 31 */ 32 #include <sys/cdefs.h> 33 #include <sys/byteorder.h> 34 35 #include <stdarg.h> 36 #include <syslog.h> 37 38 #include <libnvpair.h> 39 #include <libzfs.h> 40 41 #include <list> 42 #include <map> 43 #include <sstream> 44 #include <string> 45 46 #include <gmock/gmock.h> 47 #include <gtest/gtest.h> 48 49 #include <devdctl/guid.h> 50 #include <devdctl/event.h> 51 #include <devdctl/event_factory.h> 52 #include <devdctl/exception.h> 53 #include <devdctl/consumer.h> 54 55 #include <zfsd/callout.h> 56 #include <zfsd/vdev_iterator.h> 57 #include <zfsd/zfsd_event.h> 58 #include <zfsd/case_file.h> 59 #include <zfsd/vdev.h> 60 #include <zfsd/zfsd.h> 61 #include <zfsd/zfsd_exception.h> 62 #include <zfsd/zpool_list.h> 63 64 #include "libmocks.h" 65 /*================================== Macros ==================================*/ 66 #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) 67 68 /*============================ Namespace Control =============================*/ 69 using std::string; 70 using std::stringstream; 71 72 using DevdCtl::Event; 73 using DevdCtl::EventFactory; 74 using DevdCtl::EventList; 75 using DevdCtl::Guid; 76 using DevdCtl::NVPairMap; 77 78 /* redefine zpool_handle here because libzfs_impl.h is not includable */ 79 struct zpool_handle 80 { 81 libzfs_handle_t *zpool_hdl; 82 zpool_handle_t *zpool_next; 83 char zpool_name[ZFS_MAX_DATASET_NAME_LEN]; 84 int zpool_state; 85 size_t zpool_config_size; 86 nvlist_t *zpool_config; 87 nvlist_t *zpool_old_config; 88 nvlist_t *zpool_props; 89 diskaddr_t zpool_start_block; 90 }; 91 92 class MockZfsEvent : public ZfsEvent 93 { 94 public: 95 MockZfsEvent(Event::Type, NVPairMap&, const string&); 96 virtual ~MockZfsEvent() {} 97 98 static BuildMethod MockZfsEventBuilder; 99 100 MOCK_CONST_METHOD0(ProcessPoolEvent, void()); 101 102 static EventFactory::Record s_buildRecords[]; 103 }; 104 105 EventFactory::Record MockZfsEvent::s_buildRecords[] = 106 { 107 { Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder } 108 }; 109 110 MockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map, 111 const string& str) 112 : ZfsEvent(type, map, str) 113 { 114 } 115 116 Event * 117 MockZfsEvent::MockZfsEventBuilder(Event::Type type, 118 NVPairMap &nvpairs, 119 const string &eventString) 120 { 121 return (new MockZfsEvent(type, nvpairs, eventString)); 122 } 123 124 /* 125 * A dummy Vdev class used for testing other classes 126 */ 127 class MockVdev : public Vdev 128 { 129 public: 130 MockVdev(nvlist_t *vdevConfig); 131 virtual ~MockVdev() {} 132 133 MOCK_CONST_METHOD0(GUID, Guid()); 134 MOCK_CONST_METHOD0(PoolGUID, Guid()); 135 MOCK_CONST_METHOD0(State, vdev_state()); 136 MOCK_CONST_METHOD0(PhysicalPath, string()); 137 }; 138 139 MockVdev::MockVdev(nvlist_t *vdevConfig) 140 : Vdev(vdevConfig) 141 { 142 } 143 144 /* 145 * A CaseFile class with side effects removed, for testing 146 */ 147 class TestableCaseFile : public CaseFile 148 { 149 public: 150 static TestableCaseFile &Create(Vdev &vdev); 151 TestableCaseFile(Vdev &vdev); 152 virtual ~TestableCaseFile() {} 153 154 MOCK_METHOD0(Close, void()); 155 MOCK_METHOD1(RegisterCallout, void(const Event &event)); 156 MOCK_METHOD0(RefreshVdevState, bool()); 157 MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event)); 158 159 bool RealReEvaluate(const ZfsEvent &event) 160 { 161 return (CaseFile::ReEvaluate(event)); 162 } 163 164 /* 165 * This splices the event lists, a procedure that would normally be done 166 * by OnGracePeriodEnded, but we don't necessarily call that in the 167 * unit tests 168 */ 169 void SpliceEvents(); 170 171 /* 172 * Used by some of our expectations. CaseFile does not publicize this 173 */ 174 static int getActiveCases() 175 { 176 return (s_activeCases.size()); 177 } 178 }; 179 180 TestableCaseFile::TestableCaseFile(Vdev &vdev) 181 : CaseFile(vdev) 182 { 183 } 184 185 TestableCaseFile & 186 TestableCaseFile::Create(Vdev &vdev) 187 { 188 TestableCaseFile *newCase; 189 newCase = new TestableCaseFile(vdev); 190 return (*newCase); 191 } 192 193 void 194 TestableCaseFile::SpliceEvents() 195 { 196 m_events.splice(m_events.begin(), m_tentativeEvents); 197 } 198 199 200 /* 201 * Test class ZfsdException 202 */ 203 class ZfsdExceptionTest : public ::testing::Test 204 { 205 protected: 206 virtual void SetUp() 207 { 208 ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0)); 209 ASSERT_EQ(0, nvlist_add_string(poolConfig, 210 ZPOOL_CONFIG_POOL_NAME, "unit_test_pool")); 211 ASSERT_EQ(0, nvlist_add_uint64(poolConfig, 212 ZPOOL_CONFIG_POOL_GUID, 0x1234)); 213 214 ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0)); 215 ASSERT_EQ(0, nvlist_add_uint64(vdevConfig, 216 ZPOOL_CONFIG_GUID, 0x5678)); 217 bzero(&poolHandle, sizeof(poolHandle)); 218 poolHandle.zpool_config = poolConfig; 219 } 220 221 virtual void TearDown() 222 { 223 nvlist_free(poolConfig); 224 nvlist_free(vdevConfig); 225 } 226 227 nvlist_t *poolConfig; 228 nvlist_t *vdevConfig; 229 zpool_handle_t poolHandle; 230 }; 231 232 TEST_F(ZfsdExceptionTest, StringConstructorNull) 233 { 234 ZfsdException ze(""); 235 EXPECT_STREQ("", ze.GetString().c_str()); 236 } 237 238 TEST_F(ZfsdExceptionTest, StringConstructorFormatted) 239 { 240 ZfsdException ze(" %d %s", 55, "hello world"); 241 EXPECT_STREQ(" 55 hello world", ze.GetString().c_str()); 242 } 243 244 TEST_F(ZfsdExceptionTest, LogSimple) 245 { 246 ZfsdException ze("unit test w/o vdev or pool"); 247 ze.Log(); 248 EXPECT_EQ(LOG_ERR, syslog_last_priority); 249 EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message); 250 } 251 252 TEST_F(ZfsdExceptionTest, Pool) 253 { 254 const char msg[] = "Exception with pool name"; 255 char expected[4096]; 256 sprintf(expected, "Pool unit_test_pool: %s\n", msg); 257 ZfsdException ze(poolConfig, msg); 258 ze.Log(); 259 EXPECT_STREQ(expected, syslog_last_message); 260 } 261 262 TEST_F(ZfsdExceptionTest, PoolHandle) 263 { 264 const char msg[] = "Exception with pool handle"; 265 char expected[4096]; 266 sprintf(expected, "Pool unit_test_pool: %s\n", msg); 267 ZfsdException ze(&poolHandle, msg); 268 ze.Log(); 269 EXPECT_STREQ(expected, syslog_last_message); 270 } 271 272 /* 273 * Test class Vdev 274 */ 275 class VdevTest : public ::testing::Test 276 { 277 protected: 278 virtual void SetUp() 279 { 280 ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0)); 281 ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig, 282 ZPOOL_CONFIG_POOL_GUID, 283 0x1234)); 284 285 ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0)); 286 ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID, 287 0x5678)); 288 } 289 290 virtual void TearDown() 291 { 292 nvlist_free(m_poolConfig); 293 nvlist_free(m_vdevConfig); 294 } 295 296 nvlist_t *m_poolConfig; 297 nvlist_t *m_vdevConfig; 298 }; 299 300 301 TEST_F(VdevTest, StateFromConfig) 302 { 303 vdev_stat_t vs; 304 305 vs.vs_state = VDEV_STATE_OFFLINE; 306 307 ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig, 308 ZPOOL_CONFIG_VDEV_STATS, 309 (uint64_t*)&vs, 310 sizeof(vs) / sizeof(uint64_t))); 311 312 Vdev vdev(m_poolConfig, m_vdevConfig); 313 314 EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State()); 315 } 316 317 TEST_F(VdevTest, StateFaulted) 318 { 319 ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1)); 320 321 Vdev vdev(m_poolConfig, m_vdevConfig); 322 323 EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State()); 324 } 325 326 /* 327 * Test that we can construct a Vdev from the label information that is stored 328 * on an available spare drive 329 */ 330 TEST_F(VdevTest, ConstructAvailSpare) 331 { 332 nvlist_t *labelConfig; 333 334 ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0)); 335 ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID, 336 1948339428197961030)); 337 ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE, 338 POOL_STATE_SPARE)); 339 340 EXPECT_NO_THROW(Vdev vdev(labelConfig)); 341 342 nvlist_free(labelConfig); 343 } 344 345 /* Available spares will always show the HEALTHY state */ 346 TEST_F(VdevTest, AvailSpareState) { 347 nvlist_t *labelConfig; 348 349 ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0)); 350 ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID, 351 1948339428197961030)); 352 ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE, 353 POOL_STATE_SPARE)); 354 355 Vdev vdev(labelConfig); 356 EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State()); 357 358 nvlist_free(labelConfig); 359 } 360 361 /* Test the Vdev::IsSpare method */ 362 TEST_F(VdevTest, IsSpare) { 363 Vdev notSpare(m_poolConfig, m_vdevConfig); 364 EXPECT_EQ(false, notSpare.IsSpare()); 365 366 ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1)); 367 Vdev isSpare(m_poolConfig, m_vdevConfig); 368 EXPECT_EQ(true, isSpare.IsSpare()); 369 } 370 371 /* 372 * Test class ZFSEvent 373 */ 374 class ZfsEventTest : public ::testing::Test 375 { 376 protected: 377 virtual void SetUp() 378 { 379 m_eventFactory = new EventFactory(); 380 m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords, 381 NUM_ELEMENTS(MockZfsEvent::s_buildRecords)); 382 383 m_event = NULL; 384 } 385 386 virtual void TearDown() 387 { 388 delete m_eventFactory; 389 delete m_event; 390 } 391 392 EventFactory *m_eventFactory; 393 Event *m_event; 394 }; 395 396 TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled) 397 { 398 string evString("!system=ZFS " 399 "subsystem=ZFS " 400 "type=sysevent.fs.zfs.vdev_remove " 401 "pool_name=foo " 402 "pool_guid=9756779504028057996 " 403 "vdev_guid=1631193447431603339 " 404 "vdev_path=/dev/da1 " 405 "timestamp=1348871594"); 406 m_event = Event::CreateEvent(*m_eventFactory, evString); 407 MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event); 408 409 EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1); 410 mock_event->Process(); 411 } 412 413 /* 414 * Test class CaseFile 415 */ 416 417 class CaseFileTest : public ::testing::Test 418 { 419 protected: 420 virtual void SetUp() 421 { 422 m_eventFactory = new EventFactory(); 423 m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords, 424 NUM_ELEMENTS(MockZfsEvent::s_buildRecords)); 425 426 m_event = NULL; 427 428 nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0); 429 ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, 430 ZPOOL_CONFIG_GUID, 0xbeef)); 431 m_vdev = new MockVdev(m_vdevConfig); 432 ON_CALL(*m_vdev, GUID()) 433 .WillByDefault(::testing::Return(Guid(123))); 434 ON_CALL(*m_vdev, PoolGUID()) 435 .WillByDefault(::testing::Return(Guid(456))); 436 ON_CALL(*m_vdev, State()) 437 .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY)); 438 m_caseFile = &TestableCaseFile::Create(*m_vdev); 439 ON_CALL(*m_caseFile, ReEvaluate(::testing::_)) 440 .WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate)); 441 return; 442 } 443 444 virtual void TearDown() 445 { 446 delete m_caseFile; 447 nvlist_free(m_vdevConfig); 448 delete m_vdev; 449 delete m_event; 450 delete m_eventFactory; 451 } 452 453 nvlist_t *m_vdevConfig; 454 MockVdev *m_vdev; 455 TestableCaseFile *m_caseFile; 456 Event *m_event; 457 EventFactory *m_eventFactory; 458 }; 459 460 /* 461 * A Vdev with no events should not be degraded or faulted 462 */ 463 TEST_F(CaseFileTest, HealthyVdev) 464 { 465 EXPECT_FALSE(m_caseFile->ShouldDegrade()); 466 EXPECT_FALSE(m_caseFile->ShouldFault()); 467 } 468 469 /* 470 * A Vdev with only one event should not be degraded or faulted 471 * For performance reasons, RefreshVdevState should not be called. 472 */ 473 TEST_F(CaseFileTest, HealthyishVdev) 474 { 475 string evString("!system=ZFS " 476 "class=ereport.fs.zfs.io " 477 "ena=12091638756982918145 " 478 "parent_guid=13237004955564865395 " 479 "parent_type=raidz " 480 "pool=testpool.4415 " 481 "pool_context=0 " 482 "pool_failmode=wait " 483 "pool_guid=456 " 484 "subsystem=ZFS " 485 "timestamp=1348867914 " 486 "type=ereport.fs.zfs.io " 487 "vdev_guid=123 " 488 "vdev_path=/dev/da400 " 489 "vdev_type=disk " 490 "zio_blkid=622 " 491 "zio_err=1 " 492 "zio_level=-2 " 493 "zio_object=0 " 494 "zio_objset=37 " 495 "zio_offset=25598976 " 496 "zio_size=1024"); 497 m_event = Event::CreateEvent(*m_eventFactory, evString); 498 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 499 500 EXPECT_CALL(*m_caseFile, RefreshVdevState()) 501 .Times(::testing::Exactly(0)); 502 EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 503 EXPECT_FALSE(m_caseFile->ShouldDegrade()); 504 EXPECT_FALSE(m_caseFile->ShouldFault()); 505 } 506 507 /* The case file should be closed when its pool is destroyed */ 508 TEST_F(CaseFileTest, PoolDestroy) 509 { 510 string evString("!system=ZFS " 511 "pool_name=testpool.4415 " 512 "pool_guid=456 " 513 "subsystem=ZFS " 514 "timestamp=1348867914 " 515 "type=sysevent.fs.zfs.pool_destroy "); 516 m_event = Event::CreateEvent(*m_eventFactory, evString); 517 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 518 EXPECT_CALL(*m_caseFile, Close()); 519 EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 520 } 521 522 /* 523 * A Vdev with a very large number of Delay errors should fault 524 * For performance reasons, RefreshVdevState should be called at most once 525 */ 526 TEST_F(CaseFileTest, VeryManyDelayErrors) 527 { 528 EXPECT_CALL(*m_caseFile, RefreshVdevState()) 529 .Times(::testing::AtMost(1)) 530 .WillRepeatedly(::testing::Return(true)); 531 532 for(int i=0; i<100; i++) { 533 stringstream evStringStream; 534 evStringStream << 535 "!system=ZFS " 536 "class=ereport.fs.zfs.delay " 537 "ena=12091638756982918145 " 538 "parent_guid=13237004955564865395 " 539 "parent_type=raidz " 540 "pool=testpool.4415 " 541 "pool_context=0 " 542 "pool_failmode=wait " 543 "pool_guid=456 " 544 "pool_state= 0" 545 "subsystem=ZFS " 546 "time="; 547 evStringStream << i << "0000000000000000 "; 548 evStringStream << "timestamp=" << i << " "; 549 evStringStream << 550 "type=ereport.fs.zfs.delay " 551 "vdev_ashift=12 " 552 "vdev_cksum_errors=0 " 553 "vdev_complete_ts=948336226469 " 554 "vdev_delays=77 " 555 "vdev_delta_ts=123998485899 " 556 "vdev_guid=123 " 557 "vdev_path=/dev/da400 " 558 "vdev_read_errors=0 " 559 "vdev_spare_guids= " 560 "vdev_type=disk " 561 "vdev_write_errors=0 " 562 "zio_blkid=622 " 563 "zio_delay=31000041101 " 564 "zio_delta=123998485899 " 565 "zio_err=0 " 566 "zio_flags=1572992 " 567 "zio_level=-2 " 568 "zio_object=0 " 569 "zio_objset=37 " 570 "zio_offset=25598976 " 571 "zio_pipeline=48234496 " 572 "zio_priority=3 " 573 "zio_size=1024" 574 "zio_stage=33554432 " 575 "zio_timestamp=824337740570 "; 576 Event *event(Event::CreateEvent(*m_eventFactory, 577 evStringStream.str())); 578 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event); 579 EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 580 delete event; 581 } 582 583 m_caseFile->SpliceEvents(); 584 EXPECT_FALSE(m_caseFile->ShouldDegrade()); 585 EXPECT_TRUE(m_caseFile->ShouldFault()); 586 } 587 588 /* 589 * A Vdev with a very large number of IO errors should fault 590 * For performance reasons, RefreshVdevState should be called at most once 591 */ 592 TEST_F(CaseFileTest, VeryManyIOErrors) 593 { 594 EXPECT_CALL(*m_caseFile, RefreshVdevState()) 595 .Times(::testing::AtMost(1)) 596 .WillRepeatedly(::testing::Return(true)); 597 598 for(int i=0; i<100; i++) { 599 stringstream evStringStream; 600 evStringStream << 601 "!system=ZFS " 602 "class=ereport.fs.zfs.io " 603 "ena=12091638756982918145 " 604 "parent_guid=13237004955564865395 " 605 "parent_type=raidz " 606 "pool=testpool.4415 " 607 "pool_context=0 " 608 "pool_failmode=wait " 609 "pool_guid=456 " 610 "subsystem=ZFS " 611 "timestamp="; 612 evStringStream << i << " "; 613 evStringStream << 614 "type=ereport.fs.zfs.io " 615 "vdev_guid=123 " 616 "vdev_path=/dev/da400 " 617 "vdev_type=disk " 618 "zio_blkid=622 " 619 "zio_err=1 " 620 "zio_level=-2 " 621 "zio_object=0 " 622 "zio_objset=37 " 623 "zio_offset=25598976 " 624 "zio_size=1024"; 625 Event *event(Event::CreateEvent(*m_eventFactory, 626 evStringStream.str())); 627 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event); 628 EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 629 delete event; 630 } 631 632 m_caseFile->SpliceEvents(); 633 EXPECT_FALSE(m_caseFile->ShouldDegrade()); 634 EXPECT_TRUE(m_caseFile->ShouldFault()); 635 } 636 637 /* 638 * A Vdev with a very large number of checksum errors should degrade 639 * For performance reasons, RefreshVdevState should be called at most once 640 */ 641 TEST_F(CaseFileTest, VeryManyChecksumErrors) 642 { 643 EXPECT_CALL(*m_caseFile, RefreshVdevState()) 644 .Times(::testing::AtMost(1)) 645 .WillRepeatedly(::testing::Return(true)); 646 647 for(int i=0; i<100; i++) { 648 stringstream evStringStream; 649 evStringStream << 650 "!system=ZFS " 651 "bad_cleared_bits=03000000000000803f50b00000000000 " 652 "bad_range_clears=0000000e " 653 "bad_range_sets=00000000 " 654 "bad_ranges=0000000000000010 " 655 "bad_ranges_min_gap=8 " 656 "bad_set_bits=00000000000000000000000000000000 " 657 "class=ereport.fs.zfs.checksum " 658 "ena=12272856582652437505 " 659 "parent_guid=5838204195352909894 " 660 "parent_type=raidz pool=testpool.7640 " 661 "pool_context=0 " 662 "pool_failmode=wait " 663 "pool_guid=456 " 664 "subsystem=ZFS timestamp="; 665 evStringStream << i << " "; 666 evStringStream << 667 "type=ereport.fs.zfs.checksum " 668 "vdev_guid=123 " 669 "vdev_path=/mnt/tmp/file1.7702 " 670 "vdev_type=file " 671 "zio_blkid=0 " 672 "zio_err=0 " 673 "zio_level=0 " 674 "zio_object=3 " 675 "zio_objset=0 " 676 "zio_offset=16896 " 677 "zio_size=512"; 678 Event *event(Event::CreateEvent(*m_eventFactory, 679 evStringStream.str())); 680 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event); 681 EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 682 delete event; 683 } 684 685 m_caseFile->SpliceEvents(); 686 EXPECT_TRUE(m_caseFile->ShouldDegrade()); 687 EXPECT_FALSE(m_caseFile->ShouldFault()); 688 } 689 690 /* 691 * Test CaseFile::ReEvaluateByGuid 692 */ 693 class ReEvaluateByGuidTest : public ::testing::Test 694 { 695 protected: 696 virtual void SetUp() 697 { 698 m_eventFactory = new EventFactory(); 699 m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords, 700 NUM_ELEMENTS(MockZfsEvent::s_buildRecords)); 701 m_event = Event::CreateEvent(*m_eventFactory, s_evString); 702 nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0); 703 ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, 704 ZPOOL_CONFIG_GUID, 0xbeef)); 705 m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig); 706 m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig); 707 ON_CALL(*m_vdev456, GUID()) 708 .WillByDefault(::testing::Return(Guid(123))); 709 ON_CALL(*m_vdev456, PoolGUID()) 710 .WillByDefault(::testing::Return(Guid(456))); 711 ON_CALL(*m_vdev456, State()) 712 .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY)); 713 ON_CALL(*m_vdev789, GUID()) 714 .WillByDefault(::testing::Return(Guid(123))); 715 ON_CALL(*m_vdev789, PoolGUID()) 716 .WillByDefault(::testing::Return(Guid(789))); 717 ON_CALL(*m_vdev789, State()) 718 .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY)); 719 m_caseFile456 = NULL; 720 m_caseFile789 = NULL; 721 return; 722 } 723 724 virtual void TearDown() 725 { 726 delete m_caseFile456; 727 delete m_caseFile789; 728 nvlist_free(m_vdevConfig); 729 delete m_vdev456; 730 delete m_vdev789; 731 delete m_event; 732 delete m_eventFactory; 733 } 734 735 static string s_evString; 736 nvlist_t *m_vdevConfig; 737 ::testing::NiceMock<MockVdev> *m_vdev456; 738 ::testing::NiceMock<MockVdev> *m_vdev789; 739 TestableCaseFile *m_caseFile456; 740 TestableCaseFile *m_caseFile789; 741 Event *m_event; 742 EventFactory *m_eventFactory; 743 }; 744 745 string ReEvaluateByGuidTest::s_evString( 746 "!system=ZFS " 747 "pool_guid=16271873792808333580 " 748 "pool_name=foo " 749 "subsystem=ZFS " 750 "timestamp=1360620391 " 751 "type=sysevent.fs.zfs.config_sync"); 752 753 754 /* 755 * Test the ReEvaluateByGuid method on an empty list of casefiles. 756 * We must create one event, even though it never gets used, because it will 757 * be passed by reference to ReEvaluateByGuid 758 */ 759 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty) 760 { 761 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 762 763 EXPECT_EQ(0, TestableCaseFile::getActiveCases()); 764 CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event); 765 EXPECT_EQ(0, TestableCaseFile::getActiveCases()); 766 } 767 768 /* 769 * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only 770 * one CaseFile, which doesn't match the criteria 771 */ 772 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse) 773 { 774 m_caseFile456 = &TestableCaseFile::Create(*m_vdev456); 775 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 776 777 EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 778 EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_)) 779 .Times(::testing::Exactly(0)); 780 CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event); 781 EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 782 } 783 784 /* 785 * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only 786 * one CaseFile, which does match the criteria 787 */ 788 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue) 789 { 790 m_caseFile456 = &TestableCaseFile::Create(*m_vdev456); 791 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 792 793 EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 794 EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_)) 795 .Times(::testing::Exactly(1)) 796 .WillRepeatedly(::testing::Return(false)); 797 CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event); 798 EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 799 } 800 801 /* 802 * Test the ReEvaluateByGuid method on a long list of CaseFiles that contains a 803 * few cases which meet the criteria 804 */ 805 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five) 806 { 807 TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456); 808 TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789); 809 TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456); 810 TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789); 811 TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789); 812 ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 813 814 EXPECT_EQ(5, TestableCaseFile::getActiveCases()); 815 EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_)) 816 .Times(::testing::Exactly(1)) 817 .WillRepeatedly(::testing::Return(false)); 818 EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_)) 819 .Times(::testing::Exactly(1)) 820 .WillRepeatedly(::testing::Return(false)); 821 EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_)) 822 .Times(::testing::Exactly(0)); 823 EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_)) 824 .Times(::testing::Exactly(0)); 825 EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_)) 826 .Times(::testing::Exactly(0)); 827 CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event); 828 EXPECT_EQ(5, TestableCaseFile::getActiveCases()); 829 delete CaseFile1; 830 delete CaseFile2; 831 delete CaseFile3; 832 delete CaseFile4; 833 delete CaseFile5; 834 } 835 836 /* 837 * Test VdevIterator 838 */ 839 class VdevIteratorTest : public ::testing::Test 840 { 841 }; 842 843 bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) { 844 return (false); 845 } 846 847 /* 848 * VdevIterator::Next should not crash when run on a pool that has a previously 849 * removed vdev. Regression for 850 * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273663 851 */ 852 TEST_F(VdevIteratorTest, VdevRemoval) 853 { 854 nvlist_t* poolConfig, *rootVdev; 855 856 ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0)); 857 ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678)); 858 /* 859 * Note: pools with previously-removed top-level VDEVs will contain a 860 * TLV in their labels that has 0 children. 861 */ 862 ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN, 863 NULL, 0)); 864 ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0)); 865 ASSERT_EQ(0, nvlist_add_uint64(poolConfig, 866 ZPOOL_CONFIG_POOL_GUID, 0x1234)); 867 ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE, 868 rootVdev)); 869 870 VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL); 871 } 872