org.scalatest.wordspec.AsyncWordSpec Scala Examples

The following examples show how to use org.scalatest.wordspec.AsyncWordSpec. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: PublishServiceSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package docs.scaladsl.mb

import com.lightbend.lagom.scaladsl.api.broker.Topic
import com.lightbend.lagom.scaladsl.server.LagomApplication
import com.lightbend.lagom.scaladsl.server.LagomApplicationContext
import com.lightbend.lagom.scaladsl.server.LagomServer
import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.ServiceTest
import com.lightbend.lagom.scaladsl.testkit.TestTopicComponents
import play.api.libs.ws.ahc.AhcWSComponents
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import akka.NotUsed
import akka.Done
import akka.stream.scaladsl.Source
import akka.stream.testkit.scaladsl.TestSink
import akka.stream.testkit.TestSubscriber
import akka.stream.testkit.TestSubscriber.Probe

abstract class PublishApplication(context: LagomApplicationContext)
    extends LagomApplication(context)
    with AhcWSComponents {
  override lazy val lagomServer = serverFor[service.PublishService](new service.PublishServiceImpl())
}

package service {
  import com.lightbend.lagom.scaladsl.api.Service
  import com.lightbend.lagom.scaladsl.broker.TopicProducer

  object PublishService {
    val TOPIC_NAME = "events"
  }

  trait PublishService extends Service {
    final override def descriptor = {
      import Service._
      named("brokerdocs")
        .withTopics(topic(PublishService.TOPIC_NAME, events))
        .withAutoAcl(true)
    }

    def events(): Topic[PubMessage]
  }

  case class PubMessage(message: String)

  object PubMessage {
    import play.api.libs.json.Format
    import play.api.libs.json.Json
    implicit val format: Format[PubMessage] = Json.format[PubMessage]
  }

  class PublishServiceImpl() extends PublishService {
    override def events(): Topic[PubMessage] =
      TopicProducer.singleStreamWithOffset { offset =>
        Source((1 to 10)).map(i => (PubMessage(s"msg $i"), offset))
      }
  }
}

class PublishServiceSpec extends AsyncWordSpec with Matchers {
  import service._

  //#topic-test-publishing-into-a-topic
  "The PublishService" should {
    "publish events on the topic" in ServiceTest.withServer(ServiceTest.defaultSetup) { ctx =>
      new PublishApplication(ctx) with LocalServiceLocator with TestTopicComponents
    } { server =>
      implicit val system = server.actorSystem
      implicit val mat    = server.materializer

      val client: PublishService = server.serviceClient.implement[PublishService]
      val source                 = client.events().subscribe.atMostOnceSource
      source
        .runWith(TestSink.probe[PubMessage])
        .request(1)
        .expectNext should ===(PubMessage("msg 1"))
    }
  }
  //#topic-test-publishing-into-a-topic
} 
Example 2
Source File: UpickleCustomizationSupportSpec.scala    From akka-http-json   with Apache License 2.0 5 votes vote down vote up
package de.heikoseeberger.akkahttpupickle

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.ContentTypes.{ `application/json`, `text/plain(UTF-8)` }
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshaller.UnsupportedContentTypeException
import akka.http.scaladsl.unmarshalling.{ Unmarshal, Unmarshaller }
import akka.stream.scaladsl.{ Sink, Source }
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import upickle.AttributeTagged
import upickle.core.Visitor

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt

final class UpickleCustomizationSupportSpec
    extends AsyncWordSpec
    with Matchers
    with BeforeAndAfterAll {

  private implicit val system = ActorSystem()

  object FooApi extends AttributeTagged {
    override implicit val IntWriter: FooApi.Writer[Int] = new Writer[Int] {
      override def write0[V](out: Visitor[_, V], v: Int): V = out.visitString("foo", -1)
    }
  }
  object UpickleFoo extends UpickleCustomizationSupport {
    override type Api = FooApi.type
    override def api: FooApi.type = FooApi
  }

  import UpickleFoo._

  "UpickleCustomizationSupport" should {
    "support custom configuration" in {
      Marshal(123)
        .to[RequestEntity]
        .flatMap(Unmarshal(_).to[String])
        .map(_ shouldBe "foo")
    }
  }

  override protected def afterAll() = {
    Await.ready(system.terminate(), 42.seconds)
    super.afterAll()
  }
} 
Example 3
Source File: UpickleSupportSpec.scala    From akka-http-json   with Apache License 2.0 5 votes vote down vote up
package de.heikoseeberger.akkahttpupickle

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.ContentTypes.{ `application/json`, `text/plain(UTF-8)` }
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshaller.UnsupportedContentTypeException
import akka.http.scaladsl.unmarshalling.{ Unmarshal, Unmarshaller }
import akka.stream.scaladsl.{ Sink, Source }
import org.scalatest.BeforeAndAfterAll

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
import upickle.default.{ ReadWriter, macroRW }
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

object UpickleSupportSpec {

  final object Foo {
    implicit val rw: ReadWriter[Foo] = macroRW
  }

  final case class Foo(bar: String) {
    require(bar startsWith "bar", "bar must start with 'bar'!")
  }
}

final class UpickleSupportSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll {
  import UpickleSupport._
  import UpickleSupportSpec._

  private implicit val system = ActorSystem()

  "UpickleSupport" should {
    "enable marshalling and unmarshalling of case classes" in {
      val foo = Foo("bar")
      Marshal(foo)
        .to[RequestEntity]
        .flatMap(Unmarshal(_).to[Foo])
        .map(_ shouldBe foo)
    }

    "enable streamed marshalling and unmarshalling for json arrays" in {
      val foos = (0 to 100).map(i => Foo(s"bar-$i")).toList

      Marshal(Source(foos))
        .to[RequestEntity]
        .flatMap(entity => Unmarshal(entity).to[SourceOf[Foo]])
        .flatMap(_.runWith(Sink.seq))
        .map(_ shouldBe foos)
    }

    "provide proper error messages for requirement errors" in {
      val entity = HttpEntity(MediaTypes.`application/json`, """{ "bar": "baz" }""")
      Unmarshal(entity)
        .to[Foo]
        .failed
        .map(_ should have message "requirement failed: bar must start with 'bar'!")
    }

    "fail with NoContentException when unmarshalling empty entities" in {
      val entity = HttpEntity.empty(`application/json`)
      Unmarshal(entity)
        .to[Foo]
        .failed
        .map(_ shouldBe Unmarshaller.NoContentException)
    }

    "fail with UnsupportedContentTypeException when Content-Type is not `application/json`" in {
      val entity = HttpEntity("""{ "bar": "bar" }""")
      Unmarshal(entity)
        .to[Foo]
        .failed
        .map(
          _ shouldBe UnsupportedContentTypeException(Some(`text/plain(UTF-8)`), `application/json`)
        )
    }

    "allow unmarshalling with passed in Content-Types" in {
      val foo = Foo("bar")
      val `application/json-home` =
        MediaType.applicationWithFixedCharset("json-home", HttpCharsets.`UTF-8`, "json-home")

      final object CustomUpickleSupport extends UpickleSupport {
        override def unmarshallerContentTypes = List(`application/json`, `application/json-home`)
      }
      import CustomUpickleSupport._

      val entity = HttpEntity(`application/json-home`, """{ "bar": "bar" }""")
      Unmarshal(entity).to[Foo].map(_ shouldBe foo)
    }
  }

