1300906Sasomers/*- 2300906Sasomers * Copyright (c) 2012, 2013, 2014 Spectra Logic Corporation 3300906Sasomers * All rights reserved. 4300906Sasomers * 5300906Sasomers * Redistribution and use in source and binary forms, with or without 6300906Sasomers * modification, are permitted provided that the following conditions 7300906Sasomers * are met: 8300906Sasomers * 1. Redistributions of source code must retain the above copyright 9300906Sasomers * notice, this list of conditions, and the following disclaimer, 10300906Sasomers * without modification. 11300906Sasomers * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12300906Sasomers * substantially similar to the "NO WARRANTY" disclaimer below 13300906Sasomers * ("Disclaimer") and any redistribution must be conditioned upon 14300906Sasomers * including a substantially similar Disclaimer requirement for further 15300906Sasomers * binary redistribution. 16300906Sasomers * 17300906Sasomers * NO WARRANTY 18300906Sasomers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19300906Sasomers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20300906Sasomers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21300906Sasomers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22300906Sasomers * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23300906Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24300906Sasomers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25300906Sasomers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26300906Sasomers * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27300906Sasomers * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28300906Sasomers * POSSIBILITY OF SUCH DAMAGES. 29300906Sasomers * 30300906Sasomers * Authors: Alan Somers (Spectra Logic Corporation) 31300906Sasomers */ 32300906Sasomers#include <sys/cdefs.h> 33300906Sasomers 34300906Sasomers#include <stdarg.h> 35300906Sasomers#include <syslog.h> 36300906Sasomers 37300906Sasomers#include <libnvpair.h> 38300906Sasomers#include <libzfs.h> 39300906Sasomers 40300906Sasomers#include <list> 41300906Sasomers#include <map> 42300906Sasomers#include <sstream> 43300906Sasomers#include <string> 44300906Sasomers 45300906Sasomers#include <gmock/gmock.h> 46300906Sasomers#include <gtest/gtest.h> 47300906Sasomers 48300906Sasomers#include <devdctl/guid.h> 49300906Sasomers#include <devdctl/event.h> 50300906Sasomers#include <devdctl/event_factory.h> 51300906Sasomers#include <devdctl/exception.h> 52300906Sasomers#include <devdctl/consumer.h> 53300906Sasomers 54300906Sasomers#include <zfsd/callout.h> 55300906Sasomers#include <zfsd/vdev_iterator.h> 56300906Sasomers#include <zfsd/zfsd_event.h> 57300906Sasomers#include <zfsd/case_file.h> 58300906Sasomers#include <zfsd/vdev.h> 59300906Sasomers#include <zfsd/zfsd.h> 60300906Sasomers#include <zfsd/zfsd_exception.h> 61300906Sasomers#include <zfsd/zpool_list.h> 62300906Sasomers 63300906Sasomers#include "libmocks.h" 64300906Sasomers 65300906Sasomers__FBSDID("$FreeBSD: stable/11/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc 307108 2016-10-12 05:15:09Z mav $"); 66300906Sasomers 67300906Sasomers/*================================== Macros ==================================*/ 68300906Sasomers#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) 69300906Sasomers 70300906Sasomers/*============================ Namespace Control =============================*/ 71300906Sasomersusing std::string; 72300906Sasomersusing std::stringstream; 73300906Sasomers 74300906Sasomersusing DevdCtl::Event; 75300906Sasomersusing DevdCtl::EventFactory; 76300906Sasomersusing DevdCtl::EventList; 77300906Sasomersusing DevdCtl::Guid; 78300906Sasomersusing DevdCtl::NVPairMap; 79300906Sasomers 80300906Sasomers/* redefine zpool_handle here because libzfs_impl.h is not includable */ 81300906Sasomersstruct zpool_handle 82300906Sasomers{ 83300906Sasomers libzfs_handle_t *zpool_hdl; 84300906Sasomers zpool_handle_t *zpool_next; 85307108Smav char zpool_name[ZFS_MAX_DATASET_NAME_LEN]; 86300906Sasomers int zpool_state; 87300906Sasomers size_t zpool_config_size; 88300906Sasomers nvlist_t *zpool_config; 89300906Sasomers nvlist_t *zpool_old_config; 90300906Sasomers nvlist_t *zpool_props; 91300906Sasomers diskaddr_t zpool_start_block; 92300906Sasomers}; 93300906Sasomers 94300906Sasomersclass MockZfsEvent : public ZfsEvent 95300906Sasomers{ 96300906Sasomerspublic: 97300906Sasomers MockZfsEvent(Event::Type, NVPairMap&, const string&); 98300906Sasomers virtual ~MockZfsEvent() {} 99300906Sasomers 100300906Sasomers static BuildMethod MockZfsEventBuilder; 101300906Sasomers 102300906Sasomers MOCK_CONST_METHOD0(ProcessPoolEvent, void()); 103300906Sasomers 104300906Sasomers static EventFactory::Record s_buildRecords[]; 105300906Sasomers}; 106300906Sasomers 107300906SasomersEventFactory::Record MockZfsEvent::s_buildRecords[] = 108300906Sasomers{ 109300906Sasomers { Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder } 110300906Sasomers}; 111300906Sasomers 112300906SasomersMockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map, 113300906Sasomers const string& str) 114300906Sasomers : ZfsEvent(type, map, str) 115300906Sasomers{ 116300906Sasomers} 117300906Sasomers 118300906SasomersEvent * 119300906SasomersMockZfsEvent::MockZfsEventBuilder(Event::Type type, 120300906Sasomers NVPairMap &nvpairs, 121300906Sasomers const string &eventString) 122300906Sasomers{ 123300906Sasomers return (new MockZfsEvent(type, nvpairs, eventString)); 124300906Sasomers} 125300906Sasomers 126300906Sasomers/* 127300906Sasomers * A dummy Vdev class used for testing other classes 128300906Sasomers */ 129300906Sasomersclass MockVdev : public Vdev 130300906Sasomers{ 131300906Sasomerspublic: 132300906Sasomers MockVdev(nvlist_t *vdevConfig); 133300906Sasomers virtual ~MockVdev() {} 134300906Sasomers 135300906Sasomers MOCK_CONST_METHOD0(GUID, Guid()); 136300906Sasomers MOCK_CONST_METHOD0(PoolGUID, Guid()); 137300906Sasomers MOCK_CONST_METHOD0(State, vdev_state()); 138300906Sasomers MOCK_CONST_METHOD0(PhysicalPath, string()); 139300906Sasomers}; 140300906Sasomers 141300906SasomersMockVdev::MockVdev(nvlist_t *vdevConfig) 142300906Sasomers : Vdev(vdevConfig) 143300906Sasomers{ 144300906Sasomers} 145300906Sasomers 146300906Sasomers/* 147300906Sasomers * A CaseFile class with side effects removed, for testing 148300906Sasomers */ 149300906Sasomersclass TestableCaseFile : public CaseFile 150300906Sasomers{ 151300906Sasomerspublic: 152300906Sasomers static TestableCaseFile &Create(Vdev &vdev); 153300906Sasomers TestableCaseFile(Vdev &vdev); 154300906Sasomers virtual ~TestableCaseFile() {} 155300906Sasomers 156300906Sasomers MOCK_METHOD0(Close, void()); 157300906Sasomers MOCK_METHOD1(RegisterCallout, void(const Event &event)); 158300906Sasomers MOCK_METHOD0(RefreshVdevState, bool()); 159300906Sasomers MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event)); 160300906Sasomers 161300906Sasomers bool RealReEvaluate(const ZfsEvent &event) 162300906Sasomers { 163300906Sasomers return (CaseFile::ReEvaluate(event)); 164300906Sasomers } 165300906Sasomers 166300906Sasomers /* 167300906Sasomers * This splices the event lists, a procedure that would normally be done 168300906Sasomers * by OnGracePeriodEnded, but we don't necessarily call that in the 169300906Sasomers * unit tests 170300906Sasomers */ 171300906Sasomers void SpliceEvents(); 172300906Sasomers 173300906Sasomers /* 174300906Sasomers * Used by some of our expectations. CaseFile does not publicize this 175300906Sasomers */ 176300906Sasomers static int getActiveCases() 177300906Sasomers { 178300906Sasomers return (s_activeCases.size()); 179300906Sasomers } 180300906Sasomers}; 181300906Sasomers 182300906SasomersTestableCaseFile::TestableCaseFile(Vdev &vdev) 183300906Sasomers : CaseFile(vdev) 184300906Sasomers{ 185300906Sasomers} 186300906Sasomers 187300906SasomersTestableCaseFile & 188300906SasomersTestableCaseFile::Create(Vdev &vdev) 189300906Sasomers{ 190300906Sasomers TestableCaseFile *newCase; 191300906Sasomers newCase = new TestableCaseFile(vdev); 192300906Sasomers return (*newCase); 193300906Sasomers} 194300906Sasomers 195300906Sasomersvoid 196300906SasomersTestableCaseFile::SpliceEvents() 197300906Sasomers{ 198300906Sasomers m_events.splice(m_events.begin(), m_tentativeEvents); 199300906Sasomers} 200300906Sasomers 201300906Sasomers 202300906Sasomers/* 203300906Sasomers * Test class ZfsdException 204300906Sasomers */ 205300906Sasomersclass ZfsdExceptionTest : public ::testing::Test 206300906Sasomers{ 207300906Sasomersprotected: 208300906Sasomers virtual void SetUp() 209300906Sasomers { 210300906Sasomers ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0)); 211300906Sasomers ASSERT_EQ(0, nvlist_add_string(poolConfig, 212300906Sasomers ZPOOL_CONFIG_POOL_NAME, "unit_test_pool")); 213300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(poolConfig, 214300906Sasomers ZPOOL_CONFIG_POOL_GUID, 0x1234)); 215300906Sasomers 216300906Sasomers ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0)); 217300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(vdevConfig, 218300906Sasomers ZPOOL_CONFIG_GUID, 0x5678)); 219300906Sasomers bzero(&poolHandle, sizeof(poolHandle)); 220300906Sasomers poolHandle.zpool_config = poolConfig; 221300906Sasomers } 222300906Sasomers 223300906Sasomers virtual void TearDown() 224300906Sasomers { 225300906Sasomers nvlist_free(poolConfig); 226300906Sasomers nvlist_free(vdevConfig); 227300906Sasomers } 228300906Sasomers 229300906Sasomers nvlist_t *poolConfig; 230300906Sasomers nvlist_t *vdevConfig; 231300906Sasomers zpool_handle_t poolHandle; 232300906Sasomers}; 233300906Sasomers 234300906SasomersTEST_F(ZfsdExceptionTest, StringConstructorNull) 235300906Sasomers{ 236300906Sasomers ZfsdException ze(""); 237300906Sasomers EXPECT_STREQ("", ze.GetString().c_str()); 238300906Sasomers} 239300906Sasomers 240300906SasomersTEST_F(ZfsdExceptionTest, StringConstructorFormatted) 241300906Sasomers{ 242300906Sasomers ZfsdException ze(" %d %s", 55, "hello world"); 243300906Sasomers EXPECT_STREQ(" 55 hello world", ze.GetString().c_str()); 244300906Sasomers} 245300906Sasomers 246300906SasomersTEST_F(ZfsdExceptionTest, LogSimple) 247300906Sasomers{ 248300906Sasomers ZfsdException ze("unit test w/o vdev or pool"); 249300906Sasomers ze.Log(); 250300906Sasomers EXPECT_EQ(LOG_ERR, syslog_last_priority); 251300906Sasomers EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message); 252300906Sasomers} 253300906Sasomers 254300906SasomersTEST_F(ZfsdExceptionTest, Pool) 255300906Sasomers{ 256300906Sasomers const char msg[] = "Exception with pool name"; 257300906Sasomers char expected[4096]; 258300906Sasomers sprintf(expected, "Pool unit_test_pool: %s\n", msg); 259300906Sasomers ZfsdException ze(poolConfig, msg); 260300906Sasomers ze.Log(); 261300906Sasomers EXPECT_STREQ(expected, syslog_last_message); 262300906Sasomers} 263300906Sasomers 264300906SasomersTEST_F(ZfsdExceptionTest, PoolHandle) 265300906Sasomers{ 266300906Sasomers const char msg[] = "Exception with pool handle"; 267300906Sasomers char expected[4096]; 268300906Sasomers sprintf(expected, "Pool unit_test_pool: %s\n", msg); 269300906Sasomers ZfsdException ze(&poolHandle, msg); 270300906Sasomers ze.Log(); 271300906Sasomers EXPECT_STREQ(expected, syslog_last_message); 272300906Sasomers} 273300906Sasomers 274300906Sasomers/* 275300906Sasomers * Test class Vdev 276300906Sasomers */ 277300906Sasomersclass VdevTest : public ::testing::Test 278300906Sasomers{ 279300906Sasomersprotected: 280300906Sasomers virtual void SetUp() 281300906Sasomers { 282300906Sasomers ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0)); 283300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig, 284300906Sasomers ZPOOL_CONFIG_POOL_GUID, 285300906Sasomers 0x1234)); 286300906Sasomers 287300906Sasomers ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0)); 288300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID, 289300906Sasomers 0x5678)); 290300906Sasomers } 291300906Sasomers 292300906Sasomers virtual void TearDown() 293300906Sasomers { 294300906Sasomers nvlist_free(m_poolConfig); 295300906Sasomers nvlist_free(m_vdevConfig); 296300906Sasomers } 297300906Sasomers 298300906Sasomers nvlist_t *m_poolConfig; 299300906Sasomers nvlist_t *m_vdevConfig; 300300906Sasomers}; 301300906Sasomers 302300906Sasomers 303300906SasomersTEST_F(VdevTest, StateFromConfig) 304300906Sasomers{ 305300906Sasomers vdev_stat_t vs; 306300906Sasomers 307300906Sasomers vs.vs_state = VDEV_STATE_OFFLINE; 308300906Sasomers 309300906Sasomers ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig, 310300906Sasomers ZPOOL_CONFIG_VDEV_STATS, 311300906Sasomers (uint64_t*)&vs, 312300906Sasomers sizeof(vs) / sizeof(uint64_t))); 313300906Sasomers 314300906Sasomers Vdev vdev(m_poolConfig, m_vdevConfig); 315300906Sasomers 316300906Sasomers EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State()); 317300906Sasomers} 318300906Sasomers 319300906SasomersTEST_F(VdevTest, StateFaulted) 320300906Sasomers{ 321300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1)); 322300906Sasomers 323300906Sasomers Vdev vdev(m_poolConfig, m_vdevConfig); 324300906Sasomers 325300906Sasomers EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State()); 326300906Sasomers} 327300906Sasomers 328300906Sasomers/* 329300906Sasomers * Test that we can construct a Vdev from the label information that is stored 330300906Sasomers * on an available spare drive 331300906Sasomers */ 332300906SasomersTEST_F(VdevTest, ConstructAvailSpare) 333300906Sasomers{ 334300906Sasomers nvlist_t *labelConfig; 335300906Sasomers 336300906Sasomers ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0)); 337300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID, 338300906Sasomers 1948339428197961030)); 339300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE, 340300906Sasomers POOL_STATE_SPARE)); 341300906Sasomers 342300906Sasomers EXPECT_NO_THROW(Vdev vdev(labelConfig)); 343300906Sasomers 344300906Sasomers nvlist_free(labelConfig); 345300906Sasomers} 346300906Sasomers 347300906Sasomers/* Available spares will always show the HEALTHY state */ 348300906SasomersTEST_F(VdevTest, AvailSpareState) { 349300906Sasomers nvlist_t *labelConfig; 350300906Sasomers 351300906Sasomers ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0)); 352300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID, 353300906Sasomers 1948339428197961030)); 354300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE, 355300906Sasomers POOL_STATE_SPARE)); 356300906Sasomers 357300906Sasomers Vdev vdev(labelConfig); 358300906Sasomers EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State()); 359300906Sasomers 360300906Sasomers nvlist_free(labelConfig); 361300906Sasomers} 362300906Sasomers 363300906Sasomers/* Test the Vdev::IsSpare method */ 364300906SasomersTEST_F(VdevTest, IsSpare) { 365300906Sasomers Vdev notSpare(m_poolConfig, m_vdevConfig); 366300906Sasomers EXPECT_EQ(false, notSpare.IsSpare()); 367300906Sasomers 368300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1)); 369300906Sasomers Vdev isSpare(m_poolConfig, m_vdevConfig); 370300906Sasomers EXPECT_EQ(true, isSpare.IsSpare()); 371300906Sasomers} 372300906Sasomers 373300906Sasomers/* 374300906Sasomers * Test class ZFSEvent 375300906Sasomers */ 376300906Sasomersclass ZfsEventTest : public ::testing::Test 377300906Sasomers{ 378300906Sasomersprotected: 379300906Sasomers virtual void SetUp() 380300906Sasomers { 381300906Sasomers m_eventFactory = new EventFactory(); 382300906Sasomers m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords, 383300906Sasomers NUM_ELEMENTS(MockZfsEvent::s_buildRecords)); 384300906Sasomers 385300906Sasomers m_event = NULL; 386300906Sasomers } 387300906Sasomers 388300906Sasomers virtual void TearDown() 389300906Sasomers { 390300906Sasomers delete m_eventFactory; 391300906Sasomers delete m_event; 392300906Sasomers } 393300906Sasomers 394300906Sasomers EventFactory *m_eventFactory; 395300906Sasomers Event *m_event; 396300906Sasomers}; 397300906Sasomers 398300906SasomersTEST_F(ZfsEventTest, ProcessPoolEventGetsCalled) 399300906Sasomers{ 400300906Sasomers string evString("!system=ZFS " 401300906Sasomers "subsystem=ZFS " 402300906Sasomers "type=misc.fs.zfs.vdev_remove " 403300906Sasomers "pool_name=foo " 404300906Sasomers "pool_guid=9756779504028057996 " 405300906Sasomers "vdev_guid=1631193447431603339 " 406300906Sasomers "vdev_path=/dev/da1 " 407300906Sasomers "timestamp=1348871594"); 408300906Sasomers m_event = Event::CreateEvent(*m_eventFactory, evString); 409300906Sasomers MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event); 410300906Sasomers 411300906Sasomers EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1); 412300906Sasomers mock_event->Process(); 413300906Sasomers} 414300906Sasomers 415300906Sasomers/* 416300906Sasomers * Test class CaseFile 417300906Sasomers */ 418300906Sasomers 419300906Sasomersclass CaseFileTest : public ::testing::Test 420300906Sasomers{ 421300906Sasomersprotected: 422300906Sasomers virtual void SetUp() 423300906Sasomers { 424300906Sasomers m_eventFactory = new EventFactory(); 425300906Sasomers m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords, 426300906Sasomers NUM_ELEMENTS(MockZfsEvent::s_buildRecords)); 427300906Sasomers 428300906Sasomers m_event = NULL; 429300906Sasomers 430300906Sasomers nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0); 431300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, 432300906Sasomers ZPOOL_CONFIG_GUID, 0xbeef)); 433300906Sasomers m_vdev = new MockVdev(m_vdevConfig); 434300906Sasomers ON_CALL(*m_vdev, GUID()) 435300906Sasomers .WillByDefault(::testing::Return(Guid(123))); 436300906Sasomers ON_CALL(*m_vdev, PoolGUID()) 437300906Sasomers .WillByDefault(::testing::Return(Guid(456))); 438300906Sasomers ON_CALL(*m_vdev, State()) 439300906Sasomers .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY)); 440300906Sasomers m_caseFile = &TestableCaseFile::Create(*m_vdev); 441300906Sasomers ON_CALL(*m_caseFile, ReEvaluate(::testing::_)) 442300906Sasomers .WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate)); 443300906Sasomers return; 444300906Sasomers } 445300906Sasomers 446300906Sasomers virtual void TearDown() 447300906Sasomers { 448300906Sasomers delete m_caseFile; 449300906Sasomers nvlist_free(m_vdevConfig); 450300906Sasomers delete m_vdev; 451300906Sasomers delete m_event; 452300906Sasomers delete m_eventFactory; 453300906Sasomers } 454300906Sasomers 455300906Sasomers nvlist_t *m_vdevConfig; 456300906Sasomers MockVdev *m_vdev; 457300906Sasomers TestableCaseFile *m_caseFile; 458300906Sasomers Event *m_event; 459300906Sasomers EventFactory *m_eventFactory; 460300906Sasomers}; 461300906Sasomers 462300906Sasomers/* 463300906Sasomers * A Vdev with no events should not be degraded or faulted 464300906Sasomers */ 465300906SasomersTEST_F(CaseFileTest, HealthyVdev) 466300906Sasomers{ 467300906Sasomers EXPECT_FALSE(m_caseFile->ShouldDegrade()); 468300906Sasomers EXPECT_FALSE(m_caseFile->ShouldFault()); 469300906Sasomers} 470300906Sasomers 471300906Sasomers/* 472300906Sasomers * A Vdev with only one event should not be degraded or faulted 473300906Sasomers * For performance reasons, RefreshVdevState should not be called. 474300906Sasomers */ 475300906SasomersTEST_F(CaseFileTest, HealthyishVdev) 476300906Sasomers{ 477300906Sasomers string evString("!system=ZFS " 478300906Sasomers "class=ereport.fs.zfs.io " 479300906Sasomers "ena=12091638756982918145 " 480300906Sasomers "parent_guid=13237004955564865395 " 481300906Sasomers "parent_type=raidz " 482300906Sasomers "pool=testpool.4415 " 483300906Sasomers "pool_context=0 " 484300906Sasomers "pool_failmode=wait " 485300906Sasomers "pool_guid=456 " 486300906Sasomers "subsystem=ZFS " 487300906Sasomers "timestamp=1348867914 " 488300906Sasomers "type=ereport.fs.zfs.io " 489300906Sasomers "vdev_guid=123 " 490300906Sasomers "vdev_path=/dev/da400 " 491300906Sasomers "vdev_type=disk " 492300906Sasomers "zio_blkid=622 " 493300906Sasomers "zio_err=1 " 494300906Sasomers "zio_level=-2 " 495300906Sasomers "zio_object=0 " 496300906Sasomers "zio_objset=37 " 497300906Sasomers "zio_offset=25598976 " 498300906Sasomers "zio_size=1024"); 499300906Sasomers m_event = Event::CreateEvent(*m_eventFactory, evString); 500300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 501300906Sasomers 502300906Sasomers EXPECT_CALL(*m_caseFile, RefreshVdevState()) 503300906Sasomers .Times(::testing::Exactly(0)); 504300906Sasomers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 505300906Sasomers EXPECT_FALSE(m_caseFile->ShouldDegrade()); 506300906Sasomers EXPECT_FALSE(m_caseFile->ShouldFault()); 507300906Sasomers} 508300906Sasomers 509300906Sasomers/* The case file should be closed when its pool is destroyed */ 510300906SasomersTEST_F(CaseFileTest, PoolDestroy) 511300906Sasomers{ 512300906Sasomers string evString("!system=ZFS " 513300906Sasomers "pool_name=testpool.4415 " 514300906Sasomers "pool_guid=456 " 515300906Sasomers "subsystem=ZFS " 516300906Sasomers "timestamp=1348867914 " 517300906Sasomers "type=misc.fs.zfs.pool_destroy "); 518300906Sasomers m_event = Event::CreateEvent(*m_eventFactory, evString); 519300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 520300906Sasomers EXPECT_CALL(*m_caseFile, Close()); 521300906Sasomers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 522300906Sasomers} 523300906Sasomers 524300906Sasomers/* 525300906Sasomers * A Vdev with a very large number of IO errors should fault 526300906Sasomers * For performance reasons, RefreshVdevState should be called at most once 527300906Sasomers */ 528300906SasomersTEST_F(CaseFileTest, VeryManyIOErrors) 529300906Sasomers{ 530300906Sasomers EXPECT_CALL(*m_caseFile, RefreshVdevState()) 531300906Sasomers .Times(::testing::AtMost(1)) 532300906Sasomers .WillRepeatedly(::testing::Return(true)); 533300906Sasomers 534300906Sasomers for(int i=0; i<100; i++) { 535300906Sasomers stringstream evStringStream; 536300906Sasomers evStringStream << 537300906Sasomers "!system=ZFS " 538300906Sasomers "class=ereport.fs.zfs.io " 539300906Sasomers "ena=12091638756982918145 " 540300906Sasomers "parent_guid=13237004955564865395 " 541300906Sasomers "parent_type=raidz " 542300906Sasomers "pool=testpool.4415 " 543300906Sasomers "pool_context=0 " 544300906Sasomers "pool_failmode=wait " 545300906Sasomers "pool_guid=456 " 546300906Sasomers "subsystem=ZFS " 547300906Sasomers "timestamp="; 548300906Sasomers evStringStream << i << " "; 549300906Sasomers evStringStream << 550300906Sasomers "type=ereport.fs.zfs.io " 551300906Sasomers "vdev_guid=123 " 552300906Sasomers "vdev_path=/dev/da400 " 553300906Sasomers "vdev_type=disk " 554300906Sasomers "zio_blkid=622 " 555300906Sasomers "zio_err=1 " 556300906Sasomers "zio_level=-2 " 557300906Sasomers "zio_object=0 " 558300906Sasomers "zio_objset=37 " 559300906Sasomers "zio_offset=25598976 " 560300906Sasomers "zio_size=1024"; 561300906Sasomers Event *event(Event::CreateEvent(*m_eventFactory, 562300906Sasomers evStringStream.str())); 563300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event); 564300906Sasomers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 565300906Sasomers delete event; 566300906Sasomers } 567300906Sasomers 568300906Sasomers m_caseFile->SpliceEvents(); 569300906Sasomers EXPECT_FALSE(m_caseFile->ShouldDegrade()); 570300906Sasomers EXPECT_TRUE(m_caseFile->ShouldFault()); 571300906Sasomers} 572300906Sasomers 573300906Sasomers/* 574300906Sasomers * A Vdev with a very large number of checksum errors should degrade 575300906Sasomers * For performance reasons, RefreshVdevState should be called at most once 576300906Sasomers */ 577300906SasomersTEST_F(CaseFileTest, VeryManyChecksumErrors) 578300906Sasomers{ 579300906Sasomers EXPECT_CALL(*m_caseFile, RefreshVdevState()) 580300906Sasomers .Times(::testing::AtMost(1)) 581300906Sasomers .WillRepeatedly(::testing::Return(true)); 582300906Sasomers 583300906Sasomers for(int i=0; i<100; i++) { 584300906Sasomers stringstream evStringStream; 585300906Sasomers evStringStream << 586300906Sasomers "!system=ZFS " 587300906Sasomers "bad_cleared_bits=03000000000000803f50b00000000000 " 588300906Sasomers "bad_range_clears=0000000e " 589300906Sasomers "bad_range_sets=00000000 " 590300906Sasomers "bad_ranges=0000000000000010 " 591300906Sasomers "bad_ranges_min_gap=8 " 592300906Sasomers "bad_set_bits=00000000000000000000000000000000 " 593300906Sasomers "class=ereport.fs.zfs.checksum " 594300906Sasomers "ena=12272856582652437505 " 595300906Sasomers "parent_guid=5838204195352909894 " 596300906Sasomers "parent_type=raidz pool=testpool.7640 " 597300906Sasomers "pool_context=0 " 598300906Sasomers "pool_failmode=wait " 599300906Sasomers "pool_guid=456 " 600300906Sasomers "subsystem=ZFS timestamp="; 601300906Sasomers evStringStream << i << " "; 602300906Sasomers evStringStream << 603300906Sasomers "type=ereport.fs.zfs.checksum " 604300906Sasomers "vdev_guid=123 " 605300906Sasomers "vdev_path=/mnt/tmp/file1.7702 " 606300906Sasomers "vdev_type=file " 607300906Sasomers "zio_blkid=0 " 608300906Sasomers "zio_err=0 " 609300906Sasomers "zio_level=0 " 610300906Sasomers "zio_object=3 " 611300906Sasomers "zio_objset=0 " 612300906Sasomers "zio_offset=16896 " 613300906Sasomers "zio_size=512"; 614300906Sasomers Event *event(Event::CreateEvent(*m_eventFactory, 615300906Sasomers evStringStream.str())); 616300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event); 617300906Sasomers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event)); 618300906Sasomers delete event; 619300906Sasomers } 620300906Sasomers 621300906Sasomers m_caseFile->SpliceEvents(); 622300906Sasomers EXPECT_TRUE(m_caseFile->ShouldDegrade()); 623300906Sasomers EXPECT_FALSE(m_caseFile->ShouldFault()); 624300906Sasomers} 625300906Sasomers 626300906Sasomers/* 627300906Sasomers * Test CaseFile::ReEvaluateByGuid 628300906Sasomers */ 629300906Sasomersclass ReEvaluateByGuidTest : public ::testing::Test 630300906Sasomers{ 631300906Sasomersprotected: 632300906Sasomers virtual void SetUp() 633300906Sasomers { 634300906Sasomers m_eventFactory = new EventFactory(); 635300906Sasomers m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords, 636300906Sasomers NUM_ELEMENTS(MockZfsEvent::s_buildRecords)); 637300906Sasomers m_event = Event::CreateEvent(*m_eventFactory, s_evString); 638300906Sasomers nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0); 639300906Sasomers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, 640300906Sasomers ZPOOL_CONFIG_GUID, 0xbeef)); 641300906Sasomers m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig); 642300906Sasomers m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig); 643300906Sasomers ON_CALL(*m_vdev456, GUID()) 644300906Sasomers .WillByDefault(::testing::Return(Guid(123))); 645300906Sasomers ON_CALL(*m_vdev456, PoolGUID()) 646300906Sasomers .WillByDefault(::testing::Return(Guid(456))); 647300906Sasomers ON_CALL(*m_vdev456, State()) 648300906Sasomers .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY)); 649300906Sasomers ON_CALL(*m_vdev789, GUID()) 650300906Sasomers .WillByDefault(::testing::Return(Guid(123))); 651300906Sasomers ON_CALL(*m_vdev789, PoolGUID()) 652300906Sasomers .WillByDefault(::testing::Return(Guid(789))); 653300906Sasomers ON_CALL(*m_vdev789, State()) 654300906Sasomers .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY)); 655300906Sasomers m_caseFile456 = NULL; 656300906Sasomers m_caseFile789 = NULL; 657300906Sasomers return; 658300906Sasomers } 659300906Sasomers 660300906Sasomers virtual void TearDown() 661300906Sasomers { 662300906Sasomers delete m_caseFile456; 663300906Sasomers delete m_caseFile789; 664300906Sasomers nvlist_free(m_vdevConfig); 665300906Sasomers delete m_vdev456; 666300906Sasomers delete m_vdev789; 667300906Sasomers delete m_event; 668300906Sasomers delete m_eventFactory; 669300906Sasomers } 670300906Sasomers 671300906Sasomers static string s_evString; 672300906Sasomers nvlist_t *m_vdevConfig; 673300906Sasomers ::testing::NiceMock<MockVdev> *m_vdev456; 674300906Sasomers ::testing::NiceMock<MockVdev> *m_vdev789; 675300906Sasomers TestableCaseFile *m_caseFile456; 676300906Sasomers TestableCaseFile *m_caseFile789; 677300906Sasomers Event *m_event; 678300906Sasomers EventFactory *m_eventFactory; 679300906Sasomers}; 680300906Sasomers 681300906Sasomersstring ReEvaluateByGuidTest::s_evString( 682300906Sasomers "!system=ZFS " 683300906Sasomers "pool_guid=16271873792808333580 " 684300906Sasomers "pool_name=foo " 685300906Sasomers "subsystem=ZFS " 686300906Sasomers "timestamp=1360620391 " 687300906Sasomers "type=misc.fs.zfs.config_sync"); 688300906Sasomers 689300906Sasomers 690300906Sasomers/* 691300906Sasomers * Test the ReEvaluateByGuid method on an empty list of casefiles. 692300906Sasomers * We must create one event, even though it never gets used, because it will 693300906Sasomers * be passed by reference to ReEvaluateByGuid 694300906Sasomers */ 695300906SasomersTEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty) 696300906Sasomers{ 697300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 698300906Sasomers 699300906Sasomers EXPECT_EQ(0, TestableCaseFile::getActiveCases()); 700300906Sasomers CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event); 701300906Sasomers EXPECT_EQ(0, TestableCaseFile::getActiveCases()); 702300906Sasomers} 703300906Sasomers 704300906Sasomers/* 705300906Sasomers * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only 706300906Sasomers * one CaseFile, which doesn't match the criteria 707300906Sasomers */ 708300906SasomersTEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse) 709300906Sasomers{ 710300906Sasomers m_caseFile456 = &TestableCaseFile::Create(*m_vdev456); 711300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 712300906Sasomers 713300906Sasomers EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 714300906Sasomers EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_)) 715300906Sasomers .Times(::testing::Exactly(0)); 716300906Sasomers CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event); 717300906Sasomers EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 718300906Sasomers} 719300906Sasomers 720300906Sasomers/* 721300906Sasomers * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only 722300906Sasomers * one CaseFile, which does match the criteria 723300906Sasomers */ 724300906SasomersTEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue) 725300906Sasomers{ 726300906Sasomers m_caseFile456 = &TestableCaseFile::Create(*m_vdev456); 727300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 728300906Sasomers 729300906Sasomers EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 730300906Sasomers EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_)) 731300906Sasomers .Times(::testing::Exactly(1)) 732300906Sasomers .WillRepeatedly(::testing::Return(false)); 733300906Sasomers CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event); 734300906Sasomers EXPECT_EQ(1, TestableCaseFile::getActiveCases()); 735300906Sasomers} 736300906Sasomers 737300906Sasomers/* 738300906Sasomers * Test the ReEvaluateByGuid method on a long list of CaseFiles that contains a 739300906Sasomers * few cases which meet the criteria 740300906Sasomers */ 741300906SasomersTEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five) 742300906Sasomers{ 743300906Sasomers TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456); 744300906Sasomers TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789); 745300906Sasomers TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456); 746300906Sasomers TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789); 747300906Sasomers TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789); 748300906Sasomers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event); 749300906Sasomers 750300906Sasomers EXPECT_EQ(5, TestableCaseFile::getActiveCases()); 751300906Sasomers EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_)) 752300906Sasomers .Times(::testing::Exactly(1)) 753300906Sasomers .WillRepeatedly(::testing::Return(false)); 754300906Sasomers EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_)) 755300906Sasomers .Times(::testing::Exactly(1)) 756300906Sasomers .WillRepeatedly(::testing::Return(false)); 757300906Sasomers EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_)) 758300906Sasomers .Times(::testing::Exactly(0)); 759300906Sasomers EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_)) 760300906Sasomers .Times(::testing::Exactly(0)); 761300906Sasomers EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_)) 762300906Sasomers .Times(::testing::Exactly(0)); 763300906Sasomers CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event); 764300906Sasomers EXPECT_EQ(5, TestableCaseFile::getActiveCases()); 765300906Sasomers delete CaseFile1; 766300906Sasomers delete CaseFile2; 767300906Sasomers delete CaseFile3; 768300906Sasomers delete CaseFile4; 769300906Sasomers delete CaseFile5; 770300906Sasomers} 771