diff --git a/build.sbt b/build.sbt
index 7a3f230..a37d9b4 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,25 +1,27 @@
name := "sqsmock"
-version := "0.3.2"
+version := "0.3.3-SNAPSHOT"
organization := "io.findify"
-scalaVersion := "2.11.8"
+scalaVersion := "2.12.3"
-val akkaVersion = "2.4.9"
+val akkaVersion = "2.5.1"
+
+crossScalaVersions := Seq("2.12.3", "2.11.8")
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion,
- "com.typesafe.akka" %% "akka-http-experimental" % akkaVersion,
- "org.scala-lang.modules" %% "scala-xml" % "1.0.5",
+ "com.typesafe.akka" %% "akka-http" % "10.0.6",
+ "org.scala-lang.modules" %% "scala-xml" % "1.0.6",
"joda-time" % "joda-time" % "2.9.4",
- "org.scalatest" %% "scalatest" % "3.0.0" % "test",
- "com.amazonaws" % "aws-java-sdk-sqs" % "1.11.32" % "test"
+ "org.scalatest" %% "scalatest" % "3.0.1" % "test",
+ "com.amazonaws" % "aws-java-sdk-sqs" % "1.11.126" % "test"
)
licenses += ("MIT", url("https://opensource.org/licenses/MIT"))
bintrayOrganization := Some("findify")
-parallelExecution in Test := false
\ No newline at end of file
+parallelExecution in Test := false
diff --git a/project/build.properties b/project/build.properties
index 034c10d..3e8bd1a 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version = 0.13.10
+sbt.version = 0.13.15
diff --git a/src/main/scala/io/findify/sqsmock/SQSBackend.scala b/src/main/scala/io/findify/sqsmock/SQSBackend.scala
index 628fa36..bc220d4 100644
--- a/src/main/scala/io/findify/sqsmock/SQSBackend.scala
+++ b/src/main/scala/io/findify/sqsmock/SQSBackend.scala
@@ -15,19 +15,31 @@ import scala.collection.mutable
class SQSBackend(account:Long, port:Int, system:ActorSystem) {
val log = Logger(this.getClass, "sqs_backend")
val queueCache = mutable.Map[String, QueueCache]()
- val createQueueWorker = new CreateQueueWorker(account, port, queueCache, system)
- val sendMessageWorker = new SendMessageWorker(account, queueCache, system)
- val receiveMessageWorker = new ReceiveMessageWorker(account, queueCache, system)
+
+ val createQueueWorker = new CreateQueueWorker(account, port, queueCache, system)
+ val sendMessageWorker = new SendMessageWorker(account, queueCache, system)
+ val receiveMessageWorker = new ReceiveMessageWorker(account, queueCache, system)
val sendMessageBatchWorker = new SendMessageBatchWorker(account, queueCache, system)
- val deleteMessageWorker = new DeleteMessageWorker(account, queueCache, system)
+ val deleteMessageWorker = new DeleteMessageWorker(account, queueCache, system)
+ val listQueuesWorker = new ListQueuesWorker(account, queueCache, system)
+ val getQueueUrlWorker = new GetQueueUrlWorker(account, queueCache, system)
+ val getQueueAttributesWorker = new GetQueueAttributesWorker(account, queueCache, system)
+ val deleteMessageBatchWorker = new DeleteMessageBatchWorker(account, queueCache, system)
+ val deleteQueueUrlWorker = new DeleteQueueUrlWorker(account, queueCache, system)
+
def process(fields:Map[String,String]) = {
log.debug(s"processing request for fields $fields")
fields.get("Action") match {
- case Some("SendMessage") => sendMessageWorker.process(fields)
+ case Some("SendMessage") => sendMessageWorker.process(fields)
case Some("SendMessageBatch") => sendMessageBatchWorker.process(fields)
- case Some("ReceiveMessage") => receiveMessageWorker.process(fields)
- case Some("CreateQueue") => createQueueWorker.process(fields)
- case Some("DeleteMessage") => deleteMessageWorker.process(fields)
+ case Some("ReceiveMessage") => receiveMessageWorker.process(fields)
+ case Some("CreateQueue") => createQueueWorker.process(fields)
+ case Some("DeleteMessage") => deleteMessageWorker.process(fields)
+ case Some("ListQueues") => listQueuesWorker.process(fields)
+ case Some("GetQueueUrl") => getQueueUrlWorker.process(fields)
+ case Some("GetQueueAttributes") => getQueueAttributesWorker.process(fields)
+ case Some("DeleteMessageBatch") => deleteMessageBatchWorker.process(fields)
+ case Some("DeleteQueue") => deleteQueueUrlWorker.process(fields)
case _ => HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "operation not supported").toXML.toString())
}
}
diff --git a/src/main/scala/io/findify/sqsmock/SQSService.scala b/src/main/scala/io/findify/sqsmock/SQSService.scala
index dfabc5e..d16fa6c 100644
--- a/src/main/scala/io/findify/sqsmock/SQSService.scala
+++ b/src/main/scala/io/findify/sqsmock/SQSService.scala
@@ -17,13 +17,24 @@ import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.collection.JavaConversions._
+object SQSService {
+ def main(args: Array[String]) {
+ val sqs = new SQSService(8001, 1)
+ sqs.start()
+ sqs.block
+ }
+
+ val config = ConfigFactory.parseMap(Map("akka.http.parsing.illegal-header-warnings" -> "off"))
+}
+
/**
* Created by shutty on 3/29/16.
*/
-class SQSService(port:Int, account:Int = 1) {
- val config = ConfigFactory.parseMap(Map("akka.http.parsing.illegal-header-warnings" -> "off"))
- implicit val system = ActorSystem.create("sqsmock", config)
- def start():Unit = {
+class SQSService(port:Int, account:Int = 1)(implicit system: ActorSystem = ActorSystem.create("sqsmock", SQSService.config)) {
+
+ private var bind: Http.ServerBinding = _
+
+ def start() = {
val log = Logger(system.getClass, "sqs_client")
implicit val mat = ActorMaterializer()
val http = Http(system)
@@ -48,17 +59,10 @@ class SQSService(port:Int, account:Int = 1) {
}
}
}
- Await.result(http.bindAndHandle(route, "localhost", 8001), Duration.Inf)
+ bind = Await.result(http.bindAndHandle(route, "localhost", port), Duration.Inf)
+ bind
}
- def shutdown():Unit = Await.result(system.terminate(), Duration.Inf)
+ def stop():Unit = Await.result(system.terminate(), Duration.Inf)
def block():Unit = Await.result(system.whenTerminated, Duration.Inf)
}
-
-object SQSService {
- def main(args: Array[String]) {
- val sqs = new SQSService(8001, 1)
- sqs.start()
- sqs.block
- }
-}
diff --git a/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala b/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala
new file mode 100644
index 0000000..d4e9483
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala
@@ -0,0 +1,47 @@
+package io.findify.sqsmock.actions
+
+import akka.actor.ActorSystem
+import akka.event.slf4j.Logger
+import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
+import io.findify.sqsmock.messages.{DeleteMessageBatchResponse, ErrorResponse, SendMessageBatchResponse}
+import io.findify.sqsmock.model.{DeleteMessageBatchEntry, MessageBatchEntry, QueueCache}
+
+import scala.collection.mutable
+
+/**
+ * Handle DeleteQueue request.
+ * @since May 14 2017.
+ */
+class DeleteMessageBatchWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker {
+
+ val log = Logger(this.getClass, "delete_message_batch_worker")
+
+ val fieldFormat = """DeleteMessageBatchRequestEntry\.([0-9]+)\.([0-9A-Za-z\.]+)""".r
+
+ def process(fields:Map[String,String]) = {
+ val result = for (
+ queueUrl <- fields.get("QueueUrl");
+ queue <- queues.get(queueUrl)
+ ) yield {
+ val deletedMsgs = fields
+ .filter(_._1.startsWith("DeleteMessageBatchRequestEntry"))
+ .flatMap { case (key,value) => key match {
+ case fieldFormat(index, name) => Some((index.toInt, name, value))
+ case _ => None
+ }}
+ .groupBy(_._1)
+ .values.toList
+ .flatMap(DeleteMessageBatchEntry(_))
+ .filter { entry =>
+ log.debug(s"deleting message ${entry.id} from queue")
+ queue.delete(entry.receiptHandle)
+ }
+
+ HttpResponse(StatusCodes.OK, entity = DeleteMessageBatchResponse(deletedMsgs).toXML.toString())
+ }
+ result.getOrElse {
+ log.warn("cannot send message: possibly, some request parameter is missing")
+ HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "oops").toXML.toString())
+ }
+ }
+}
diff --git a/src/main/scala/io/findify/sqsmock/actions/DeleteQueueUrlWorker.scala b/src/main/scala/io/findify/sqsmock/actions/DeleteQueueUrlWorker.scala
new file mode 100644
index 0000000..370403e
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/actions/DeleteQueueUrlWorker.scala
@@ -0,0 +1,36 @@
+package io.findify.sqsmock.actions
+
+import akka.actor.ActorSystem
+import akka.event.slf4j.Logger
+import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
+import io.findify.sqsmock.messages.{DeleteQueueResponse, ErrorResponse, GetQueueUrlResponse}
+import io.findify.sqsmock.model.{QueueCache, Queues}
+
+import scala.collection.mutable
+
+/**
+ * Worker to respond to DeleteQueue requests.
+ * @since May 14 2017
+ *
+ * @param account
+ * @param queues
+ * @param system
+ */
+class DeleteQueueUrlWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker {
+
+ val log = Logger(this.getClass, "get_queue_url_worker")
+ def process(fields:Map[String,String]) = {
+ val result = for (
+ queueUrl <- fields.get("QueueUrl")
+ ) yield {
+ log.debug(s"Deleting queue '$queueUrl'")
+ queues.remove(queueUrl)
+ HttpResponse(StatusCodes.OK, entity = DeleteQueueResponse.toXML.toString)
+ }
+
+ result.getOrElse{
+ log.warn("cannot send message: possibly, some request parameter is missing")
+ HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "oops").toXML.toString())
+ }
+ }
+}
diff --git a/src/main/scala/io/findify/sqsmock/actions/GetQueueAttributesWorker.scala b/src/main/scala/io/findify/sqsmock/actions/GetQueueAttributesWorker.scala
new file mode 100644
index 0000000..afcc31f
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/actions/GetQueueAttributesWorker.scala
@@ -0,0 +1,28 @@
+package io.findify.sqsmock.actions
+
+import akka.actor.ActorSystem
+import akka.event.slf4j.Logger
+import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
+import io.findify.sqsmock.messages.{ErrorResponse, GetQueueAttributesResponse, GetQueueUrlResponse}
+import io.findify.sqsmock.model.{QueueCache, Queues}
+
+import scala.collection.mutable
+
+/**
+ * Worker to respond to GetQueueUrl requests.
+ * @since May 14 2017
+ *
+ * @param account
+ * @param queues
+ * @param system
+ */
+class GetQueueAttributesWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker {
+
+ val log = Logger(this.getClass, "get_queue_url_worker")
+ def process(fields:Map[String,String]) = {
+ // TODO Implement completely. See http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_GetQueueAttributes.html
+
+ log.warn("Not implemented completely. Returning static result.")
+ HttpResponse(StatusCodes.OK, entity = GetQueueAttributesResponse(Map.empty).toXML.toString())
+ }
+}
diff --git a/src/main/scala/io/findify/sqsmock/actions/GetQueueUrlWorker.scala b/src/main/scala/io/findify/sqsmock/actions/GetQueueUrlWorker.scala
new file mode 100644
index 0000000..7b09282
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/actions/GetQueueUrlWorker.scala
@@ -0,0 +1,52 @@
+package io.findify.sqsmock.actions
+
+import akka.actor.ActorSystem
+import akka.event.slf4j.Logger
+import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
+import io.findify.sqsmock.messages.{ErrorResponse, GetQueueUrlResponse, ListQueuesResponse, ReceiveMessageResponse}
+import io.findify.sqsmock.model.{QueueCache, Queues}
+
+import scala.collection.mutable
+
+/**
+ * Worker to respond to GetQueueUrl requests.
+ * @since May 14 2017
+ *
+ * @param account
+ * @param queues
+ * @param system
+ */
+class GetQueueUrlWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker {
+
+ val log = Logger(this.getClass, "get_queue_url_worker")
+ def process(fields:Map[String,String]) = {
+ val result = for (
+ queueName <- fields.get("QueueName")
+ ) yield {
+ // optional field
+ val accountId = fields.get("QueueOwnerAWSAccountId")
+ val validAccount = accountId.map(_ == s"$account").getOrElse(true)
+
+ if (validAccount) {
+ // filter queue on name
+ Queues.queueWithName(queues.keys, queueName) match {
+ case Some(url) =>
+ log.debug(s"Found url $url for queue name $queueName")
+ HttpResponse(StatusCodes.OK, entity = GetQueueUrlResponse(Option(url)).toXML.toString())
+ case None =>
+ log.debug(s"No url found for queue name $queueName")
+ HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "AWS.SimpleQueueService.NonExistentQueue", s"No queue with name '$queueName'").toXML.toString())
+ }
+ } else {
+ // return empty list
+ log.debug(s"Given account ${accountId.get} does not match current account $account")
+ HttpResponse(StatusCodes.OK, entity = GetQueueUrlResponse(None).toXML.toString())
+ }
+ }
+
+ result.getOrElse{
+ log.warn("cannot send message: possibly, some request parameter is missing")
+ HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "oops").toXML.toString())
+ }
+ }
+}
diff --git a/src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala b/src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala
new file mode 100644
index 0000000..b9d1d86
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala
@@ -0,0 +1,31 @@
+package io.findify.sqsmock.actions
+
+import akka.actor.ActorSystem
+import akka.event.slf4j.Logger
+import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
+import io.findify.sqsmock.messages.ListQueuesResponse
+import io.findify.sqsmock.model.{QueueCache, Queues}
+
+import scala.collection.mutable
+
+/**
+ * Worker to respond to ListQueue requests.
+ * @since May 13 2017
+ *
+ * @param account
+ * @param queues
+ * @param system
+ */
+class ListQueuesWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker {
+
+ val log = Logger(this.getClass, "list_queues_worker")
+ def process(fields:Map[String,String]) = {
+ // get queues with prefix or all queues
+ val queueNames = fields.get("QueueNamePrefix").map(
+ prefix => Queues.queuesWithPrefix(queues.keys, prefix)
+ ).getOrElse(queues.keys.toList)
+
+ log.debug("listing queues: {}", queueNames.mkString(","))
+ HttpResponse(StatusCodes.OK, entity = ListQueuesResponse(queueNames).toXML.toString)
+ }
+}
diff --git a/src/main/scala/io/findify/sqsmock/messages/DeleteMessageBatchResponse.scala b/src/main/scala/io/findify/sqsmock/messages/DeleteMessageBatchResponse.scala
new file mode 100644
index 0000000..41a513f
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/messages/DeleteMessageBatchResponse.scala
@@ -0,0 +1,27 @@
+package io.findify.sqsmock.messages
+
+import io.findify.sqsmock.model.{DeleteMessageBatchEntry, MessageBatchEntry}
+
+/**
+ * Response to DeleteMessageBatch request.
+ * @see http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html
+ * @since May 14 2017
+ * @param entries List of deleted messages
+ */
+case class DeleteMessageBatchResponse(entries:List[DeleteMessageBatchEntry]) extends Response {
+ def toXML =
+
+
+ {
+ entries.map { entry =>
+
+ { entry.id }
+
+ }
+ }
+
+
+ {uuid}
+
+
+}
diff --git a/src/main/scala/io/findify/sqsmock/messages/DeleteQueueResponse.scala b/src/main/scala/io/findify/sqsmock/messages/DeleteQueueResponse.scala
new file mode 100644
index 0000000..884fcd9
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/messages/DeleteQueueResponse.scala
@@ -0,0 +1,15 @@
+package io.findify.sqsmock.messages
+
+/**
+ * Response to DeleteQueue request.
+ * @see http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteQueue.html
+ * @since May 14 2017.
+ */
+case object DeleteQueueResponse extends Response {
+ def toXML =
+
+
+ {uuid}
+
+
+}
diff --git a/src/main/scala/io/findify/sqsmock/messages/GetQueueAttributesResponse.scala b/src/main/scala/io/findify/sqsmock/messages/GetQueueAttributesResponse.scala
new file mode 100644
index 0000000..925fe5d
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/messages/GetQueueAttributesResponse.scala
@@ -0,0 +1,27 @@
+package io.findify.sqsmock.messages
+
+/**
+ * Response to ListQueues request.
+ * @see http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_GetQueueAttributes.html
+ * @since May 13 2017
+ * @param attributesMap map of attributes names and value to be returned in the response
+ */
+case class GetQueueAttributesResponse(attributesMap: Map[String, Any]) extends Response {
+ def toXML =
+
+
+
+ VisibilityTimeout
+ 30
+
+
+ DelaySeconds
+ 0
+
+
+ ReceiveMessageWaitTimeSeconds
+ 2
+
+
+
+}
diff --git a/src/main/scala/io/findify/sqsmock/messages/GetQueueUrlResponse.scala b/src/main/scala/io/findify/sqsmock/messages/GetQueueUrlResponse.scala
new file mode 100644
index 0000000..f7b0c88
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/messages/GetQueueUrlResponse.scala
@@ -0,0 +1,24 @@
+package io.findify.sqsmock.messages
+
+/**
+ * Response to ListQueues request.
+ * @see http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_GetQueueUrl.html
+ * @since May 13 2017
+ * @param queueUrl Optional queue url. If None, not queue url is returned.
+ */
+case class GetQueueUrlResponse(queueUrl:Option[String]) extends Response {
+ def toXML =
+
+
+ {
+ queueUrl match {
+ case Some(url) => { url }
+ case None =>
+ }
+ }
+
+
+ 470a6f13-2ed9-4181-ad8a-2fdea142988e
+
+
+}
diff --git a/src/main/scala/io/findify/sqsmock/messages/ListQueuesResponse.scala b/src/main/scala/io/findify/sqsmock/messages/ListQueuesResponse.scala
new file mode 100644
index 0000000..8d3d3b1
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/messages/ListQueuesResponse.scala
@@ -0,0 +1,25 @@
+package io.findify.sqsmock.messages
+
+/**
+ * Response to ListQueues request.
+ * @see http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ListQueues.html
+ * @since May 13 2017
+ * @param queueNames Names of all queues.
+ */
+case class ListQueuesResponse(queueNames:Seq[String]) extends Response {
+ def toXML =
+
+
+ {
+ queueNames.map { queueName =>
+ {queueName}
+ }
+ }
+
+
+
+ {uuid}
+
+
+
+}
diff --git a/src/main/scala/io/findify/sqsmock/model/DeleteMessageBatchEntry.scala b/src/main/scala/io/findify/sqsmock/model/DeleteMessageBatchEntry.scala
new file mode 100644
index 0000000..8395c68
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/model/DeleteMessageBatchEntry.scala
@@ -0,0 +1,20 @@
+package io.findify.sqsmock.model
+
+/**
+ * Representing a DeleteMessageBatchRequestEntry.
+ *
+ * @see http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatchRequestEntry.html
+ * @since May 14 2017
+ */
+case class DeleteMessageBatchEntry(id:String, receiptHandle: String)
+
+object DeleteMessageBatchEntry {
+
+ def apply(fields:Iterable[(Int,String,String)]) = {
+ val attrs = fields.map(f => f._2 -> f._3).toMap
+ for (
+ id <- attrs.get("Id");
+ handle <- attrs.get("ReceiptHandle")
+ ) yield new DeleteMessageBatchEntry(id, handle)
+ }
+}
\ No newline at end of file
diff --git a/src/main/scala/io/findify/sqsmock/model/Queues.scala b/src/main/scala/io/findify/sqsmock/model/Queues.scala
new file mode 100644
index 0000000..c6c55bb
--- /dev/null
+++ b/src/main/scala/io/findify/sqsmock/model/Queues.scala
@@ -0,0 +1,42 @@
+package io.findify.sqsmock.model
+
+/**
+ * Utility functions for queues.
+ */
+object Queues {
+
+ val queueUrlRegex = """https?://(?:\w+)(?::[0-9]{2,5})?/(?:\w+)/([\w-]+)""".r
+
+ /**
+ * @param queueUrls Seq of queue urls.
+ * @return A map of queue name and urls.
+ */
+ def mapQueueUrlsWithName(queueUrls: Traversable[String]): Map[String, String] = {
+ queueUrls.map { url =>
+ val queueUrlRegex(name) = url
+ name -> url
+ }.toMap
+ }
+
+ /**
+ * @param queueUrls All queue urls.
+ * @param queueName Wanted queue name.
+ * @return Queue urls of queue with given name (if found)
+ */
+ def queueWithName(queueUrls: Traversable[String], queueName: String): Option[String] = {
+ mapQueueUrlsWithName(queueUrls).find {
+ case (name, url) => name == queueName
+ }.map(_._2)
+ }
+
+ /**
+ * @param queueUrls All queue urls.
+ * @param prefix Wanted queue name prefix.
+ * @return All queues with matching prefix.
+ */
+ def queuesWithPrefix(queueUrls: Traversable[String], prefix: String): Seq[String] = {
+ mapQueueUrlsWithName(queueUrls).filter {
+ case (name, _) => name.startsWith(prefix)
+ }.values.toSeq
+ }
+}
diff --git a/src/test/scala/io/findify/sqsmock/BatchDeleteTest.scala b/src/test/scala/io/findify/sqsmock/BatchDeleteTest.scala
new file mode 100644
index 0000000..5a16a2b
--- /dev/null
+++ b/src/test/scala/io/findify/sqsmock/BatchDeleteTest.scala
@@ -0,0 +1,47 @@
+package io.findify.sqsmock
+
+import com.amazonaws.services.sqs.model.{DeleteMessageBatchRequestEntry, ReceiveMessageRequest, SendMessageBatchRequestEntry}
+import org.scalatest._
+
+import scala.collection.JavaConversions._
+
+/**
+ * Testing [[io.findify.sqsmock.actions.DeleteMessageBatchWorker]].
+ */
+class BatchDeleteTest extends FlatSpec with Matchers with SQSStartStop {
+ import collection.JavaConverters._
+
+ val queue = "http://localhost:8001/123/foo"
+
+ "sqs mock" should "send delete messages in batch" in {
+ // setup some messages
+ client.createQueue("foo")
+ val batch = List(
+ new SendMessageBatchRequestEntry("1", "hello"),
+ new SendMessageBatchRequestEntry("2", "world")
+ )
+ val sendResult = client.sendMessageBatch(queue, batch)
+ assert(sendResult.getFailed.isEmpty)
+ assert(sendResult.getSuccessful.length == 2)
+
+ // can only delete the message after they have been received
+ // since the delete request requires a receive handle.
+ val request = new ReceiveMessageRequest()
+ .withMaxNumberOfMessages(10)
+ .withQueueUrl(queue)
+ val result = client.receiveMessage(request)
+ assert(result.getMessages.size() == 2)
+
+ // delete the messages
+ val deleteBatch = result.getMessages.asScala.map { msg =>
+ new DeleteMessageBatchRequestEntry(msg.getMessageId, msg.getReceiptHandle)
+ }
+ val deleteResult = client.deleteMessageBatch(queue, deleteBatch)
+ assert(deleteResult.getFailed.isEmpty)
+ assert(deleteResult.getSuccessful.length == 2)
+
+ // queue should now be empty
+ val receiveResult = client.receiveMessage(queue)
+ assert(receiveResult.getMessages.isEmpty)
+ }
+}
diff --git a/src/test/scala/io/findify/sqsmock/BatchSendReceiveTest.scala b/src/test/scala/io/findify/sqsmock/BatchSendReceiveTest.scala
index 5e92891..70e0d58 100644
--- a/src/test/scala/io/findify/sqsmock/BatchSendReceiveTest.scala
+++ b/src/test/scala/io/findify/sqsmock/BatchSendReceiveTest.scala
@@ -1,6 +1,5 @@
package io.findify.sqsmock
-import com.amazonaws.services.sqs.AmazonSQSClient
import com.amazonaws.services.sqs.model.{ReceiveMessageRequest, SendMessageBatchRequestEntry}
import org.scalatest._
diff --git a/src/test/scala/io/findify/sqsmock/DeleteQueueTest.scala b/src/test/scala/io/findify/sqsmock/DeleteQueueTest.scala
new file mode 100644
index 0000000..e49e1b3
--- /dev/null
+++ b/src/test/scala/io/findify/sqsmock/DeleteQueueTest.scala
@@ -0,0 +1,31 @@
+package io.findify.sqsmock
+
+import org.scalatest.{FlatSpec, Matchers}
+
+/**
+ * Testing [[io.findify.sqsmock.actions.ListQueuesWorker]]
+ */
+class DeleteQueueTest extends FlatSpec with Matchers with SQSStartStop {
+
+ import collection.JavaConverters._
+
+ override def beforeAll: Unit = {
+ super.beforeAll
+ // create some queues
+ client.createQueue("foo").getQueueUrl should be ("http://localhost:8001/123/foo")
+ client.createQueue("bar").getQueueUrl should be ("http://localhost:8001/123/bar")
+ client.createQueue("baz").getQueueUrl should be ("http://localhost:8001/123/baz")
+ }
+
+ "sqs mock" should "delete a queue" in {
+ val deleteResponse = client.deleteQueue("http://localhost:8001/123/foo")
+
+ // verify queue has been removed
+ val listResponse = client.listQueues()
+ val queueUrls = listResponse.getQueueUrls.asScala.toList
+ queueUrls should contain theSameElementsAs(List(
+ "http://localhost:8001/123/bar",
+ "http://localhost:8001/123/baz"
+ ))
+ }
+}
diff --git a/src/test/scala/io/findify/sqsmock/GetQueueAttributesTest.scala b/src/test/scala/io/findify/sqsmock/GetQueueAttributesTest.scala
new file mode 100644
index 0000000..08a59f6
--- /dev/null
+++ b/src/test/scala/io/findify/sqsmock/GetQueueAttributesTest.scala
@@ -0,0 +1,22 @@
+package io.findify.sqsmock
+
+import java.util
+
+import org.scalatest.{FlatSpec, Matchers}
+
+/**
+ * Testing [[io.findify.sqsmock.actions.GetQueueAttributesWorker]]
+ */
+class GetQueueAttributesTest extends FlatSpec with Matchers with SQSStartStop {
+
+ override def beforeAll: Unit = {
+ super.beforeAll
+ // create some queues
+ client.createQueue("foo").getQueueUrl should be ("http://localhost:8001/123/foo")
+ }
+
+ "sqs mock" should "return queue attributes" in {
+ val response = client.getQueueAttributes("http://localhost:8001/123/foo", new util.ArrayList())
+ response.getAttributes.size() should be (3)
+ }
+}
diff --git a/src/test/scala/io/findify/sqsmock/GetQueueUrlTest.scala b/src/test/scala/io/findify/sqsmock/GetQueueUrlTest.scala
new file mode 100644
index 0000000..6070a69
--- /dev/null
+++ b/src/test/scala/io/findify/sqsmock/GetQueueUrlTest.scala
@@ -0,0 +1,39 @@
+package io.findify.sqsmock
+
+import com.amazonaws.services.sqs.model.{GetQueueUrlRequest, QueueDoesNotExistException}
+import org.scalatest.{FlatSpec, Matchers}
+
+/**
+ * Testing [[io.findify.sqsmock.actions.GetQueueUrlWorker]]
+ */
+class GetQueueUrlTest extends FlatSpec with Matchers with SQSStartStop {
+
+ override def beforeAll: Unit = {
+ super.beforeAll
+ // create some queues
+ client.createQueue("foo").getQueueUrl should be ("http://localhost:8001/123/foo")
+ client.createQueue("bar").getQueueUrl should be ("http://localhost:8001/123/bar")
+ client.createQueue("baz").getQueueUrl should be ("http://localhost:8001/123/baz")
+ }
+
+ "sqs mock" should "return queue with name" in {
+ val response = client.getQueueUrl("foo")
+ response.getQueueUrl should be("http://localhost:8001/123/foo")
+ }
+
+ it should "return queue if name and account match" in {
+ val response = client.getQueueUrl(new GetQueueUrlRequest().withQueueName("foo").withQueueOwnerAWSAccountId("123"))
+ response.getQueueUrl should be("http://localhost:8001/123/foo")
+ }
+
+ it should "return no url if account does not match" in {
+ val response = client.getQueueUrl(new GetQueueUrlRequest().withQueueName("foo").withQueueOwnerAWSAccountId("1"))
+ response.getQueueUrl should be("")
+ }
+
+ it should "return error if no name matches" in {
+ intercept[QueueDoesNotExistException] {
+ client.getQueueUrl("non-existant")
+ }
+ }
+}
diff --git a/src/test/scala/io/findify/sqsmock/ListQueuesTest.scala b/src/test/scala/io/findify/sqsmock/ListQueuesTest.scala
new file mode 100644
index 0000000..7f270b5
--- /dev/null
+++ b/src/test/scala/io/findify/sqsmock/ListQueuesTest.scala
@@ -0,0 +1,44 @@
+package io.findify.sqsmock
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import scala.collection.JavaConversions._
+
+/**
+ * Testing [[io.findify.sqsmock.actions.ListQueuesWorker]]
+ */
+class ListQueuesTest extends FlatSpec with Matchers with SQSStartStop {
+
+ import collection.JavaConverters._
+
+ override def beforeAll: Unit = {
+ super.beforeAll
+ // create some queues
+ client.createQueue("foo").getQueueUrl should be ("http://localhost:8001/123/foo")
+ client.createQueue("bar").getQueueUrl should be ("http://localhost:8001/123/bar")
+ client.createQueue("baz").getQueueUrl should be ("http://localhost:8001/123/baz")
+ }
+
+ "sqs mock" should "list all queus" in {
+ val response = client.listQueues()
+ val queueUrls = response.getQueueUrls.asScala.toList
+ queueUrls should contain theSameElementsAs(List(
+ "http://localhost:8001/123/foo",
+ "http://localhost:8001/123/bar",
+ "http://localhost:8001/123/baz"
+ ))
+ }
+
+ it should "list some queues" in {
+ val response1 = client.listQueues("ba")
+ response1.getQueueUrls.asScala.toList should contain theSameElementsAs(List(
+ "http://localhost:8001/123/bar",
+ "http://localhost:8001/123/baz"
+ ))
+
+ val response2 = client.listQueues("fo")
+ response2.getQueueUrls.asScala.toList should contain theSameElementsAs(List(
+ "http://localhost:8001/123/foo"
+ ))
+ }
+}
diff --git a/src/test/scala/io/findify/sqsmock/ReceiveDeleteTest.scala b/src/test/scala/io/findify/sqsmock/ReceiveDeleteTest.scala
index 3d73928..4806436 100644
--- a/src/test/scala/io/findify/sqsmock/ReceiveDeleteTest.scala
+++ b/src/test/scala/io/findify/sqsmock/ReceiveDeleteTest.scala
@@ -1,8 +1,7 @@
package io.findify.sqsmock
-import com.amazonaws.services.sqs.AmazonSQSClient
import com.amazonaws.services.sqs.model.CreateQueueRequest
-import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers}
+import org.scalatest.{FlatSpec, Matchers}
import scala.collection.JavaConversions._
/**
diff --git a/src/test/scala/io/findify/sqsmock/SQSStartStop.scala b/src/test/scala/io/findify/sqsmock/SQSStartStop.scala
index a37fe84..db03705 100644
--- a/src/test/scala/io/findify/sqsmock/SQSStartStop.scala
+++ b/src/test/scala/io/findify/sqsmock/SQSStartStop.scala
@@ -1,22 +1,31 @@
package io.findify.sqsmock
-import com.amazonaws.auth.AnonymousAWSCredentials
-import com.amazonaws.services.sqs.AmazonSQSClient
+import com.amazonaws.auth.{AWSCredentials, AWSCredentialsProvider, AnonymousAWSCredentials}
+import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration
+import com.amazonaws.services.sqs.{AmazonSQS, AmazonSQSClient, AmazonSQSClientBuilder}
import org.scalatest.{BeforeAndAfterAll, FlatSpec}
/**
* Created by shutty on 3/31/16.
*/
trait SQSStartStop extends FlatSpec with BeforeAndAfterAll {
- var sqs:SQSService = _
- var client:AmazonSQSClient = _
+ var sqs: SQSService = _
+ var client: AmazonSQS = _
+
override def beforeAll = {
sqs = new SQSService(8001, 123)
sqs.start()
- client = new AmazonSQSClient(new AnonymousAWSCredentials())
- client.setEndpoint("http://localhost:8001")
+
+ client = AmazonSQSClientBuilder.standard()
+ .withCredentials(new AWSCredentialsProvider {
+ val creds = new AnonymousAWSCredentials()
+ override def refresh(): Unit = ()
+ override def getCredentials: AWSCredentials = creds
+ })
+ .withEndpointConfiguration(new EndpointConfiguration("http://localhost:8001", "us-east-1"))
+ .build()
}
override def afterAll = {
- sqs.shutdown()
+ sqs.stop()
}
}
diff --git a/src/test/scala/io/findify/sqsmock/SendReceiveTest.scala b/src/test/scala/io/findify/sqsmock/SendReceiveTest.scala
index 5b2799f..4b06365 100644
--- a/src/test/scala/io/findify/sqsmock/SendReceiveTest.scala
+++ b/src/test/scala/io/findify/sqsmock/SendReceiveTest.scala
@@ -1,7 +1,6 @@
package io.findify.sqsmock
-import com.amazonaws.services.sqs.AmazonSQSClient
-import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers}
+import org.scalatest.{FlatSpec, Matchers}
import scala.collection.JavaConversions._
/**