  override protected def afterAll() = {
    Await.ready(system.terminate(), 42.seconds)
    super.afterAll()
  }
} 
Example 4
Source File: JsoniterScalaSupportSpec.scala    From akka-http-json   with Apache License 2.0 5 votes vote down vote up
package de.heikoseeberger.akkahttpjsoniterscala

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.ContentTypes.{ `application/json`, `text/plain(UTF-8)` }
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshaller.UnsupportedContentTypeException
import akka.http.scaladsl.unmarshalling.{ Unmarshal, Unmarshaller }
import akka.stream.scaladsl.{ Sink, Source }
import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
import com.github.plokhotnyuk.jsoniter_scala.macros._
import org.scalatest.BeforeAndAfterAll

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

object JsoniterScalaSupportSpec {

  final case class Foo(bar: String) {
    require(bar startsWith "bar", "bar must start with 'bar'!")
  }
}

final class JsoniterScalaSupportSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll {
  import JsoniterScalaSupport._
  import JsoniterScalaSupportSpec._

  private implicit val system: ActorSystem        = ActorSystem()
  private implicit val codec: JsonValueCodec[Foo] = JsonCodecMaker.make[Foo](CodecMakerConfig)

  "JsoniterScalaSupport" should {
    "should enable marshalling and unmarshalling" in {
      val foo = Foo("bar")
      Marshal(foo)
        .to[RequestEntity]
        .flatMap(Unmarshal(_).to[Foo])
        .map(_ shouldBe foo)
    }

    "enable streamed marshalling and unmarshalling for json arrays" in {
      val foos = (0 to 100).map(i => Foo(s"bar-$i")).toList

      Marshal(Source(foos))
        .to[RequestEntity]
        .flatMap(entity => Unmarshal(entity).to[SourceOf[Foo]])
        .flatMap(_.runWith(Sink.seq))
        .map(_ shouldBe foos)
    }

    "provide proper error messages for requirement errors" in {
      val entity = HttpEntity(MediaTypes.`application/json`, """{ "bar": "baz" }""")
      Unmarshal(entity)
        .to[Foo]
        .failed
        .map(_ should have message "requirement failed: bar must start with 'bar'!")
    }

    "fail with NoContentException when unmarshalling empty entities" in {
      val entity = HttpEntity.empty(`application/json`)
      Unmarshal(entity)
        .to[Foo]
        .failed
        .map(_ shouldBe Unmarshaller.NoContentException)
    }

    "fail with UnsupportedContentTypeException when Content-Type is not `application/json`" in {
      val entity = HttpEntity("""{ "bar": "bar" }""")
      Unmarshal(entity)
        .to[Foo]
        .failed
        .map(
          _ shouldBe UnsupportedContentTypeException(Some(`text/plain(UTF-8)`), `application/json`)
        )
    }

    "allow unmarshalling with passed in Content-Types" in {
      val foo = Foo("bar")
      val `application/json-home` =
        MediaType.applicationWithFixedCharset("json-home", HttpCharsets.`UTF-8`, "json-home")

      final object CustomJsoniterScalaSupport extends JsoniterScalaSupport {
        override def unmarshallerContentTypes: List[ContentTypeRange] =
          List(`application/json`, `application/json-home`)
      }
      import CustomJsoniterScalaSupport._

      val entity = HttpEntity(`application/json-home`, """{ "bar": "bar" }""")
      Unmarshal(entity).to[Foo].map(_ shouldBe foo)
    }
  }

  override protected def afterAll(): Unit = {
    Await.ready(system.terminate(), 42.seconds)
    super.afterAll()
  }
} 
Example 5
Source File: RespondeeTests.scala    From streamee   with Apache License 2.0 5 votes vote down vote up
package io.moia.streamee

import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import scala.concurrent.duration.DurationInt

final class RespondeeTests extends AsyncWordSpec with AkkaSuite with Matchers {
  import Respondee._

  "A Respondee" should {
    "fail its promise with a TimeoutException if not receiving a Response in time" in {
      val timeout       = 100.milliseconds
      val (_, response) = Respondee.spawn[Int](timeout)
      response.future.failed.map { case ResponseTimeoutException(t) => t shouldBe timeout }
    }

    "successfully complete its promise with the received Response" in {
      val (respondee, response) = Respondee.spawn[Int](1.second)
      respondee ! Response(42)
      response.future.map(_ shouldBe 42)
    }
  }
} 
Example 6
Source File: AkkaHttpRouteBackendTest.scala    From sttp   with Apache License 2.0 5 votes vote down vote up
package sttp.client.akkahttp

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import org.scalatest.BeforeAndAfterAll
import sttp.client.{NothingT, SttpBackend}
import sttp.model.StatusCode

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

class AkkaHttpRouteBackendTest extends AsyncWordSpec with Matchers with BeforeAndAfterAll {

  implicit val system: ActorSystem = ActorSystem()
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  override protected def afterAll(): Unit = {
    Await.result(system.terminate(), 5.seconds)
  }

  val backend: SttpBackend[Future, Nothing, NothingT] = {
    AkkaHttpBackend.usingClient(system, http = AkkaHttpClient.stubFromRoute(Routes.route))
  }

  import sttp.client._

  "matched route" should {

    "respond" in {
      backend.send(basicRequest.get(uri"http://localhost/hello")).map { response =>
        response.code shouldBe StatusCode.Ok
        response.body.right.get shouldBe "Hello, world!"
      }
    }
  }

  "unmatched route" should {
    "respond with 404" in {
      backend.send(basicRequest.get(uri"http://localhost/not-matching")).map { response =>
        response.code shouldBe StatusCode.NotFound
        response.body.left.get shouldBe "The requested resource could not be found."
      }
    }
  }

}

object Routes {
  import akka.http.scaladsl.server.Directives._

