@Test
  public void existingNonSpringTransaction() {
    MockUOWManager manager = new MockUOWManager();
    manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(
        "result",
        ptm.execute(
            definition,
            new TransactionCallback<String>() {
              @Override
              public String doInTransaction(TransactionStatus status) {
                assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
                assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
                assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                return "result";
              }
            }));

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(0, manager.getUOWTimeout());
    assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
    assertTrue(manager.getJoined());
    assertFalse(manager.getRollbackOnly());
  }
  @Test
  public void uowManagerFoundInJndi() {
    MockUOWManager manager = new MockUOWManager();
    ExpectedLookupTemplate jndiTemplate =
        new ExpectedLookupTemplate(
            WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
    ptm.setJndiTemplate(jndiTemplate);
    ptm.afterPropertiesSet();

    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    assertEquals(
        "result",
        ptm.execute(
            definition,
            new TransactionCallback<String>() {
              @Override
              public String doInTransaction(TransactionStatus status) {
                return "result";
              }
            }));

    assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
    assertFalse(manager.getJoined());
    assertFalse(manager.getRollbackOnly());
  }
  private void doTestExistingTransactionWithSuspension(final int propagationBehavior) {
    MockUOWManager manager = new MockUOWManager();
    final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
    definition2.setPropagationBehavior(propagationBehavior);
    definition2.setReadOnly(true);

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(
        "result",
        ptm.execute(
            definition,
            new TransactionCallback<String>() {
              @Override
              public String doInTransaction(TransactionStatus status) {
                assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
                assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
                assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                assertEquals(
                    "result2",
                    ptm.execute(
                        definition2,
                        new TransactionCallback<String>() {
                          @Override
                          public String doInTransaction(TransactionStatus status) {
                            assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
                            assertEquals(
                                propagationBehavior
                                    == TransactionDefinition.PROPAGATION_REQUIRES_NEW,
                                TransactionSynchronizationManager.isActualTransactionActive());
                            assertTrue(
                                TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                            return "result2";
                          }
                        }));
                return "result";
              }
            }));

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(0, manager.getUOWTimeout());
    if (propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
      assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
    } else {
      assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
    }
    assertFalse(manager.getJoined());
    assertFalse(manager.getRollbackOnly());
  }
  @Test
  public void existingTransactionUsingPropagationNotSupported() {
    MockUOWManager manager = new MockUOWManager();
    final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
    definition2.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
    definition2.setReadOnly(true);

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(
        "result",
        ptm.execute(
            definition,
            new TransactionCallback<String>() {
              @Override
              public String doInTransaction(TransactionStatus status) {
                assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
                assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
                assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                assertEquals(
                    "result2",
                    ptm.execute(
                        definition2,
                        new TransactionCallback<String>() {
                          @Override
                          public String doInTransaction(TransactionStatus status) {
                            assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
                            assertFalse(
                                TransactionSynchronizationManager.isActualTransactionActive());
                            assertTrue(
                                TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                            return "result2";
                          }
                        }));
                return "result";
              }
            }));

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(0, manager.getUOWTimeout());
    assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
    assertFalse(manager.getJoined());
    assertFalse(manager.getRollbackOnly());
  }
  @Test
  public void newTransactionWithCommitException() {
    final RollbackException rex = new RollbackException();
    MockUOWManager manager =
        new MockUOWManager() {
          @Override
          public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWException {
            throw new UOWException(rex);
          }
        };
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    try {
      ptm.execute(
          definition,
          new TransactionCallback<String>() {
            @Override
            public String doInTransaction(TransactionStatus status) {
              assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
              assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
              assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
              return "result";
            }
          });
      fail("Should have thrown TransactionSystemException");
    } catch (TransactionSystemException ex) {
      // expected
      assertTrue(ex.getCause() instanceof UOWException);
      assertSame(rex, ex.getRootCause());
      assertSame(rex, ex.getMostSpecificCause());
    }

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(0, manager.getUOWTimeout());
  }
  private void doTestNewTransactionWithCommit(int propagationBehavior, final int synchMode) {
    MockUOWManager manager = new MockUOWManager();
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    ptm.setTransactionSynchronization(synchMode);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    definition.setPropagationBehavior(propagationBehavior);
    definition.setReadOnly(true);

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(
        "result",
        ptm.execute(
            definition,
            new TransactionCallback<String>() {
              @Override
              public String doInTransaction(TransactionStatus status) {
                if (synchMode != WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER) {
                  assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
                  assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
                  assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                } else {
                  assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
                  assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
                  assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
                }
                return "result";
              }
            }));

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(0, manager.getUOWTimeout());
    assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
    assertFalse(manager.getJoined());
    assertFalse(manager.getRollbackOnly());
  }
  @Test
  public void propagationMandatoryFailsInCaseOfNoExistingTransaction() {
    MockUOWManager manager = new MockUOWManager();
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);

    try {
      ptm.execute(
          definition,
          new TransactionCallback<String>() {
            @Override
            public String doInTransaction(TransactionStatus status) {
              return "result";
            }
          });
      fail("Should have thrown IllegalTransactionStateException");
    } catch (IllegalTransactionStateException ex) {
      // expected
    }
  }
  @Test
  public void uowManagerAndUserTransactionFoundInJndi() throws Exception {
    UserTransaction ut = mock(UserTransaction.class);
    given(ut.getStatus())
        .willReturn(Status.STATUS_NO_TRANSACTION, Status.STATUS_ACTIVE, Status.STATUS_ACTIVE);

    MockUOWManager manager = new MockUOWManager();
    ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
    jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut);
    jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
    ptm.setJndiTemplate(jndiTemplate);
    ptm.afterPropertiesSet();

    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    TransactionStatus ts = ptm.getTransaction(definition);
    ptm.commit(ts);
    assertEquals(
        "result",
        ptm.execute(
            definition,
            new TransactionCallback<String>() {
              @Override
              public String doInTransaction(TransactionStatus status) {
                return "result";
              }
            }));

    assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
    assertFalse(manager.getJoined());
    assertFalse(manager.getRollbackOnly());
    verify(ut).begin();
    verify(ut).commit();
  }
  @Test
  public void propagationNestedFailsInCaseOfExistingTransaction() {
    MockUOWManager manager = new MockUOWManager();
    manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);

    try {
      ptm.execute(
          definition,
          new TransactionCallback<String>() {
            @Override
            public String doInTransaction(TransactionStatus status) {
              return "result";
            }
          });
      fail("Should have thrown NestedTransactionNotSupportedException");
    } catch (NestedTransactionNotSupportedException ex) {
      // expected
    }
  }
  @Test
  public void newTransactionWithRollback() {
    MockUOWManager manager = new MockUOWManager();
    WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    try {
      ptm.execute(
          definition,
          new TransactionCallback<String>() {
            @Override
            public String doInTransaction(TransactionStatus status) {
              assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
              assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
              assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
              throw new OptimisticLockingFailureException("");
            }
          });
      fail("Should have thrown OptimisticLockingFailureException");
    } catch (OptimisticLockingFailureException ex) {
      // expected
    }

    assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
    assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
    assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());

    assertEquals(0, manager.getUOWTimeout());
    assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
    assertFalse(manager.getJoined());
    assertTrue(manager.getRollbackOnly());
  }