/**
* JBoss, Home of Professional Open Source
* Copyright Red Hat, Inc., and individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.aerogear.unifiedpush.message.serviceHolder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.jms.JMSException;
import javax.jms.Queue;
import org.jboss.aerogear.unifiedpush.message.serviceHolder.ApnsServiceHolder;
import org.jboss.aerogear.unifiedpush.message.serviceHolder.ServiceConstructor;
import org.jboss.aerogear.unifiedpush.message.serviceHolder.ServiceDestroyer;
import org.jboss.aerogear.unifiedpush.message.util.JmsClient;
import org.jboss.aerogear.unifiedpush.test.archive.UnifiedPushArchive;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.OperateOnDeployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(Arquillian.class)
public class TestAbstractServiceHolderClustered {
private static final String PUSH_MESSAGE_ID = TestAbstractServiceHolderClustered.class.getName();
private static final String VARIANT_ID = TestAbstractServiceHolderClustered.class.getName();
@Deployment(name = "war-1") @TargetsContainer("container-1")
public static WebArchive archive() {
return UnifiedPushArchive.forTestClass(TestAbstractServiceHolderClustered.class)
.withMessaging()
.addPackage(org.jboss.aerogear.unifiedpush.message.serviceHolder.AbstractServiceHolder.class.getPackage())
.deleteClass(ApnsServiceHolder.class)
.addClasses(MockServiceHolderForCluster.class)
.addAsWebInfResource("test-jms.xml")
.withMockito()
.as(WebArchive.class);
}
@Deployment(name = "war-2") @TargetsContainer("container-2")
public static WebArchive archive2() {
return archive();
}
private ServiceConstructor<Integer> mockConstructor;
private ServiceDestroyer<Integer> mockDestroyer;
@Inject
private MockServiceHolderForCluster holder;
@Resource(mappedName = "java:/queue/CountingQueue")
private Queue countingQueue;
private static final int TOTAL_COUNT = 5;
@Inject
private JmsClient jmsClient;
@Before
public void setUp() {
mockConstructor = new ServiceConstructor<Integer>() {
@Override
public Integer construct() {
try {
return (Integer) jmsClient.receive().from(countingQueue).getObject();
} catch (JMSException e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
}
};
mockDestroyer = new ServiceDestroyer<Integer>() {
@Override
public void destroy(Integer serviceNumber) {
jmsClient.send(serviceNumber).to(countingQueue);
}
};
}
@Test @OperateOnDeployment("war-1") @InSequence(1)
public void initializeQueuesOnFirstNode() throws InterruptedException {
// initialize holder with the service slots
holder.initialize(PUSH_MESSAGE_ID, VARIANT_ID);
// remove all numbers from counting queue so that we start test with blank slate (in case of previous errors)
for (int i = 1; i <= TOTAL_COUNT; i++) {
if (jmsClient.receive().withTimeout(1500L).from(countingQueue) == null) {
break;
}
}
// then push new numbers to counting queue
for (int i = 1; i <= TOTAL_COUNT; i++) {
jmsClient.send(new Integer(i)).to(countingQueue);
}
}
@Test @OperateOnDeployment("war-1") @InSequence(2)
public void testLeaseFewNumbers() throws InterruptedException {
assertEquals(1, borrowServiceSlot());
assertEquals(2, borrowServiceSlot());
assertEquals(3, borrowServiceSlot());
}
@Test @OperateOnDeployment("war-2") @InSequence(3)
public void testLeaseTwoAndReturnOne() throws InterruptedException {
assertEquals(4, borrowServiceSlot());
assertEquals(5, borrowServiceSlot());
assertEquals("the sixth lease operation should fail to retrieve a service", 0, borrowServiceSlot());
returnServiceSlot(4);
}
@Test @OperateOnDeployment("war-1") @InSequence(4)
public void testLeaseOneAndReturnOne() throws InterruptedException {
assertEquals(4, borrowServiceSlot());
returnServiceSlot(1);
}
@Test @OperateOnDeployment("war-2") @InSequence(5)
public void testReturnAndLease() throws InterruptedException {
returnServiceSlot(5);
Set<Integer> leased = new HashSet<>(Arrays.asList(borrowServiceSlot(), borrowServiceSlot()));
assertTrue("leased tokens should contain 1", leased.contains(1));
assertTrue("leased tokens should contain 5", leased.contains(5));
assertEquals("the borrow operation should fail when no slots are available", 0, borrowServiceSlot());
}
private int borrowServiceSlot() {
Integer borrowed = holder.dequeueOrCreateNewService(PUSH_MESSAGE_ID, VARIANT_ID, mockConstructor);
return (borrowed == null) ? 0 : borrowed;
}
private void returnServiceSlot(int service) {
holder.queueFreedUpService(PUSH_MESSAGE_ID, VARIANT_ID, service, mockDestroyer);
}
}