  val route: Route =
    pathPrefix("hello") {
      complete("Hello, world!")
    }
} 
Example 7
Source File: HelloServiceSpec.scala    From play-grpc   with Apache License 2.0 5 votes vote down vote up
package scala.com.example.hello.impl

import akka.stream.Materializer
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.GreeterServiceClient
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.HelloRequest
import com.lightbend.lagom.scaladsl.grpc.interop.test.HelloApplication
import com.lightbend.lagom.scaladsl.grpc.interop.test.HelloService
import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.ServiceTest
import com.lightbend.lagom.scaladsl.testkit.grpc.AkkaGrpcClientHelpers
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

class HelloServiceSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll {

  private val server: ServiceTest.TestServer[HelloApplication with LocalServiceLocator] = ServiceTest.startServer(
    ServiceTest.defaultSetup.withSsl(true),
  ) { ctx =>
    new HelloApplication(ctx) with LocalServiceLocator
  }

  implicit val mat: Materializer = server.materializer

  val client: HelloService = server.serviceClient.implement[HelloService]
  val grpcClient: GreeterServiceClient = AkkaGrpcClientHelpers.grpcClient(
    server,
    GreeterServiceClient.apply,
  )

  protected override def afterAll(): Unit = {
    grpcClient.close()
    server.stop()
  }

  "Hello service" should {

    "say hello over HTTP" in {
      client.hello("Alice").invoke().map { answer =>
        answer should ===("Hi Alice!")
      }
    }

    "say hello over gRPC" in {
      grpcClient
        .sayHello(HelloRequest("Alice"))
        .map {
          _.message should be("Hi Alice! (gRPC)")
        }
    }

  }
} 
Example 8
Source File: HelloServiceSpec.scala    From play-grpc   with Apache License 2.0 5 votes vote down vote up
package com.example.hello.impl

import akka.stream.Materializer
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.GreeterServiceClient
import com.lightbend.lagom.scaladsl.grpc.interop.helloworld.HelloRequest
import com.lightbend.lagom.scaladsl.grpc.interop.test.HelloApplication
import com.lightbend.lagom.scaladsl.grpc.interop.test.HelloService
import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.ServiceTest
import com.lightbend.lagom.scaladsl.testkit.grpc.AkkaGrpcClientHelpers
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.wordspec.AsyncWordSpec

class HelloServiceAsyncSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll {

  private val server: ServiceTest.TestServer[HelloApplication with LocalServiceLocator] = ServiceTest.startServer(
    ServiceTest.defaultSetup.withSsl(true).withCluster(false),
  ) { ctx =>
    new HelloApplication(ctx) with LocalServiceLocator
  }

  implicit val mat: Materializer = server.materializer
  val client: HelloService       = server.serviceClient.implement[HelloService]

  // #unmanaged-client
  val grpcClient: GreeterServiceClient = AkkaGrpcClientHelpers.grpcClient(
    server,
    GreeterServiceClient.apply,
  )

  protected override def afterAll(): Unit = {
    grpcClient.close()
    server.stop()
  }

  // #unmanaged-client

  "Hello service (Async)" should {

    "say hello over HTTP" in {
      client.hello("Alice").invoke().map { answer =>
        answer should ===("Hi Alice!")
      }
    }

    // #unmanaged-client
    "say hello over gRPC (unmnanaged client)" in {
      grpcClient
        .sayHello(HelloRequest("Alice"))
        .map {
          _.message should be("Hi Alice! (gRPC)")
        }
    }
    // #unmanaged-client

  }

}

class HelloServiceSpec extends AnyWordSpec with Matchers with BeforeAndAfterAll {

  private val server: ServiceTest.TestServer[HelloApplication with LocalServiceLocator] = ServiceTest.startServer(
    ServiceTest.defaultSetup.withSsl(true).withCluster(false),
  ) { ctx =>
    new HelloApplication(ctx) with LocalServiceLocator
  }

  implicit val mat: Materializer = server.materializer
  implicit val ctx               = server.executionContext
  val client: HelloService       = server.serviceClient.implement[HelloService]

  protected override def afterAll(): Unit = {
    server.stop()
  }

  "Hello service (Sync)" should {

    // #managed-client
    "say hello over gRPC (managed client)" in {
      AkkaGrpcClientHelpers.withGrpcClient(server, GreeterServiceClient.apply _) { grpcClient =>
        grpcClient
          .sayHello(HelloRequest("Alice"))
          .map {
            _.message should be("Hi Alice! (gRPC)")
          }
      }
    }
    // #managed-client

  }

} 
Example 9
Source File: ProducerStubSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.scaladsl.testkit

import com.lightbend.lagom.scaladsl.api.broker.Topic
import com.lightbend.lagom.scaladsl.server.LagomApplicationContext
import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.services._
import org.scalatest.concurrent.Eventually
import org.scalatest.time.Seconds
import org.scalatest.time.Span
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

class ProducerStubSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll with Eventually {
  var producerStub: ProducerStub[AlphaEvent] = _

  private val stubbedApplication: LagomApplicationContext => DownstreamApplication = { ctx =>
    new DownstreamApplication(ctx) with LocalServiceLocator with TestTopicComponents {
      val stubFactory = new ProducerStubFactory(actorSystem, materializer)
      producerStub = stubFactory.producer[AlphaEvent](AlphaService.TOPIC_ID)
      override lazy val alphaService = new AlphaServiceStub(producerStub)
    }
  }

  "The ProducerStub" should {
    "send message to consuming services" in ServiceTest.withServer(ServiceTest.defaultSetup.withCluster())(
      stubbedApplication
    ) { server =>
      implicit val exCtx = server.application.actorSystem.dispatcher
      producerStub.send(AlphaEvent(22))
      eventually(timeout(Span(5, Seconds))) {
        server.serviceClient
          .implement[CharlieService]
          .messages
          .invoke()
          .map { response =>
            response should ===(Seq(ReceivedMessage("A", 22)))
          }
          .recover {
            case t: Throwable => fail(t)
          }
      }
    }
  }
}

class AlphaServiceStub(stub: ProducerStub[AlphaEvent]) extends AlphaService {
  override def messages: Topic[AlphaEvent] = stub.topic
} 
Example 10
Source File: TopicPublishingSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.scaladsl.testkit

import akka.persistence.query.Offset
import akka.stream.scaladsl.Source
import akka.stream.testkit.scaladsl.TestSink
import com.lightbend.lagom.scaladsl.api.broker.Topic
import com.lightbend.lagom.scaladsl.broker.TopicProducer
import com.lightbend.lagom.scaladsl.persistence.cassandra.CassandraPersistenceComponents
import com.lightbend.lagom.scaladsl.playjson.EmptyJsonSerializerRegistry
import com.lightbend.lagom.scaladsl.server.LagomApplication
import com.lightbend.lagom.scaladsl.server.LagomApplicationContext
import com.lightbend.lagom.scaladsl.server.LagomServer
import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.services.AlphaEvent
import com.lightbend.lagom.scaladsl.testkit.services.AlphaService
import play.api.libs.ws.ahc.AhcWSComponents
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

