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