added tests and attributes calls to sqs

This commit is contained in:
Adrian Cole 2012-09-12 21:36:03 -07:00
parent a0b1ffb625
commit b0626e3324
20 changed files with 1067 additions and 99 deletions

View File

@ -19,6 +19,7 @@
package org.jclouds.sqs;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -61,27 +62,27 @@ public interface SQSApi {
Set<URI> listQueuesInRegion(@Nullable String region, ListQueuesOptions options);
/**
*
* The CreateQueue action creates a new queue.
* <p/>
*
* When you request CreateQueue, you provide a name for the queue. To
* successfully create a new queue, you must provide a name that is unique
* within the scope of your own queues. If you provide the name of an
* existing queue, a new queue isn't created and an error isn't returned.
* Instead, the request succeeds and the queue URL for the existing queue is
* returned (for more information about queue URLs, see Queue and Message
* Identifiers in the Amazon SQS Developer Guide). Exception: if you provide
* a value for DefaultVisibilityTimeout that is different from the value for
* the existing queue, you receive an error.
* <h3>Note</h3>
* within the scope of your own queues.
*
* <h4>Note</h4>
*
* If you delete a queue, you must wait at least 60 seconds before creating a
* queue with the same name.
* <p/>
* A default value for the queue's visibility timeout (30 seconds) is set
* when the queue is created. You can override this value with the
* DefaultVisibilityTimeout request parameter. For more information, see
* Visibility Timeout in the Amazon SQS Developer Guide.
*
* If you provide the name of an existing queue, along with the exact names
* and values of all the queue's attributes, CreateQueue returns the queue
* URL for the existing queue. If the queue name, attribute names, or
* attribute values do not match an existing queue, CreateQueue returns an
* error.
*
* <h4>Tip</h4>
*
* Use GetQueueUrl to get a queue's URL. GetQueueUrl requires only the
* QueueName parameter.
*
* @param region
* Queues are Region-specific.
@ -89,29 +90,39 @@ public interface SQSApi {
* The name to use for the queue created. Constraints: Maximum 80
* characters; alphanumeric characters, hyphens (-), and
* underscores (_) are allowed.
* @param options
* like the visibility timeout (in seconds) to use for this queue.
*/
// this will gracefully attempt to resolve name issues
@Timeout(duration = 61, timeUnit = TimeUnit.SECONDS)
URI createQueueInRegion(@Nullable String region, String queueName);
/**
* same as {@link #createQueueInRegion(String, String)} except you can
* control options such as delay seconds.
*
* @param options
* options such as delay seconds
* @see #createQueueInRegion(String, String)
*/
@Timeout(duration = 61, timeUnit = TimeUnit.SECONDS)
URI createQueueInRegion(@Nullable String region, String queueName, CreateQueueOptions options);
/**
* The DeleteQueue action deletes the queue specified by the queue URL,
* regardless of whether the queue is empty. If the specified queue does not
* exist, SQS returns a successful response. <h3>
* Caution</h3>
* exist, SQS returns a successful response.
*
* <h4>Caution</h4>
*
* Use DeleteQueue with care; once you delete your queue, any messages in the
* queue are no longer available.
* <p/>
*
* When you delete a queue, the deletion process takes up to 60 seconds.
* Requests you send involving that queue during the 60 seconds might
* succeed. For example, a SendMessage request might succeed, but after the
* 60 seconds, the queue and that message you sent no longer exist. Also,
* when you delete a queue, you must wait at least 60 seconds before creating
* a queue with the same name.
* <p/>
*
* We reserve the right to delete queues that have had no activity for more
* than 30 days. For more information, see About SQS Queues in the Amazon SQS
* Developer Guide.
@ -121,37 +132,204 @@ public interface SQSApi {
*/
void deleteQueue(URI queue);
/**
* The DeleteMessage action deletes the specified message from the specified
* queue. You specify the message by using the message's receipt handle and
* not the message ID you received when you sent the message. Even if the
* message is locked by another reader due to the visibility timeout setting,
* it is still deleted from the queue. If you leave a message in the queue
* for more than 4 days, SQS automatically deletes it.
*
* <h4>Note</h4>
*
* The receipt handle is associated with a specific instance of receiving the
* message. If you receive a message more than once, the receipt handle you
* get each time you receive the message is different. When you request
* DeleteMessage, if you don't provide the most recently received receipt
* handle for the message, the request will still succeed, but the message
* might not be deleted.
*
* <h4>Important</h4>
*
* It is possible you will receive a message even after you have deleted it.
* This might happen on rare occasions if one of the servers storing a copy
* of the message is unavailable when you request to delete the message. The
* copy remains on the server and might be returned to you again on a
* subsequent receive request. You should create your system to be idempotent
* so that receiving a particular message more than once is not a problem.
*
* @param queue
* the queue the message is in
* @param receiptHandle
* The receipt handle associated with the message you want to
* delete.
*/
void deleteMessage(URI queue, String receiptHandle);
/**
* The SendMessage action delivers a message to the specified queue. The
* maximum allowed message size is 8 KB.
* <p/>
* Important
* <p/>
* maximum allowed message size is 64 KB.
*
* <h4>Important</h4>
*
* The following list shows the characters (in Unicode) allowed in your
* message, according to the W3C XML specification (for more information, go
* to http://www.w3.org/TR/REC-xml/#charsets). If you send any characters not
* included in the list, your request will be rejected.
* <p/>
* #x9 | #xA | #xD | [#x20 to #xD7FF] | [#xE000 to #xFFFD] | [#x10000 to
* #x10FFFF]
*
*
* {@code #x9 | #xA | #xD | [#x20 to #xD7FF] | [#xE000 to #xFFFD] | [#x10000 to #x10FFFF]}
*
* @param queue
* queue you want to send to
*
* @param message
* The message to send. Type: String maximum 8 KB in size. For a
* list of allowed characters, see the preceding important note
* @return md5 of the content sent
* Type: String maximum 64 KB in size. For a list of allowed
* characters, see the preceding important note.
* @return id of the message and md5 of the content sent
*/
MessageIdAndMD5 sendMessage(URI queue, String message);
/**
* same as {@link #sendMessage(URI, String)} except you can control options
* such as delay seconds.
*
* @param options
* options such as delay seconds
* @see #sendMessage(URI, String)
*/
MessageIdAndMD5 sendMessage(URI queue, String message, SendMessageOptions options);
/**
* The ReceiveMessage action retrieves one or more messages from the
* specified queue. The ReceiveMessage action does not delete the message
* after it is retrieved. To delete a message, you must use the DeleteMessage
* action. For more information about message deletion in the message life
* cycle, see Message Lifecycle.
*
* <h4>Note</h4>
*
* Due to the distributed nature of the queue, a weighted random set of
* machines is sampled on a ReceiveMessage call. That means only the messages
* on the sampled machines are returned. If the number of messages in the
* queue is small (less than 1000), it is likely you will get fewer messages
* than you requested per ReceiveMessage call. If the number of messages in
* the queue is extremely small, you might not receive any messages in a
* particular ReceiveMessage response; in which case you should repeat the
* request.
*
* @param queue
* from where you are receiving messages
* @return message including the receipt handle you can use to delete it
*/
Message receiveMessage(URI queue);
/**
* same as {@link #receiveMessage(URI)} except you can provide options like
* VisibilityTimeout parameter in your request, which will be applied to the
* messages that SQS returns in the response. If you do not include the
* parameter, the overall visibility timeout for the queue is used for the
* returned messages.
*
* @param options
* options such as VisibilityTimeout
* @see #receiveMessage(URI)
*/
Message receiveMessage(URI queue, ReceiveMessageOptions options);
/**
* same as {@link #receiveMessage(URI)} except you can receive multiple
* messages.
*
* @param max
* maximum messages to receive, current limit is 10
* @see #receiveMessage(URI)
*/
Set<Message> receiveMessages(URI queue, int max);
/**
* returns all attributes of a queue.
*
* @param queue
* queue to get the attributes of
*/
Map<String, String> getQueueAttributes(URI queue);
/**
* The SetQueueAttributes action sets one attribute of a queue per request.
* When you change a queue's attributes, the change can take up to 60 seconds
* to propagate throughout the SQS system.
*
* @param queue
* queue to set the attribute on
* @param name
*
* The name of the attribute you want to set.
*
* VisibilityTimeout - The length of time (in seconds) that a
* message received from a queue will be invisible to other
* receiving components when they ask to receive messages. For more
* information about VisibilityTimeout, see Visibility Timeout in
* the Amazon SQS Developer Guide.
*
* Policy - The formal description of the permissions for a
* resource. For more information about Policy, see Basic Policy
* Structure in the Amazon SQS Developer Guide.
*
* MaximumMessageSize - The limit of how many bytes a message can
* contain before Amazon SQS rejects it.
*
* MessageRetentionPeriod - The number of seconds Amazon SQS
* retains a message.
*
* DelaySeconds - The time in seconds that the delivery of all
* messages in the queue will be delayed.
* @param value
* The value of the attribute you want to set. To delete a queue's
* access control policy, set the policy to "".
*
* Constraints: Constraints are specific for each value.
*
* VisibilityTimeout - An integer from 0 to 43200 (12 hours). The
* default for this attribute is 30 seconds.
*
* Policy - A valid form-url-encoded policy. For more information
* about policy structure, see Basic Policy Structure in the Amazon
* SQS Developer Guide. For more information about
* form-url-encoding, see
* http://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2.1.
*
* MaximumMessageSize - An integer from 1024 bytes (1 KiB) up to
* 65536 bytes (64 KiB). The default for this attribute is 65536
* (64 KiB).
*
* MessageRetentionPeriod - Integer representing seconds, from 60
* (1 minute) to 1209600 (14 days). The default for this attribute
* is 345600 (4 days).
*
* DelaySeconds - An integer from 0 to 900 (15 minutes). The
* default for this attribute is 0.
*/
void setQueueAttribute(URI queue, String name, String value);
/**
* returns some attributes of a queue.
*
* @param queue
* queue to get the attributes of
*/
Map<String, String> getQueueAttributes(URI queue, Iterable<String> attributeNames);
/**
* same as {@link #receiveMessages(URI, int)} except you can provide options
* like VisibilityTimeout parameter in your request, which will be applied to
* the messages that SQS returns in the response. If you do not include the
* parameter, the overall visibility timeout for the queue is used for the
* returned messages.
*
* @param options
* options such as VisibilityTimeout
* @see #receiveMessages(URI, int)
*/
Set<Message> receiveMessages(URI queue, int max, ReceiveMessageOptions options);
}