abstract class AlphaApplication(context: LagomApplicationContext)
    extends LagomApplication(context)
    with CassandraPersistenceComponents
    with TestTopicComponents
    with AhcWSComponents {
  override lazy val lagomServer = serverFor[AlphaService](new AlphaServiceImpl())

  override lazy val jsonSerializerRegistry = EmptyJsonSerializerRegistry
}

class AlphaServiceImpl extends AlphaService {
  override def messages: Topic[AlphaEvent] =
    TopicProducer.singleStreamWithOffset { offset =>
      val events = (1 to 10).filter(_ % 2 == 0).map(AlphaEvent.apply)
      Source(events).map(event => (event, Offset.sequence(event.message / 2)))
    }
}

class TopicPublishingSpec extends AsyncWordSpec with Matchers {
  "The AlphaService" should {
    "publish events on alpha topic" in ServiceTest.withServer(ServiceTest.defaultSetup.withCluster()) { ctx =>
      new AlphaApplication(ctx) with LocalServiceLocator
    } { server =>
      implicit val system = server.actorSystem
      implicit val mat    = server.materializer

      val client: AlphaService = server.serviceClient.implement[AlphaService]
      val source               = client.messages.subscribe.atMostOnceSource

      source
        .runWith(TestSink.probe[AlphaEvent])
        .request(1)
        .expectNext should ===(AlphaEvent(2))
    }
  }
} 
Example 11
Source File: JdbcPersistenceModuleSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.persistence.jdbc

import javax.inject.Inject
import org.scalatest._
import play.api.PlayException
import play.api.db.DBApi
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.inject.{ bind => playBind }
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec


class JdbcPersistenceModuleSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll {
  "The JdbcPersistenceModule" should {
    "should start the service when database is not available" in {
      // Should be okay to build an application since Lagom configuration
      // enables it without a database being available.
      val app =
        new GuiceApplicationBuilder()
          .bindings(playBind[DbWrapper].toSelf)
          .configure(
            // Correct configuration, but the database is not available
            "db.default.driver"                             -> "org.h2.Driver",
            "db.default.url"                                -> "jdbc:h2:tcp://localhost/~/notavailable",
            "lagom.cluster.exit-jvm-when-system-terminated" -> "off",
            "lagom.cluster.bootstrap.enabled"               -> "off"
          )
          .build()

      val dbWrapper = app.injector.instanceOf[DbWrapper]
      dbWrapper should not be (null)

      app.stop().map(_ => succeed)
    }

    "should fail to start the service when database is not available and configured to fail fast" in {
      assertThrows[PlayException] {
        new GuiceApplicationBuilder()
          .bindings(playBind[DbWrapper].toSelf)
          .configure(
            // Correct configuration, but the database is not available
            "db.default.driver" -> "org.h2.Driver",
            "db.default.url"    -> "jdbc:h2:tcp://localhost/~/notavailable",
            // And it is configured to fail fast
            "play.db.prototype.hikaricp.initializationFailTimeout" -> "1",
            "lagom.cluster.exit-jvm-when-system-terminated"        -> "off",
            "lagom.cluster.bootstrap.enabled"                      -> "off"
          )
          .build()
      }
    }
  }
}

// So that we can confirm DBApi was created
class DbWrapper @Inject() (val dbApi: DBApi) 
Example 12
Source File: AkkaDiscoveryServiceLocatorSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.scaladsl.akka.discovery

import akka.NotUsed
import com.lightbend.lagom.scaladsl.api.Service
import com.lightbend.lagom.scaladsl.api.ServiceCall
import com.lightbend.lagom.scaladsl.api.ServiceLocator
import com.lightbend.lagom.scaladsl.server.LagomApplication
import com.lightbend.lagom.scaladsl.server.LagomApplicationContext
import com.lightbend.lagom.scaladsl.server.LagomServer
import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.ServiceTest
import org.scalatest._
import play.api.libs.ws.WSClient
import play.api.libs.ws.ahc.AhcWSComponents

import scala.concurrent.Future
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

class AkkaDiscoveryServiceLocatorSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll with OptionValues {
  "ServiceLocator" should {
    "retrieve registered services" in {
      val serviceLocator = server.application.serviceLocator

      serviceLocator.locate("fake-service").map { res =>
        res.value.toString shouldBe "http://fake-service-host:9119"
      }
    }
  }

  private val server = ServiceTest.startServer(ServiceTest.defaultSetup) { ctx =>
    new LagomTestApplication(ctx)
  }

  protected override def afterAll() = server.stop()

  class LagomTestApplication(ctx: LagomApplicationContext)
      extends LagomApplication(ctx)
      with AhcWSComponents
      with AkkaDiscoveryComponents {
    override def lagomServer: LagomServer = serverFor[TestService](new TestServiceImpl)
  }

  trait TestService extends Service {
    def hello(name: String): ServiceCall[NotUsed, String]

    override def descriptor = {
      import Service._
      named("test-service")
        .withCalls(
          pathCall("/hello/:name", hello _)
        )
        .withAutoAcl(true)
    }
  }

  class TestServiceImpl extends TestService {
    override def hello(name: String) = ServiceCall { _ =>
      Future.successful(s"Hello $name")
    }
  }
} 
Example 13
Source File: DSLSpec.scala    From scarango   with MIT License 5 votes vote down vote up
package spec

import com.outr.arango.{Collection, Document, DocumentModel, DocumentRef, Field, Graph, Id, Index, Query, Serialization}
import com.outr.arango.query._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import profig.Profig

