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