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