/**
* Copyright 2012 Comcast Corporation
*
* 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 com.comcast.cqs.test.unit;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Random;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import com.amazonaws.services.sqs.model.ChangeMessageVisibilityRequest;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.comcast.cmb.test.tools.CMBAWSBaseTest;
public class CQSMessageVisibilityTest extends CMBAWSBaseTest {
private static final String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static Random rand = new Random();
private static String message = generateRandomMessage(1024);
private static String queueUrl;
private static ScheduledThreadPoolExecutor ep = new ScheduledThreadPoolExecutor(10);
private static String generateRandomMessage(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i=0; i<length; i++) {
sb.append(ALPHABET.charAt(rand.nextInt(ALPHABET.length())));
}
return sb.toString();
}
@Test
public void messageVisibilityTest() {
try {
queueUrl = getQueueUrl(1, USR.USER1);
Thread.sleep(1000);
ep.submit(new MessageSender());
//give initial thread time to launch more thread
Thread.sleep(5*1000);
ep.shutdown();
ep.awaitTermination(60, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
logger.error("test failed", ex);
fail(ex.getMessage());
}
}
private static class MessageSender extends Thread {
@Override
public void run() {
logger.info("starting sender");
try {
SendMessageRequest sendMessageRequest = new SendMessageRequest(queueUrl, message);
cqs1.sendMessage(sendMessageRequest);
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest();
receiveMessageRequest.setQueueUrl(queueUrl);
receiveMessageRequest.setMaxNumberOfMessages(1);
// use long poll style requests
receiveMessageRequest.setWaitTimeSeconds(20);
// set initial vto to 20 sec
receiveMessageRequest.setVisibilityTimeout(20);
ReceiveMessageResult receiveMessageResult = cqs1.receiveMessage(receiveMessageRequest);
if (receiveMessageResult.getMessages().size() == 1) {
assertTrue("wrong message content", receiveMessageResult.getMessages().get(0).getBody().equals(message));
logger.info("message found for first time");
ep.submit(new MessageReceiver(50));
// push message out 11 sec
logger.info("sleeping for 19 sec");
Thread.sleep(19*1000);
ChangeMessageVisibilityRequest changeMessageVisibilityRequest = new ChangeMessageVisibilityRequest();
changeMessageVisibilityRequest.setVisibilityTimeout(11);
changeMessageVisibilityRequest.setReceiptHandle(receiveMessageResult.getMessages().get(0).getReceiptHandle());
changeMessageVisibilityRequest.setQueueUrl(queueUrl);
cqs1.changeMessageVisibility(changeMessageVisibilityRequest);
logger.info("changed visibility timeout to 11 sec");
// push message out 10 sec
logger.info("sleeping for 10 sec");
Thread.sleep(10*1000);
changeMessageVisibilityRequest = new ChangeMessageVisibilityRequest();
changeMessageVisibilityRequest.setVisibilityTimeout(10);
changeMessageVisibilityRequest.setReceiptHandle(receiveMessageResult.getMessages().get(0).getReceiptHandle());
changeMessageVisibilityRequest.setQueueUrl(queueUrl);
cqs1.changeMessageVisibility(changeMessageVisibilityRequest);
logger.info("changed visibility timeout to 10 sec");
// push message out 11 sec
logger.info("sleeping for 9 sec");
Thread.sleep(9*1000);
changeMessageVisibilityRequest = new ChangeMessageVisibilityRequest();
changeMessageVisibilityRequest.setVisibilityTimeout(11);
changeMessageVisibilityRequest.setReceiptHandle(receiveMessageResult.getMessages().get(0).getReceiptHandle());
changeMessageVisibilityRequest.setQueueUrl(queueUrl);
cqs1.changeMessageVisibility(changeMessageVisibilityRequest);
logger.info("changed visibility timeout to 11 sec");
} else {
fail ("no message found");
}
} catch (Exception ex) {
logger.error("test failed", ex);
fail(ex.getMessage());
}
}
}
private static class MessageReceiver extends Thread {
public int expectedDelaySeconds = 30;
public MessageReceiver(int expectedDelaySeconds) {
this.expectedDelaySeconds = expectedDelaySeconds;
}
@Override
public void run() {
logger.info("starting receiver");
try {
long start = System.currentTimeMillis();
int waitTime = 1;
while (true) {
logger.info("checking for messages");
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest();
receiveMessageRequest.setQueueUrl(queueUrl);
receiveMessageRequest.setMaxNumberOfMessages(1);
receiveMessageRequest.setWaitTimeSeconds(waitTime);
ReceiveMessageResult receiveMessageResult = cqs1.receiveMessage(receiveMessageRequest);
if (receiveMessageResult.getMessages().size() == 1) {
assertTrue("wrong message content", receiveMessageResult.getMessages().get(0).getBody().equals(message));
long durationSec = (System.currentTimeMillis() - start)/1000;
logger.info("message found again after " + durationSec + " sec");
DeleteMessageRequest deleteMessageRequest = new DeleteMessageRequest();
deleteMessageRequest.setQueueUrl(queueUrl);
deleteMessageRequest.setReceiptHandle(receiveMessageResult.getMessages().get(0).getReceiptHandle());
cqs1.deleteMessage(deleteMessageRequest);
logger.info("deleted message");
assertTrue("message became visible already after " + durationSec + " sec", durationSec >= expectedDelaySeconds);
break;
}
// long polling calls will not react to messages becoming revisible, so we need to wait for the next call plus some grace period
if (System.currentTimeMillis() - start > expectedDelaySeconds*1000 + 2*waitTime*1000) {
fail("no message found in " + (expectedDelaySeconds+waitTime*2) + " sec, expected to find one in " + expectedDelaySeconds + " sec");
}
//Thread.sleep(500);
}
} catch (Exception ex) {
logger.error("test failed", ex);
fail(ex.getMessage());
}
}
}
}