View File

@ -20,6 +20,8 @@ package org.jclouds.sqs;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_MAX_RETRIES;
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_RETRY_INTERVAL;
import java.net.URI;
import java.util.Properties;
@ -62,6 +64,8 @@ public class SQSApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(CREATE_QUEUE_MAX_RETRIES, "60");
properties.setProperty(CREATE_QUEUE_RETRY_INTERVAL, "1000");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

View File

@ -22,6 +22,7 @@ import static org.jclouds.sqs.reference.SQSParameters.ACTION;
import static org.jclouds.sqs.reference.SQSParameters.VERSION;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.FormParam;
@ -32,18 +33,21 @@ import org.jclouds.Constants;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.sqs.binders.BindAttributeNamesToIndexedFormParams;
import org.jclouds.sqs.domain.Message;
import org.jclouds.sqs.domain.MessageIdAndMD5;
import org.jclouds.sqs.options.CreateQueueOptions;
import org.jclouds.sqs.options.ListQueuesOptions;
import org.jclouds.sqs.options.ReceiveMessageOptions;
import org.jclouds.sqs.options.SendMessageOptions;
import org.jclouds.sqs.xml.AttributesHandler;
import org.jclouds.sqs.xml.MessageHandler;
import org.jclouds.sqs.xml.ReceiveMessageResponseHandler;
import org.jclouds.sqs.xml.RegexListQueuesResponseHandler;
@ -114,6 +118,14 @@ public interface SQSAsyncApi {
@FormParams(keys = ACTION, values = "DeleteQueue")
ListenableFuture<Void> deleteQueue(@EndpointParam URI queue);
/**
* @see SQSApi#deleteMessage
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DeleteMessage")
ListenableFuture<Void> deleteMessage(@EndpointParam URI queue, @FormParam("ReceiptHandle") String receiptHandle);
/**
* @see SQSApi#sendMessage
*/
@ -151,6 +163,34 @@ public interface SQSAsyncApi {
@XMLResponseParser(MessageHandler.class)
ListenableFuture<Message> receiveMessage(@EndpointParam URI queue, ReceiveMessageOptions options);
/**
* @see SQSApi#getQueueAttributes(URI)
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "AttributeName.1" }, values = { "GetQueueAttributes", "All" })
@XMLResponseParser(AttributesHandler.class)
ListenableFuture<Map<String, String>> getQueueAttributes(@EndpointParam URI queue);
/**
* @see SQSApi#getQueueAttributes(URI, Iterable)
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "GetQueueAttributes")
@XMLResponseParser(AttributesHandler.class)
ListenableFuture<Map<String, String>> getQueueAttributes(@EndpointParam URI queue,
@BinderParam(BindAttributeNamesToIndexedFormParams.class) Iterable<String> attributeNames);
/**
* @see SQSApi#setQueueAttribute
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "SetQueueAttributes")
ListenableFuture<Void> setQueueAttribute(@EndpointParam URI queue, @FormParam("Attribute.Name") String name,
@FormParam("Attribute.Value") String value);
/**
* @see SQSApi#receiveMessages
*/

View File

@ -0,0 +1,52 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
* Binds the Iterable<String> to form parameters named with AttributeName.index
*
* @author Adrian Cole
*/
@Singleton
public class BindAttributeNamesToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
Iterable<?> values = Iterable.class.cast(checkNotNull(input, "attributeNames"));
Builder<String, String> builder = ImmutableMultimap.builder();
int i = 0;
for (Object o : values) {
builder.put("AttributeName." + (i++ + 1), o.toString());
}
ImmutableMultimap<String, String> forms = builder.build();
return (R) (forms.size() == 0 ? request : request.toBuilder().replaceFormParams(forms).build());
}
}

