/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc. and/or its affiliates,
* 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, by Red Hat.
*/
package com.hp.mwtests.ts.arjuna.tools;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.arjuna.ats.arjuna.AtomicAction;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
import com.arjuna.ats.arjuna.coordinator.ActionStatus;
import com.arjuna.ats.arjuna.coordinator.RecordType;
import com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeManager;
import com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeMap;
import com.arjuna.ats.arjuna.recovery.RecoveryDriver;
import com.arjuna.ats.arjuna.recovery.RecoveryManager;
import com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean;
import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapper;
import com.arjuna.ats.arjuna.tools.osb.mbean.OSEntryBean;
import com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowser;
import com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreItemMBean;
import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
import com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule;
import com.arjuna.ats.internal.arjuna.recovery.RecoveryManagerImple;
import com.hp.mwtests.ts.arjuna.resources.CrashRecord;
/**
* @deprecated as of 5.0.5.Final In a subsequent release we will change packages names in order to
* provide a better separation between public and internal classes.
*/
@Deprecated // in order to provide a better separation between public and internal classes.
public class ObjStoreBrowserTest {
private RecoveryManagerImple rcm;
@Before
public void setUp () throws Exception
{
recoveryPropertyManager.getRecoveryEnvironmentBean().setRecoveryBackoffPeriod(1);
rcm = new RecoveryManagerImple(false);
rcm.addModule(new AtomicActionRecoveryModule());
}
@After
public void tearDown () throws Exception
{
rcm.removeAllModules(false);
rcm.stop(false);
}
/**
* create an MBean to represent an ObjectStore
* @return An object that maintains MBeans representing completing transactions
*/
private ObjStoreBrowser createObjStoreBrowser() {
ObjStoreBrowser osb = new ObjStoreBrowser();
// define which object store types we are prepared to represent by mbeans
osb.setType("com.arjuna.ats.arjuna.AtomicAction", "com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
return osb;
}
@Test
public void testOSEntryBean() throws Exception {
com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new OSEntryBean());
}
@Test
public void testLogRecordWrapper() throws Exception {
com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new LogRecordWrapper(Uid.nullUid()));
}
@Test
public void testObjectStoreBrowser() throws Exception {
com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(createObjStoreBrowser());
}
@Test
public void basicOSBTest () throws Exception
{
ObjStoreBrowser osb = new ObjStoreBrowser("os");
osb.start();
osb.probe();
// there should not be any MBeans
assertNull(osb.findUid(Uid.nullUid()));
// listing beans of an invalid type returns null
assertNull(osb.probe("InvalidType"));
// JBTM-1230
// This does not work on the JDBC object store as this test assumes a previous
// run has left the "Recovery" entry on disk which won't happen in a JDBC store
// // TODO windows
// if (System.getProperty("os.name").toLowerCase().indexOf("windows") == -1) {
// // listing beans of a valid type returns an empty list
// assertNotNull(osb.probe("Recovery"));
// }
osb.stop();
}
/**
* Create an atomic action with two participants, one of which will generate a heuristic during phase 2.
* The test will move the heuristic back into the prepared state and trigger recovery to replay phase 2.
* The test then asserts that the corresponding MBeans have been unregistered.
* @throws Exception if test fails unexpectedly
*/
@Test
public void aaReplayTest() throws Exception {
// TODO windows
aaTest(true);
}
/**
* Similar to aaReplayTest except that the whole transaction record is removed from the object store
* (instead of replaying the record that generates a heuristic).
* @throws Exception if test fails unexpectedly
*/
@Test
public void aaRemoveTest() throws Exception {
// TODO windows
aaTest(false);
}
public void aaTest(boolean replay) throws Exception {
ObjStoreBrowser osb = createObjStoreBrowser();
AtomicAction A = new AtomicAction();
CrashRecord recs[] = {
new CrashRecord(CrashRecord.CrashLocation.NoCrash, CrashRecord.CrashType.Normal),
new CrashRecord(CrashRecord.CrashLocation.CrashInCommit, CrashRecord.CrashType.HeuristicHazard)
};
// register CrashRecord record type so that it is persisted in the object store correctly
RecordTypeManager.manager().add(new RecordTypeMap() {
public Class<? extends AbstractRecord> getRecordClass () { return CrashRecord.class;}
public int getType () {return RecordType.USER_DEF_FIRST0;}
});
// create an atomic action, register crash records with it and then commit
A.begin();
for (CrashRecord rec : recs)
A.add(rec);
int outcome = A.commit();
// the second participant should have generated a heuristic during commit
assertEquals(ActionStatus.H_HAZARD, outcome);
// generate MBeans representing the atomic action that was just committed
osb.start();
osb.probe();
// there should be one MBean corresponding to the AtomicAction A
UidWrapper w = osb.findUid(A.get_uid());
assertNotNull(w);
OSEntryBean ai = w.getMBean();
assertNotNull(ai);
// the MBean should wrap an ActionBean
assertTrue(ai instanceof ActionBean);
ActionBean actionBean = (ActionBean) ai;
// and there should be one MBean corresponding to the CrashRecord that got the heuristic:
int recCount = 0;
for (CrashRecord rec : recs) {
LogRecordWrapper lw = actionBean.getParticipant(rec);
if (lw != null) {
recCount += 1;
assertTrue(lw.isHeuristic());
// put the participant back onto the pending list
lw.setStatus("PREPARED");
// and check that the record is no longer in a heuristic state
assertFalse(lw.isHeuristic());
}
}
assertEquals(1, recCount);
if (!replay) {
actionBean.remove();
} else {
/*
* prompt the recovery manager to replay the record that was
* moved off the heuristic list and back onto the prepared list
*/
rcm.scan();
}
/*
* Since the recovery scan (or explicit remove request) will have successfully removed the record from
* the object store another probe should cause the MBean representing the record to be unregistered
*/
osb.probe();
// look up the MBean and verify that it no longer exists
w = osb.findUid(A.get_uid());
assertNull(w);
osb.dump(new StringBuilder());
osb.stop();
}
// define an MBean interface for use in the next test
public interface NotAnotherMBean extends ObjStoreItemMBean {}
@Test
public void testJMXServer() throws Exception {
class NonCompliantBean implements NotAnotherMBean {}
ObjStoreBrowser osb = createObjStoreBrowser();
OSEntryBean bean;
String validName = "jboss.jta:type=TestObjectStore";
osb.start();
osb.probe();
bean = new OSEntryBean();
// MalformedObjectNameException
assertNull(JMXServer.getAgent().registerMBean("InvalidName", bean));
assertFalse(JMXServer.getAgent().unregisterMBean("InvalidName"));
// InstanceNotFoundException
assertFalse(JMXServer.getAgent().unregisterMBean(validName));
// NotCompliantMBeanException
assertNull(JMXServer.getAgent().registerMBean(validName, new NonCompliantBean()));
// Do it right this time
int cnt = JMXServer.getAgent().queryNames(validName, null).size();
assertNotNull(JMXServer.getAgent().registerMBean(validName, bean));
assertEquals(cnt + 1, JMXServer.getAgent().queryNames(validName, null).size());
// InstanceAlreadyExistsException
assertNull(JMXServer.getAgent().registerMBean(validName, bean));
// Make sure unregistering a valid bean works
assertTrue(JMXServer.getAgent().unregisterMBean(validName));
assertEquals(0, JMXServer.getAgent().queryNames(validName, null).size());
osb.stop();
}
}