class DSLSpec extends AsyncWordSpec with Matchers {
  "DSL" should {
    "initialize configuration" in {
      Profig.loadDefaults()
      succeed
    }
    "build a simple query" in {
      val p = Person.ref

      val query = aql {
        FOR (p) IN Database.people
        SORT (p.age.desc)
        RETURN (p)
      }
      query should be(Query(
        """FOR arg1 IN people
          |SORT arg1.age DESC
          |RETURN arg1""".stripMargin, Map.empty))
    }
    "build a query with a filter" in {
      val p = Person.ref

      val query = aql {
        FOR (p) IN Database.people
        FILTER((p.age is 21) && (p.name isNot "Adam"))
        RETURN (p)
      }
      query should be(Query(
        """FOR arg1 IN people
          |FILTER arg1.age == @arg2 && arg1.name != @arg3
          |RETURN arg1""".stripMargin, Map("arg2" -> 21, "arg3" -> "Adam")
      ))
    }
    "build an update query" in {
      val p = Person.ref

      val query = aql {
        FOR(p) IN Database.people
        FILTER ((p.age is 21) && (p.name isNot "Adam"))
        UPDATE (p, p.age(22))
        RETURN (NEW)
      }
      query should be(Query(
        """FOR arg1 IN people
          |FILTER arg1.age == @arg2 && arg1.name != @arg3
          |UPDATE arg1 WITH {age: @arg4} IN people
          |RETURN NEW""".stripMargin, Map("arg2" -> 21, "arg3" -> "Adam", "arg4" -> 22)))
    }
    "build a query to return result count" in {
      val p = Person.ref
      val count = ref("count")
      val query = aql {
        FOR (p) IN Database.people
        FILTER (p.age >= 20)
        COLLECT WITH COUNT INTO count
        RETURN (count)
      }
      query should be(Query(
        """FOR arg1 IN people
          |FILTER arg1.age >= @arg2
          |COLLECT WITH COUNT INTO count
          |RETURN count""".stripMargin, Map("arg2" -> 20)))
    }
  }

  object Database extends Graph(databaseName = "advanced") {
    val people: Collection[Person] = vertex[Person]
  }

  case class Person(name: String, age: Int, _id: Id[Person] = Person.id()) extends Document[Person]

  object Person extends DocumentModel[Person] {
    val name: Field[String] = Field[String]("name")
    val age: Field[Int] = Field[Int]("age")

    override def indexes: List[Index] = Nil

    def ref: DocumentRef[Person, Person.type] = DocumentRef(this)

    override val collectionName: String = "people"
    override implicit val serialization: Serialization[Person] = Serialization.auto[Person]
  }
} 
Example 14
Source File: AbstractLoggingServiceRegistryClientSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.devmode.internal.registry

import java.net.URI

import scala.concurrent.Future
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

class AbstractLoggingServiceRegistryClientSpec extends AsyncWordSpec with Matchers {
  private val client = new AbstractLoggingServiceRegistryClient {
    override def internalLocateAll(serviceName: String, portName: Option[String]): Future[List[URI]] =
      serviceName match {
        case "failing-service"    => Future.failed(new IllegalArgumentException("Ignore: expected error"))
        case "empty-service"      => Future.successful(List())
        case "successful-service" => Future.successful(List(URI.create("http://localhost:8080")))
      }
  }

  "AbstractLoggingServiceRegistryClient" when {
    

    "internal lookup fails" in {
      client
        .locateAll("failing-service", None)
        .failed
        .map(_ shouldBe an[IllegalArgumentException])
    }

    "internal lookup has no result" in {
      client
        .locateAll("empty-service", None)
        .map(_ shouldEqual Nil)
    }

    "internal lookup has a successful result" in {
      client
        .locateAll("successful-service", None)
        .map(_ shouldEqual List(URI.create("http://localhost:8080")))
    }
  }
} 
Example 15
Source File: HelloWorldServiceSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.example.helloworld.impl

import com.lightbend.lagom.scaladsl.server.LocalServiceLocator
import com.lightbend.lagom.scaladsl.testkit.ServiceTest
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import com.example.helloworld.api._
import org.scalatest.concurrent.Eventually

import scala.concurrent.Await
import scala.concurrent.duration._

class HelloWorldServiceSpec
    extends AsyncWordSpec
    with Matchers
    with BeforeAndAfterAll
    with Eventually {

  private val server = ServiceTest.startServer(
    ServiceTest.defaultSetup
      .withCassandra()
  ) { ctx =>
    new HelloWorldApplication(ctx) with LocalServiceLocator
  }

  val client: HelloWorldService =
    server.serviceClient.implement[HelloWorldService]

  override protected def afterAll(): Unit = server.stop()

  "Hello World service" should {

    "say hello" in {
      client.hello("Alice").invoke().map { answer =>
        answer should ===("""Hello, Alice!
            |Started reports: default-projected-message
            |Stopped reports: default-projected-message
            |""".stripMargin)
      }
    }

    "allow responding with a custom message" in {
      for {
        _ <- client.useGreeting("Bob", "Hi").invoke()
        answer <- client.hello("Bob").invoke()
      } yield {
        answer should ===("""Hi, Bob!
              |Started reports: default-projected-message
              |Stopped reports: default-projected-message
              |""".stripMargin)
      }

      implicit val patienceConfig: PatienceConfig = PatienceConfig(timeout = 25.seconds, interval = 300.millis)
      eventually{
        client.hello("Bob").invoke().map(_ should ===(
            """Hi, Bob!
              |Started reports: Hi
              |Stopped reports: default-projected-message
              |""".stripMargin
          )
        )
      }

    }
  }
} 
Example 16
Source File: ReplicatorSpec.scala    From kafka-journal   with MIT License 5 votes vote down vote up
package com.evolutiongaming.kafka.journal.replicator

import cats.effect.{IO, Resource}
import cats.implicits._
import com.evolutiongaming.catshelper.LogOf
import com.evolutiongaming.kafka.journal.replicator.Replicator.Consumer
import com.evolutiongaming.kafka.journal.IOSuite._
import com.evolutiongaming.skafka.Topic
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

import scala.concurrent.duration._
import scala.util.control.NoStackTrace

class ReplicatorSpec extends AsyncWordSpec with Matchers {

  "Replicator" should {

    "fail if any of replicators failed" in {

      implicit val logOf = LogOf.empty[IO]

      val error = new RuntimeException with NoStackTrace

      val consumer = new Consumer[IO] {
        def topics = Set("journal").pure[IO]
      }

      val start = (_: Topic) => Resource.pure[IO, IO[Unit]](error.raiseError[IO, Unit])
      val result = for {
        result <- Replicator.of(
          Replicator.Config(topicDiscoveryInterval = 0.millis),
          Resource.pure[IO, Consumer[IO]](consumer),
          start).use(identity).attempt
      } yield {
        result shouldEqual error.asLeft
      }

      result.run()
    }
  }
} 
Example 17
Source File: AsynchronousLoggingSpec.scala    From scribe   with MIT License 5 votes vote down vote up
package spec

import java.io.File
import java.util.concurrent.ConcurrentLinkedQueue

import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec
import perfolation._
import scribe.{LogRecord, Logger}
import scribe.format._
import scribe.output.LogOutput
import scribe.writer.{FileWriter, Writer}

import scala.collection.JavaConverters._
import scala.concurrent.Future
import scala.io.Source

