17a0c41d5SAlan Somers /*-
27a0c41d5SAlan Somers * Copyright (c) 2012, 2013, 2014 Spectra Logic Corporation
37a0c41d5SAlan Somers * All rights reserved.
47a0c41d5SAlan Somers *
57a0c41d5SAlan Somers * Redistribution and use in source and binary forms, with or without
67a0c41d5SAlan Somers * modification, are permitted provided that the following conditions
77a0c41d5SAlan Somers * are met:
87a0c41d5SAlan Somers * 1. Redistributions of source code must retain the above copyright
97a0c41d5SAlan Somers * notice, this list of conditions, and the following disclaimer,
107a0c41d5SAlan Somers * without modification.
117a0c41d5SAlan Somers * 2. Redistributions in binary form must reproduce at minimum a disclaimer
127a0c41d5SAlan Somers * substantially similar to the "NO WARRANTY" disclaimer below
137a0c41d5SAlan Somers * ("Disclaimer") and any redistribution must be conditioned upon
147a0c41d5SAlan Somers * including a substantially similar Disclaimer requirement for further
157a0c41d5SAlan Somers * binary redistribution.
167a0c41d5SAlan Somers *
177a0c41d5SAlan Somers * NO WARRANTY
187a0c41d5SAlan Somers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197a0c41d5SAlan Somers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207a0c41d5SAlan Somers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
217a0c41d5SAlan Somers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227a0c41d5SAlan Somers * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
237a0c41d5SAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
247a0c41d5SAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
257a0c41d5SAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
267a0c41d5SAlan Somers * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
277a0c41d5SAlan Somers * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
287a0c41d5SAlan Somers * POSSIBILITY OF SUCH DAMAGES.
297a0c41d5SAlan Somers *
307a0c41d5SAlan Somers * Authors: Alan Somers (Spectra Logic Corporation)
317a0c41d5SAlan Somers */
327a0c41d5SAlan Somers #include <sys/cdefs.h>
339e5787d2SMatt Macy #include <sys/byteorder.h>
347a0c41d5SAlan Somers
357a0c41d5SAlan Somers #include <stdarg.h>
367a0c41d5SAlan Somers #include <syslog.h>
377a0c41d5SAlan Somers
387a0c41d5SAlan Somers #include <libnvpair.h>
397a0c41d5SAlan Somers #include <libzfs.h>
407a0c41d5SAlan Somers
417a0c41d5SAlan Somers #include <list>
427a0c41d5SAlan Somers #include <map>
437a0c41d5SAlan Somers #include <sstream>
447a0c41d5SAlan Somers #include <string>
457a0c41d5SAlan Somers
467a0c41d5SAlan Somers #include <gmock/gmock.h>
477a0c41d5SAlan Somers #include <gtest/gtest.h>
487a0c41d5SAlan Somers
497a0c41d5SAlan Somers #include <devdctl/guid.h>
507a0c41d5SAlan Somers #include <devdctl/event.h>
517a0c41d5SAlan Somers #include <devdctl/event_factory.h>
527a0c41d5SAlan Somers #include <devdctl/exception.h>
537a0c41d5SAlan Somers #include <devdctl/consumer.h>
547a0c41d5SAlan Somers
557a0c41d5SAlan Somers #include <zfsd/callout.h>
567a0c41d5SAlan Somers #include <zfsd/vdev_iterator.h>
577a0c41d5SAlan Somers #include <zfsd/zfsd_event.h>
587a0c41d5SAlan Somers #include <zfsd/case_file.h>
597a0c41d5SAlan Somers #include <zfsd/vdev.h>
607a0c41d5SAlan Somers #include <zfsd/zfsd.h>
617a0c41d5SAlan Somers #include <zfsd/zfsd_exception.h>
627a0c41d5SAlan Somers #include <zfsd/zpool_list.h>
637a0c41d5SAlan Somers
647a0c41d5SAlan Somers #include "libmocks.h"
657a0c41d5SAlan Somers /*================================== Macros ==================================*/
667a0c41d5SAlan Somers #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
677a0c41d5SAlan Somers
687a0c41d5SAlan Somers /*============================ Namespace Control =============================*/
697a0c41d5SAlan Somers using std::string;
707a0c41d5SAlan Somers using std::stringstream;
717a0c41d5SAlan Somers
727a0c41d5SAlan Somers using DevdCtl::Event;
737a0c41d5SAlan Somers using DevdCtl::EventFactory;
747a0c41d5SAlan Somers using DevdCtl::EventList;
757a0c41d5SAlan Somers using DevdCtl::Guid;
767a0c41d5SAlan Somers using DevdCtl::NVPairMap;
777a0c41d5SAlan Somers
787a0c41d5SAlan Somers /* redefine zpool_handle here because libzfs_impl.h is not includable */
797a0c41d5SAlan Somers struct zpool_handle
807a0c41d5SAlan Somers {
817a0c41d5SAlan Somers libzfs_handle_t *zpool_hdl;
827a0c41d5SAlan Somers zpool_handle_t *zpool_next;
8341b9077eSAlexander Motin char zpool_name[ZFS_MAX_DATASET_NAME_LEN];
847a0c41d5SAlan Somers int zpool_state;
85*a58ece87SMark Johnston unsigned int zpool_n_propnames;
86*a58ece87SMark Johnston #define ZHP_MAX_PROPNAMES 4
87*a58ece87SMark Johnston const char *zpool_propnames[ZHP_MAX_PROPNAMES];
887a0c41d5SAlan Somers size_t zpool_config_size;
897a0c41d5SAlan Somers nvlist_t *zpool_config;
907a0c41d5SAlan Somers nvlist_t *zpool_old_config;
917a0c41d5SAlan Somers nvlist_t *zpool_props;
927a0c41d5SAlan Somers diskaddr_t zpool_start_block;
937a0c41d5SAlan Somers };
947a0c41d5SAlan Somers
957a0c41d5SAlan Somers class MockZfsEvent : public ZfsEvent
967a0c41d5SAlan Somers {
977a0c41d5SAlan Somers public:
987a0c41d5SAlan Somers MockZfsEvent(Event::Type, NVPairMap&, const string&);
~MockZfsEvent()997a0c41d5SAlan Somers virtual ~MockZfsEvent() {}
1007a0c41d5SAlan Somers
1017a0c41d5SAlan Somers static BuildMethod MockZfsEventBuilder;
1027a0c41d5SAlan Somers
1037a0c41d5SAlan Somers MOCK_CONST_METHOD0(ProcessPoolEvent, void());
1047a0c41d5SAlan Somers
1057a0c41d5SAlan Somers static EventFactory::Record s_buildRecords[];
1067a0c41d5SAlan Somers };
1077a0c41d5SAlan Somers
1087a0c41d5SAlan Somers EventFactory::Record MockZfsEvent::s_buildRecords[] =
1097a0c41d5SAlan Somers {
1107a0c41d5SAlan Somers { Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder }
1117a0c41d5SAlan Somers };
1127a0c41d5SAlan Somers
MockZfsEvent(Event::Type type,NVPairMap & map,const string & str)1137a0c41d5SAlan Somers MockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map,
1147a0c41d5SAlan Somers const string& str)
1157a0c41d5SAlan Somers : ZfsEvent(type, map, str)
1167a0c41d5SAlan Somers {
1177a0c41d5SAlan Somers }
1187a0c41d5SAlan Somers
1197a0c41d5SAlan Somers Event *
MockZfsEventBuilder(Event::Type type,NVPairMap & nvpairs,const string & eventString)1207a0c41d5SAlan Somers MockZfsEvent::MockZfsEventBuilder(Event::Type type,
1217a0c41d5SAlan Somers NVPairMap &nvpairs,
1227a0c41d5SAlan Somers const string &eventString)
1237a0c41d5SAlan Somers {
1247a0c41d5SAlan Somers return (new MockZfsEvent(type, nvpairs, eventString));
1257a0c41d5SAlan Somers }
1267a0c41d5SAlan Somers
1277a0c41d5SAlan Somers /*
1287a0c41d5SAlan Somers * A dummy Vdev class used for testing other classes
1297a0c41d5SAlan Somers */
1307a0c41d5SAlan Somers class MockVdev : public Vdev
1317a0c41d5SAlan Somers {
1327a0c41d5SAlan Somers public:
1337a0c41d5SAlan Somers MockVdev(nvlist_t *vdevConfig);
~MockVdev()1347a0c41d5SAlan Somers virtual ~MockVdev() {}
1357a0c41d5SAlan Somers
1367a0c41d5SAlan Somers MOCK_CONST_METHOD0(GUID, Guid());
1377a0c41d5SAlan Somers MOCK_CONST_METHOD0(PoolGUID, Guid());
1387a0c41d5SAlan Somers MOCK_CONST_METHOD0(State, vdev_state());
1397a0c41d5SAlan Somers MOCK_CONST_METHOD0(PhysicalPath, string());
14025038e8dSAlan Somers MOCK_CONST_METHOD2(Name, string(zpool_handle_t * zhp, bool verbose));
1417a0c41d5SAlan Somers };
1427a0c41d5SAlan Somers
MockVdev(nvlist_t * vdevConfig)1437a0c41d5SAlan Somers MockVdev::MockVdev(nvlist_t *vdevConfig)
1447a0c41d5SAlan Somers : Vdev(vdevConfig)
1457a0c41d5SAlan Somers {
1467a0c41d5SAlan Somers }
1477a0c41d5SAlan Somers
1487a0c41d5SAlan Somers /*
1497a0c41d5SAlan Somers * A CaseFile class with side effects removed, for testing
1507a0c41d5SAlan Somers */
1517a0c41d5SAlan Somers class TestableCaseFile : public CaseFile
1527a0c41d5SAlan Somers {
1537a0c41d5SAlan Somers public:
1547a0c41d5SAlan Somers static TestableCaseFile &Create(Vdev &vdev);
1557a0c41d5SAlan Somers TestableCaseFile(Vdev &vdev);
~TestableCaseFile()1567a0c41d5SAlan Somers virtual ~TestableCaseFile() {}
1577a0c41d5SAlan Somers
1587a0c41d5SAlan Somers MOCK_METHOD0(Close, void());
1597a0c41d5SAlan Somers MOCK_METHOD1(RegisterCallout, void(const Event &event));
1607a0c41d5SAlan Somers MOCK_METHOD0(RefreshVdevState, bool());
1617a0c41d5SAlan Somers MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event));
1627a0c41d5SAlan Somers
RealReEvaluate(const ZfsEvent & event)1637a0c41d5SAlan Somers bool RealReEvaluate(const ZfsEvent &event)
1647a0c41d5SAlan Somers {
1657a0c41d5SAlan Somers return (CaseFile::ReEvaluate(event));
1667a0c41d5SAlan Somers }
1677a0c41d5SAlan Somers
1687a0c41d5SAlan Somers /*
1697a0c41d5SAlan Somers * This splices the event lists, a procedure that would normally be done
1707a0c41d5SAlan Somers * by OnGracePeriodEnded, but we don't necessarily call that in the
1717a0c41d5SAlan Somers * unit tests
1727a0c41d5SAlan Somers */
1737a0c41d5SAlan Somers void SpliceEvents();
1747a0c41d5SAlan Somers
1757a0c41d5SAlan Somers /*
1767a0c41d5SAlan Somers * Used by some of our expectations. CaseFile does not publicize this
1777a0c41d5SAlan Somers */
getActiveCases()1787a0c41d5SAlan Somers static int getActiveCases()
1797a0c41d5SAlan Somers {
1807a0c41d5SAlan Somers return (s_activeCases.size());
1817a0c41d5SAlan Somers }
1827a0c41d5SAlan Somers };
1837a0c41d5SAlan Somers
TestableCaseFile(Vdev & vdev)1847a0c41d5SAlan Somers TestableCaseFile::TestableCaseFile(Vdev &vdev)
1857a0c41d5SAlan Somers : CaseFile(vdev)
1867a0c41d5SAlan Somers {
1877a0c41d5SAlan Somers }
1887a0c41d5SAlan Somers
1897a0c41d5SAlan Somers TestableCaseFile &
Create(Vdev & vdev)1907a0c41d5SAlan Somers TestableCaseFile::Create(Vdev &vdev)
1917a0c41d5SAlan Somers {
1927a0c41d5SAlan Somers TestableCaseFile *newCase;
1937a0c41d5SAlan Somers newCase = new TestableCaseFile(vdev);
1947a0c41d5SAlan Somers return (*newCase);
1957a0c41d5SAlan Somers }
1967a0c41d5SAlan Somers
1977a0c41d5SAlan Somers void
SpliceEvents()1987a0c41d5SAlan Somers TestableCaseFile::SpliceEvents()
1997a0c41d5SAlan Somers {
2007a0c41d5SAlan Somers m_events.splice(m_events.begin(), m_tentativeEvents);
2017a0c41d5SAlan Somers }
2027a0c41d5SAlan Somers
2037a0c41d5SAlan Somers
2047a0c41d5SAlan Somers /*
2057a0c41d5SAlan Somers * Test class ZfsdException
2067a0c41d5SAlan Somers */
2077a0c41d5SAlan Somers class ZfsdExceptionTest : public ::testing::Test
2087a0c41d5SAlan Somers {
2097a0c41d5SAlan Somers protected:
SetUp()2107a0c41d5SAlan Somers virtual void SetUp()
2117a0c41d5SAlan Somers {
2127a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
2137a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_string(poolConfig,
2147a0c41d5SAlan Somers ZPOOL_CONFIG_POOL_NAME, "unit_test_pool"));
2157a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
2167a0c41d5SAlan Somers ZPOOL_CONFIG_POOL_GUID, 0x1234));
2177a0c41d5SAlan Somers
2187a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0));
2197a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(vdevConfig,
2207a0c41d5SAlan Somers ZPOOL_CONFIG_GUID, 0x5678));
2217a0c41d5SAlan Somers bzero(&poolHandle, sizeof(poolHandle));
2227a0c41d5SAlan Somers poolHandle.zpool_config = poolConfig;
2237a0c41d5SAlan Somers }
2247a0c41d5SAlan Somers
TearDown()2257a0c41d5SAlan Somers virtual void TearDown()
2267a0c41d5SAlan Somers {
2277a0c41d5SAlan Somers nvlist_free(poolConfig);
2287a0c41d5SAlan Somers nvlist_free(vdevConfig);
2297a0c41d5SAlan Somers }
2307a0c41d5SAlan Somers
2317a0c41d5SAlan Somers nvlist_t *poolConfig;
2327a0c41d5SAlan Somers nvlist_t *vdevConfig;
2337a0c41d5SAlan Somers zpool_handle_t poolHandle;
2347a0c41d5SAlan Somers };
2357a0c41d5SAlan Somers
TEST_F(ZfsdExceptionTest,StringConstructorNull)2367a0c41d5SAlan Somers TEST_F(ZfsdExceptionTest, StringConstructorNull)
2377a0c41d5SAlan Somers {
2387a0c41d5SAlan Somers ZfsdException ze("");
2397a0c41d5SAlan Somers EXPECT_STREQ("", ze.GetString().c_str());
2407a0c41d5SAlan Somers }
2417a0c41d5SAlan Somers
TEST_F(ZfsdExceptionTest,StringConstructorFormatted)2427a0c41d5SAlan Somers TEST_F(ZfsdExceptionTest, StringConstructorFormatted)
2437a0c41d5SAlan Somers {
2447a0c41d5SAlan Somers ZfsdException ze(" %d %s", 55, "hello world");
2457a0c41d5SAlan Somers EXPECT_STREQ(" 55 hello world", ze.GetString().c_str());
2467a0c41d5SAlan Somers }
2477a0c41d5SAlan Somers
TEST_F(ZfsdExceptionTest,LogSimple)2487a0c41d5SAlan Somers TEST_F(ZfsdExceptionTest, LogSimple)
2497a0c41d5SAlan Somers {
2507a0c41d5SAlan Somers ZfsdException ze("unit test w/o vdev or pool");
2517a0c41d5SAlan Somers ze.Log();
2527a0c41d5SAlan Somers EXPECT_EQ(LOG_ERR, syslog_last_priority);
2537a0c41d5SAlan Somers EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message);
2547a0c41d5SAlan Somers }
2557a0c41d5SAlan Somers
TEST_F(ZfsdExceptionTest,Pool)2567a0c41d5SAlan Somers TEST_F(ZfsdExceptionTest, Pool)
2577a0c41d5SAlan Somers {
2587a0c41d5SAlan Somers const char msg[] = "Exception with pool name";
2597a0c41d5SAlan Somers char expected[4096];
2607a0c41d5SAlan Somers sprintf(expected, "Pool unit_test_pool: %s\n", msg);
2617a0c41d5SAlan Somers ZfsdException ze(poolConfig, msg);
2627a0c41d5SAlan Somers ze.Log();
2637a0c41d5SAlan Somers EXPECT_STREQ(expected, syslog_last_message);
2647a0c41d5SAlan Somers }
2657a0c41d5SAlan Somers
TEST_F(ZfsdExceptionTest,PoolHandle)2667a0c41d5SAlan Somers TEST_F(ZfsdExceptionTest, PoolHandle)
2677a0c41d5SAlan Somers {
2687a0c41d5SAlan Somers const char msg[] = "Exception with pool handle";
2697a0c41d5SAlan Somers char expected[4096];
2707a0c41d5SAlan Somers sprintf(expected, "Pool unit_test_pool: %s\n", msg);
2717a0c41d5SAlan Somers ZfsdException ze(&poolHandle, msg);
2727a0c41d5SAlan Somers ze.Log();
2737a0c41d5SAlan Somers EXPECT_STREQ(expected, syslog_last_message);
2747a0c41d5SAlan Somers }
2757a0c41d5SAlan Somers
2767a0c41d5SAlan Somers /*
2777a0c41d5SAlan Somers * Test class Vdev
2787a0c41d5SAlan Somers */
2797a0c41d5SAlan Somers class VdevTest : public ::testing::Test
2807a0c41d5SAlan Somers {
2817a0c41d5SAlan Somers protected:
SetUp()2827a0c41d5SAlan Somers virtual void SetUp()
2837a0c41d5SAlan Somers {
2847a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0));
2857a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig,
2867a0c41d5SAlan Somers ZPOOL_CONFIG_POOL_GUID,
2877a0c41d5SAlan Somers 0x1234));
2887a0c41d5SAlan Somers
2897a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0));
2907a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID,
2917a0c41d5SAlan Somers 0x5678));
2927a0c41d5SAlan Somers }
2937a0c41d5SAlan Somers
TearDown()2947a0c41d5SAlan Somers virtual void TearDown()
2957a0c41d5SAlan Somers {
2967a0c41d5SAlan Somers nvlist_free(m_poolConfig);
2977a0c41d5SAlan Somers nvlist_free(m_vdevConfig);
2987a0c41d5SAlan Somers }
2997a0c41d5SAlan Somers
3007a0c41d5SAlan Somers nvlist_t *m_poolConfig;
3017a0c41d5SAlan Somers nvlist_t *m_vdevConfig;
3027a0c41d5SAlan Somers };
3037a0c41d5SAlan Somers
3047a0c41d5SAlan Somers
TEST_F(VdevTest,StateFromConfig)3057a0c41d5SAlan Somers TEST_F(VdevTest, StateFromConfig)
3067a0c41d5SAlan Somers {
3077a0c41d5SAlan Somers vdev_stat_t vs;
3087a0c41d5SAlan Somers
3097a0c41d5SAlan Somers vs.vs_state = VDEV_STATE_OFFLINE;
3107a0c41d5SAlan Somers
3117a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig,
3127a0c41d5SAlan Somers ZPOOL_CONFIG_VDEV_STATS,
3137a0c41d5SAlan Somers (uint64_t*)&vs,
3147a0c41d5SAlan Somers sizeof(vs) / sizeof(uint64_t)));
3157a0c41d5SAlan Somers
3167a0c41d5SAlan Somers Vdev vdev(m_poolConfig, m_vdevConfig);
3177a0c41d5SAlan Somers
3187a0c41d5SAlan Somers EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State());
3197a0c41d5SAlan Somers }
3207a0c41d5SAlan Somers
TEST_F(VdevTest,StateFaulted)3217a0c41d5SAlan Somers TEST_F(VdevTest, StateFaulted)
3227a0c41d5SAlan Somers {
3237a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1));
3247a0c41d5SAlan Somers
3257a0c41d5SAlan Somers Vdev vdev(m_poolConfig, m_vdevConfig);
3267a0c41d5SAlan Somers
3277a0c41d5SAlan Somers EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State());
3287a0c41d5SAlan Somers }
3297a0c41d5SAlan Somers
3307a0c41d5SAlan Somers /*
3317a0c41d5SAlan Somers * Test that we can construct a Vdev from the label information that is stored
3327a0c41d5SAlan Somers * on an available spare drive
3337a0c41d5SAlan Somers */
TEST_F(VdevTest,ConstructAvailSpare)3347a0c41d5SAlan Somers TEST_F(VdevTest, ConstructAvailSpare)
3357a0c41d5SAlan Somers {
3367a0c41d5SAlan Somers nvlist_t *labelConfig;
3377a0c41d5SAlan Somers
3387a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
3397a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
3407a0c41d5SAlan Somers 1948339428197961030));
3417a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
3427a0c41d5SAlan Somers POOL_STATE_SPARE));
3437a0c41d5SAlan Somers
3447a0c41d5SAlan Somers EXPECT_NO_THROW(Vdev vdev(labelConfig));
3457a0c41d5SAlan Somers
3467a0c41d5SAlan Somers nvlist_free(labelConfig);
3477a0c41d5SAlan Somers }
3487a0c41d5SAlan Somers
3497a0c41d5SAlan Somers /* Available spares will always show the HEALTHY state */
TEST_F(VdevTest,AvailSpareState)3507a0c41d5SAlan Somers TEST_F(VdevTest, AvailSpareState) {
3517a0c41d5SAlan Somers nvlist_t *labelConfig;
3527a0c41d5SAlan Somers
3537a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
3547a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
3557a0c41d5SAlan Somers 1948339428197961030));
3567a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
3577a0c41d5SAlan Somers POOL_STATE_SPARE));
3587a0c41d5SAlan Somers
3597a0c41d5SAlan Somers Vdev vdev(labelConfig);
3607a0c41d5SAlan Somers EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State());
3617a0c41d5SAlan Somers
3627a0c41d5SAlan Somers nvlist_free(labelConfig);
3637a0c41d5SAlan Somers }
3647a0c41d5SAlan Somers
3657a0c41d5SAlan Somers /* Test the Vdev::IsSpare method */
TEST_F(VdevTest,IsSpare)3667a0c41d5SAlan Somers TEST_F(VdevTest, IsSpare) {
3677a0c41d5SAlan Somers Vdev notSpare(m_poolConfig, m_vdevConfig);
3687a0c41d5SAlan Somers EXPECT_EQ(false, notSpare.IsSpare());
3697a0c41d5SAlan Somers
3707a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1));
3717a0c41d5SAlan Somers Vdev isSpare(m_poolConfig, m_vdevConfig);
3727a0c41d5SAlan Somers EXPECT_EQ(true, isSpare.IsSpare());
3737a0c41d5SAlan Somers }
3747a0c41d5SAlan Somers
3757a0c41d5SAlan Somers /*
3767a0c41d5SAlan Somers * Test class ZFSEvent
3777a0c41d5SAlan Somers */
3787a0c41d5SAlan Somers class ZfsEventTest : public ::testing::Test
3797a0c41d5SAlan Somers {
3807a0c41d5SAlan Somers protected:
SetUp()3817a0c41d5SAlan Somers virtual void SetUp()
3827a0c41d5SAlan Somers {
3837a0c41d5SAlan Somers m_eventFactory = new EventFactory();
3847a0c41d5SAlan Somers m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
3857a0c41d5SAlan Somers NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
3867a0c41d5SAlan Somers
3877a0c41d5SAlan Somers m_event = NULL;
3887a0c41d5SAlan Somers }
3897a0c41d5SAlan Somers
TearDown()3907a0c41d5SAlan Somers virtual void TearDown()
3917a0c41d5SAlan Somers {
3927a0c41d5SAlan Somers delete m_eventFactory;
3937a0c41d5SAlan Somers delete m_event;
3947a0c41d5SAlan Somers }
3957a0c41d5SAlan Somers
3967a0c41d5SAlan Somers EventFactory *m_eventFactory;
3977a0c41d5SAlan Somers Event *m_event;
3987a0c41d5SAlan Somers };
3997a0c41d5SAlan Somers
TEST_F(ZfsEventTest,ProcessPoolEventGetsCalled)4007a0c41d5SAlan Somers TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled)
4017a0c41d5SAlan Somers {
4027a0c41d5SAlan Somers string evString("!system=ZFS "
4037a0c41d5SAlan Somers "subsystem=ZFS "
4042a0c0aeaSAlan Somers "type=sysevent.fs.zfs.vdev_remove "
4057a0c41d5SAlan Somers "pool_name=foo "
4067a0c41d5SAlan Somers "pool_guid=9756779504028057996 "
4077a0c41d5SAlan Somers "vdev_guid=1631193447431603339 "
4087a0c41d5SAlan Somers "vdev_path=/dev/da1 "
4097a0c41d5SAlan Somers "timestamp=1348871594");
4107a0c41d5SAlan Somers m_event = Event::CreateEvent(*m_eventFactory, evString);
4117a0c41d5SAlan Somers MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event);
4127a0c41d5SAlan Somers
4137a0c41d5SAlan Somers EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1);
4147a0c41d5SAlan Somers mock_event->Process();
4157a0c41d5SAlan Somers }
4167a0c41d5SAlan Somers
4177a0c41d5SAlan Somers /*
4187a0c41d5SAlan Somers * Test class CaseFile
4197a0c41d5SAlan Somers */
4207a0c41d5SAlan Somers
4217a0c41d5SAlan Somers class CaseFileTest : public ::testing::Test
4227a0c41d5SAlan Somers {
4237a0c41d5SAlan Somers protected:
SetUp()4247a0c41d5SAlan Somers virtual void SetUp()
4257a0c41d5SAlan Somers {
4267a0c41d5SAlan Somers m_eventFactory = new EventFactory();
4277a0c41d5SAlan Somers m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
4287a0c41d5SAlan Somers NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
4297a0c41d5SAlan Somers
4307a0c41d5SAlan Somers m_event = NULL;
4317a0c41d5SAlan Somers
4327a0c41d5SAlan Somers nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
4337a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
4347a0c41d5SAlan Somers ZPOOL_CONFIG_GUID, 0xbeef));
4357a0c41d5SAlan Somers m_vdev = new MockVdev(m_vdevConfig);
4367a0c41d5SAlan Somers ON_CALL(*m_vdev, GUID())
4377a0c41d5SAlan Somers .WillByDefault(::testing::Return(Guid(123)));
43825038e8dSAlan Somers ON_CALL(*m_vdev, Name(::testing::_, ::testing::_))
43925038e8dSAlan Somers .WillByDefault(::testing::Return(string("/dev/da999")));
4407a0c41d5SAlan Somers ON_CALL(*m_vdev, PoolGUID())
4417a0c41d5SAlan Somers .WillByDefault(::testing::Return(Guid(456)));
4427a0c41d5SAlan Somers ON_CALL(*m_vdev, State())
4437a0c41d5SAlan Somers .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
4447a0c41d5SAlan Somers m_caseFile = &TestableCaseFile::Create(*m_vdev);
4457a0c41d5SAlan Somers ON_CALL(*m_caseFile, ReEvaluate(::testing::_))
4467a0c41d5SAlan Somers .WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate));
4477a0c41d5SAlan Somers return;
4487a0c41d5SAlan Somers }
4497a0c41d5SAlan Somers
TearDown()4507a0c41d5SAlan Somers virtual void TearDown()
4517a0c41d5SAlan Somers {
4527a0c41d5SAlan Somers delete m_caseFile;
4537a0c41d5SAlan Somers nvlist_free(m_vdevConfig);
4547a0c41d5SAlan Somers delete m_vdev;
4557a0c41d5SAlan Somers delete m_event;
4567a0c41d5SAlan Somers delete m_eventFactory;
4577a0c41d5SAlan Somers }
4587a0c41d5SAlan Somers
4597a0c41d5SAlan Somers nvlist_t *m_vdevConfig;
4607a0c41d5SAlan Somers MockVdev *m_vdev;
4617a0c41d5SAlan Somers TestableCaseFile *m_caseFile;
4627a0c41d5SAlan Somers Event *m_event;
4637a0c41d5SAlan Somers EventFactory *m_eventFactory;
4647a0c41d5SAlan Somers };
4657a0c41d5SAlan Somers
4667a0c41d5SAlan Somers /*
4677a0c41d5SAlan Somers * A Vdev with no events should not be degraded or faulted
4687a0c41d5SAlan Somers */
TEST_F(CaseFileTest,HealthyVdev)4697a0c41d5SAlan Somers TEST_F(CaseFileTest, HealthyVdev)
4707a0c41d5SAlan Somers {
4717a0c41d5SAlan Somers EXPECT_FALSE(m_caseFile->ShouldDegrade());
4727a0c41d5SAlan Somers EXPECT_FALSE(m_caseFile->ShouldFault());
4737a0c41d5SAlan Somers }
4747a0c41d5SAlan Somers
4757a0c41d5SAlan Somers /*
4767a0c41d5SAlan Somers * A Vdev with only one event should not be degraded or faulted
4777a0c41d5SAlan Somers * For performance reasons, RefreshVdevState should not be called.
4787a0c41d5SAlan Somers */
TEST_F(CaseFileTest,HealthyishVdev)4797a0c41d5SAlan Somers TEST_F(CaseFileTest, HealthyishVdev)
4807a0c41d5SAlan Somers {
4817a0c41d5SAlan Somers string evString("!system=ZFS "
4827a0c41d5SAlan Somers "class=ereport.fs.zfs.io "
4837a0c41d5SAlan Somers "ena=12091638756982918145 "
4847a0c41d5SAlan Somers "parent_guid=13237004955564865395 "
4857a0c41d5SAlan Somers "parent_type=raidz "
4867a0c41d5SAlan Somers "pool=testpool.4415 "
4877a0c41d5SAlan Somers "pool_context=0 "
4887a0c41d5SAlan Somers "pool_failmode=wait "
4897a0c41d5SAlan Somers "pool_guid=456 "
4907a0c41d5SAlan Somers "subsystem=ZFS "
4917a0c41d5SAlan Somers "timestamp=1348867914 "
4927a0c41d5SAlan Somers "type=ereport.fs.zfs.io "
4937a0c41d5SAlan Somers "vdev_guid=123 "
4947a0c41d5SAlan Somers "vdev_path=/dev/da400 "
4957a0c41d5SAlan Somers "vdev_type=disk "
4967a0c41d5SAlan Somers "zio_blkid=622 "
4977a0c41d5SAlan Somers "zio_err=1 "
4987a0c41d5SAlan Somers "zio_level=-2 "
4997a0c41d5SAlan Somers "zio_object=0 "
5007a0c41d5SAlan Somers "zio_objset=37 "
5017a0c41d5SAlan Somers "zio_offset=25598976 "
5027a0c41d5SAlan Somers "zio_size=1024");
5037a0c41d5SAlan Somers m_event = Event::CreateEvent(*m_eventFactory, evString);
5047a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
5057a0c41d5SAlan Somers
5067a0c41d5SAlan Somers EXPECT_CALL(*m_caseFile, RefreshVdevState())
5077a0c41d5SAlan Somers .Times(::testing::Exactly(0));
5087a0c41d5SAlan Somers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
5097a0c41d5SAlan Somers EXPECT_FALSE(m_caseFile->ShouldDegrade());
5107a0c41d5SAlan Somers EXPECT_FALSE(m_caseFile->ShouldFault());
5117a0c41d5SAlan Somers }
5127a0c41d5SAlan Somers
5137a0c41d5SAlan Somers /* The case file should be closed when its pool is destroyed */
TEST_F(CaseFileTest,PoolDestroy)5147a0c41d5SAlan Somers TEST_F(CaseFileTest, PoolDestroy)
5157a0c41d5SAlan Somers {
5167a0c41d5SAlan Somers string evString("!system=ZFS "
5177a0c41d5SAlan Somers "pool_name=testpool.4415 "
5187a0c41d5SAlan Somers "pool_guid=456 "
5197a0c41d5SAlan Somers "subsystem=ZFS "
5207a0c41d5SAlan Somers "timestamp=1348867914 "
5212a0c0aeaSAlan Somers "type=sysevent.fs.zfs.pool_destroy ");
5227a0c41d5SAlan Somers m_event = Event::CreateEvent(*m_eventFactory, evString);
5237a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
5247a0c41d5SAlan Somers EXPECT_CALL(*m_caseFile, Close());
5257a0c41d5SAlan Somers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
5267a0c41d5SAlan Somers }
5277a0c41d5SAlan Somers
5287a0c41d5SAlan Somers /*
529d565784aSAlan Somers * A Vdev with a very large number of Delay errors should fault
530d565784aSAlan Somers * For performance reasons, RefreshVdevState should be called at most once
531d565784aSAlan Somers */
TEST_F(CaseFileTest,VeryManyDelayErrors)532d565784aSAlan Somers TEST_F(CaseFileTest, VeryManyDelayErrors)
533d565784aSAlan Somers {
534d565784aSAlan Somers EXPECT_CALL(*m_caseFile, RefreshVdevState())
535d565784aSAlan Somers .Times(::testing::AtMost(1))
536d565784aSAlan Somers .WillRepeatedly(::testing::Return(true));
537d565784aSAlan Somers
538d565784aSAlan Somers for(int i=0; i<100; i++) {
539d565784aSAlan Somers stringstream evStringStream;
540d565784aSAlan Somers evStringStream <<
541d565784aSAlan Somers "!system=ZFS "
542d565784aSAlan Somers "class=ereport.fs.zfs.delay "
543d565784aSAlan Somers "ena=12091638756982918145 "
544d565784aSAlan Somers "parent_guid=13237004955564865395 "
545d565784aSAlan Somers "parent_type=raidz "
546d565784aSAlan Somers "pool=testpool.4415 "
547d565784aSAlan Somers "pool_context=0 "
548d565784aSAlan Somers "pool_failmode=wait "
549d565784aSAlan Somers "pool_guid=456 "
550d565784aSAlan Somers "pool_state= 0"
551d565784aSAlan Somers "subsystem=ZFS "
552d565784aSAlan Somers "time=";
553d565784aSAlan Somers evStringStream << i << "0000000000000000 ";
554d565784aSAlan Somers evStringStream << "timestamp=" << i << " ";
555d565784aSAlan Somers evStringStream <<
556d565784aSAlan Somers "type=ereport.fs.zfs.delay "
557d565784aSAlan Somers "vdev_ashift=12 "
558d565784aSAlan Somers "vdev_cksum_errors=0 "
559d565784aSAlan Somers "vdev_complete_ts=948336226469 "
560d565784aSAlan Somers "vdev_delays=77 "
561d565784aSAlan Somers "vdev_delta_ts=123998485899 "
562d565784aSAlan Somers "vdev_guid=123 "
563d565784aSAlan Somers "vdev_path=/dev/da400 "
564d565784aSAlan Somers "vdev_read_errors=0 "
565d565784aSAlan Somers "vdev_spare_guids= "
566d565784aSAlan Somers "vdev_type=disk "
567d565784aSAlan Somers "vdev_write_errors=0 "
568d565784aSAlan Somers "zio_blkid=622 "
569d565784aSAlan Somers "zio_delay=31000041101 "
570d565784aSAlan Somers "zio_delta=123998485899 "
571d565784aSAlan Somers "zio_err=0 "
572d565784aSAlan Somers "zio_flags=1572992 "
573d565784aSAlan Somers "zio_level=-2 "
574d565784aSAlan Somers "zio_object=0 "
575d565784aSAlan Somers "zio_objset=37 "
576d565784aSAlan Somers "zio_offset=25598976 "
577d565784aSAlan Somers "zio_pipeline=48234496 "
578d565784aSAlan Somers "zio_priority=3 "
579d565784aSAlan Somers "zio_size=1024"
580d565784aSAlan Somers "zio_stage=33554432 "
581d565784aSAlan Somers "zio_timestamp=824337740570 ";
582d565784aSAlan Somers Event *event(Event::CreateEvent(*m_eventFactory,
583d565784aSAlan Somers evStringStream.str()));
584d565784aSAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
585d565784aSAlan Somers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
586d565784aSAlan Somers delete event;
587d565784aSAlan Somers }
588d565784aSAlan Somers
589d565784aSAlan Somers m_caseFile->SpliceEvents();
590d565784aSAlan Somers EXPECT_FALSE(m_caseFile->ShouldDegrade());
591d565784aSAlan Somers EXPECT_TRUE(m_caseFile->ShouldFault());
592d565784aSAlan Somers }
593d565784aSAlan Somers
594d565784aSAlan Somers /*
5957a0c41d5SAlan Somers * A Vdev with a very large number of IO errors should fault
5967a0c41d5SAlan Somers * For performance reasons, RefreshVdevState should be called at most once
5977a0c41d5SAlan Somers */
TEST_F(CaseFileTest,VeryManyIOErrors)5987a0c41d5SAlan Somers TEST_F(CaseFileTest, VeryManyIOErrors)
5997a0c41d5SAlan Somers {
6007a0c41d5SAlan Somers EXPECT_CALL(*m_caseFile, RefreshVdevState())
6017a0c41d5SAlan Somers .Times(::testing::AtMost(1))
6027a0c41d5SAlan Somers .WillRepeatedly(::testing::Return(true));
6037a0c41d5SAlan Somers
6047a0c41d5SAlan Somers for(int i=0; i<100; i++) {
6057a0c41d5SAlan Somers stringstream evStringStream;
6067a0c41d5SAlan Somers evStringStream <<
6077a0c41d5SAlan Somers "!system=ZFS "
6087a0c41d5SAlan Somers "class=ereport.fs.zfs.io "
6097a0c41d5SAlan Somers "ena=12091638756982918145 "
6107a0c41d5SAlan Somers "parent_guid=13237004955564865395 "
6117a0c41d5SAlan Somers "parent_type=raidz "
6127a0c41d5SAlan Somers "pool=testpool.4415 "
6137a0c41d5SAlan Somers "pool_context=0 "
6147a0c41d5SAlan Somers "pool_failmode=wait "
6157a0c41d5SAlan Somers "pool_guid=456 "
6167a0c41d5SAlan Somers "subsystem=ZFS "
6177a0c41d5SAlan Somers "timestamp=";
6187a0c41d5SAlan Somers evStringStream << i << " ";
6197a0c41d5SAlan Somers evStringStream <<
6207a0c41d5SAlan Somers "type=ereport.fs.zfs.io "
6217a0c41d5SAlan Somers "vdev_guid=123 "
6227a0c41d5SAlan Somers "vdev_path=/dev/da400 "
6237a0c41d5SAlan Somers "vdev_type=disk "
6247a0c41d5SAlan Somers "zio_blkid=622 "
6257a0c41d5SAlan Somers "zio_err=1 "
6267a0c41d5SAlan Somers "zio_level=-2 "
6277a0c41d5SAlan Somers "zio_object=0 "
6287a0c41d5SAlan Somers "zio_objset=37 "
6297a0c41d5SAlan Somers "zio_offset=25598976 "
6307a0c41d5SAlan Somers "zio_size=1024";
6317a0c41d5SAlan Somers Event *event(Event::CreateEvent(*m_eventFactory,
6327a0c41d5SAlan Somers evStringStream.str()));
6337a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
6347a0c41d5SAlan Somers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
6357a0c41d5SAlan Somers delete event;
6367a0c41d5SAlan Somers }
6377a0c41d5SAlan Somers
6387a0c41d5SAlan Somers m_caseFile->SpliceEvents();
6397a0c41d5SAlan Somers EXPECT_FALSE(m_caseFile->ShouldDegrade());
6407a0c41d5SAlan Somers EXPECT_TRUE(m_caseFile->ShouldFault());
6417a0c41d5SAlan Somers }
6427a0c41d5SAlan Somers
6437a0c41d5SAlan Somers /*
6447a0c41d5SAlan Somers * A Vdev with a very large number of checksum errors should degrade
6457a0c41d5SAlan Somers * For performance reasons, RefreshVdevState should be called at most once
6467a0c41d5SAlan Somers */
TEST_F(CaseFileTest,VeryManyChecksumErrors)6477a0c41d5SAlan Somers TEST_F(CaseFileTest, VeryManyChecksumErrors)
6487a0c41d5SAlan Somers {
6497a0c41d5SAlan Somers EXPECT_CALL(*m_caseFile, RefreshVdevState())
6507a0c41d5SAlan Somers .Times(::testing::AtMost(1))
6517a0c41d5SAlan Somers .WillRepeatedly(::testing::Return(true));
6527a0c41d5SAlan Somers
6537a0c41d5SAlan Somers for(int i=0; i<100; i++) {
6547a0c41d5SAlan Somers stringstream evStringStream;
6557a0c41d5SAlan Somers evStringStream <<
6567a0c41d5SAlan Somers "!system=ZFS "
6577a0c41d5SAlan Somers "bad_cleared_bits=03000000000000803f50b00000000000 "
6587a0c41d5SAlan Somers "bad_range_clears=0000000e "
6597a0c41d5SAlan Somers "bad_range_sets=00000000 "
6607a0c41d5SAlan Somers "bad_ranges=0000000000000010 "
6617a0c41d5SAlan Somers "bad_ranges_min_gap=8 "
6627a0c41d5SAlan Somers "bad_set_bits=00000000000000000000000000000000 "
6637a0c41d5SAlan Somers "class=ereport.fs.zfs.checksum "
6647a0c41d5SAlan Somers "ena=12272856582652437505 "
6657a0c41d5SAlan Somers "parent_guid=5838204195352909894 "
6667a0c41d5SAlan Somers "parent_type=raidz pool=testpool.7640 "
6677a0c41d5SAlan Somers "pool_context=0 "
6687a0c41d5SAlan Somers "pool_failmode=wait "
6697a0c41d5SAlan Somers "pool_guid=456 "
6707a0c41d5SAlan Somers "subsystem=ZFS timestamp=";
6717a0c41d5SAlan Somers evStringStream << i << " ";
6727a0c41d5SAlan Somers evStringStream <<
6737a0c41d5SAlan Somers "type=ereport.fs.zfs.checksum "
6747a0c41d5SAlan Somers "vdev_guid=123 "
6757a0c41d5SAlan Somers "vdev_path=/mnt/tmp/file1.7702 "
6767a0c41d5SAlan Somers "vdev_type=file "
6777a0c41d5SAlan Somers "zio_blkid=0 "
6787a0c41d5SAlan Somers "zio_err=0 "
6797a0c41d5SAlan Somers "zio_level=0 "
6807a0c41d5SAlan Somers "zio_object=3 "
6817a0c41d5SAlan Somers "zio_objset=0 "
6827a0c41d5SAlan Somers "zio_offset=16896 "
6837a0c41d5SAlan Somers "zio_size=512";
6847a0c41d5SAlan Somers Event *event(Event::CreateEvent(*m_eventFactory,
6857a0c41d5SAlan Somers evStringStream.str()));
6867a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
6877a0c41d5SAlan Somers EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
6887a0c41d5SAlan Somers delete event;
6897a0c41d5SAlan Somers }
6907a0c41d5SAlan Somers
6917a0c41d5SAlan Somers m_caseFile->SpliceEvents();
6927a0c41d5SAlan Somers EXPECT_TRUE(m_caseFile->ShouldDegrade());
6937a0c41d5SAlan Somers EXPECT_FALSE(m_caseFile->ShouldFault());
6947a0c41d5SAlan Somers }
6957a0c41d5SAlan Somers
6967a0c41d5SAlan Somers /*
6977a0c41d5SAlan Somers * Test CaseFile::ReEvaluateByGuid
6987a0c41d5SAlan Somers */
6997a0c41d5SAlan Somers class ReEvaluateByGuidTest : public ::testing::Test
7007a0c41d5SAlan Somers {
7017a0c41d5SAlan Somers protected:
SetUp()7027a0c41d5SAlan Somers virtual void SetUp()
7037a0c41d5SAlan Somers {
7047a0c41d5SAlan Somers m_eventFactory = new EventFactory();
7057a0c41d5SAlan Somers m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
7067a0c41d5SAlan Somers NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
7077a0c41d5SAlan Somers m_event = Event::CreateEvent(*m_eventFactory, s_evString);
7087a0c41d5SAlan Somers nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
7097a0c41d5SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
7107a0c41d5SAlan Somers ZPOOL_CONFIG_GUID, 0xbeef));
7117a0c41d5SAlan Somers m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
7127a0c41d5SAlan Somers m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
7137a0c41d5SAlan Somers ON_CALL(*m_vdev456, GUID())
7147a0c41d5SAlan Somers .WillByDefault(::testing::Return(Guid(123)));
7157a0c41d5SAlan Somers ON_CALL(*m_vdev456, PoolGUID())
7167a0c41d5SAlan Somers .WillByDefault(::testing::Return(Guid(456)));
7177a0c41d5SAlan Somers ON_CALL(*m_vdev456, State())
7187a0c41d5SAlan Somers .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
7197a0c41d5SAlan Somers ON_CALL(*m_vdev789, GUID())
7207a0c41d5SAlan Somers .WillByDefault(::testing::Return(Guid(123)));
7217a0c41d5SAlan Somers ON_CALL(*m_vdev789, PoolGUID())
7227a0c41d5SAlan Somers .WillByDefault(::testing::Return(Guid(789)));
7237a0c41d5SAlan Somers ON_CALL(*m_vdev789, State())
7247a0c41d5SAlan Somers .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
7257a0c41d5SAlan Somers m_caseFile456 = NULL;
7267a0c41d5SAlan Somers m_caseFile789 = NULL;
7277a0c41d5SAlan Somers return;
7287a0c41d5SAlan Somers }
7297a0c41d5SAlan Somers
TearDown()7307a0c41d5SAlan Somers virtual void TearDown()
7317a0c41d5SAlan Somers {
7327a0c41d5SAlan Somers delete m_caseFile456;
7337a0c41d5SAlan Somers delete m_caseFile789;
7347a0c41d5SAlan Somers nvlist_free(m_vdevConfig);
7357a0c41d5SAlan Somers delete m_vdev456;
7367a0c41d5SAlan Somers delete m_vdev789;
7377a0c41d5SAlan Somers delete m_event;
7387a0c41d5SAlan Somers delete m_eventFactory;
7397a0c41d5SAlan Somers }
7407a0c41d5SAlan Somers
7417a0c41d5SAlan Somers static string s_evString;
7427a0c41d5SAlan Somers nvlist_t *m_vdevConfig;
7437a0c41d5SAlan Somers ::testing::NiceMock<MockVdev> *m_vdev456;
7447a0c41d5SAlan Somers ::testing::NiceMock<MockVdev> *m_vdev789;
7457a0c41d5SAlan Somers TestableCaseFile *m_caseFile456;
7467a0c41d5SAlan Somers TestableCaseFile *m_caseFile789;
7477a0c41d5SAlan Somers Event *m_event;
7487a0c41d5SAlan Somers EventFactory *m_eventFactory;
7497a0c41d5SAlan Somers };
7507a0c41d5SAlan Somers
7517a0c41d5SAlan Somers string ReEvaluateByGuidTest::s_evString(
7527a0c41d5SAlan Somers "!system=ZFS "
7537a0c41d5SAlan Somers "pool_guid=16271873792808333580 "
7547a0c41d5SAlan Somers "pool_name=foo "
7557a0c41d5SAlan Somers "subsystem=ZFS "
7567a0c41d5SAlan Somers "timestamp=1360620391 "
7572a0c0aeaSAlan Somers "type=sysevent.fs.zfs.config_sync");
7587a0c41d5SAlan Somers
7597a0c41d5SAlan Somers
7607a0c41d5SAlan Somers /*
7617a0c41d5SAlan Somers * Test the ReEvaluateByGuid method on an empty list of casefiles.
7627a0c41d5SAlan Somers * We must create one event, even though it never gets used, because it will
7637a0c41d5SAlan Somers * be passed by reference to ReEvaluateByGuid
7647a0c41d5SAlan Somers */
TEST_F(ReEvaluateByGuidTest,ReEvaluateByGuid_empty)7657a0c41d5SAlan Somers TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty)
7667a0c41d5SAlan Somers {
7677a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
7687a0c41d5SAlan Somers
7697a0c41d5SAlan Somers EXPECT_EQ(0, TestableCaseFile::getActiveCases());
7707a0c41d5SAlan Somers CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
7717a0c41d5SAlan Somers EXPECT_EQ(0, TestableCaseFile::getActiveCases());
7727a0c41d5SAlan Somers }
7737a0c41d5SAlan Somers
7747a0c41d5SAlan Somers /*
7757a0c41d5SAlan Somers * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
7767a0c41d5SAlan Somers * one CaseFile, which doesn't match the criteria
7777a0c41d5SAlan Somers */
TEST_F(ReEvaluateByGuidTest,ReEvaluateByGuid_oneFalse)7787a0c41d5SAlan Somers TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse)
7797a0c41d5SAlan Somers {
7807a0c41d5SAlan Somers m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
7817a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
7827a0c41d5SAlan Somers
7837a0c41d5SAlan Somers EXPECT_EQ(1, TestableCaseFile::getActiveCases());
7847a0c41d5SAlan Somers EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
7857a0c41d5SAlan Somers .Times(::testing::Exactly(0));
7867a0c41d5SAlan Somers CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event);
7877a0c41d5SAlan Somers EXPECT_EQ(1, TestableCaseFile::getActiveCases());
7887a0c41d5SAlan Somers }
7897a0c41d5SAlan Somers
7907a0c41d5SAlan Somers /*
7917a0c41d5SAlan Somers * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
7927a0c41d5SAlan Somers * one CaseFile, which does match the criteria
7937a0c41d5SAlan Somers */
TEST_F(ReEvaluateByGuidTest,ReEvaluateByGuid_oneTrue)7947a0c41d5SAlan Somers TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue)
7957a0c41d5SAlan Somers {
7967a0c41d5SAlan Somers m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
7977a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
7987a0c41d5SAlan Somers
7997a0c41d5SAlan Somers EXPECT_EQ(1, TestableCaseFile::getActiveCases());
8007a0c41d5SAlan Somers EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
8017a0c41d5SAlan Somers .Times(::testing::Exactly(1))
8027a0c41d5SAlan Somers .WillRepeatedly(::testing::Return(false));
8037a0c41d5SAlan Somers CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
8047a0c41d5SAlan Somers EXPECT_EQ(1, TestableCaseFile::getActiveCases());
8057a0c41d5SAlan Somers }
8067a0c41d5SAlan Somers
8077a0c41d5SAlan Somers /*
8087a0c41d5SAlan Somers * Test the ReEvaluateByGuid method on a long list of CaseFiles that contains a
8097a0c41d5SAlan Somers * few cases which meet the criteria
8107a0c41d5SAlan Somers */
TEST_F(ReEvaluateByGuidTest,ReEvaluateByGuid_five)8117a0c41d5SAlan Somers TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
8127a0c41d5SAlan Somers {
8137a0c41d5SAlan Somers TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456);
8147a0c41d5SAlan Somers TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789);
8157a0c41d5SAlan Somers TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456);
8167a0c41d5SAlan Somers TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789);
8177a0c41d5SAlan Somers TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789);
8187a0c41d5SAlan Somers ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
8197a0c41d5SAlan Somers
8207a0c41d5SAlan Somers EXPECT_EQ(5, TestableCaseFile::getActiveCases());
8217a0c41d5SAlan Somers EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_))
8227a0c41d5SAlan Somers .Times(::testing::Exactly(1))
8237a0c41d5SAlan Somers .WillRepeatedly(::testing::Return(false));
8247a0c41d5SAlan Somers EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_))
8257a0c41d5SAlan Somers .Times(::testing::Exactly(1))
8267a0c41d5SAlan Somers .WillRepeatedly(::testing::Return(false));
8277a0c41d5SAlan Somers EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_))
8287a0c41d5SAlan Somers .Times(::testing::Exactly(0));
8297a0c41d5SAlan Somers EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_))
8307a0c41d5SAlan Somers .Times(::testing::Exactly(0));
8317a0c41d5SAlan Somers EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_))
8327a0c41d5SAlan Somers .Times(::testing::Exactly(0));
8337a0c41d5SAlan Somers CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
8347a0c41d5SAlan Somers EXPECT_EQ(5, TestableCaseFile::getActiveCases());
8357a0c41d5SAlan Somers delete CaseFile1;
8367a0c41d5SAlan Somers delete CaseFile2;
8377a0c41d5SAlan Somers delete CaseFile3;
8387a0c41d5SAlan Somers delete CaseFile4;
8397a0c41d5SAlan Somers delete CaseFile5;
8407a0c41d5SAlan Somers }
8410b294a38SAlan Somers
8420b294a38SAlan Somers /*
8430b294a38SAlan Somers * Test VdevIterator
8440b294a38SAlan Somers */
8450b294a38SAlan Somers class VdevIteratorTest : public ::testing::Test
8460b294a38SAlan Somers {
8470b294a38SAlan Somers };
8480b294a38SAlan Somers
VdevIteratorTestCB(Vdev & vdev,void * cbArg)8490b294a38SAlan Somers bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) {
8500b294a38SAlan Somers return (false);
8510b294a38SAlan Somers }
8520b294a38SAlan Somers
8530b294a38SAlan Somers /*
8540b294a38SAlan Somers * VdevIterator::Next should not crash when run on a pool that has a previously
8550b294a38SAlan Somers * removed vdev. Regression for
8560b294a38SAlan Somers * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273663
8570b294a38SAlan Somers */
TEST_F(VdevIteratorTest,VdevRemoval)8580b294a38SAlan Somers TEST_F(VdevIteratorTest, VdevRemoval)
8590b294a38SAlan Somers {
8600b294a38SAlan Somers nvlist_t* poolConfig, *rootVdev;
8610b294a38SAlan Somers
8620b294a38SAlan Somers ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0));
8630b294a38SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678));
8640b294a38SAlan Somers /*
8650b294a38SAlan Somers * Note: pools with previously-removed top-level VDEVs will contain a
8660b294a38SAlan Somers * TLV in their labels that has 0 children.
8670b294a38SAlan Somers */
8680b294a38SAlan Somers ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN,
8690b294a38SAlan Somers NULL, 0));
8700b294a38SAlan Somers ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
8710b294a38SAlan Somers ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
8720b294a38SAlan Somers ZPOOL_CONFIG_POOL_GUID, 0x1234));
8730b294a38SAlan Somers ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE,
8740b294a38SAlan Somers rootVdev));
8750b294a38SAlan Somers
8760b294a38SAlan Somers VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL);
8770b294a38SAlan Somers }
878