xref: /freebsd/cddl/usr.sbin/zfsd/tests/zfsd_unittest.cc (revision 83823d063ab57db8d3954c1530d036f1ccdceb41)
1 /*-
2  * Copyright (c) 2012, 2013, 2014 Spectra Logic Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    substantially similar to the "NO WARRANTY" disclaimer below
13  *    ("Disclaimer") and any redistribution must be conditioned upon
14  *    including a substantially similar Disclaimer requirement for further
15  *    binary redistribution.
16  *
17  * NO WARRANTY
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGES.
29  *
30  * Authors: Alan Somers         (Spectra Logic Corporation)
31  */
32 #include <sys/cdefs.h>
33 #include <sys/byteorder.h>
34 
35 #include <stdarg.h>
36 #include <syslog.h>
37 
38 #include <libnvpair.h>
39 #include <libzfs.h>
40 
41 #include <list>
42 #include <map>
43 #include <sstream>
44 #include <string>
45 
46 #include <gmock/gmock.h>
47 #include <gtest/gtest.h>
48 
49 #include <devdctl/guid.h>
50 #include <devdctl/event.h>
51 #include <devdctl/event_factory.h>
52 #include <devdctl/exception.h>
53 #include <devdctl/consumer.h>
54 
55 #include <zfsd/callout.h>
56 #include <zfsd/vdev_iterator.h>
57 #include <zfsd/zfsd_event.h>
58 #include <zfsd/case_file.h>
59 #include <zfsd/vdev.h>
60 #include <zfsd/zfsd.h>
61 #include <zfsd/zfsd_exception.h>
62 #include <zfsd/zpool_list.h>
63 
64 #include "libmocks.h"
65 /*================================== Macros ==================================*/
66 #define	NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
67 
68 /*============================ Namespace Control =============================*/
69 using std::string;
70 using std::stringstream;
71 
72 using DevdCtl::Event;
73 using DevdCtl::EventFactory;
74 using DevdCtl::EventList;
75 using DevdCtl::Guid;
76 using DevdCtl::NVPairMap;
77 
78 /* redefine zpool_handle here because libzfs_impl.h is not includable */
79 struct zpool_handle
80 {
81         libzfs_handle_t *zpool_hdl;
82         zpool_handle_t *zpool_next;
83         char zpool_name[ZFS_MAX_DATASET_NAME_LEN];
84         int zpool_state;
85         size_t zpool_config_size;
86         nvlist_t *zpool_config;
87         nvlist_t *zpool_old_config;
88         nvlist_t *zpool_props;
89         diskaddr_t zpool_start_block;
90 };
91 
92 class MockZfsEvent : public ZfsEvent
93 {
94 public:
95 	MockZfsEvent(Event::Type, NVPairMap&, const string&);
96 	virtual ~MockZfsEvent() {}
97 
98 	static BuildMethod MockZfsEventBuilder;
99 
100 	MOCK_CONST_METHOD0(ProcessPoolEvent, void());
101 
102 	static EventFactory::Record s_buildRecords[];
103 };
104 
105 EventFactory::Record MockZfsEvent::s_buildRecords[] =
106 {
107         { Event::NOTIFY, "ZFS", &MockZfsEvent::MockZfsEventBuilder }
108 };
109 
110 MockZfsEvent::MockZfsEvent(Event::Type type, NVPairMap& map,
111 			   const string& str)
112  : ZfsEvent(type, map, str)
113 {
114 }
115 
116 Event *
117 MockZfsEvent::MockZfsEventBuilder(Event::Type type,
118 				  NVPairMap &nvpairs,
119 			  	  const string &eventString)
120 {
121 	return (new MockZfsEvent(type, nvpairs, eventString));
122 }
123 
124 /*
125  * A dummy Vdev class used for testing other classes
126  */
127 class MockVdev : public Vdev
128 {
129 public:
130 	MockVdev(nvlist_t *vdevConfig);
131 	virtual ~MockVdev() {}
132 
133 	MOCK_CONST_METHOD0(GUID, Guid());
134 	MOCK_CONST_METHOD0(PoolGUID, Guid());
135 	MOCK_CONST_METHOD0(State, vdev_state());
136 	MOCK_CONST_METHOD0(PhysicalPath, string());
137 };
138 
139 MockVdev::MockVdev(nvlist_t *vdevConfig)
140  : Vdev(vdevConfig)
141 {
142 }
143 
144 /*
145  * A CaseFile class with side effects removed, for testing
146  */
147 class TestableCaseFile : public CaseFile
148 {
149 public:
150 	static TestableCaseFile &Create(Vdev &vdev);
151 	TestableCaseFile(Vdev &vdev);
152 	virtual ~TestableCaseFile() {}
153 
154 	MOCK_METHOD0(Close, void());
155 	MOCK_METHOD1(RegisterCallout, void(const Event &event));
156 	MOCK_METHOD0(RefreshVdevState, bool());
157 	MOCK_METHOD1(ReEvaluate, bool(const ZfsEvent &event));
158 
159 	bool RealReEvaluate(const ZfsEvent &event)
160 	{
161 		return (CaseFile::ReEvaluate(event));
162 	}
163 
164 	/*
165 	 * This splices the event lists, a procedure that would normally be done
166 	 * by OnGracePeriodEnded, but we don't necessarily call that in the
167 	 * unit tests
168 	 */
169 	void SpliceEvents();
170 
171 	/*
172 	 * Used by some of our expectations.  CaseFile does not publicize this
173 	 */
174 	static int getActiveCases()
175 	{
176 		return (s_activeCases.size());
177 	}
178 };
179 
180 TestableCaseFile::TestableCaseFile(Vdev &vdev)
181  : CaseFile(vdev)
182 {
183 }
184 
185 TestableCaseFile &
186 TestableCaseFile::Create(Vdev &vdev)
187 {
188 	TestableCaseFile *newCase;
189 	newCase = new TestableCaseFile(vdev);
190 	return (*newCase);
191 }
192 
193 void
194 TestableCaseFile::SpliceEvents()
195 {
196 	m_events.splice(m_events.begin(), m_tentativeEvents);
197 }
198 
199 
200 /*
201  * Test class ZfsdException
202  */
203 class ZfsdExceptionTest : public ::testing::Test
204 {
205 protected:
206 	virtual void SetUp()
207 	{
208 		ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
209 		ASSERT_EQ(0, nvlist_add_string(poolConfig,
210 				ZPOOL_CONFIG_POOL_NAME, "unit_test_pool"));
211 		ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
212 				ZPOOL_CONFIG_POOL_GUID, 0x1234));
213 
214 		ASSERT_EQ(0, nvlist_alloc(&vdevConfig, NV_UNIQUE_NAME, 0));
215 		ASSERT_EQ(0, nvlist_add_uint64(vdevConfig,
216 				ZPOOL_CONFIG_GUID, 0x5678));
217 		bzero(&poolHandle, sizeof(poolHandle));
218 		poolHandle.zpool_config = poolConfig;
219 	}
220 
221 	virtual void TearDown()
222 	{
223 		nvlist_free(poolConfig);
224 		nvlist_free(vdevConfig);
225 	}
226 
227 	nvlist_t	*poolConfig;
228 	nvlist_t	*vdevConfig;
229 	zpool_handle_t   poolHandle;
230 };
231 
232 TEST_F(ZfsdExceptionTest, StringConstructorNull)
233 {
234 	ZfsdException ze("");
235 	EXPECT_STREQ("", ze.GetString().c_str());
236 }
237 
238 TEST_F(ZfsdExceptionTest, StringConstructorFormatted)
239 {
240 	ZfsdException ze(" %d %s", 55, "hello world");
241 	EXPECT_STREQ(" 55 hello world", ze.GetString().c_str());
242 }
243 
244 TEST_F(ZfsdExceptionTest, LogSimple)
245 {
246 	ZfsdException ze("unit test w/o vdev or pool");
247 	ze.Log();
248 	EXPECT_EQ(LOG_ERR, syslog_last_priority);
249 	EXPECT_STREQ("unit test w/o vdev or pool\n", syslog_last_message);
250 }
251 
252 TEST_F(ZfsdExceptionTest, Pool)
253 {
254 	const char msg[] = "Exception with pool name";
255 	char expected[4096];
256 	sprintf(expected, "Pool unit_test_pool: %s\n", msg);
257 	ZfsdException ze(poolConfig, msg);
258 	ze.Log();
259 	EXPECT_STREQ(expected, syslog_last_message);
260 }
261 
262 TEST_F(ZfsdExceptionTest, PoolHandle)
263 {
264 	const char msg[] = "Exception with pool handle";
265 	char expected[4096];
266 	sprintf(expected, "Pool unit_test_pool: %s\n", msg);
267 	ZfsdException ze(&poolHandle, msg);
268 	ze.Log();
269 	EXPECT_STREQ(expected, syslog_last_message);
270 }
271 
272 /*
273  * Test class Vdev
274  */
275 class VdevTest : public ::testing::Test
276 {
277 protected:
278 	virtual void SetUp()
279 	{
280 		ASSERT_EQ(0, nvlist_alloc(&m_poolConfig, NV_UNIQUE_NAME, 0));
281 		ASSERT_EQ(0, nvlist_add_uint64(m_poolConfig,
282 					       ZPOOL_CONFIG_POOL_GUID,
283 					       0x1234));
284 
285 		ASSERT_EQ(0, nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0));
286 		ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_GUID,
287 					       0x5678));
288 	}
289 
290 	virtual void TearDown()
291 	{
292 		nvlist_free(m_poolConfig);
293 		nvlist_free(m_vdevConfig);
294 	}
295 
296 	nvlist_t	*m_poolConfig;
297 	nvlist_t	*m_vdevConfig;
298 };
299 
300 
301 TEST_F(VdevTest, StateFromConfig)
302 {
303 	vdev_stat_t vs;
304 
305 	vs.vs_state = VDEV_STATE_OFFLINE;
306 
307 	ASSERT_EQ(0, nvlist_add_uint64_array(m_vdevConfig,
308 					     ZPOOL_CONFIG_VDEV_STATS,
309 					     (uint64_t*)&vs,
310 					     sizeof(vs) / sizeof(uint64_t)));
311 
312 	Vdev vdev(m_poolConfig, m_vdevConfig);
313 
314 	EXPECT_EQ(VDEV_STATE_OFFLINE, vdev.State());
315 }
316 
317 TEST_F(VdevTest, StateFaulted)
318 {
319 	ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_FAULTED, 1));
320 
321 	Vdev vdev(m_poolConfig, m_vdevConfig);
322 
323 	EXPECT_EQ(VDEV_STATE_FAULTED, vdev.State());
324 }
325 
326 /*
327  * Test that we can construct a Vdev from the label information that is stored
328  * on an available spare drive
329  */
330 TEST_F(VdevTest, ConstructAvailSpare)
331 {
332 	nvlist_t	*labelConfig;
333 
334 	ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
335 	ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
336 				       1948339428197961030));
337 	ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
338 				       POOL_STATE_SPARE));
339 
340 	EXPECT_NO_THROW(Vdev vdev(labelConfig));
341 
342 	nvlist_free(labelConfig);
343 }
344 
345 /* Available spares will always show the HEALTHY state */
346 TEST_F(VdevTest, AvailSpareState) {
347 	nvlist_t	*labelConfig;
348 
349 	ASSERT_EQ(0, nvlist_alloc(&labelConfig, NV_UNIQUE_NAME, 0));
350 	ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_GUID,
351 				       1948339428197961030));
352 	ASSERT_EQ(0, nvlist_add_uint64(labelConfig, ZPOOL_CONFIG_POOL_STATE,
353 				       POOL_STATE_SPARE));
354 
355 	Vdev vdev(labelConfig);
356 	EXPECT_EQ(VDEV_STATE_HEALTHY, vdev.State());
357 
358 	nvlist_free(labelConfig);
359 }
360 
361 /* Test the Vdev::IsSpare method */
362 TEST_F(VdevTest, IsSpare) {
363 	Vdev notSpare(m_poolConfig, m_vdevConfig);
364 	EXPECT_EQ(false, notSpare.IsSpare());
365 
366 	ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1));
367 	Vdev isSpare(m_poolConfig, m_vdevConfig);
368 	EXPECT_EQ(true, isSpare.IsSpare());
369 }
370 
371 /*
372  * Test class ZFSEvent
373  */
374 class ZfsEventTest : public ::testing::Test
375 {
376 protected:
377 	virtual void SetUp()
378 	{
379 		m_eventFactory = new EventFactory();
380 		m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
381 		    NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
382 
383 		m_event = NULL;
384 	}
385 
386 	virtual void TearDown()
387 	{
388 		delete m_eventFactory;
389 		delete m_event;
390 	}
391 
392 	EventFactory	*m_eventFactory;
393 	Event		*m_event;
394 };
395 
396 TEST_F(ZfsEventTest, ProcessPoolEventGetsCalled)
397 {
398 	string evString("!system=ZFS "
399 			"subsystem=ZFS "
400 			"type=sysevent.fs.zfs.vdev_remove "
401 			"pool_name=foo "
402 			"pool_guid=9756779504028057996 "
403 			"vdev_guid=1631193447431603339 "
404 			"vdev_path=/dev/da1 "
405 			"timestamp=1348871594");
406 	m_event = Event::CreateEvent(*m_eventFactory, evString);
407 	MockZfsEvent *mock_event = static_cast<MockZfsEvent*>(m_event);
408 
409 	EXPECT_CALL(*mock_event, ProcessPoolEvent()).Times(1);
410 	mock_event->Process();
411 }
412 
413 /*
414  * Test class CaseFile
415  */
416 
417 class CaseFileTest : public ::testing::Test
418 {
419 protected:
420 	virtual void SetUp()
421 	{
422 		m_eventFactory = new EventFactory();
423 		m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
424 		    NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
425 
426 		m_event = NULL;
427 
428 		nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
429 		ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
430 					       ZPOOL_CONFIG_GUID, 0xbeef));
431 		m_vdev = new MockVdev(m_vdevConfig);
432 		ON_CALL(*m_vdev, GUID())
433 		    .WillByDefault(::testing::Return(Guid(123)));
434 		ON_CALL(*m_vdev, PoolGUID())
435 		    .WillByDefault(::testing::Return(Guid(456)));
436 		ON_CALL(*m_vdev, State())
437 		    .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
438 		m_caseFile = &TestableCaseFile::Create(*m_vdev);
439 		ON_CALL(*m_caseFile, ReEvaluate(::testing::_))
440 		    .WillByDefault(::testing::Invoke(m_caseFile, &TestableCaseFile::RealReEvaluate));
441 		return;
442 	}
443 
444 	virtual void TearDown()
445 	{
446 		delete m_caseFile;
447 		nvlist_free(m_vdevConfig);
448 		delete m_vdev;
449 		delete m_event;
450 		delete m_eventFactory;
451 	}
452 
453 	nvlist_t		*m_vdevConfig;
454 	MockVdev		*m_vdev;
455 	TestableCaseFile 	*m_caseFile;
456 	Event			*m_event;
457 	EventFactory		*m_eventFactory;
458 };
459 
460 /*
461  * A Vdev with no events should not be degraded or faulted
462  */
463 TEST_F(CaseFileTest, HealthyVdev)
464 {
465 	EXPECT_FALSE(m_caseFile->ShouldDegrade());
466 	EXPECT_FALSE(m_caseFile->ShouldFault());
467 }
468 
469 /*
470  * A Vdev with only one event should not be degraded or faulted
471  * For performance reasons, RefreshVdevState should not be called.
472  */
473 TEST_F(CaseFileTest, HealthyishVdev)
474 {
475 	string evString("!system=ZFS "
476 			"class=ereport.fs.zfs.io "
477 			"ena=12091638756982918145 "
478 			"parent_guid=13237004955564865395 "
479 			"parent_type=raidz "
480 			"pool=testpool.4415 "
481 			"pool_context=0 "
482 			"pool_failmode=wait "
483 			"pool_guid=456 "
484 			"subsystem=ZFS "
485 			"timestamp=1348867914 "
486 			"type=ereport.fs.zfs.io "
487 			"vdev_guid=123 "
488 			"vdev_path=/dev/da400 "
489 			"vdev_type=disk "
490 			"zio_blkid=622 "
491 			"zio_err=1 "
492 			"zio_level=-2 "
493 			"zio_object=0 "
494 			"zio_objset=37 "
495 			"zio_offset=25598976 "
496 			"zio_size=1024");
497 	m_event = Event::CreateEvent(*m_eventFactory, evString);
498 	ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
499 
500 	EXPECT_CALL(*m_caseFile, RefreshVdevState())
501 	    .Times(::testing::Exactly(0));
502 	EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
503 	EXPECT_FALSE(m_caseFile->ShouldDegrade());
504 	EXPECT_FALSE(m_caseFile->ShouldFault());
505 }
506 
507 /* The case file should be closed when its pool is destroyed */
508 TEST_F(CaseFileTest, PoolDestroy)
509 {
510 	string evString("!system=ZFS "
511 			"pool_name=testpool.4415 "
512 			"pool_guid=456 "
513 			"subsystem=ZFS "
514 			"timestamp=1348867914 "
515 			"type=sysevent.fs.zfs.pool_destroy ");
516 	m_event = Event::CreateEvent(*m_eventFactory, evString);
517 	ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
518 	EXPECT_CALL(*m_caseFile, Close());
519 	EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
520 }
521 
522 /*
523  * A Vdev with a very large number of IO errors should fault
524  * For performance reasons, RefreshVdevState should be called at most once
525  */
526 TEST_F(CaseFileTest, VeryManyIOErrors)
527 {
528 	EXPECT_CALL(*m_caseFile, RefreshVdevState())
529 	    .Times(::testing::AtMost(1))
530 	    .WillRepeatedly(::testing::Return(true));
531 
532 	for(int i=0; i<100; i++) {
533 		stringstream evStringStream;
534 		evStringStream <<
535 			"!system=ZFS "
536 			"class=ereport.fs.zfs.io "
537 			"ena=12091638756982918145 "
538 			"parent_guid=13237004955564865395 "
539 			"parent_type=raidz "
540 			"pool=testpool.4415 "
541 			"pool_context=0 "
542 			"pool_failmode=wait "
543 			"pool_guid=456 "
544 			"subsystem=ZFS "
545 			"timestamp=";
546 		evStringStream << i << " ";
547 		evStringStream <<
548 			"type=ereport.fs.zfs.io "
549 			"vdev_guid=123 "
550 			"vdev_path=/dev/da400 "
551 			"vdev_type=disk "
552 			"zio_blkid=622 "
553 			"zio_err=1 "
554 			"zio_level=-2 "
555 			"zio_object=0 "
556 			"zio_objset=37 "
557 			"zio_offset=25598976 "
558 			"zio_size=1024";
559 		Event *event(Event::CreateEvent(*m_eventFactory,
560 						evStringStream.str()));
561 		ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
562 		EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
563 		delete event;
564 	}
565 
566 	m_caseFile->SpliceEvents();
567 	EXPECT_FALSE(m_caseFile->ShouldDegrade());
568 	EXPECT_TRUE(m_caseFile->ShouldFault());
569 }
570 
571 /*
572  * A Vdev with a very large number of checksum errors should degrade
573  * For performance reasons, RefreshVdevState should be called at most once
574  */
575 TEST_F(CaseFileTest, VeryManyChecksumErrors)
576 {
577 	EXPECT_CALL(*m_caseFile, RefreshVdevState())
578 	    .Times(::testing::AtMost(1))
579 	    .WillRepeatedly(::testing::Return(true));
580 
581 	for(int i=0; i<100; i++) {
582 		stringstream evStringStream;
583 		evStringStream <<
584 			"!system=ZFS "
585 			"bad_cleared_bits=03000000000000803f50b00000000000 "
586 			"bad_range_clears=0000000e "
587 			"bad_range_sets=00000000 "
588 			"bad_ranges=0000000000000010 "
589 			"bad_ranges_min_gap=8 "
590 			"bad_set_bits=00000000000000000000000000000000 "
591 			"class=ereport.fs.zfs.checksum "
592 			"ena=12272856582652437505 "
593 			"parent_guid=5838204195352909894 "
594 			"parent_type=raidz pool=testpool.7640 "
595 			"pool_context=0 "
596 			"pool_failmode=wait "
597 			"pool_guid=456 "
598 			"subsystem=ZFS timestamp=";
599 		evStringStream << i << " ";
600 		evStringStream <<
601 			"type=ereport.fs.zfs.checksum "
602 			"vdev_guid=123 "
603 			"vdev_path=/mnt/tmp/file1.7702 "
604 			"vdev_type=file "
605 			"zio_blkid=0 "
606 			"zio_err=0 "
607 			"zio_level=0 "
608 			"zio_object=3 "
609 			"zio_objset=0 "
610 			"zio_offset=16896 "
611 			"zio_size=512";
612 		Event *event(Event::CreateEvent(*m_eventFactory,
613 						evStringStream.str()));
614 		ZfsEvent *zfs_event = static_cast<ZfsEvent*>(event);
615 		EXPECT_TRUE(m_caseFile->ReEvaluate(*zfs_event));
616 		delete event;
617 	}
618 
619 	m_caseFile->SpliceEvents();
620 	EXPECT_TRUE(m_caseFile->ShouldDegrade());
621 	EXPECT_FALSE(m_caseFile->ShouldFault());
622 }
623 
624 /*
625  * Test CaseFile::ReEvaluateByGuid
626  */
627 class ReEvaluateByGuidTest : public ::testing::Test
628 {
629 protected:
630 	virtual void SetUp()
631 	{
632 		m_eventFactory = new EventFactory();
633 		m_eventFactory->UpdateRegistry(MockZfsEvent::s_buildRecords,
634 		    NUM_ELEMENTS(MockZfsEvent::s_buildRecords));
635 		m_event = Event::CreateEvent(*m_eventFactory, s_evString);
636 		nvlist_alloc(&m_vdevConfig, NV_UNIQUE_NAME, 0);
637 		ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig,
638 					       ZPOOL_CONFIG_GUID, 0xbeef));
639 		m_vdev456 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
640 		m_vdev789 = new ::testing::NiceMock<MockVdev>(m_vdevConfig);
641 		ON_CALL(*m_vdev456, GUID())
642 		    .WillByDefault(::testing::Return(Guid(123)));
643 		ON_CALL(*m_vdev456, PoolGUID())
644 		    .WillByDefault(::testing::Return(Guid(456)));
645 		ON_CALL(*m_vdev456, State())
646 		    .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
647 		ON_CALL(*m_vdev789, GUID())
648 		    .WillByDefault(::testing::Return(Guid(123)));
649 		ON_CALL(*m_vdev789, PoolGUID())
650 		    .WillByDefault(::testing::Return(Guid(789)));
651 		ON_CALL(*m_vdev789, State())
652 		    .WillByDefault(::testing::Return(VDEV_STATE_HEALTHY));
653 		m_caseFile456 = NULL;
654 		m_caseFile789 = NULL;
655 		return;
656 	}
657 
658 	virtual void TearDown()
659 	{
660 		delete m_caseFile456;
661 		delete m_caseFile789;
662 		nvlist_free(m_vdevConfig);
663 		delete m_vdev456;
664 		delete m_vdev789;
665 		delete m_event;
666 		delete m_eventFactory;
667 	}
668 
669 	static string			 s_evString;
670 	nvlist_t			*m_vdevConfig;
671 	::testing::NiceMock<MockVdev>	*m_vdev456;
672 	::testing::NiceMock<MockVdev>	*m_vdev789;
673 	TestableCaseFile 		*m_caseFile456;
674 	TestableCaseFile 		*m_caseFile789;
675 	Event				*m_event;
676 	EventFactory			*m_eventFactory;
677 };
678 
679 string ReEvaluateByGuidTest::s_evString(
680 	"!system=ZFS "
681 	"pool_guid=16271873792808333580 "
682 	"pool_name=foo "
683 	"subsystem=ZFS "
684 	"timestamp=1360620391 "
685 	"type=sysevent.fs.zfs.config_sync");
686 
687 
688 /*
689  * Test the ReEvaluateByGuid method on an empty list of casefiles.
690  * We must create one event, even though it never gets used, because it will
691  * be passed by reference to ReEvaluateByGuid
692  */
693 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_empty)
694 {
695 	ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
696 
697 	EXPECT_EQ(0, TestableCaseFile::getActiveCases());
698 	CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
699 	EXPECT_EQ(0, TestableCaseFile::getActiveCases());
700 }
701 
702 /*
703  * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
704  * one CaseFile, which doesn't match the criteria
705  */
706 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneFalse)
707 {
708 	m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
709 	ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
710 
711 	EXPECT_EQ(1, TestableCaseFile::getActiveCases());
712 	EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
713 	    .Times(::testing::Exactly(0));
714 	CaseFile::ReEvaluateByGuid(Guid(789), *zfs_event);
715 	EXPECT_EQ(1, TestableCaseFile::getActiveCases());
716 }
717 
718 /*
719  * Test the ReEvaluateByGuid method on a list of CaseFiles that contains only
720  * one CaseFile, which does match the criteria
721  */
722 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_oneTrue)
723 {
724 	m_caseFile456 = &TestableCaseFile::Create(*m_vdev456);
725 	ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
726 
727 	EXPECT_EQ(1, TestableCaseFile::getActiveCases());
728 	EXPECT_CALL(*m_caseFile456, ReEvaluate(::testing::_))
729 	    .Times(::testing::Exactly(1))
730 	    .WillRepeatedly(::testing::Return(false));
731 	CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
732 	EXPECT_EQ(1, TestableCaseFile::getActiveCases());
733 }
734 
735 /*
736  * Test the ReEvaluateByGuid method on a long list of CaseFiles that contains a
737  * few cases which meet the criteria
738  */
739 TEST_F(ReEvaluateByGuidTest, ReEvaluateByGuid_five)
740 {
741 	TestableCaseFile *CaseFile1 = &TestableCaseFile::Create(*m_vdev456);
742 	TestableCaseFile *CaseFile2 = &TestableCaseFile::Create(*m_vdev789);
743 	TestableCaseFile *CaseFile3 = &TestableCaseFile::Create(*m_vdev456);
744 	TestableCaseFile *CaseFile4 = &TestableCaseFile::Create(*m_vdev789);
745 	TestableCaseFile *CaseFile5 = &TestableCaseFile::Create(*m_vdev789);
746 	ZfsEvent *zfs_event = static_cast<ZfsEvent*>(m_event);
747 
748 	EXPECT_EQ(5, TestableCaseFile::getActiveCases());
749 	EXPECT_CALL(*CaseFile1, ReEvaluate(::testing::_))
750 	    .Times(::testing::Exactly(1))
751 	    .WillRepeatedly(::testing::Return(false));
752 	EXPECT_CALL(*CaseFile3, ReEvaluate(::testing::_))
753 	    .Times(::testing::Exactly(1))
754 	    .WillRepeatedly(::testing::Return(false));
755 	EXPECT_CALL(*CaseFile2, ReEvaluate(::testing::_))
756 	    .Times(::testing::Exactly(0));
757 	EXPECT_CALL(*CaseFile4, ReEvaluate(::testing::_))
758 	    .Times(::testing::Exactly(0));
759 	EXPECT_CALL(*CaseFile5, ReEvaluate(::testing::_))
760 	    .Times(::testing::Exactly(0));
761 	CaseFile::ReEvaluateByGuid(Guid(456), *zfs_event);
762 	EXPECT_EQ(5, TestableCaseFile::getActiveCases());
763 	delete CaseFile1;
764 	delete CaseFile2;
765 	delete CaseFile3;
766 	delete CaseFile4;
767 	delete CaseFile5;
768 }
769 
770 /*
771  * Test VdevIterator
772  */
773 class VdevIteratorTest : public ::testing::Test
774 {
775 };
776 
777 bool VdevIteratorTestCB(Vdev &vdev, void *cbArg) {
778 	return (false);
779 }
780 
781 /*
782  * VdevIterator::Next should not crash when run on a pool that has a previously
783  * removed vdev.  Regression for
784  * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273663
785  */
786 TEST_F(VdevIteratorTest, VdevRemoval)
787 {
788 	nvlist_t* poolConfig, *rootVdev;
789 
790 	ASSERT_EQ(0, nvlist_alloc(&rootVdev, NV_UNIQUE_NAME, 0));
791 	ASSERT_EQ(0, nvlist_add_uint64(rootVdev, ZPOOL_CONFIG_GUID, 0x5678));
792 	/*
793 	 * Note: pools with previously-removed top-level VDEVs will contain a
794 	 * TLV in their labels that has 0 children.
795 	 */
796 	ASSERT_EQ(0, nvlist_add_nvlist_array(rootVdev, ZPOOL_CONFIG_CHILDREN,
797 				NULL, 0));
798 	ASSERT_EQ(0, nvlist_alloc(&poolConfig, NV_UNIQUE_NAME, 0));
799 	ASSERT_EQ(0, nvlist_add_uint64(poolConfig,
800 			ZPOOL_CONFIG_POOL_GUID, 0x1234));
801 	ASSERT_EQ(0, nvlist_add_nvlist(poolConfig, ZPOOL_CONFIG_VDEV_TREE,
802 				rootVdev));
803 
804 	VdevIterator(poolConfig).Each(VdevIteratorTestCB, NULL);
805 }
806