class AsynchronousLoggingSpec extends AsyncWordSpec with Matchers {
  private val Regex = """(\d+) - (.+)""".r
  private val threads = "abcdefghijklmnopqrstuvwxyz"
  private val iterations = 10
  private val total = threads.length * iterations

  "Asynchronous Logging" should {
    s"log $total records in the proper order with simple logging" in {
      val queue = new ConcurrentLinkedQueue[String]
      val logger = Logger.empty.orphan().withHandler(
        formatter = AsynchronousLoggingSpec.format,
        writer = new Writer {
          override def write[M](record: LogRecord[M], output: LogOutput): Unit = queue.add(output.plainText.trim)
        }
      )

      Future.sequence(threads.map { char =>
        Future {
          (0 until iterations).foreach { index =>
            logger.info(p"$char:$index")
          }
        }
      }).map { _ =>
        var previous = 0L
        queue.iterator().asScala.foreach {
          case Regex(ts, _) => {
            val timeStamp = ts.toLong
            timeStamp should be >= previous
            previous = timeStamp
          }
        }
        queue.size() should be(total)
      }
    }
    s"log $total records in the proper order with file logging" in {
      val file = new File("logs/app.log")
      file.delete()

      val fileWriter = FileWriter().nio
      val logger = Logger.empty.orphan().withHandler(
        formatter = AsynchronousLoggingSpec.format,
        writer = fileWriter
      )

      Future.sequence(threads.map { char =>
        Future {
          (0 until iterations).foreach { index =>
            logger.info(p"$char:$index")
          }
        }
      }).map { _ =>
        var previous = 0L
        fileWriter.flush()
        fileWriter.dispose()
        val lines = Source.fromFile(file).getLines().toList
        lines.foreach {
          case Regex(ts, message) => {
            val timeStamp = ts.toLong
            timeStamp should be >= previous
            previous = timeStamp
          }
        }
        lines.length should be(threads.length * iterations)
      }
    }
  }
}

object AsynchronousLoggingSpec {
  val format = formatter"$timeStamp - $message"
} 
Example 18
Source File: UnitSpec.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi

import org.joda.time.{DateTime, DateTimeZone, LocalDate}
import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.{AnyWordSpec, AsyncWordSpec}
import play.api.test.{DefaultAwaitTimeout, FutureAwaits}

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.language.postfixOps

trait BaseUnitSpec extends Matchers with OptionValues with TestUtils with FutureAwaits
  with DefaultAwaitTimeout {
  implicit val timeout: FiniteDuration = 5 seconds

  def await[T](f: Future[T])(implicit duration: FiniteDuration = timeout): T =
    Await.result(f, duration)
}

trait UnitSpec extends AnyWordSpec with BaseUnitSpec{
  implicit def extractAwait[A](future: Future[A]): A = await[A](future)

  def await[A](future: Future[A])(implicit timeout: Duration): A = Await.result(future, timeout)
}

trait AsyncUnitSpec extends AsyncWordSpec with BaseUnitSpec

trait TestUtils {
  private val vrnGenerator = VrnGenerator()

  def now: DateTime = DateTime.now(DateTimeZone.UTC)
  def generateVrn = vrnGenerator.nextVrn()

  implicit def toLocalDate(d: DateTime): LocalDate = d.toLocalDate
}

object TestUtils extends TestUtils 
Example 19
Source File: RequestHandlerS3Spec.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.handler

import akka.actor.ActorSystem
import akka.http.scaladsl.model._
import com.ing.wbaa.rokku.proxy.config.StorageS3Settings
import com.ing.wbaa.rokku.proxy.data._
import com.ing.wbaa.rokku.proxy.queue.MemoryUserRequestQueue
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AsyncWordSpec

import scala.concurrent.{ ExecutionContext, Future }

class RequestHandlerS3Spec extends AsyncWordSpec with Diagrams with RequestHandlerS3 with MemoryUserRequestQueue {

  override implicit val system: ActorSystem = ActorSystem.create("test-system")
  override implicit val executionContext: ExecutionContext = system.dispatcher
  override val storageS3Settings: StorageS3Settings = new StorageS3Settings(system.settings.config) {
    override val storageS3Authority: Uri.Authority = Uri.Authority(Uri.Host("1.2.3.4"), 1234)
  }

  implicit val requestId: RequestId = RequestId("test")

  var numFiredRequests = 0

  override def fireRequestToS3(request: HttpRequest)(implicit id: RequestId): Future[HttpResponse] = {
    numFiredRequests = numFiredRequests + 1
    Future.successful(HttpResponse(status = StatusCodes.Forbidden))
  }

  override def handleUserCreationRadosGw(userSTS: User)(implicit id: RequestId): Boolean = true

  def isUserAuthorizedForRequest(request: S3Request, user: User): Boolean = true

  override protected def filterResponse(request: HttpRequest, userSTS: User, s3request: S3Request, response: HttpResponse)(implicit id: RequestId): HttpResponse = null

  "Request Handler" should {
    "execute a request" that {
      "retries a request when forbidden and user needs to be created" in {
        val initialNumFiredRequests = numFiredRequests
        executeRequest(
          HttpRequest(),
          User(UserRawJson("u", Some(Set.empty[String]), "a", "s", None)),
          S3Request(AwsRequestCredential(AwsAccessKey(""), None), Uri.Path("/demobucket/user"), HttpMethods.GET, RemoteAddress.Unknown, HeaderIPs(), MediaTypes.`text/plain`)
        ).map(_ => assert(numFiredRequests - initialNumFiredRequests == 2))
      }
    }
  }

} 
Example 20
Source File: FilterRecursiveMultiDeleteSpec.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.handler

import akka.NotUsed
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Source
import akka.util.ByteString
import com.ing.wbaa.rokku.proxy.handler.FilterRecursiveMultiDelete._
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AsyncWordSpec

import scala.collection.mutable.ListBuffer
import scala.concurrent.ExecutionContext
import scala.util.Random

class FilterRecursiveMultiDeleteSpec extends AsyncWordSpec with Diagrams {

  implicit val system: ActorSystem = ActorSystem.create("test-system")
  override implicit val executionContext: ExecutionContext = system.dispatcher

  implicit def materializer: ActorMaterializer = ActorMaterializer()(system)