View File

@ -0,0 +1,48 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.config;
/**
* Configuration properties and constants used in SQS connections.
*
* @author Adrian Cole
*/
public interface SQSProperties {
/**
* Integer property.
* <p/>
* When creating a queue, you can encounter
* {@code AWS.SimpleQueueService.QueueDeletedRecently}, which is typically a
* resolvable error. default tries are 60,
*/
public static final String CREATE_QUEUE_MAX_RETRIES = "jclouds.sqs.create-queue.max-retries";
/**
* Long property.
* <p/>
* When creating a queue, you can encounter
* {@code AWS.SimpleQueueService.QueueDeletedRecently}, which is typically a
* resolvable error. default interval between tries is 1000 milliseconds (1
* second).
*/
public static final String CREATE_QUEUE_RETRY_INTERVAL = "jclouds.sqs.create-queue.retry-interval";
}

View File

@ -19,9 +19,16 @@
package org.jclouds.sqs.config;
import org.jclouds.aws.config.FormSigningRestClientModule;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.sqs.SQSApi;
import org.jclouds.sqs.SQSAsyncApi;
import org.jclouds.sqs.handlers.ParseSQSErrorFromXmlContent;
import org.jclouds.sqs.handlers.SQSErrorRetryHandler;
import com.google.common.reflect.TypeToken;
@ -37,4 +44,16 @@ public class SQSRestClientModule extends FormSigningRestClientModule<SQSApi, SQS
super(TypeToken.of(SQSApi.class), TypeToken.of(SQSAsyncApi.class));
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseSQSErrorFromXmlContent.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseSQSErrorFromXmlContent.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseSQSErrorFromXmlContent.class);
}
@Override
protected void bindRetryHandlers() {
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(SQSErrorRetryHandler.class);
}
}

