View Javadoc

1   package com.atlassian.sal.core.rdbms;
2   
3   import com.atlassian.sal.api.rdbms.RdbmsException;
4   import org.hamcrest.Description;
5   import org.hamcrest.Matcher;
6   import org.hamcrest.TypeSafeMatcher;
7   import org.junit.Test;
8   import org.junit.runner.RunWith;
9   import org.junit.runners.Parameterized;
10  
11  import java.sql.SQLException;
12  import java.util.Arrays;
13  import java.util.Collection;
14  
15  import static org.hamcrest.Matchers.nullValue;
16  import static org.hamcrest.core.Is.is;
17  import static org.hamcrest.core.Is.isA;
18  import static org.junit.Assert.assertThat;
19  import static org.mockito.Matchers.any;
20  import static org.mockito.Mockito.*;
21  
22  @RunWith (Parameterized.class)
23  public class TestDefaultTransactionalExecutorExceptions extends TestDefaultTransactionalExecutorBase
24  {
25      @Parameterized.Parameters(name = "{index}: throwing {0}")
26      public static Collection data () {
27          return Arrays.asList(new Object[][] {
28                  { new SQLException("horrible commit exception") },
29                  { new LinkageError("horrible linkage error") },
30          });
31      }
32      @Parameterized.Parameter(0)
33      public Throwable exception;
34  
35      @Test
36      public void executeCommitFails() throws SQLException
37      {
38          doThrow(exception).when(connection).commit();
39  
40          expectedException.expect(RdbmsException.class);
41          expectedException.expectCause(isA(exception.getClass()));
42  
43          defaultTransactionalExecutor.executeInternal(connection, callback);
44          assertThat(wrappedConnection.connection, nullValue());
45  
46          verify(callback).execute(any(WrappedConnection.class));
47          verify(connection).commit();
48          verify(connection, never()).rollback();
49      }
50  
51      @Test
52      public void executeRollbackFails() throws SQLException
53      {
54          callbackThrows = new TestDefaultTransactionalExecutorBase.CallbackException("epic fail");
55  
56          doThrow(exception).when(connection).rollback();
57  
58          expectedException.expect(CallbackException.class);
59          expectedException.expectMessage("epic fail");
60          expectedException.expect(new SuppressedMatches(is(exception)));
61  
62          defaultTransactionalExecutor.executeInternal(connection, callback);
63          assertThat(wrappedConnection.connection, nullValue());
64  
65          verify(callback).execute(any(WrappedConnection.class));
66          verify(connection, never()).commit();
67          verify(connection).rollback();
68      }
69  
70      private static class SuppressedMatches<T extends Throwable> extends TypeSafeMatcher<T> {
71          private Matcher<T> expectedSuppressed;
72          public SuppressedMatches(Matcher<T> expectedSuppressed)
73          {
74              this.expectedSuppressed = expectedSuppressed;
75          }
76  
77          @Override
78          protected void describeMismatchSafely(final T item, final Description mismatchDescription)
79          {
80              mismatchDescription.appendText("was not found in ").appendValue(item.getSuppressed());
81          }
82  
83          @Override
84          public void describeTo(final Description description)
85          {
86              description.appendText("a suppressed exception matching(");
87              expectedSuppressed.describeTo(description);
88              description.appendText(")");
89          }
90  
91          @Override
92          public boolean matchesSafely(final Throwable t)
93          {
94              for (Throwable s: t.getSuppressed())
95              {
96                  if (expectedSuppressed.matches(s))
97                  {
98                      return true;
99                  }
100             }
101 
102             return false;
103         }
104     }
105 }