public XATransactionContext<K, V> getCurrentContext() { if (currentXid == null) { return null; } return transactionContextFactory.get(new TransactionId(currentXid)); }
@Test public void testRecoverIgnoresInFlightTx() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(journal.recover()).thenReturn(Collections.singletonMap(new TransactionId(new TestXid(0, 0)), (Collection<Long>) Arrays.asList(1L, 2L, 3L))); when(xaTransactionContextFactory.contains(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(true); Xid[] recovered = xaResource.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN); assertThat(recovered.length, is(0)); }
@Test public void testPrepareReadOnly() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); when(xaTransactionContext.prepare()).thenReturn(0); int prepareRc = xaResource.prepare(new TestXid(0, 0)); assertThat(prepareRc, is(XAResource.XA_RDONLY)); verify(xaTransactionContextFactory, times(1)).destroy(eq(new TransactionId(new TestXid(0, 0)))); }
@Test public void testPrepareOk() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); when(xaTransactionContext.prepare()).thenReturn(1); int prepareRc = xaResource.prepare(new TestXid(0, 0)); assertThat(prepareRc, is(XAResource.XA_OK)); verify(xaTransactionContextFactory, times(0)).destroy(eq(new TransactionId(new TestXid(0, 0)))); }
@Test public void testCommit1Pc() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); xaResource.commit(new TestXid(0, 0), true); verify(xaTransactionContextFactory, times(1)).destroy(eq(new TransactionId(new TestXid(0, 0)))); }
@Test public void testRollback() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); xaResource.rollback(new TestXid(0, 0)); verify(xaTransactionContextFactory, times(1)).destroy(eq(new TransactionId(new TestXid(0, 0)))); }
@Test public void testHeuristicDecisionsReported() throws Exception { journal.saveInDoubt(new TransactionId(new TestXid(0, 0)), Arrays.asList(1L, 2L, 3L)); journal.saveInDoubt(new TransactionId(new TestXid(1, 0)), Arrays.asList(4L, 5L, 6L)); journal.saveCommitted(new TransactionId(new TestXid(0, 0)), true); assertThat(journal.heuristicDecisions().keySet(), containsInAnyOrder(new TransactionId(new TestXid(0, 0)))); journal.saveRolledBack(new TransactionId(new TestXid(1, 0)), true); assertThat(journal.heuristicDecisions().keySet(), containsInAnyOrder(new TransactionId(new TestXid(0, 0)), new TransactionId(new TestXid(1, 0)))); }
@Test public void testHeuristicDecisionsForget() throws Exception { journal.saveInDoubt(new TransactionId(new TestXid(0, 0)), Arrays.asList(1L, 2L, 3L)); journal.saveInDoubt(new TransactionId(new TestXid(1, 0)), Arrays.asList(4L, 5L, 6L)); journal.saveCommitted(new TransactionId(new TestXid(0, 0)), true); journal.saveRolledBack(new TransactionId(new TestXid(1, 0)), true); assertThat(journal.heuristicDecisions().keySet(), containsInAnyOrder(new TransactionId(new TestXid(0, 0)), new TransactionId(new TestXid(1, 0)))); journal.forget(new TransactionId(new TestXid(0, 0))); assertThat(journal.heuristicDecisions().keySet(), containsInAnyOrder(new TransactionId(new TestXid(1, 0)))); journal.forget(new TransactionId(new TestXid(1, 0))); assertThat(journal.heuristicDecisions().keySet().isEmpty(), is(true)); }
@Test public void testHasTimedOut() { XATransactionContext<Long, String> xaTransactionContext = new XATransactionContext<>(new TransactionId(new TestXid(0, 0)), null, null, timeSource, timeSource .getTimeMillis() + 30000); assertThat(xaTransactionContext.hasTimedOut(), is(false)); timeSource.advanceTime(30000); assertThat(xaTransactionContext.hasTimedOut(), is(true)); }
@Test public void testSaveInDoubtTwiceThrows() throws Exception { journal.saveInDoubt(new TransactionId(new TestXid(0, 0)), Arrays.asList(1L, 2L, 3L)); try { journal.saveInDoubt(new TransactionId(new TestXid(0, 0)), Arrays.asList(4L, 5L, 6L)); fail("expected IllegalStateException"); } catch (IllegalStateException ise) { // expected } }
@Test public void testCannotForgetNonHeuristicTransaction() throws Exception { journal.saveInDoubt(new TransactionId(new TestXid(0, 0)), Arrays.asList(1L, 2L, 3L)); try { journal.forget(new TransactionId(new TestXid(0, 0))); fail("expected IllegalStateException"); } catch (IllegalStateException ise) { // expected } }
@Test public void testCommitInOnePhasePreparedThrows() throws Exception { XATransactionContext<Long, String> xaTransactionContext = getXaTransactionContext(); when(journal.isInDoubt(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(true); try { xaTransactionContext.commitInOnePhase(); fail("expected IllegalStateException"); } catch (IllegalStateException ise) { // expected } }
@Test public void testStartEndWorks() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.createTransactionContext(eq(new TransactionId(new TestXid(0, 0))), refEq(underlyingStore), refEq(journal), anyInt())).thenReturn(xaTransactionContext); xaResource.start(new TestXid(0, 0), XAResource.TMNOFLAGS); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); xaResource.end(new TestXid(0, 0), XAResource.TMSUCCESS); when(xaTransactionContextFactory.createTransactionContext(eq(new TransactionId(new TestXid(0, 1))), refEq(underlyingStore), refEq(journal), anyInt())).thenReturn(xaTransactionContext); xaResource.start(new TestXid(0, 1), XAResource.TMNOFLAGS); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 1))))).thenReturn(xaTransactionContext); xaResource.end(new TestXid(0, 1), XAResource.TMSUCCESS); }
@Test public void testSaveCommittedTwiceWorks() throws Exception { journal.saveCommitted(new TransactionId(new TestXid(0, 0)), false); journal.saveCommitted(new TransactionId(new TestXid(0, 0)), false); }
@Test public void testCannotCommitNonPreparedXid() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); doThrow(IllegalStateException.class).when(xaTransactionContext).commit(anyBoolean()); try { xaResource.commit(new TestXid(0, 0), false); fail("expected XAException"); } catch (XAException xae) { assertThat(xae.errorCode, is(XAException.XAER_PROTO)); } }
@Test public void testCannotCommitUnknownXidRecovered() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(journal.isInDoubt(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(false); try { xaResource.commit(new TestXid(0, 0), false); fail("expected XAException"); } catch (XAException xae) { assertThat(xae.errorCode, is(XAException.XAER_PROTO)); } }
@Test public void testCannotRollbackUnknownXidRecovered() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(journal.isInDoubt(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(false); try { xaResource.rollback(new TestXid(0, 0)); fail("expected XAException"); } catch (XAException xae) { assertThat(xae.errorCode, is(XAException.XAER_NOTA)); } }
@Test public void testJoinWorks() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.createTransactionContext(eq(new TransactionId(new TestXid(0, 0))), refEq(underlyingStore), refEq(journal), anyInt())).thenReturn(xaTransactionContext); xaResource.start(new TestXid(0, 0), XAResource.TMNOFLAGS); when(xaTransactionContextFactory.get(eq(new TransactionId(new TestXid(0, 0))))).thenReturn(xaTransactionContext); xaResource.end(new TestXid(0, 0), XAResource.TMSUCCESS); xaResource.start(new TestXid(0, 0), XAResource.TMJOIN); xaResource.end(new TestXid(0, 0), XAResource.TMSUCCESS); }
@Test public void testCannotPrepareNonEndedXid() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.createTransactionContext(eq(new TransactionId(new TestXid(0, 0))), refEq(underlyingStore), refEq(journal), anyInt())).thenReturn(xaTransactionContext); xaResource.start(new TestXid(0, 0), XAResource.TMNOFLAGS); try { xaResource.prepare(new TestXid(0, 0)); fail("expected XAException"); } catch (XAException xae) { assertThat(xae.errorCode, is(XAException.XAER_PROTO)); } }
@Test public void testCannotCommit1PcNonEndedXid() throws Exception { EhcacheXAResource<Long, String> xaResource = new EhcacheXAResource<>(underlyingStore, journal, xaTransactionContextFactory); when(xaTransactionContextFactory.createTransactionContext(eq(new TransactionId(new TestXid(0, 0))), refEq(underlyingStore), refEq(journal), anyInt())).thenReturn(xaTransactionContext); xaResource.start(new TestXid(0, 0), XAResource.TMNOFLAGS); try { xaResource.commit(new TestXid(0, 0), true); fail("expected XAException"); } catch (XAException xae) { assertThat(xae.errorCode, is(XAException.XAER_PROTO)); } }