@Test
  public void testHeuristicCommitBeforePrepare() throws JAXBException {
    txSupport.startTx();

    final List<LoggingParticipant> participants =
        Arrays.asList(
            new LoggingParticipant[] {
              new LoggingParticipant(new Prepared()), new LoggingParticipant(new Prepared())
            });

    String lastParticipantid = null;

    for (LoggingParticipant p : participants) {
      lastParticipantid =
          ParticipantsManagerFactory.getInstance()
              .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), p);
    }

    ParticipantsManagerFactory.getInstance()
        .reportHeuristic(lastParticipantid, HeuristicType.HEURISTIC_COMMIT);

    final String transactionStatus = TxSupport.getStatus(txSupport.commitTx());

    Assert.assertEquals(TxStatus.TransactionCommitted.name(), transactionStatus);
    Assert.assertEquals(
        Arrays.asList(new String[] {"prepare", "commit"}), participants.get(0).getInvocations());
    Assert.assertEquals(Collections.EMPTY_LIST, participants.get(1).getInvocations());
  }
  @Test
  public void testHeuristicRollbackBeforePrepare() throws JAXBException {
    txSupport.startTx();

    final List<LoggingParticipant> participants =
        Arrays.asList(
            new LoggingParticipant[] {
              new LoggingParticipant(new Prepared()), new LoggingParticipant(new Prepared())
            });

    String lastParticipantid = null;

    for (LoggingParticipant p : participants) {
      lastParticipantid =
          ParticipantsManagerFactory.getInstance()
              .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), p);
    }

    ParticipantsManagerFactory.getInstance()
        .reportHeuristic(lastParticipantid, HeuristicType.HEURISTIC_ROLLBACK);

    final String transactionStatus = TxSupport.getStatus(txSupport.commitTx());

    Assert.assertEquals(TxStatus.TransactionRolledBack.name(), transactionStatus);

    if (participants.get(0).getInvocations().size() == 1) {
      Assert.assertEquals(
          Arrays.asList(new String[] {"rollback"}), participants.get(0).getInvocations());
    } else {
      Assert.assertEquals(
          Arrays.asList(new String[] {"prepare", "rollback"}),
          participants.get(0).getInvocations());
    }
  }
  @Test
  public void testRollbackByParticipant() {
    txSupport.startTx();

    final List<LoggingParticipant> participants =
        Arrays.asList(
            new LoggingParticipant[] {
              new LoggingParticipant(new Aborted()), new LoggingParticipant(new Aborted()),
            });

    for (LoggingParticipant p : participants) {
      ParticipantsManagerFactory.getInstance()
          .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), p);
    }

    txSupport.commitTx();

    // One of the participants was prepared and then decided to rollback, the other was rolledback
    // straight away.
    Assert.assertEquals(
        3,
        participants.get(0).getInvocations().size() + participants.get(1).getInvocations().size());

    for (LoggingParticipant p : participants) {
      if (p.getInvocations().size() == 1) {
        Assert.assertEquals(Arrays.asList(new String[] {"rollback"}), p.getInvocations());
      } else {
        Assert.assertEquals(
            Arrays.asList(new String[] {"prepare", "rollback"}), p.getInvocations());
      }
    }
  }
  @Test
  public void testReadOnly() {
    txSupport.startTx();

    final List<LoggingParticipant> participants =
        Arrays.asList(
            new LoggingParticipant[] {
              new LoggingParticipant(new ReadOnly()),
              new LoggingParticipant(new Prepared()),
              new LoggingParticipant(new Prepared())
            });

    for (LoggingParticipant p : participants) {
      ParticipantsManagerFactory.getInstance()
          .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), p);
    }

    txSupport.commitTx();

    // One of the participants was only prepared, while other two were prepared and committed.
    Assert.assertEquals(
        5,
        participants.get(0).getInvocations().size()
            + participants.get(1).getInvocations().size()
            + participants.get(2).getInvocations().size());

    for (LoggingParticipant p : participants) {
      if (p.getInvocations().size() == 1) {
        Assert.assertEquals(Arrays.asList(new String[] {"prepare"}), p.getInvocations());
      } else {
        Assert.assertEquals(Arrays.asList(new String[] {"prepare", "commit"}), p.getInvocations());
      }
    }
  }
  @Test
  public void testRollback() {
    txSupport.startTx();

    LoggingParticipant participant1 = new LoggingParticipant(new Prepared());
    LoggingParticipant participant2 = new LoggingParticipant(new Prepared());

    ParticipantsManagerFactory.getInstance()
        .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), participant1);
    ParticipantsManagerFactory.getInstance()
        .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), participant2);

    txSupport.rollbackTx();

    Assert.assertEquals(Arrays.asList(new String[] {"rollback"}), participant1.getInvocations());
    Assert.assertEquals(Arrays.asList(new String[] {"rollback"}), participant2.getInvocations());
  }
  @Test
  public void testCommitOnePhase() {
    txSupport.startTx();

    LoggingParticipant participant = new LoggingParticipant(new Prepared());

    ParticipantsManagerFactory.getInstance()
        .enlist(APPLICATION_ID, txSupport.getDurableParticipantEnlistmentURI(), participant);

    txSupport.commitTx();

    Assert.assertEquals(
        Arrays.asList(new String[] {"commitOnePhase"}), participant.getInvocations());
  }