From f1df5fd3c23e0d31ad10af885797ae4f06c974ce Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sat, 13 May 2017 21:55:29 +0200 Subject: [PATCH 01/10] Updated dependencies to latest versions. Updated sbt to 0.13.15. Set version to 0.3.3-SNAPSHOT. --- build.sbt | 16 ++++++++-------- project/build.properties | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.sbt b/build.sbt index 7a3f230..1175eda 100644 --- a/build.sbt +++ b/build.sbt @@ -1,25 +1,25 @@ name := "sqsmock" -version := "0.3.2" +version := "0.3.3-SNAPSHOT" organization := "io.findify" -scalaVersion := "2.11.8" +scalaVersion := "2.12.2" -val akkaVersion = "2.4.9" +val akkaVersion = "2.5.1" 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 From 44e59ba9aaa6b45acbb22ad3104465714c3488c7 Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sat, 13 May 2017 21:55:55 +0200 Subject: [PATCH 02/10] Added support for ListQueues request. --- .../scala/io/findify/sqsmock/SQSBackend.scala | 20 +++++---- .../sqsmock/actions/ListQueuesWorker.scala | 41 +++++++++++++++++ .../sqsmock/messages/ListQueuesResponse.scala | 25 +++++++++++ .../io/findify/sqsmock/ListQueuesTest.scala | 44 +++++++++++++++++++ 4 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala create mode 100644 src/main/scala/io/findify/sqsmock/messages/ListQueuesResponse.scala create mode 100644 src/test/scala/io/findify/sqsmock/ListQueuesTest.scala diff --git a/src/main/scala/io/findify/sqsmock/SQSBackend.scala b/src/main/scala/io/findify/sqsmock/SQSBackend.scala index 628fa36..2c93bec 100644 --- a/src/main/scala/io/findify/sqsmock/SQSBackend.scala +++ b/src/main/scala/io/findify/sqsmock/SQSBackend.scala @@ -15,19 +15,23 @@ 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) + 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 _ => HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "operation not supported").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..db25379 --- /dev/null +++ b/src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala @@ -0,0 +1,41 @@ +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 + +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 queueUrlRegex = """https?://(?:[a-zA-Z0-9]+)(?::[0-9]{2,5})?/(?:[a-zA-Z0-9]+)/([a-zA-Z0-9]+)""".r + + def queuesWithName: Map[String, String] = { + queues.keys.map { key => + val queueUrlRegex(name) = key + name -> key + }.toMap + } + + val log = Logger(this.getClass, "list_queues_worker") + def process(fields:Map[String,String]) = { + val queueNames = fields.get("QueueNamePrefix").map( + prefix => queuesWithName.filter { + case (key,_) => key.startsWith(prefix) + }.values.toList + ).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/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/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" + )) + } +} From efe7556a4a093a471a7029a8bdc0fe184d895709 Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sat, 13 May 2017 21:57:27 +0200 Subject: [PATCH 03/10] Fixed issue where service was not actually started on given port. Also did some changes to make it inline with S3Mock (start now returns ServerBinding, shutdown renamed to stop, takes implicit system argument). --- .../scala/io/findify/sqsmock/SQSService.scala | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) 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 - } -} From 4e091a47791dc8fef742ab846cf28e32e75d095b Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sat, 13 May 2017 21:57:58 +0200 Subject: [PATCH 04/10] Removed unused imports. --- src/test/scala/io/findify/sqsmock/BatchSendReceiveTest.scala | 1 - src/test/scala/io/findify/sqsmock/ReceiveDeleteTest.scala | 3 +-- src/test/scala/io/findify/sqsmock/SendReceiveTest.scala | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) 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/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/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._ /** From 1ac1dd29671c62d3ace016e12bf955ad3a6a2d05 Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sat, 13 May 2017 21:58:41 +0200 Subject: [PATCH 05/10] Changed creation of client to use builder. --- .../io/findify/sqsmock/SQSStartStop.scala | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) 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() } } From d7b386ba53b2eb47e87f928bbdf9449acc7ffa9e Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sun, 14 May 2017 15:49:23 +0200 Subject: [PATCH 06/10] Added support for GetQueueUrl. --- .../scala/io/findify/sqsmock/SQSBackend.scala | 2 + .../sqsmock/actions/GetQueueUrlWorker.scala | 52 +++++++++++++++++++ .../sqsmock/actions/ListQueuesWorker.scala | 16 ++---- .../messages/GetQueueUrlResponse.scala | 24 +++++++++ .../io/findify/sqsmock/model/Queues.scala | 42 +++++++++++++++ .../io/findify/sqsmock/GetQueueUrlTest.scala | 39 ++++++++++++++ 6 files changed, 162 insertions(+), 13 deletions(-) create mode 100644 src/main/scala/io/findify/sqsmock/actions/GetQueueUrlWorker.scala create mode 100644 src/main/scala/io/findify/sqsmock/messages/GetQueueUrlResponse.scala create mode 100644 src/main/scala/io/findify/sqsmock/model/Queues.scala create mode 100644 src/test/scala/io/findify/sqsmock/GetQueueUrlTest.scala diff --git a/src/main/scala/io/findify/sqsmock/SQSBackend.scala b/src/main/scala/io/findify/sqsmock/SQSBackend.scala index 2c93bec..5b6ad74 100644 --- a/src/main/scala/io/findify/sqsmock/SQSBackend.scala +++ b/src/main/scala/io/findify/sqsmock/SQSBackend.scala @@ -22,6 +22,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { val sendMessageBatchWorker = new SendMessageBatchWorker(account, queueCache, system) val deleteMessageWorker = new DeleteMessageWorker(account, queueCache, system) val listQueuesWorker = new ListQueuesWorker(account, queueCache, system) + val getQueueUrlWorker = new GetQueueUrlWorker(account, queueCache, system) def process(fields:Map[String,String]) = { log.debug(s"processing request for fields $fields") @@ -32,6 +33,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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 _ => HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "operation not supported").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 index db25379..b9d1d86 100644 --- a/src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala +++ b/src/main/scala/io/findify/sqsmock/actions/ListQueuesWorker.scala @@ -4,7 +4,7 @@ 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 +import io.findify.sqsmock.model.{QueueCache, Queues} import scala.collection.mutable @@ -18,21 +18,11 @@ import scala.collection.mutable */ class ListQueuesWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker { - val queueUrlRegex = """https?://(?:[a-zA-Z0-9]+)(?::[0-9]{2,5})?/(?:[a-zA-Z0-9]+)/([a-zA-Z0-9]+)""".r - - def queuesWithName: Map[String, String] = { - queues.keys.map { key => - val queueUrlRegex(name) = key - name -> key - }.toMap - } - 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 => queuesWithName.filter { - case (key,_) => key.startsWith(prefix) - }.values.toList + prefix => Queues.queuesWithPrefix(queues.keys, prefix) ).getOrElse(queues.keys.toList) log.debug("listing queues: {}", queueNames.mkString(",")) 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/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/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") + } + } +} From c13af51114259235adc38bc60847813b5599a42d Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sun, 14 May 2017 16:37:58 +0200 Subject: [PATCH 07/10] Partially implemented GetQueueAttributes. --- .../scala/io/findify/sqsmock/SQSBackend.scala | 2 ++ .../actions/GetQueueAttributesWorker.scala | 28 +++++++++++++++++++ .../messages/GetQueueAttributesResponse.scala | 27 ++++++++++++++++++ .../sqsmock/GetQueueAttributesTest.scala | 22 +++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 src/main/scala/io/findify/sqsmock/actions/GetQueueAttributesWorker.scala create mode 100644 src/main/scala/io/findify/sqsmock/messages/GetQueueAttributesResponse.scala create mode 100644 src/test/scala/io/findify/sqsmock/GetQueueAttributesTest.scala diff --git a/src/main/scala/io/findify/sqsmock/SQSBackend.scala b/src/main/scala/io/findify/sqsmock/SQSBackend.scala index 5b6ad74..f621fec 100644 --- a/src/main/scala/io/findify/sqsmock/SQSBackend.scala +++ b/src/main/scala/io/findify/sqsmock/SQSBackend.scala @@ -23,6 +23,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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) def process(fields:Map[String,String]) = { log.debug(s"processing request for fields $fields") @@ -34,6 +35,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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 _ => HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "operation not supported").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/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/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) + } +} From 303dc4bb5d6107d80959f8a4fc0c10f43fc6ab0b Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sun, 14 May 2017 17:21:41 +0200 Subject: [PATCH 08/10] Added support for DeleteMessageBatch --- .../scala/io/findify/sqsmock/SQSBackend.scala | 2 + .../actions/DeleteMessageBatchWorker.scala | 46 ++++++++++++++++++ .../messages/DeleteMessageBatchResponse.scala | 27 +++++++++++ .../model/DeleteMessageBatchEntry.scala | 20 ++++++++ .../io/findify/sqsmock/BatchDeleteTest.scala | 47 +++++++++++++++++++ 5 files changed, 142 insertions(+) create mode 100644 src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala create mode 100644 src/main/scala/io/findify/sqsmock/messages/DeleteMessageBatchResponse.scala create mode 100644 src/main/scala/io/findify/sqsmock/model/DeleteMessageBatchEntry.scala create mode 100644 src/test/scala/io/findify/sqsmock/BatchDeleteTest.scala diff --git a/src/main/scala/io/findify/sqsmock/SQSBackend.scala b/src/main/scala/io/findify/sqsmock/SQSBackend.scala index f621fec..8ef1fae 100644 --- a/src/main/scala/io/findify/sqsmock/SQSBackend.scala +++ b/src/main/scala/io/findify/sqsmock/SQSBackend.scala @@ -24,6 +24,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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) def process(fields:Map[String,String]) = { log.debug(s"processing request for fields $fields") @@ -36,6 +37,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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 _ => HttpResponse(StatusCodes.BadRequest, entity = ErrorResponse("Sender", "InvalidParameterValue", "operation not supported").toXML.toString()) } } 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..880033c --- /dev/null +++ b/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala @@ -0,0 +1,46 @@ +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 + +/** + * Created by shutty on 3/30/16. + */ +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/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/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/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) + } +} From 1731c4ea58aa6e8f7c2147c0a58f65666304caf8 Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Sun, 14 May 2017 17:31:46 +0200 Subject: [PATCH 09/10] Added support for DeleteQueue. --- .../scala/io/findify/sqsmock/SQSBackend.scala | 2 ++ .../actions/DeleteMessageBatchWorker.scala | 3 +- .../actions/DeleteQueueUrlWorker.scala | 36 +++++++++++++++++++ .../messages/DeleteQueueResponse.scala | 15 ++++++++ .../io/findify/sqsmock/DeleteQueueTest.scala | 31 ++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/io/findify/sqsmock/actions/DeleteQueueUrlWorker.scala create mode 100644 src/main/scala/io/findify/sqsmock/messages/DeleteQueueResponse.scala create mode 100644 src/test/scala/io/findify/sqsmock/DeleteQueueTest.scala diff --git a/src/main/scala/io/findify/sqsmock/SQSBackend.scala b/src/main/scala/io/findify/sqsmock/SQSBackend.scala index 8ef1fae..bc220d4 100644 --- a/src/main/scala/io/findify/sqsmock/SQSBackend.scala +++ b/src/main/scala/io/findify/sqsmock/SQSBackend.scala @@ -25,6 +25,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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") @@ -38,6 +39,7 @@ class SQSBackend(account:Long, port:Int, system:ActorSystem) { 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/actions/DeleteMessageBatchWorker.scala b/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala index 880033c..d4e9483 100644 --- a/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala +++ b/src/main/scala/io/findify/sqsmock/actions/DeleteMessageBatchWorker.scala @@ -9,7 +9,8 @@ import io.findify.sqsmock.model.{DeleteMessageBatchEntry, MessageBatchEntry, Que import scala.collection.mutable /** - * Created by shutty on 3/30/16. + * Handle DeleteQueue request. + * @since May 14 2017. */ class DeleteMessageBatchWorker(account:Long, queues:mutable.Map[String,QueueCache], system:ActorSystem) extends Worker { 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/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/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" + )) + } +} From e4ee8e7e8950535ba131b134574dca17493d7a3a Mon Sep 17 00:00:00 2001 From: Joost den Boer Date: Mon, 23 Oct 2017 16:26:25 +0200 Subject: [PATCH 10/10] Added cross compile so this library can be used by AWScala which also provides versions for Scala 2.11 and 2.12. --- build.sbt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1175eda..a37d9b4 100644 --- a/build.sbt +++ b/build.sbt @@ -4,10 +4,12 @@ version := "0.3.3-SNAPSHOT" organization := "io.findify" -scalaVersion := "2.12.2" +scalaVersion := "2.12.3" 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,