View File

@ -0,0 +1,66 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.handlers;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*
*/
@Singleton
public class ParseSQSErrorFromXmlContent extends ParseAWSErrorFromXmlContent {
protected Set<String> resourceNotFoundCodes = ImmutableSet.of("AWS.SimpleQueueService.NonExistentQueue");
protected Set<String> illegalStateCodes = ImmutableSet.of("AWS.SimpleQueueService.QueueDeletedRecently",
"AWS.SimpleQueueService.QueueNameExists");
protected Set<String> illegalArgumentCodes = ImmutableSet.of("InvalidAttributeName", "ReadCountOutOfRange",
"InvalidMessageContents", "MessageTooLong");
@Inject
public ParseSQSErrorFromXmlContent(AWSUtils utils) {
super(utils);
}
@Override
protected Exception refineException(HttpCommand command, HttpResponse response, Exception exception, AWSError error,
String message) {
String errorCode = (error != null && error.getCode() != null) ? error.getCode() : null;
if (resourceNotFoundCodes.contains(errorCode))
exception = new ResourceNotFoundException(message, exception);
else if (illegalStateCodes.contains(errorCode))
exception = new IllegalStateException(message, exception);
else if (illegalArgumentCodes.contains(errorCode))
exception = new IllegalArgumentException(message, exception);
else
exception = super.refineException(command, response, exception, error, message);
return exception;
}
}

View File

@ -0,0 +1,71 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.handlers;
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_MAX_RETRIES;
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_RETRY_INTERVAL;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
*/
public class SQSErrorRetryHandler extends AWSClientErrorRetryHandler {
private final long retryInterval;
private final int maxTries;
@Inject
public SQSErrorRetryHandler(AWSUtils utils, BackoffLimitedRetryHandler backoffLimitedRetryHandler,
@ClientError Set<String> retryableCodes, @Named(CREATE_QUEUE_MAX_RETRIES) int maxTries,
@Named(CREATE_QUEUE_RETRY_INTERVAL) long retryInterval) {
super(utils, backoffLimitedRetryHandler, retryableCodes);
this.maxTries = maxTries;
this.retryInterval = retryInterval;
}
@VisibleForTesting
public boolean shouldRetryRequestOnError(HttpCommand command, HttpResponse response, AWSError error) {
if ("AWS.SimpleQueueService.QueueDeletedRecently".equals(error.getCode())) {
if (command.incrementFailureCount() - 1 < maxTries) {
Uninterruptibles.sleepUninterruptibly(retryInterval, TimeUnit.MILLISECONDS);
return true;
}
return false;
}
return super.shouldRetryRequestOnError(command, response, error);
}
}

View File