  val multiDeleteRequestXml: String = scala.io.Source.fromResource("multiDeleteRequest.xml").mkString.stripMargin.trim
  val multiDeleteRequestV4Xml: String = scala.io.Source.fromResource("multiDeleteRequestV4.xml").mkString.stripMargin.trim
  val multiPartComplete: String = scala.io.Source.fromResource("multipartUploadComplete.xml").mkString.stripMargin.trim
  val data: Source[ByteString, NotUsed] = Source.single(ByteString.fromString(multiDeleteRequestXml))
  val dataV4: Source[ByteString, NotUsed] = Source.single(ByteString.fromString(multiDeleteRequestV4Xml))
  val otherData: Source[ByteString, NotUsed] = Source.single(ByteString.fromString(multiPartComplete))

  val numberOfObjects = 1000

  "multiDelete request" should {
    "should be parsed to objects list" in {
      exctractMultideleteObjectsFlow(data).map { r =>
        assert(r.contains("testuser/file1"))
        assert(r.contains("testuser/file2"))
        assert(r.contains("testuser/file3"))
      }
    }
    "v4 should be parsed to objects list" in {
      exctractMultideleteObjectsFlow(dataV4).map { r =>
        assert(r.contains("testuser/issue"))
        assert(!r.contains("true"))
      }
    }

    "should return empty list" in {
      exctractMultideleteObjectsFlow(otherData).map(r => assert(r == Vector()))
    }

    "should return correct size for large xml objects" in {
      val rand = new Random()
      val doc = new ListBuffer[String]()
      for (c <- 1 to numberOfObjects) doc +=
        s"<Object><Key>testuser/one/two/three/four/five/six/seven/eight/nine/ten/eleven/twelve/sub$c/${rand.alphanumeric.take(32).mkString}=${rand.alphanumeric.take(12).mkString}.txt</Key></Object>"

      exctractMultideleteObjectsFlow(Source.single(ByteString("<Delete>" + doc.mkString + "</Delete>"))).map { r =>
        assert(r.length == numberOfObjects)
      }
    }
  }
} 
Example 21
Source File: FilterRecursiveListBucketHandlerSpec.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.handler

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.{ HttpMethods, MediaTypes, RemoteAddress, Uri }
import akka.stream.scaladsl.{ Sink, Source }
import akka.stream.{ ActorMaterializer, Materializer }
import akka.util.ByteString
import com.ing.wbaa.rokku.proxy.data._
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AsyncWordSpec

import scala.concurrent.ExecutionContext

class FilterRecursiveListBucketHandlerSpec extends AsyncWordSpec with Diagrams with FilterRecursiveListBucketHandler {

  implicit val system: ActorSystem = ActorSystem.create("test-system")
  override implicit val executionContext: ExecutionContext = system.dispatcher
  implicit val requestId: RequestId = RequestId("test")

  implicit def materializer: Materializer = ActorMaterializer()(system)

  def isUserAuthorizedForRequest(request: S3Request, user: User)(implicit id: RequestId): Boolean = {
    user match {
      case User(userName, _, _, _, _) if userName.value == "admin" => true
      case User(userName, _, _, _, _) if userName.value == "user1" =>
        request match {
          case S3Request(_, s3BucketPath, _, _, _, _, _) =>
            if (s3BucketPath.get.startsWith("/demobucket/user/user2")) false else true
        }
      case _ => true
    }
  }

  val listBucketXmlResponse: String = scala.io.Source.fromResource("listBucket.xml").mkString.stripMargin.trim

  val adminUser = User(UserRawJson("admin", Some(Set.empty[String]), "a", "s", None))
  val user1 = User(UserRawJson("user1", Some(Set.empty[String]), "a", "s", None))
  val s3Request = S3Request(AwsRequestCredential(AwsAccessKey(""), None), Uri.Path("/demobucket/user"), HttpMethods.GET, RemoteAddress.Unknown, HeaderIPs(), MediaTypes.`text/plain`)
  val data: Source[ByteString, NotUsed] = Source.single(ByteString.fromString(listBucketXmlResponse))

  "List bucket object response" should {
    "returns all objects to admin" in {
      data.via(filterRecursiveListObjects(adminUser, s3Request)).map(_.utf8String).runWith(Sink.seq).map(x => {
        assert(x.mkString.stripMargin.equals(listBucketXmlResponse))
      })
    }

    val filteredXml: String = scala.io.Source.fromResource("filteredListBucket.xml").mkString.stripMargin.trim
    "returns filtered object for user 1" in {
      data.via(filterRecursiveListObjects(user1, s3Request)).map(_.utf8String).runWith(Sink.seq).map(x => {
        assert(x.mkString.stripMargin.replaceAll("[\n\r\\s]", "")
          .equals(filteredXml.replaceAll("[\n\r\\s]", "")))
      })
    }
  }
} 
Example 22
Source File: AuthenticationProviderSTSItTest.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.provider

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import com.amazonaws.services.securitytoken.model.{AssumeRoleRequest, GetSessionTokenRequest}
import com.ing.wbaa.rokku.proxy.config.StsSettings
import com.ing.wbaa.rokku.proxy.data._
import com.ing.wbaa.testkit.awssdk.StsSdkHelpers
import com.ing.wbaa.testkit.oauth.OAuth2TokenRequest
import org.scalatest.Assertion
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AsyncWordSpec

import scala.concurrent.{ExecutionContext, Future}

