#include <sys/cdefs.h>
#include <sys/byteorder.h>
#include <stdarg.h>
#include <syslog.h>
#include <libnvpair.h>
#include <libzfs.h>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <devdctl/guid.h>
#include <devdctl/event.h>
#include <devdctl/event_factory.h>
#include <devdctl/exception.h>
#include <devdctl/consumer.h>
#include <zfsd/callout.h>
#include <zfsd/vdev_iterator.h>
#include <zfsd/zfsd_event.h>
#include <zfsd/case_file.h>
#include <zfsd/vdev.h>
#include <zfsd/zfsd.h>
#include <zfsd/zfsd_exception.h>
#include <zfsd/zpool_list.h>
#include "libmocks.h"
#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
using std::string;
using std::stringstream;
using DevdCtl::Event;
using DevdCtl::EventFactory;
using DevdCtl::EventList;
using DevdCtl::Guid;
using DevdCtl::NVPairMap;
struct zpool_handle
{
libzfs_handle_t *zpool_hdl;
zpool_handle_t *zpool_next;
char zpool_name[ZFS_MAX_DATASET_NAME_LEN];
int zpool_state;
unsigned int zpool_n_propnames;
#define ZHP_MAX_PROPNAMES 4
const char *zpool_propnames[ZHP_MAX_PROPNAMES];
size_t zpool_config_size;
nvlist_t *zpool_config;
nvlist_t *zpool_old_config;
nvlist_t *zpool_props;
diskaddr_t zpool_start_block;
};
class MockZfsEvent : public ZfsEvent
{
public:
MockZfsEvent(Event::Type, NVPairMap&, const string&);
virtual ~MockZfsEvent() {}
static BuildMethod MockZfsEventBuilder;
MOCK_CONST_METHOD0(ProcessPoolEvent, void());
static EventFactory::Record s_buildRecords[];
};
EventFactory::Record MockZfsEvent::s_buildRecords[] =
{
{ Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder }
};
MockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map,
const string& str)
: ZfsEvent(type, map, str)
{
}
Event *
MockZfsEvent::MockZfsEventBuilder(Event::Type type,
NVPairMap &nvpairs,
const string &eventString)
{
return (new MockZfsEvent(type, nvpairs, eventString));
}
class MockVdev : public Vdev
{
public:
MockVdev(nvlist_t *vdevConfig);
virtual ~MockVdev() {}
MOCK_CONST_METHOD0(GUID, Guid());
MOCK_CONST_METHOD0(PoolGUID, Guid());
MOCK_CONST_METHOD0(State, vdev_state());
MOCK_CONST_METHOD0(PhysicalPath, string());
MOCK_CONST_METHOD2(Name, string(zpool_handle_t * zhp, bool verbose));
};
MockVdev::MockVdev(nvlist_t *vdevConfig)
: Vdev(vdevConfig)
{
}
class TestableCaseFile : public CaseFile
{
public:
static TestableCaseFile &Create(Vdev &vdev);
TestableCaseFile(Vdev &vdev);
virtual ~TestableCaseFile() {}
MOCK_METHOD0(Close, void());
MOCK_METHOD1(RegisterCallout, void(const Event &event));
MOCK_METHOD0(RefreshVdevState, bool());
MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event));
bool RealReEvaluate(const ZfsEvent &event)
{
return (CaseFile::ReEvaluate(event));
}
void SpliceEvents();
static int getActiveCases()
{
return (s_activeCases.size());
}
};
TestableCaseFile::TestableCaseFile(Vdev &vdev)
: CaseFile(vdev)
{
}
TestableCaseFile &
TestableCaseFile::Create(Vdev &vdev)
{
TestableCaseFile *newCase;
newCase = new TestableCaseFile(vdev);
return (*newCase);
}
void
TestableCaseFile::SpliceEvents()
{
m_events.splice(m_events.begin(), m_tentativeEvents);
}
class ZfsdExceptionTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_string(poolConfig,
ZPOOL_CONFIG_POOL_NAME, "unit_test_pool"));
ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
ZPOOL_CONFIG_POOL_GUID, 0x1234));
ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(vdevConfig,
ZPOOL_CONFIG_GUID, 0x5678));
bzero(&poolHandle, sizeof(poolHandle));
poolHandle.zpool_config = poolConfig;
}
virtual void TearDown()
{
nvlist_free(poolConfig);
nvlist_free(vdevConfig);
}
nvlist_t *poolConfig;
nvlist_t *vdevConfig;
zpool_handle_t poolHandle;
};
TEST_F(ZfsdExceptionTest, StringConstructorNull)
{
ZfsdException ze("");
EXPECT_STREQ("", ze.GetString().c_str());
}
TEST_F(ZfsdExceptionTest, StringConstructorFormatted)
{
ZfsdException ze(" %d %s", 55, "hello world");
EXPECT_STREQ(" 55 hello world", ze.GetString().c_str());
}
TEST_F(ZfsdExceptionTest, LogSimple)
{
ZfsdException ze("unit test w/o vdev or pool");
ze.Log();
EXPECT_EQ(LOG_ERR, syslog_last_priority);
EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message);
}
TEST_F(ZfsdExceptionTest, Pool)
{
const char msg[] = "Exception with pool name";
char expected[4096];
sprintf(expected, "Pool unit_test_pool: %s\n", msg);
ZfsdException ze(poolConfig, msg);
ze.Log();
EXPECT_STREQ(expected, syslog_last_message);
}
TEST_F(ZfsdExceptionTest, PoolHandle)
{
const char msg[] = "Exception with pool handle";
char expected[4096];
sprintf(expected, "Pool unit_test_pool: %s\n", msg);
ZfsdException ze(&poolHandle, msg);
ze.Log();
EXPECT_STREQ(expected, syslog_last_message);
}
class VdevTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig,
ZPOOL_CONFIG_POOL_GUID,
0x1234));
ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID,
0x5678));
}
virtual void TearDown()
{
nvlist_free(m_poolConfig);
nvlist_free(m_vdevConfig);
}
nvlist_t *m_poolConfig;
nvlist_t *m_vdevConfig;
};
TEST_F(VdevTest, StateFromConfig)
{
vdev_stat_t vs;
vs.vs_state = VDEV_STATE_OFFLINE;
ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig,
ZPOOL_CONFIG_VDEV_STATS,
(uint64_t*)&vs,
sizeof(vs) / sizeof(uint64_t)));
Vdev vdev(m_poolConfig, m_vdevConfig);
EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State());
}
TEST_F(VdevTest, StateFaulted)
{
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1));
Vdev vdev(m_poolConfig, m_vdevConfig);
EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State());
}
TEST_F(VdevTest, ConstructAvailSpare)
{
nvlist_t *labelConfig;
ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
1948339428197961030));
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
POOL_STATE_SPARE));
EXPECT_NO_THROW(Vdev vdev(labelConfig));
nvlist_free(labelConfig);
}
TEST_F(VdevTest, AvailSpareState) {
nvlist_t *labelConfig;
ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
1948339428197961030));
ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
POOL_STATE_SPARE));
Vdev vdev(labelConfig);
EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State());
nvlist_free(labelConfig);
}
TEST_F(VdevTest, IsSpare) {
Vdev notSpare(m_poolConfig, m_vdevConfig);
EXPECT_EQ(false, notSpare.IsSpare());
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1));
Vdev isSpare(m_poolConfig, m_vdevConfig);
EXPECT_EQ(true, isSpare.IsSpare());
}
class ZfsEventTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
m_eventFactory = new EventFactory();
m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
m_event = NULL;
}
virtual void TearDown()
{
delete m_eventFactory;
delete m_event;
}
EventFactory *m_eventFactory;
Event *m_event;
};
TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled)
{
string evString("!system=ZFS "
"subsystem=ZFS "
"type=sysevent.fs.zfs.vdev_remove "
"pool_name=foo "
"pool_guid=9756779504028057996 "
"vdev_guid=1631193447431603339 "
"vdev_path=/dev/da1 "
"timestamp=1348871594");
m_event = Event::CreateEvent(*m_eventFactory, evString);
MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event);
EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1);
mock_event->Process();
}
class CaseFileTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
m_eventFactory = new EventFactory();
m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
m_event = NULL;
nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
ZPOOL_CONFIG_GUID, 0xbeef));
m_vdev = new MockVdev(m_vdevConfig);
ON_CALL(*m_vdev, GUID())
.WillByDefault(::testing::Return(Guid(123)));
ON_CALL(*m_vdev, Name(::testing::_, ::testing::_))
.WillByDefault(::testing::Return(string("/dev/da999")));
ON_CALL(*m_vdev, PoolGUID())
.WillByDefault(::testing::Return(Guid(456)));
ON_CALL(*m_vdev, State())
.WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
m_caseFile = &TestableCaseFile::Create(*m_vdev);
ON_CALL(*m_caseFile, ReEvaluate(::testing::_))
.WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate));
return;
}
virtual void TearDown()
{
delete m_caseFile;
nvlist_free(m_vdevConfig);
delete m_vdev;
delete m_event;
delete m_eventFactory;
}
nvlist_t *m_vdevConfig;
MockVdev *m_vdev;
TestableCaseFile *m_caseFile;
Event *m_event;
EventFactory *m_eventFactory;
};
TEST_F(CaseFileTest, HealthyVdev)
{
EXPECT_FALSE(m_caseFile->ShouldDegrade());
EXPECT_FALSE(m_caseFile->ShouldFault());
}
TEST_F(CaseFileTest, HealthyishVdev)
{
string evString("!system=ZFS "
"class=ereport.fs.zfs.io "
"ena=12091638756982918145 "
"parent_guid=13237004955564865395 "
"parent_type=raidz "
"pool=testpool.4415 "
"pool_context=0 "
"pool_failmode=wait "
"pool_guid=456 "
"subsystem=ZFS "
"timestamp=1348867914 "
"type=ereport.fs.zfs.io "
"vdev_guid=123 "
"vdev_path=/dev/da400 "
"vdev_type=disk "
"zio_blkid=622 "
"zio_err=1 "
"zio_level=-2 "
"zio_object=0 "
"zio_objset=37 "
"zio_offset=25598976 "
"zio_size=1024");
m_event = Event::CreateEvent(*m_eventFactory, evString);
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_CALL(*m_caseFile, RefreshVdevState())
.Times(::testing::Exactly(0));
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
EXPECT_FALSE(m_caseFile->ShouldDegrade());
EXPECT_FALSE(m_caseFile->ShouldFault());
}
TEST_F(CaseFileTest, PoolDestroy)
{
string evString("!system=ZFS "
"pool_name=testpool.4415 "
"pool_guid=456 "
"subsystem=ZFS "
"timestamp=1348867914 "
"type=sysevent.fs.zfs.pool_destroy ");
m_event = Event::CreateEvent(*m_eventFactory, evString);
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_CALL(*m_caseFile, Close());
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
}
TEST_F(CaseFileTest, VeryManyDelayErrors)
{
EXPECT_CALL(*m_caseFile, RefreshVdevState())
.Times(::testing::AtMost(1))
.WillRepeatedly(::testing::Return(true));
for(int i=0; i<100; i++) {
stringstream evStringStream;
evStringStream <<
"!system=ZFS "
"class=ereport.fs.zfs.delay "
"ena=12091638756982918145 "
"parent_guid=13237004955564865395 "
"parent_type=raidz "
"pool=testpool.4415 "
"pool_context=0 "
"pool_failmode=wait "
"pool_guid=456 "
"pool_state= 0"
"subsystem=ZFS "
"time=";
evStringStream << i << "0000000000000000 ";
evStringStream << "timestamp=" << i << " ";
evStringStream <<
"type=ereport.fs.zfs.delay "
"vdev_ashift=12 "
"vdev_cksum_errors=0 "
"vdev_complete_ts=948336226469 "
"vdev_delays=77 "
"vdev_delta_ts=123998485899 "
"vdev_guid=123 "
"vdev_path=/dev/da400 "
"vdev_read_errors=0 "
"vdev_spare_guids= "
"vdev_type=disk "
"vdev_write_errors=0 "
"zio_blkid=622 "
"zio_delay=31000041101 "
"zio_delta=123998485899 "
"zio_err=0 "
"zio_flags=1572992 "
"zio_level=-2 "
"zio_object=0 "
"zio_objset=37 "
"zio_offset=25598976 "
"zio_pipeline=48234496 "
"zio_priority=3 "
"zio_size=1024"
"zio_stage=33554432 "
"zio_timestamp=824337740570 ";
Event *event(Event::CreateEvent(*m_eventFactory,
evStringStream.str()));
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
delete event;
}
m_caseFile->SpliceEvents();
EXPECT_FALSE(m_caseFile->ShouldDegrade());
EXPECT_TRUE(m_caseFile->ShouldFault());
}
TEST_F(CaseFileTest, VeryManyIOErrors)
{
EXPECT_CALL(*m_caseFile, RefreshVdevState())
.Times(::testing::AtMost(1))
.WillRepeatedly(::testing::Return(true));
for(int i=0; i<100; i++) {
stringstream evStringStream;
evStringStream <<
"!system=ZFS "
"class=ereport.fs.zfs.io "
"ena=12091638756982918145 "
"parent_guid=13237004955564865395 "
"parent_type=raidz "
"pool=testpool.4415 "
"pool_context=0 "
"pool_failmode=wait "
"pool_guid=456 "
"subsystem=ZFS "
"timestamp=";
evStringStream << i << " ";
evStringStream <<
"type=ereport.fs.zfs.io "
"vdev_guid=123 "
"vdev_path=/dev/da400 "
"vdev_type=disk "
"zio_blkid=622 "
"zio_err=1 "
"zio_level=-2 "
"zio_object=0 "
"zio_objset=37 "
"zio_offset=25598976 "
"zio_size=1024";
Event *event(Event::CreateEvent(*m_eventFactory,
evStringStream.str()));
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
delete event;
}
m_caseFile->SpliceEvents();
EXPECT_FALSE(m_caseFile->ShouldDegrade());
EXPECT_TRUE(m_caseFile->ShouldFault());
}
TEST_F(CaseFileTest, VeryManyChecksumErrors)
{
EXPECT_CALL(*m_caseFile, RefreshVdevState())
.Times(::testing::AtMost(1))
.WillRepeatedly(::testing::Return(true));
for(int i=0; i<100; i++) {
stringstream evStringStream;
evStringStream <<
"!system=ZFS "
"bad_cleared_bits=03000000000000803f50b00000000000 "
"bad_range_clears=0000000e "
"bad_range_sets=00000000 "
"bad_ranges=0000000000000010 "
"bad_ranges_min_gap=8 "
"bad_set_bits=00000000000000000000000000000000 "
"class=ereport.fs.zfs.checksum "
"ena=12272856582652437505 "
"parent_guid=5838204195352909894 "
"parent_type=raidz pool=testpool.7640 "
"pool_context=0 "
"pool_failmode=wait "
"pool_guid=456 "
"subsystem=ZFS timestamp=";
evStringStream << i << " ";
evStringStream <<
"type=ereport.fs.zfs.checksum "
"vdev_guid=123 "
"vdev_path=/mnt/tmp/file1.7702 "
"vdev_type=file "
"zio_blkid=0 "
"zio_err=0 "
"zio_level=0 "
"zio_object=3 "
"zio_objset=0 "
"zio_offset=16896 "
"zio_size=512";
Event *event(Event::CreateEvent(*m_eventFactory,
evStringStream.str()));
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
delete event;
}
m_caseFile->SpliceEvents();
EXPECT_TRUE(m_caseFile->ShouldDegrade());
EXPECT_FALSE(m_caseFile->ShouldFault());
}
class ReEvaluateByGuidTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
m_eventFactory = new EventFactory();
m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
m_event = Event::CreateEvent(*m_eventFactory, s_evString);
nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
ZPOOL_CONFIG_GUID, 0xbeef));
m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
ON_CALL(*m_vdev456, GUID())
.WillByDefault(::testing::Return(Guid(123)));
ON_CALL(*m_vdev456, PoolGUID())
.WillByDefault(::testing::Return(Guid(456)));
ON_CALL(*m_vdev456, State())
.WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
ON_CALL(*m_vdev789, GUID())
.WillByDefault(::testing::Return(Guid(123)));
ON_CALL(*m_vdev789, PoolGUID())
.WillByDefault(::testing::Return(Guid(789)));
ON_CALL(*m_vdev789, State())
.WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
m_caseFile456 = NULL;
m_caseFile789 = NULL;
return;
}
virtual void TearDown()
{
delete m_caseFile456;
delete m_caseFile789;
nvlist_free(m_vdevConfig);
delete m_vdev456;
delete m_vdev789;
delete m_event;
delete m_eventFactory;
}
static string s_evString;
nvlist_t *m_vdevConfig;
::testing::NiceMock<MockVdev> *m_vdev456;
::testing::NiceMock<MockVdev> *m_vdev789;
TestableCaseFile *m_caseFile456;
TestableCaseFile *m_caseFile789;
Event *m_event;
EventFactory *m_eventFactory;
};
string ReEvaluateByGuidTest::s_evString(
"!system=ZFS "
"pool_guid=16271873792808333580 "
"pool_name=foo "
"subsystem=ZFS "
"timestamp=1360620391 "
"type=sysevent.fs.zfs.config_sync");
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty)
{
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_EQ(0, TestableCaseFile::getActiveCases());
CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
EXPECT_EQ(0, TestableCaseFile::getActiveCases());
}
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse)
{
m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
.Times(::testing::Exactly(0));
CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event);
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
}
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue)
{
m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
.Times(::testing::Exactly(1))
.WillRepeatedly(::testing::Return(false));
CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
EXPECT_EQ(1, TestableCaseFile::getActiveCases());
}
TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
{
TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456);
TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789);
TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456);
TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789);
TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789);
ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
EXPECT_EQ(5, TestableCaseFile::getActiveCases());
EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_))
.Times(::testing::Exactly(1))
.WillRepeatedly(::testing::Return(false));
EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_))
.Times(::testing::Exactly(1))
.WillRepeatedly(::testing::Return(false));
EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_))
.Times(::testing::Exactly(0));
EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_))
.Times(::testing::Exactly(0));
EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_))
.Times(::testing::Exactly(0));
CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
EXPECT_EQ(5, TestableCaseFile::getActiveCases());
delete CaseFile1;
delete CaseFile2;
delete CaseFile3;
delete CaseFile4;
delete CaseFile5;
}
class VdevIteratorTest : public ::testing::Test
{
};
bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) {
return (false);
}
TEST_F(VdevIteratorTest, VdevRemoval)
{
nvlist_t* poolConfig, *rootVdev;
ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678));
ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN,
NULL, 0));
ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
ZPOOL_CONFIG_POOL_GUID, 0x1234));
ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE,
rootVdev));
VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL);
}