/* * JBoss, Home of Professional Open Source * Copyright 2010, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. * See the copyright.txt in the distribution for a * full listing of individual contributors. * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * (C) 2010 * @author JBoss Inc. */ package org.jboss.jbossts.star.test; import java.io.IOException; import java.net.HttpURLConnection; import org.jboss.jbossts.star.util.TxMediaType; import org.jboss.jbossts.star.util.TxStatusMediaType; import org.jboss.jbossts.star.util.TxSupport; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import javax.ws.rs.client.*; import javax.ws.rs.core.Form; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; public class CoordinatorTest extends BaseTest { @BeforeClass public static void beforeClass() throws Exception { startContainer(TXN_MGR_URL); } /* * Note: TxSupport methods throw exceptions if unexpected status codes are returned. * use the TxSupport.httpRequest(...) if you want to specify other status codes */ // list transactions @Test public void testListTransactions() throws IOException { TxSupport[] txns = {new TxSupport(), new TxSupport()}; int txnCount = new TxSupport().txCount(); for (TxSupport txn : txns) txn.startTx(); // there should be txns.length more transactions Assert.assertEquals(txnCount + txns.length, txns[0].txCount()); for (TxSupport txn : txns) txn.commitTx(); // the number of transactions should be back to the original number Assert.assertEquals(txnCount, txns[0].txCount()); } // 1PC commit abort @Test public void test1PCAbort() throws Exception { TxSupport txn = new TxSupport(); String pUrl = PURL; String pid = null; String pVal; pid = modifyResource(txn, pUrl, pid, "p1", "v1"); pVal = getResourceProperty(txn, pUrl, pid, "p1"); Assert.assertEquals(pVal, "v1"); txn.startTx(); pid = enlistResource(txn, pUrl + "?pId=" + pid); modifyResource(txn, pUrl, pid, "p1", "v2"); pVal = getResourceProperty(txn, pUrl, pid, "p1"); Assert.assertEquals(pVal, "v2"); txn.rollbackTx(); pVal = getResourceProperty(txn, pUrl, pid, "p1"); Assert.assertEquals(pVal, "v1"); } // 1PC commit @Test public void test1PCCommit() throws Exception { TxSupport txn = new TxSupport(); String pUrl = PURL; String pid = null; String pVal; pid = modifyResource(txn, pUrl, pid, "p1", "v1"); pVal = getResourceProperty(txn, pUrl, pid, "p1"); Assert.assertEquals(pVal, "v1"); txn.startTx(); pid = enlistResource(txn, pUrl + "?pId=" + pid); modifyResource(txn, pUrl, pid, "p1", "v2"); pVal = getResourceProperty(txn, pUrl, pid, "p1"); Assert.assertEquals(pVal, "v2"); txn.commitTx(); pVal = getResourceProperty(txn, pUrl, pid, "p1"); Assert.assertEquals(pVal, "v2"); } // 2PC commit @Test public void test2PC() throws Exception { TxSupport txn = new TxSupport(); String pUrl = PURL; String[] pid = new String[2]; String[] pVal = new String[2]; for (int i = 0; i < pid.length; i++) { pid[i] = modifyResource(txn, pUrl, null, "p1", "v1"); pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v1"); } txn.startTx(); for (int i = 0; i < pid.length; i++) { enlistResource(txn, pUrl + "?pId=" + pid[i]); modifyResource(txn, pUrl, pid[i], "p1", "v2"); pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v2"); } txn.rollbackTx(); for (int i = 0; i < pid.length; i++) { pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v1"); } } @Test public void test2PCCommitWithoutResponse() throws Exception { TxSupport txn = new TxSupport(); String pUrl = PURL; String[] pid = new String[2]; String[] pVal = new String[2]; for (int i = 0; i < pid.length; i++) { pid[i] = modifyResource(txn, pUrl, null, "p1", "v1"); pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v1"); } txn.startTx(); for (int i = 0; i < pid.length; i++) { enlistResource(txn, PURL_NO_RESPONSE + "?pId=" + pid[i]); modifyResource(txn, pUrl, pid[i], "p1", "v2"); pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v2"); } String status = txn.commitTx(); for (int i = 0; i < pid.length; i++) { pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v2"); } } @Test public void test2PCRollbackWithoutResponse() throws Exception { TxSupport txn = new TxSupport(); String pUrl = PURL; String[] pid = new String[2]; String[] pVal = new String[2]; for (int i = 0; i < pid.length; i++) { pid[i] = modifyResource(txn, pUrl, null, "p1", "v1"); pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v1"); } txn.startTx(); for (int i = 0; i < pid.length; i++) { enlistResource(txn, PURL_NO_RESPONSE + "?pId=" + pid[i]); modifyResource(txn, pUrl, pid[i], "p1", "v2"); pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v2"); } String status = txn.rollbackTx(); for (int i = 0; i < pid.length; i++) { pVal[i] = getResourceProperty(txn, pUrl, pid[i], "p1"); Assert.assertEquals(pVal[i], "v1"); } } // commit an invalid transaction @Test public void testCommitInvalidTx() throws IOException { // start a transaction TxSupport txn = new TxSupport().startTx(); String terminator = txn.getTerminatorURI(); // mangle the terminator URI //terminator = terminator.replace("/terminate", "_dead/terminate"); terminator += "/_dead"; // an attempt to commit on this URI should fail: txn.httpRequest(new int[] {HttpURLConnection.HTTP_NOT_FOUND}, terminator, "PUT", TxMediaType.TX_STATUS_MEDIA_TYPE, TxStatusMediaType.TX_COMMITTED); // commit it properly txn.commitTx(); } @Test public void testTimeoutCleanup() throws InterruptedException { TxSupport txn = new TxSupport(); int txnCount = txn.txCount(); txn.startTx(1000); txn.enlistTestResource(PURL, false); // Let the txn timeout Thread.sleep(2000); Assert.assertEquals(txnCount, txn.txCount()); } @Test public void testClientAPI() throws Exception { Client client = ClientBuilder.newClient(); WebTarget resource = client.target(TXN_MGR_URL); Response response = resource.request(MediaType.APPLICATION_FORM_URLENCODED).post(Entity.entity(new Form(), MediaType.APPLICATION_FORM_URLENCODED_TYPE)); int status = response.getStatus(); Assert.assertEquals(HttpURLConnection.HTTP_CREATED, status); response.close(); Invocation inv = resource.request(MediaType.APPLICATION_FORM_URLENCODED).buildPost(Entity.entity(new Form(), MediaType.APPLICATION_FORM_URLENCODED_TYPE)); response = inv.invoke(); response.close(); String r1 = resource.request("application/txlist").get(String.class); Assert.assertTrue("response should have contained 2 transaction urls",r1.length() != 0); String r2 = resource.request().get(String.class); Assert.assertTrue("xml response should have contained 2 transaction urls",r2.length() != 0); } @Test public void testFailureInSecondParticipantDuringCommit() { final TxSupport txn = new TxSupport(); final int originalTxCount = txn.txCount(); final String pUrl = PURL; final String[] pid = new String[2]; pid[0] = modifyResource(txn, pUrl, null, "p1", "v1"); pid[1] = modifyResource(txn, pUrl, null, "p1", "v1"); txn.startTx(); enlistResource(txn, pUrl + "?pId=" + pid[0]); enlistResource(txn, pUrl + "?pId=" + pid[1] + "&fault=CRUNTIME"); modifyResource(txn, pUrl, pid[0], "p1", "v2"); modifyResource(txn, pUrl, pid[1], "p1", "v2"); Assert.assertEquals("v2", getResourceProperty(txn, pUrl, pid[0], "p1")); Assert.assertEquals("v2", getResourceProperty(txn, pUrl, pid[1], "p1")); txn.commitTx(); Assert.assertEquals("v2", getResourceProperty(txn, pUrl, pid[0], "p1")); Assert.assertEquals("v1", getResourceProperty(txn, pUrl, pid[1], "p1")); // Transaction should not be removed because of the failure Assert.assertEquals(originalTxCount + 1, txn.txCount()); } }