class AuthenticationProviderSTSItTest extends AsyncWordSpec with Diagrams
  with AuthenticationProviderSTS
  with StsSdkHelpers
  with OAuth2TokenRequest {
  override implicit val testSystem: ActorSystem = ActorSystem.create("test-system")
  override implicit val system: ActorSystem = testSystem
  override implicit val executionContext: ExecutionContext = testSystem.dispatcher
  override implicit val materializer: ActorMaterializer = ActorMaterializer()(testSystem)

  override val stsSettings: StsSettings = StsSettings(testSystem)

  implicit val requestId: RequestId = RequestId("test")

  private val validKeycloakCredentials = Map(
    "grant_type" -> "password",
    "username" -> "testuser",
    "password" -> "password",
    "client_id" -> "sts-rokku"
  )
  private val userOneKeycloakCredentials = Map(
    "grant_type" -> "password",
    "username" -> "userone",
    "password" -> "password",
    "client_id" -> "sts-rokku"
  )

  def withAwsCredentialsValidInSTS(testCode: AwsRequestCredential => Future[Assertion]): Future[Assertion] = {
    val stsSdk = getAmazonSTSSdk(StsSettings(testSystem).stsBaseUri)
    retrieveKeycloackToken(validKeycloakCredentials).flatMap { keycloakToken =>
      val cred = stsSdk.getSessionToken(new GetSessionTokenRequest()
        .withTokenCode(keycloakToken.access_token))
        .getCredentials

      testCode(AwsRequestCredential(AwsAccessKey(cred.getAccessKeyId), Some(AwsSessionToken(cred.getSessionToken))))
    }
  }

  def withAssumeRoleInSTS(testCode: AwsRequestCredential => Future[Assertion]): Future[Assertion] = {
    val stsSdk = getAmazonSTSSdk(StsSettings(testSystem).stsBaseUri)
    retrieveKeycloackToken(userOneKeycloakCredentials).flatMap { keycloakToken =>
      val assumeRoleReq = new AssumeRoleRequest().withTokenCode(keycloakToken.access_token)
      assumeRoleReq.setRoleArn("arn:aws:iam::account-id:role/admin")
      assumeRoleReq.setRoleSessionName("testRole")
      val cred = stsSdk.assumeRole(assumeRoleReq).getCredentials

      testCode(AwsRequestCredential(AwsAccessKey(cred.getAccessKeyId), Some(AwsSessionToken(cred.getSessionToken))))
    }
  }

  "Authentication Provider STS" should {
    "check authentication" that {
      "succeeds for valid credentials" in {
        withAwsCredentialsValidInSTS { awsCredential =>
          areCredentialsActive(awsCredential).map { userResult =>
            assert(userResult.map(_.userName).contains(UserName("testuser")))
            assert(userResult.map(_.userGroups).head.contains(UserGroup("testgroup")))
            assert(userResult.map(_.userGroups).head.contains(UserGroup("group3")))
            assert(userResult.map(_.userGroups).head.size == 2)
            assert(userResult.exists(_.accessKey.value.length == 32))
            assert(userResult.exists(_.secretKey.value.length == 32))
          }
        }
      }

      "fail when user is not authenticated" in {
        areCredentialsActive(AwsRequestCredential(AwsAccessKey("notauthenticated"), Some(AwsSessionToken("okSessionToken")))).map { userResult =>
          assert(userResult.isEmpty)
        }
      }

      "succeeds for valid role" in {
        withAssumeRoleInSTS { awsCredential =>
          areCredentialsActive(awsCredential).map { roleResult =>
            assert(roleResult.map(_.userRole).contains(UserAssumeRole("admin")))
            assert(roleResult.map(_.userGroups).contains(Set()))
            assert(roleResult.exists(_.accessKey.value.length == 32))
            assert(roleResult.exists(_.secretKey.value.length == 32))
          }
        }
      }
    }
  }
} 
Example 23
Source File: HttpRequestRecorderItTest.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.persistence

import akka.Done
import akka.actor.{ActorSystem, Props}
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.Uri.{Authority, Host}
import akka.persistence.cassandra.query.scaladsl.CassandraReadJournal
import akka.persistence.query.PersistenceQuery
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink
import com.amazonaws.services.s3.AmazonS3
import com.ing.wbaa.rokku.proxy.RokkuS3Proxy
import com.ing.wbaa.rokku.proxy.config.{HttpSettings, KafkaSettings, StorageS3Settings}
import com.ing.wbaa.rokku.proxy.data._
import com.ing.wbaa.rokku.proxy.handler.parsers.RequestParser
import com.ing.wbaa.rokku.proxy.handler.{FilterRecursiveListBucketHandler, RequestHandlerS3Cache}
import com.ing.wbaa.rokku.proxy.provider.{AuditLogProvider, MessageProviderKafka, SignatureProviderAws}
import com.ing.wbaa.rokku.proxy.queue.MemoryUserRequestQueue
import com.ing.wbaa.testkit.RokkuFixtures
import org.scalatest.Assertion
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AsyncWordSpec

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

class HttpRequestRecorderItTest extends AsyncWordSpec with Diagrams with RokkuFixtures {
  implicit val testSystem: ActorSystem = ActorSystem.create("test-system")
  implicit val mat: ActorMaterializer = ActorMaterializer()

  val rokkuHttpSettings: HttpSettings = new HttpSettings(testSystem.settings.config) {
    override val httpPort: Int = 0
    override val httpBind: String = "127.0.0.1"
  }

  def withS3SdkToMockProxy(testCode: AmazonS3 => Assertion): Future[Assertion] = {
    val proxy: RokkuS3Proxy = new RokkuS3Proxy with RequestHandlerS3Cache with SignatureProviderAws
      with FilterRecursiveListBucketHandler with MessageProviderKafka with AuditLogProvider with MemoryUserRequestQueue with RequestParser {
      override implicit lazy val system: ActorSystem = testSystem
      override val httpSettings: HttpSettings = rokkuHttpSettings

      override def isUserAuthorizedForRequest(request: S3Request, user: User)(implicit id: RequestId): Boolean = true

      override def isUserAuthenticated(httpRequest: HttpRequest, awsSecretKey: AwsSecretKey)(implicit id: RequestId): Boolean = true

      override val storageS3Settings: StorageS3Settings = StorageS3Settings(testSystem)
      override val kafkaSettings: KafkaSettings = KafkaSettings(testSystem)

      override def areCredentialsActive(awsRequestCredential: AwsRequestCredential)(implicit id: RequestId): Future[Option[User]] =
        Future(Some(User(UserRawJson("userId", Some(Set("group")), "accesskey", "secretkey", None))))

      def createLineageFromRequest(httpRequest: HttpRequest, userSTS: User, userIPs: UserIps)(implicit id: RequestId): Future[Done] = Future.successful(Done)

      override protected def auditEnabled: Boolean = false

      override val requestPersistenceEnabled: Boolean = true
      override val configuredPersistenceId: String = "localhost-1"
    }
    proxy.startup.map { binding =>
      try testCode(getAmazonS3(
        authority = Authority(Host(binding.localAddress.getAddress), binding.localAddress.getPort)
      ))
      finally proxy.shutdown()
    }
  }

  private val CHECKER_PERSISTENCE_ID = "localhost-1"
  val requestRecorder = testSystem.actorOf(Props(classOf[HttpRequestRecorder]), CHECKER_PERSISTENCE_ID)

  val queries = PersistenceQuery(testSystem)
    .readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier)


  "S3 Proxy" should {
    s"with Request Recorder" that {
      "persists requests in Cassandra" in withS3SdkToMockProxy { sdk =>
        withBucket(sdk) { bucketName =>
          Thread.sleep(6000)
          val storedInCassandraF = queries.currentEventsByPersistenceId(CHECKER_PERSISTENCE_ID, 1L, Long.MaxValue)
            .map(_.event)
            .runWith(Sink.seq)
            .mapTo[Seq[ExecutedRequestEvt]]
          val r = Await.result(storedInCassandraF, 5.seconds).filter(_.httpRequest.getUri().toString.contains(bucketName))
          assert(r.size == 1)
          assert(r.head.userSTS.userName.value == "userId")
        }
      }
    }
  }
}