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.doThrow;
21  import static org.mockito.Mockito.never;
22  import static org.mockito.Mockito.verify;
23  
24  @RunWith(Parameterized.class)
25  public class TestDefaultTransactionalExecutorExceptions extends TestDefaultTransactionalExecutorBase {
26      @Parameterized.Parameters(name = "{index}: throwing {0}")
27      public static Collection data() {
28          return Arrays.asList(new Object[][]{
29                  {new SQLException("horrible commit exception")},
30                  {new LinkageError("horrible linkage error")},
31          });
32      }
33  
34      @Parameterized.Parameter(0)
35      public Throwable exception;
36  
37      @Test
38      public void executeCommitFails() throws SQLException {
39          doThrow(exception).when(connection).commit();
40  
41          expectedException.expect(RdbmsException.class);
42          expectedException.expectCause(isA(exception.getClass()));
43  
44          defaultTransactionalExecutor.executeInternal(connection, callback);
45          assertThat(wrappedConnection.connection, nullValue());
46  
47          verify(callback).execute(any(WrappedConnection.class));
48          verify(connection).commit();
49          verify(connection, never()).rollback();
50      }
51  
52      @Test
53      public void executeRollbackFails() throws SQLException {
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  
73          public SuppressedMatches(Matcher<T> expectedSuppressed) {
74              this.expectedSuppressed = expectedSuppressed;
75          }
76  
77          @Override
78          protected void describeMismatchSafely(final T item, final Description mismatchDescription) {
79              mismatchDescription.appendText("was not found in ").appendValue(item.getSuppressed());
80          }
81  
82          @Override
83          public void describeTo(final Description description) {
84              description.appendText("a suppressed exception matching(");
85              expectedSuppressed.describeTo(description);
86              description.appendText(")");
87          }
88  
89          @Override
90          public boolean matchesSafely(final Throwable t) {
91              for (Throwable s : t.getSuppressed()) {
92                  if (expectedSuppressed.matches(s)) {
93                      return true;
94                  }
95              }
96  
97              return false;
98          }
99      }
100 }