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