View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.errorhandling;
19  
20  import static org.junit.Assert.assertTrue;
21  import static org.junit.Assert.fail;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.hbase.testclassification.SmallTests;
26  import org.junit.Test;
27  import org.junit.experimental.categories.Category;
28  import org.mockito.Mockito;
29  
30  /**
31   * Test that we propagate errors through an dispatcher exactly once via different failure
32   * injection mechanisms.
33   */
34  @Category(SmallTests.class)
35  public class TestForeignExceptionDispatcher {
36    private static final Log LOG = LogFactory.getLog(TestForeignExceptionDispatcher.class);
37  
38    /**
39     * Exception thrown from the test
40     */
41    final ForeignException EXTEXN = new ForeignException("FORTEST", new IllegalArgumentException("FORTEST"));
42    final ForeignException EXTEXN2 = new ForeignException("FORTEST2", new IllegalArgumentException("FORTEST2"));
43  
44    /**
45     * Tests that a dispatcher only dispatches only the first exception, and does not propagate
46     * subsequent exceptions.
47     */
48    @Test
49    public void testErrorPropagation() {
50      ForeignExceptionListener listener1 = Mockito.mock(ForeignExceptionListener.class);
51      ForeignExceptionListener listener2 = Mockito.mock(ForeignExceptionListener.class);
52      ForeignExceptionDispatcher dispatcher = new ForeignExceptionDispatcher();
53  
54      // add the listeners
55      dispatcher.addListener(listener1);
56      dispatcher.addListener(listener2);
57  
58      // create an artificial error
59      dispatcher.receive(EXTEXN);
60  
61      // make sure the listeners got the error
62      Mockito.verify(listener1, Mockito.times(1)).receive(EXTEXN);
63      Mockito.verify(listener2, Mockito.times(1)).receive(EXTEXN);
64  
65      // make sure that we get an exception
66      try {
67        dispatcher.rethrowException();
68        fail("Monitor should have thrown an exception after getting error.");
69      } catch (ForeignException ex) {
70        assertTrue("Got an unexpected exception:" + ex, ex.getCause() == EXTEXN.getCause());
71        LOG.debug("Got the testing exception!");
72      }
73  
74      // push another error, which should be not be passed to listeners
75      dispatcher.receive(EXTEXN2);
76      Mockito.verify(listener1, Mockito.never()).receive(EXTEXN2);
77      Mockito.verify(listener2, Mockito.never()).receive(EXTEXN2);
78    }
79  
80    @Test
81    public void testSingleDispatcherWithTimer() {
82      ForeignExceptionListener listener1 = Mockito.mock(ForeignExceptionListener.class);
83      ForeignExceptionListener listener2 = Mockito.mock(ForeignExceptionListener.class);
84  
85      ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher();
86  
87      // add the listeners
88      monitor.addListener(listener1);
89      monitor.addListener(listener2);
90  
91      TimeoutExceptionInjector timer = new TimeoutExceptionInjector(monitor, 1000);
92      timer.start();
93      timer.trigger();
94  
95      assertTrue("Monitor didn't get timeout", monitor.hasException());
96  
97      // verify that that we propagated the error
98      Mockito.verify(listener1).receive(Mockito.any(ForeignException.class));
99      Mockito.verify(listener2).receive(Mockito.any(ForeignException.class));
100   }
101 
102   /**
103    * Test that the dispatcher can receive an error via the timer mechanism.
104    */
105   @Test
106   public void testAttemptTimer() {
107     ForeignExceptionListener listener1 = Mockito.mock(ForeignExceptionListener.class);
108     ForeignExceptionListener listener2 = Mockito.mock(ForeignExceptionListener.class);
109     ForeignExceptionDispatcher orchestrator = new ForeignExceptionDispatcher();
110 
111     // add the listeners
112     orchestrator.addListener(listener1);
113     orchestrator.addListener(listener2);
114 
115     // now create a timer and check for that error
116     TimeoutExceptionInjector timer = new TimeoutExceptionInjector(orchestrator, 1000);
117     timer.start();
118     timer.trigger();
119     // make sure that we got the timer error
120     Mockito.verify(listener1, Mockito.times(1)).receive(Mockito.any(ForeignException.class));
121     Mockito.verify(listener2, Mockito.times(1)).receive(Mockito.any(ForeignException.class));
122   }
123 }