package org.jboss.as.test.integration.ejb.timerservice.mgmt;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Set;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.jboss.as.arquillian.api.ContainerResource;
import org.jboss.as.arquillian.container.ManagementClient;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.client.helpers.Operations;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.junit.Assert;
/**
*
* Base test class for timer mgmt operations
*
* @author: baranowb
*/
public abstract class AbstractTimerManagementTestCase {
@ContainerResource
protected ManagementClient managementClient;
private static final String APP_NAME = "ejb-mgmt-timers";
protected SimpleFace bean;
protected PathAddress timerAddress;
protected String timerId;
public static String getArchiveName() {
return APP_NAME + ".jar";
}
public void clean() {
if (bean != null) {
try {
bean.clean();
} catch (Exception e) {
}
}
this.timerId = null;
this.bean = null;
}
public void setup() throws Exception {
this.lookupBean();
this.bean.setPersistent(isPersistent());
this.bean.setInfo(getInfo());
this.bean.setDelay(getDelay());
}
protected void lookupBean() throws Exception {
final Hashtable<String, String> jndiProperties = new Hashtable<String, String>();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.as.naming.InitialContextFactory");
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
this.bean = (SimpleFace) context.lookup("ejb:/" + APP_NAME + "/" + getBeanClassName()
+ "!org.jboss.as.test.integration.ejb.timerservice.mgmt.SimpleFace");
}
protected String getBeanClassName() {
return IntervalTimerBean.class.getSimpleName();
}
public void testResourceExistence() throws Exception {
assertNoTimers();
this.bean.createTimer();
ModelNode timerDetails = getTimerDetails();
Assert.assertEquals("Persistent", this.isPersistent(), this.isPersistent(timerDetails));
Assert.assertEquals("Serializable Info", this.getInfo(), this.getInfo(timerDetails));
Assert.assertTrue("Active", this.isActive(timerDetails));
assertCalendar(timerDetails);
final int left = this.getTimeRemaining(timerDetails);
final int to = getDelay();
Assert.assertTrue("Not enough time? '"+left+"'<='"+to+"'", left <= to);
if(this.isCalendarTimer(timerDetails)){
final ModelNode schedule = timerDetails.get("schedule");
checkCalendardSchedule("year", "*", true, schedule);
checkCalendardSchedule("month", "*", true, schedule);
checkCalendardSchedule("day-of-month", "*", true, schedule);
checkCalendardSchedule("day-of-week", "*", true, schedule);
checkCalendardSchedule("hour", "*", true, schedule);
checkCalendardSchedule("minute", "*", true, schedule);
checkCalendardSchedule("second", getCalendarTimerDetail(), true, schedule);
checkCalendardSchedule("timezone", null, false, schedule);
checkCalendardSchedule("start", null, false, schedule);
checkCalendardSchedule("end", null, false, schedule);
}
}
public void testSuspendAndActivate() throws Exception {
assertNoTimers();
this.bean.createTimer();
this.bean.waitOnTimeout();
this.suspendTimer();
final long ticksCount = this.bean.getTimerTicks();
this.waitOverTimer();
Assert.assertEquals("Timer ticks should not change after suspension!", ticksCount, this.bean.getTimerTicks());
this.activateTimer();
this.bean.waitOnTimeout();
}
public void testCancel() throws Exception {
assertNoTimers();
this.bean.createTimer();
this.bean.waitOnTimeout();
getTimerDetails();
this.cancelTimer();
try {
getTimerDetails();
} catch (OperationFailedException ofe) {
final ModelNode failureDescription = ofe.getFailureDescription();
Assert.assertTrue(failureDescription.toString(), failureDescription.toString().contains("WFLYCTL0216"));
}
}
public void testTrigger() throws Exception {
assertNoTimers();
this.bean.createTimer();
Assert.assertEquals("Wrong initial timer ticks!", 0, this.bean.getTimerTicks());
triggerTimer();
Assert.assertEquals("Wrong after trigger timer ticks!", 1, this.bean.getTimerTicks());
this.bean.waitOnTimeout();
Assert.assertEquals("Timer should fire twice!", 2, this.bean.getTimerTicks());
}
public void testSuspendAndTrigger() throws Exception {
assertNoTimers();
this.bean.createTimer();
Assert.assertEquals("Wrong initial timer ticks!", 0, this.bean.getTimerTicks());
triggerTimer();
this.suspendTimer();
int ticksCount = this.bean.getTimerTicks();
Assert.assertTrue("Timer should fire at least once!", ticksCount >= 1);
this.waitOverTimer();
Assert.assertEquals("The tick count should not increase while the timer was suspended!",
ticksCount, this.bean.getTimerTicks());
this.activateTimer();
this.bean.waitOnTimeout();
Assert.assertTrue("Number of ticks should increase after timer activation!",
this.bean.getTimerTicks() > ticksCount);
}
protected void suspendTimer() throws Exception {
final PathAddress address = getTimerAddress();
final ModelNode operation = Util.createOperation("suspend", address);
final ModelNode outcome = this.managementClient.getControllerClient().execute(operation);
if (!Operations.isSuccessfulOutcome(outcome)) {
throw new OperationFailedException(operation);
}
}
protected void activateTimer() throws Exception {
final PathAddress address = getTimerAddress();
final ModelNode operation = Util.createOperation("activate", address);
final ModelNode outcome = this.managementClient.getControllerClient().execute(operation);
if (!Operations.isSuccessfulOutcome(outcome)) {
throw new OperationFailedException(operation);
}
}
protected void triggerTimer() throws Exception {
final PathAddress address = getTimerAddress();
final ModelNode operation = Util.createOperation("trigger", address);
final ModelNode outcome = this.managementClient.getControllerClient().execute(operation);
if (!Operations.isSuccessfulOutcome(outcome)) {
throw new OperationFailedException(operation);
}
}
protected void cancelTimer() throws Exception {
final PathAddress address = getTimerAddress();
final ModelNode operation = Util.createOperation("cancel", address);
final ModelNode outcome = this.managementClient.getControllerClient().execute(operation);
if (!Operations.isSuccessfulOutcome(outcome)) {
throw new OperationFailedException(operation);
}
}
protected ModelNode getTimerDetails() throws Exception {
final PathAddress address = getTimerAddress();
final ModelNode operation = Util.createOperation("read-resource", address);
operation.get(ModelDescriptionConstants.INCLUDE_RUNTIME).set(Boolean.toString(true));
final ModelNode result = this.managementClient.getControllerClient().execute(operation);
if (!Operations.isSuccessfulOutcome(result)) {
throw new OperationFailedException(result.asString());
}
return result.get(ModelDescriptionConstants.RESULT);
}
protected PathAddress getTimerAddress() throws Exception {
if (this.timerAddress != null) {
return this.timerAddress;
}
final PathAddress address = PathAddress.pathAddress(
PathElement.pathElement(ModelDescriptionConstants.DEPLOYMENT, APP_NAME + ".jar"),
PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, "ejb3"),
PathElement.pathElement("stateless-session-bean", getBeanClassName()),
PathElement.pathElement("service", "timer-service"));
final ModelNode operation = Util.createOperation("read-resource", address);
operation.get(ModelDescriptionConstants.INCLUDE_RUNTIME).set(true);
final ModelNode result = managementClient.getControllerClient().execute(operation);
Assert.assertEquals(result.toString(), ModelDescriptionConstants.SUCCESS, result.get(ModelDescriptionConstants.OUTCOME)
.asString());
final ModelNode tmp = result.get("result").get("timer");
final Set<String> lst = tmp.keys();
Assert.assertEquals(1, lst.size());
this.timerId = lst.iterator().next();
this.timerAddress = PathAddress.pathAddress(address, PathElement.pathElement("timer", this.timerId));
return this.timerAddress;
}
protected boolean isActive(final ModelNode timerDetails) {
return timerDetails.get("active").asString().equalsIgnoreCase("true");
}
protected boolean isCalendarTimer(final ModelNode timerDetails) {
return timerDetails.get("calendar-timer").asString().equalsIgnoreCase("true");
}
protected boolean isPersistent(final ModelNode timerDetails) {
return timerDetails.get("persistent").asString().equalsIgnoreCase("true");
}
protected Serializable getInfo(final ModelNode timerDetails) {
// TODO this is just wrong
return timerDetails.get("info").asString();
}
protected int getTimeRemaining(final ModelNode timerDetails) {
return timerDetails.get("time-remaining").asInt();
}
protected ModelNode getSchedule(final ModelNode timerDetails) {
return timerDetails.get("schedule");
}
protected void checkCalendardSchedule(final String name, final String expected, final boolean mustBeDefined, final ModelNode schedule ){
final ModelNode target = schedule.get(name);
if(mustBeDefined){
Assert.assertEquals("The '"+name+"' has wrong value!",expected, target.asString());
} else {
Assert.assertEquals("The '"+name+"' should be undefined!",ModelType.UNDEFINED, target.getType());
}
}
protected int getDelay() {
return 3000;
}
protected void waitOverTimer() throws Exception {
Thread.currentThread().sleep(this.getDelay() + 1000);
}
protected void assertNoTimers() {
Assert.assertEquals("No timers should be present!", 0, this.bean.getTimerCount());
}
protected abstract Serializable getInfo();
protected abstract boolean isPersistent();
protected abstract void assertCalendar(final ModelNode timerDetails);
protected String getCalendarTimerDetail(){
return this.bean.getComparableTimerDetail();
}
}