@ -0,0 +1,70 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import java.util.Map;
import org.jclouds.http.functions.ParseSax;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
/**
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/2011-10-01/APIReference/Query_QueryGetQueueAttributes.html"
* />
*
* @author Adrian Cole
*/
public class AttributesHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Map<String, String>> {
private StringBuilder currentText = new StringBuilder();
private Builder<String, String> builder = ImmutableMap.<String, String> builder();
private String name;
@Override
public Map<String, String> getResult() {
try {
return builder.build();
} catch (NullPointerException e) {
return null;
} finally {
builder = ImmutableMap.<String, String> builder();
}
}
@Override
public void endElement(String uri, String name, String qName) {
if (qName.equals("Name")) {
this.name = currentOrNull(currentText);
} else if (qName.equals("Value")) {
builder.put(this.name, currentOrNull(currentText));
this.name = null;
}
currentText = new StringBuilder();
}
@Override
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -42,7 +42,7 @@ public class RegexQueueHandler extends BaseRegexQueueHandler implements Function
private final ReturnStringIf2xx returnStringIf200;
@Inject
RegexQueueHandler(ReturnStringIf2xx returnStringIf200) {
public RegexQueueHandler(ReturnStringIf2xx returnStringIf200) {
this.returnStringIf200 = returnStringIf200;
}

View File

@ -25,10 +25,13 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.sqs.internal.BaseSQSApiExpectTest;
import org.jclouds.sqs.parse.CreateQueueResponseTest;
import org.jclouds.sqs.parse.GetQueueAttributesResponseTest;
import org.jclouds.sqs.parse.ReceiveMessageResponseTest;
import org.jclouds.sqs.parse.SendMessageResponseTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
@ -37,7 +40,30 @@ import com.google.common.collect.Iterables;
@Test(groups = "unit", testName = "SQSApiExpectTest")
public class SQSApiExpectTest extends BaseSQSApiExpectTest {
HttpRequest sendMessage = HttpRequest.builder()
public HttpRequest createQueue = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "CreateQueue")
.addFormParam("QueueName", "queueName")
.addFormParam("Signature", "I7tmwiCzJ9cvw79pmlz1rOILh2C2ZV6OpLk23JGx6AU%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testCreateQueueWhenResponseIs2xx() throws Exception {
HttpResponse createQueueResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/create_queue.xml", "text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(createQueue, createQueueResponse);
assertEquals(apiWhenExist.createQueueInRegion(null, "queueName").toString(), new CreateQueueResponseTest().expected().toString());
}
public HttpRequest sendMessage = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
@ -61,7 +87,7 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest {
}
HttpRequest receiveMessage = HttpRequest.builder()
public HttpRequest receiveMessage = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
@ -86,7 +112,7 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest {
}
HttpRequest receiveMessages = HttpRequest.builder()
public HttpRequest receiveMessages = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
@ -110,4 +136,113 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest {
apiWhenExist.receiveMessages(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), 10)
.toString(), new ReceiveMessageResponseTest().expected().toString());
}
public HttpRequest deleteMessage = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "DeleteMessage")
.addFormParam("ReceiptHandle", "eXJYhj5rDr9cAe")
.addFormParam("Signature", "9%2FkuCc2i78gMsmul%2BRsOPcdQ1OLUKrItqgGIRRBJb8M%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testDeleteMessageWhenResponseIs2xx() throws Exception {
HttpResponse deleteMessageResponse = HttpResponse.builder()
.statusCode(200)
.payload(
payloadFromStringWithContentType(
"<DeleteMessageResponse><ResponseMetadata><RequestId>b5293cb5-d306-4a17-9048-b263635abe42</RequestId></ResponseMetadata></DeleteMessageResponse>",
"text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(deleteMessage, deleteMessageResponse);
apiWhenExist.deleteMessage(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"),
"eXJYhj5rDr9cAe");
}
public HttpRequest getQueueAttributes = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "GetQueueAttributes")
.addFormParam("AttributeName.1", "All")
.addFormParam("Signature", "welFLn0TV6JlH6s6s60XZTJeJfFXGiXN4qNPrBx7aHc%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testGetQueueAttributesWhenResponseIs2xx() throws Exception {
HttpResponse getQueueAttributesResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/attributes.xml", "text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(getQueueAttributes, getQueueAttributesResponse);
assertEquals(apiWhenExist.getQueueAttributes(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")).toString(), new GetQueueAttributesResponseTest().expected().toString());
}
public HttpRequest getQueueAttributesSubset = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "GetQueueAttributes")
.addFormParam("AttributeName.1", "VisibilityTimeout")
.addFormParam("AttributeName.2", "DelaySeconds")
.addFormParam("Signature", "9KaiOOWWyFPTVMOnyHA3ZoXbPBPSD4AZ4q460UNMfDs%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testGetQueueAttributesSubsetWhenResponseIs2xx() throws Exception {
HttpResponse getQueueAttributesSubsetResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/attributes.xml", "text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(getQueueAttributesSubset, getQueueAttributesSubsetResponse);
assertEquals(
apiWhenExist.getQueueAttributes(
URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"),
ImmutableSet.of("VisibilityTimeout", "DelaySeconds")).toString(),
new GetQueueAttributesResponseTest().expected().toString());
}
public HttpRequest setQueueAttribute = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "SetQueueAttributes")
.addFormParam("Attribute.Name", "MaximumMessageSize")
.addFormParam("Attribute.Value", "1")
.addFormParam("Signature", "ktBkQ3c%2FrwGcBSec0fkckfo73xmcoTuub5fxudM1qh0%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testSetQueueAttributeWhenResponseIs2xx() throws Exception {
HttpResponse setQueueAttributeResponse = HttpResponse.builder()
.statusCode(200)
.payload(
payloadFromStringWithContentType(
"<SetQueueAttributesResponse><ResponseMetadata><RequestId>b5293cb5-d306-4a17-9048-b263635abe42</RequestId></ResponseMetadata></SetQueueAttributesResponse>",
"text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(setQueueAttribute, setQueueAttributeResponse);
apiWhenExist.setQueueAttribute(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"),
"MaximumMessageSize", "1");
}
}

View File

@ -19,18 +19,17 @@
package org.jclouds.sqs;
import static org.jclouds.sqs.options.ListQueuesOptions.Builder.queuePrefix;
import static org.jclouds.sqs.options.ReceiveMessageOptions.Builder.attribute;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.sqs.internal.BaseSQSApiLiveTest;
import org.jclouds.sqs.options.ReceiveMessageOptions;
import org.testng.annotations.AfterTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
@ -55,7 +54,7 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest {
}
protected void listQueuesInRegion(String region) throws InterruptedException {
SortedSet<URI> allResults = Sets.newTreeSet(context.getApi().listQueuesInRegion(region));
SortedSet<URI> allResults = Sets.newTreeSet(api().listQueuesInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
URI queue = allResults.last();
@ -66,35 +65,17 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest {
public static final String PREFIX = System.getProperty("user.name") + "-sqs";
@Test
protected void testCreateQueue() throws InterruptedException {
createQueueInRegion(null, PREFIX + "1");
protected void testCanRecreateQueueGracefully() throws InterruptedException {
recreateQueueInRegion(PREFIX + "1", null);
recreateQueueInRegion(PREFIX + "1", null);
}
public String createQueueInRegion(final String region, String queueName) throws InterruptedException {
try {
Set<URI> result = context.getApi().listQueuesInRegion(region, queuePrefix(queueName));
public String recreateQueueInRegion(String queueName, String region) throws InterruptedException {
Set<URI> result = api().listQueuesInRegion(region, queuePrefix(queueName));
if (result.size() >= 1) {
context.getApi().deleteQueue(Iterables.getLast(result));
queueName += 1;// cannot recreate a queue within 60 seconds
}
} catch (Exception e) {
}
URI queue = null;
int tries = 0;
while (queue == null && tries < 5) {
try {
tries++;
queue = context.getApi().createQueueInRegion(region, queueName);
} catch (AWSResponseException e) {
queueName += "1";
if (e.getError().getCode().equals("AWS.SimpleQueueService.QueueDeletedRecently"))// TODO
// retry
// handler
continue;
throw e;
}
api().deleteQueue(Iterables.getLast(result));
}
URI queue = api().createQueueInRegion(region, queueName);
assertQueueInList(region, queue);
queues.add(queue);
return queueName;
@ -103,35 +84,53 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest {
String message = "hardyharhar";
HashCode md5 = Hashing.md5().hashString(message, Charsets.UTF_8);
@Test(dependsOnMethods = "testCreateQueue")
@Test(dependsOnMethods = "testCanRecreateQueueGracefully")
protected void testGetQueueAttributes() {
for (URI queue : queues) {
Map<String, String> attributes = api().getQueueAttributes(queue);
assertEquals(api().getQueueAttributes(queue, attributes.keySet()), attributes);
}
}
@Test(dependsOnMethods = "testCanRecreateQueueGracefully")
protected void testSetQueueAttribute() {
for (URI queue : queues) {
api().setQueueAttribute(queue, "MaximumMessageSize", "1024");
assertEquals(api().getQueueAttributes(queue).get("MaximumMessageSize"), "1024");
}
}
@Test(dependsOnMethods = "testCanRecreateQueueGracefully")
protected void testSendMessage() {
for (URI queue : queues) {
assertEquals(context.getApi().sendMessage(queue, message).getMD5(), md5);
assertEquals(api().sendMessage(queue, message).getMD5(), md5);
}
}
@Test(dependsOnMethods = "testSendMessage")
protected void testReceiveMessage() {
protected void testReceiveMessageWithoutHidingMessage() {
for (URI queue : queues) {
assertEquals(context.getApi().receiveMessage(queue, ReceiveMessageOptions.Builder.attribute("All")).getMD5(),
md5);
assertEquals(api().receiveMessage(queue, attribute("All").visibilityTimeout(0)).getMD5(), md5);
}
}
private void assertQueueInList(final String region, URI queue) throws InterruptedException {
final URI finalQ = queue;
assertEventually(new Runnable() {
public void run() {
Set<URI> result = context.getApi().listQueuesInRegion(region);
assertNotNull(result);
assert result.size() >= 1 : result;
assertTrue(result.contains(finalQ), finalQ + " not in " + result);
@Test(dependsOnMethods = "testReceiveMessageWithoutHidingMessage")
protected void testDeleteMessage() throws InterruptedException {
for (URI queue : queues) {
String receiptHandle = api().receiveMessage(queue, attribute("None").visibilityTimeout(0)).getReceiptHandle();
api().deleteMessage(queue, receiptHandle);
assertNoMessages(queue);
}
});
}
@AfterTest
public void shutdown() {
context.close();
@Override
@AfterClass(groups = "live")
protected void tearDownContext() {
for (URI queue : queues) {
api().deleteQueue(queue);
}
super.tearDownContext();
}
protected SQSApi api() {
return context.getApi();
}
}

View File

@ -0,0 +1,137 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.handlers;
import static org.easymock.EasyMock.createMock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.testng.annotations.Test;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code SQSErrorRetryHandler}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "SQSErrorRetryHandlerTest")
public class SQSErrorRetryHandlerTest {
String code = "AWS.SimpleQueueService.QueueDeletedRecently";
AWSError error;
HttpResponse response = HttpResponse.builder().statusCode(400)
.payload(String.format("<Error><Code>%s</Code></Error>", code)).build();
public SQSErrorRetryHandlerTest() {
error = new AWSError();
error.setCode(code);
}
public void testQueueDeletedRecentlyRetriesWhen59SleepsAndTries() {
SQSErrorRetryHandler retry = new SQSErrorRetryHandler(createMock(AWSUtils.class),
createMock(BackoffLimitedRetryHandler.class), ImmutableSet.<String> of(), 60, 100);
HttpCommand command = createHttpCommandForFailureCount(59);
Stopwatch watch = new Stopwatch().start();
assertTrue(retry.shouldRetryRequestOnError(command, response, error));
assertEquals(command.getFailureCount(), 60);
assertTrue(watch.stop().elapsedTime(TimeUnit.MILLISECONDS) >= 100);
}
public void testQueueDeletedRecentlyRetriesWhen60DoesntTry() {
SQSErrorRetryHandler retry = new SQSErrorRetryHandler(createMock(AWSUtils.class),
createMock(BackoffLimitedRetryHandler.class), ImmutableSet.<String> of(), 60, 100);
HttpCommand command = createHttpCommandForFailureCount(60);
Stopwatch watch = new Stopwatch().start();
assertFalse(retry.shouldRetryRequestOnError(command, response, error));
assertEquals(command.getFailureCount(), 61);
assertTrue(watch.stop().elapsedTime(TimeUnit.MILLISECONDS) < 100);
}
//TODO: make a builder for this
HttpCommand createHttpCommandForFailureCount(final int failureCount) {
return new HttpCommand() {
int fCount = failureCount;
@Override
public int incrementRedirectCount() {
return 0;
}
@Override
public int getRedirectCount() {
return 0;
}
@Override
public boolean isReplayable() {
return false;
}
@Override
public int incrementFailureCount() {
return ++fCount;
}
@Override
public int getFailureCount() {
return fCount;
}
@Override
public HttpRequest getCurrentRequest() {
return null;
}
@Override
public void setCurrentRequest(HttpRequest request) {
}
@Override
public void setException(Exception exception) {
}
@Override
public Exception getException() {
return null;
}
};
}
}

View File

@ -18,11 +18,19 @@
*/
package org.jclouds.sqs.internal;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.Set;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.rest.RestContext;
import org.jclouds.sqs.SQSApi;
import org.jclouds.sqs.SQSApiMetadata;
import org.jclouds.sqs.SQSAsyncApi;
import org.jclouds.sqs.domain.Message;
import org.testng.annotations.Test;
import com.google.common.reflect.TypeToken;
@ -43,6 +51,31 @@ public class BaseSQSApiLiveTest extends BaseContextLiveTest<RestContext<SQSApi,
return SQSApiMetadata.CONTEXT_TOKEN;
}
protected void assertNoMessages(final URI queue) throws InterruptedException {
assertEventually(new Runnable() {
public void run() {
Message message = api().receiveMessage(queue);
assertNull(message, "message: " + message + " left in queue " + queue);
}
});
}
protected void assertQueueInList(final String region, URI queue) throws InterruptedException {
final URI finalQ = queue;
assertEventually(new Runnable() {
public void run() {
Set<URI> result = api().listQueuesInRegion(region);
assertNotNull(result);
assert result.size() >= 1 : result;
assertTrue(result.contains(finalQ), finalQ + " not in " + result);
}
});
}
private SQSApi api() {
return context.getApi();
}
private static final int INCONSISTENCY_WINDOW = 10000;
/**

View File

@ -0,0 +1,54 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.parse;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.URI;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.sqs.xml.RegexQueueHandler;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "CreateQueueResponseTest")
public class CreateQueueResponseTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/create_queue.xml");
URI expected = expected();
RegexQueueHandler handler = new RegexQueueHandler(new ReturnStringIf2xx());
URI result = handler.apply(HttpResponse.builder().statusCode(200).payload(is).build());
assertEquals(result.toString(), expected.toString());
}
public URI expected() {
return URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11");
}
}

View File

@ -0,0 +1,58 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.jclouds.sqs.parse;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Map;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.sqs.xml.AttributesHandler;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "GetQueueAttributesResponseTest")
public class GetQueueAttributesResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/attributes.xml");
Map<String, String> expected = expected();
AttributesHandler handler = injector.getInstance(AttributesHandler.class);
Map<String, String> result = factory.create(handler).parse(is);
assertEquals(result.toString(), expected.toString());
}
public Map<String, String> expected() {
return ImmutableMap.<String, String>builder()
.put("VisibilityTimeout", "30")
.put("DelaySeconds", "0")
.build();
}
}

View File

@ -57,9 +57,7 @@ public class ReceiveMessageResponseTest extends BaseHandlerTest {
.builder()
.id("5fea7756-0ea4-451a-a703-a558b933e274")
.receiptHandle(
"MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw" + "\n"
+ " Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE" + "\n"
+ " auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=")
"+eXJYhj5rDr9cAe/9BuheT5fysi9BoqtEZSkO7IazVbNHg60eCCINxLqaSVv2pFHrWeWNpZwbleSkWRbCtZaQGgpOx/3cWJZiNSG1KKlJX4IOwISFvb3FwByMx4w0lnINeXzcw2VcKQXNrCatO9gdIiVPvJC3SCKatYM/7YTidtjqc8igrtYW2E2mHlCy3NXPCeXxP4tSvyEwIxpDAmMT7IF0mWvTHS6+JBUtFUsrmi61oIHlESNrD1OjdB1QQw+kdvJ6VbsntbJNNYKw+YqdqWNpZkiGQ8y1z9OdHsr1+4=")
.md5(HashCodes.fromBytes(CryptoStreams.hex("fafb00f5732ab283681e124bf8747ed1")))
.body("This is a test message")
.addAttribute("SenderId", "195004372649")

View File

@ -52,9 +52,7 @@ public class SendMessageResponseTest {
}
public MessageIdAndMD5 expected() {
return MessageIdAndMD5.builder()
.id("c332b2b0-b61f-42d3-8832-d03ebd89f68d")
.md5(HashCodes.fromBytes(CryptoStreams.hex("e32aedf2b2b25355d04b1507055532e6")))
.build();
return MessageIdAndMD5.builder().id("c332b2b0-b61f-42d3-8832-d03ebd89f68d")
.md5(HashCodes.fromBytes(CryptoStreams.hex("e32aedf2b2b25355d04b1507055532e6"))).build();
}
}

View File

@ -0,0 +1,12 @@
<GetQueueAttributesResponse>
<GetQueueAttributesResult>
<Attribute>
<Name>VisibilityTimeout</Name>
<Value>30</Value>
</Attribute>
<Attribute>
<Name>DelaySeconds</Name>
<Value>0</Value>
</Attribute>
</GetQueueAttributesResult>
</GetQueueAttributesResponse>

View File

@ -4,11 +4,7 @@
<MessageId>
5fea7756-0ea4-451a-a703-a558b933e274
</MessageId>
<ReceiptHandle>
MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
</ReceiptHandle>
<ReceiptHandle>+eXJYhj5rDr9cAe/9BuheT5fysi9BoqtEZSkO7IazVbNHg60eCCINxLqaSVv2pFHrWeWNpZwbleSkWRbCtZaQGgpOx/3cWJZiNSG1KKlJX4IOwISFvb3FwByMx4w0lnINeXzcw2VcKQXNrCatO9gdIiVPvJC3SCKatYM/7YTidtjqc8igrtYW2E2mHlCy3NXPCeXxP4tSvyEwIxpDAmMT7IF0mWvTHS6+JBUtFUsrmi61oIHlESNrD1OjdB1QQw+kdvJ6VbsntbJNNYKw+YqdqWNpZkiGQ8y1z9OdHsr1+4=</ReceiptHandle>
<MD5OfBody>
fafb00f5732ab283681e124bf8747ed1
</MD5OfBody>