org.specs2.concurrent.ExecutionEnv Scala Examples

The following examples show how to use org.specs2.concurrent.ExecutionEnv. 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: TestNetworkJourney.scala    From scala-stellar-sdk   with Apache License 2.0 5 votes vote down vote up
package stellar.sdk

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import org.specs2.specification.BeforeAfterAll
import stellar.sdk.model._
import stellar.sdk.model.op.PaymentOperation
import stellar.sdk.util.ByteArrays

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

class TestNetworkJourney(implicit ee: ExecutionEnv) extends Specification with BeforeAfterAll {

  implicit val network = TestNetwork

  private val testAccounts = new TestAccounts(4)

  def beforeAll() = testAccounts.open()
  def afterAll() = testAccounts.close()

  "a client" should {
    "be able to send a payment" >> {
      val List(senderKey, recipientKey) = testAccounts.take(2)
      val response = for {
        sender <- network.account(senderKey)
        payment = PaymentOperation(recipientKey.toAccountId, Amount.lumens(2))
        txn = Transaction(sender, List(payment), NoMemo, TimeBounds.Unbounded, Amount.lumens(1))
        response <- txn.sign(senderKey).submit()
      } yield response

      response.map(_.isSuccess) must beTrue.await(0, 1.minute)
    }

    "be able to fee bump a v0 transaction" >> {
      val List(senderKey, recipientKey) = testAccounts.take(2)
      val sender = Await.result(network.account((senderKey)), 10.seconds)
      val payment = PaymentOperation(recipientKey.toAccountId, Amount.lumens(2))
      val signedTransaction = Transaction(sender, List(payment), NoMemo, TimeBounds.Unbounded, NativeAmount(100))
        .sign(senderKey)
      val parsedV0Txn: SignedTransaction = SignedTransaction.decode.run(signedTransaction.encodeV0).value._2

      val bumpedTxn = parsedV0Txn.bumpFee(NativeAmount(500), recipientKey)
      val response = Await.result(bumpedTxn.submit(), 20.seconds)
      response.isSuccess must beTrue
    }
  }
} 
Example 2
Source File: SystemShutdownSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.core

import akka.actor.{ActorSystem, Terminated}
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification


class SystemShutdownSpec extends Specification {

  "SystemShutdown" should {

    "allow the ActorSystem to be shutdown" in {
      val sys = ActorSystem()
      val shut = new SystemShutdown {
        val system = sys
      }

      shut.shutdownActorSystem(false) {}
      implicit val ec = ExecutionEnv.fromExecutionContext(sys.dispatcher)
      shut.system.whenTerminated must beAnInstanceOf[Terminated].await

      sys.whenTerminated.isCompleted must beTrue
      success
    }
  }
} 
Example 3
Source File: ContainerServiceSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.service

import akka.actor.{ActorSystem, Terminated}
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import com.github.vonnagy.service.container.{AkkaTestkitSpecs2Support, TestUtils}
import com.typesafe.config.ConfigFactory
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.FutureMatchers
import org.specs2.mutable.SpecificationLike

class ContainerServiceSpec extends AkkaTestkitSpecs2Support(ActorSystem("test", {
  val http = TestUtils.temporaryServerHostnameAndPort()

  ConfigFactory.parseString(
  s"""
      container.http.interface="${http._2}"
      container.http.port=${http._3}
    """)})) with SpecificationLike with FutureMatchers {

  sequential
  val cont = new ContainerService(Nil, Nil, name = "test")

  "The ContainerService" should {

    "create the appropriate parts during construction" in {
      cont.registeredHealthChecks must be equalTo Nil
      cont.registeredRoutes must be equalTo Nil
      cont.started must beFalse
    }

    "start properly and respond to a `/ping` request" in {
      cont.start()
      cont.started must beTrue

      val host = system.settings.config.getString("container.http.interface")
      val port = system.settings.config.getInt("container.http.port")

      val resp = Http().singleRequest(HttpRequest(uri = s"http://$host:$port/ping"))
      resp.value.get.get.status must eventually(be_==(StatusCodes.OK))

    }

    "shut down properly when asked" in {
      cont.shutdown
      implicit val ec = ExecutionEnv.fromExecutionContext(system.dispatcher)
      cont.system.whenTerminated must beAnInstanceOf[Terminated].await
    }
  }
} 
Example 4
Source File: SystemStatusSpec.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.controllers

import com.mohiva.play.silhouette.test._
import org.hatdex.hat.api.HATTestContext
import org.hatdex.hat.api.json.HatJsonFormats
import org.hatdex.hat.api.models.{ HatStatus, StatusKind }
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.specification.BeforeAll
import play.api.Logger
import play.api.test.{ FakeRequest, PlaySpecification }

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

class SystemStatusSpec(implicit ee: ExecutionEnv) extends PlaySpecification with Mockito with HATTestContext with BeforeAll with HatJsonFormats {

  val logger = Logger(this.getClass)

  sequential

  def beforeAll: Unit = {
    Await.result(databaseReady, 60.seconds)
  }

  "The `update` method" should {
    "Return success response after updating HAT database" in {
      val request = FakeRequest("GET", "http://hat.hubofallthings.net")

      val controller = application.injector.instanceOf[SystemStatus]
      val result = controller.update().apply(request)

      status(result) must equalTo(OK)
      (contentAsJson(result) \ "message").as[String] must be equalTo "Database updated"
    }
  }

  "The `status` method" should {
    "Return current utilisation" in {
      val request = FakeRequest("GET", "http://hat.hubofallthings.net")
        .withAuthenticator(owner.loginInfo)

      val controller = application.injector.instanceOf[SystemStatus]
      val result = controller.status().apply(request)

      status(result) must equalTo(OK)
      val stats = contentAsJson(result).as[List[HatStatus]]

      stats.length must be greaterThan 0
      stats.find(_.title == "Previous Login").get.kind must be equalTo StatusKind.Text("Never", None)
      stats.find(_.title == "Owner Email").get.kind must be equalTo StatusKind.Text("[email protected]", None)
      stats.find(_.title == "Database Storage").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "File Storage").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "Database Storage Used").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "File Storage Used").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "Database Storage Used Share").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "File Storage Used Share").get.kind must haveClass[StatusKind.Numeric]
    }

    "Return last login information when present" in {
      val authRequest = FakeRequest("GET", "http://hat.hubofallthings.net")
        .withHeaders("username" -> "hatuser", "password" -> "pa55w0rd")

      val authController = application.injector.instanceOf[Authentication]

      val request = FakeRequest("GET", "http://hat.hubofallthings.net")
        .withAuthenticator(owner.loginInfo)

      val controller = application.injector.instanceOf[SystemStatus]

      val result = for {
        _ <- authController.accessToken().apply(authRequest)
        // login twice - the second login is considered "current", not previous
        _ <- authController.accessToken().apply(authRequest)
        r <- controller.status().apply(request)
      } yield r

      status(result) must equalTo(OK)
      val stats = contentAsJson(result).as[List[HatStatus]]

      stats.length must be greaterThan 0
      stats.find(_.title == "Previous Login").get.kind must be equalTo StatusKind.Text("moments ago", None)
    }
  }
} 
Example 5
Source File: FileManagerS3Spec.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service

import org.hatdex.hat.api.HATTestContext
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import play.api.Logger
import play.api.test.PlaySpecification

import scala.concurrent.Future
import scala.concurrent.duration._

class FileManagerS3Spec(implicit ee: ExecutionEnv) extends PlaySpecification with Mockito with FileManagerContext {

  val logger = Logger(this.getClass)

  sequential

  "The `getUploadUrl` method" should {
    "return a signed url for a provided key" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[String] = fileManager.getUploadUrl("testFile", None)

      result must startWith("https://hat-storage-test.s3.eu-west-1.amazonaws.com/hat.hubofallthings.net/testFile").await
    }
  }

  "The `getContentUrl` method" should {
    "return a signed url for a provided key" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[String] = fileManager.getContentUrl("testFile")

      result must startWith("https://hat-storage-test.s3.eu-west-1.amazonaws.com/hat.hubofallthings.net/testFile").await
    }
  }

  "The `deleteContents` method" should {
    "return quietly when deleting any file" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[Unit] = fileManager.deleteContents("deleteFile")

      result must not(throwAn[Exception]).await
      there was one(mockS3client).deleteObject("hat-storage-test", "hat.hubofallthings.net/deleteFile")
    }
  }

  "The `getFileSize` method" should {
    "return 0 for files that do not exist" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[Long] = fileManager.getFileSize("nonExistentFile")

      result must equalTo(0L).await(3, 10.seconds)
    }

    "extract file size for files that do exist" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[Long] = fileManager.getFileSize("testFile")

      result must equalTo(123456L).await
      there was one(mockS3client).getObjectMetadata("hat-storage-test", "hat.hubofallthings.net/testFile")
    }
  }
}

trait FileManagerContext extends HATTestContext {
  val mockS3client = fileManagerS3Mock.mockS3client
} 
Example 6
Source File: AkkaHttpServerSupportSpec.scala    From typedapi   with MIT License 5 votes vote down vote up
package http.support.tests.server

import http.support.tests.{Api, UserCoding}
import typedapi.server._
import typedapi.server.akkahttp._
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import cats.implicits._
import org.specs2.concurrent.ExecutionEnv

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

final class AkkaHttpServerSupportSpec(implicit ee: ExecutionEnv) extends ServerSupportSpec[Future]()(catsStdInstancesForFuture(ee.ec)) {

  import UserCoding._
  import FailFastCirceSupport._

  implicit val timeout = 5.second
  implicit val system  = ActorSystem("akka-http-server-spec", defaultExecutionContext = Some(ee.ec))
  implicit val mat     = ActorMaterializer()

  import system.dispatcher

  val endpoints = deriveAll[Future](Api).from(
    path, 
    segment, 
    query, 
    header, 
    fixed, 
    input, 
    clientHdr,
    coll,
    matching, 
    send, 
    get, 
    put, 
    putB, 
    post, 
    postB, 
    delete, 
    code200, 
    code400, 
    code500
  )
  val sm        = ServerManager(Http(), "localhost", 9000)
  val server    = mount(sm, endpoints)

  "akka http implements TypedApi's server interface" >> {
    tests(9000)

    step {
      Await.ready(server.map(_.unbind()), timeout)
      Await.ready(system.terminate, timeout)
    }
  }

} 
Example 7
Source File: AkkaHttpClientSupportSpec.scala    From typedapi   with MIT License 5 votes vote down vote up
package http.support.tests.client

import http.support.tests.{User, UserCoding, Api}
import typedapi.client._
import typedapi.client.akkahttp._
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import org.specs2.mutable.Specification
import org.specs2.concurrent.ExecutionEnv

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

final class AkkaHttpClientSupportSpec(implicit ee: ExecutionEnv) extends Specification {

  import UserCoding._
  import FailFastCirceSupport._

  sequential

  implicit val timeout = 5.second
  implicit val system  = ActorSystem("akka-http-client-spec", defaultExecutionContext = Some(ee.ec))
  implicit val mat     = ActorMaterializer()

  import system.dispatcher

  val cm     = ClientManager(Http(), "http://localhost", 9001)
  val server = TestServer.start()

  "akka http client support" >> {
    val (p, s, q, header, fixed, clInH, clFixH, clColl, serMatchH, serSendH, m0, m1, m2, m3, m4, m5, _, _, _) = deriveAll(Api)

    "paths and segments" >> {
      p().run[Future](cm) must beEqualTo(User("foo", 27)).awaitFor(timeout)
      s("jim").run[Future](cm) must beEqualTo(User("jim", 27)).awaitFor(timeout)
    }
    
    "queries" >> {
      q(42).run[Future](cm) must beEqualTo(User("foo", 42)).awaitFor(timeout)
    }
    
    "headers" >> {
      header(42).run[Future](cm) must beEqualTo(User("foo", 42)).awaitFor(timeout)
      fixed().run[Future](cm) must beEqualTo(User("joe", 27)).awaitFor(timeout)
      clInH("jim").run[Future](cm) must beEqualTo(User("jim", 27)).awaitFor(timeout)
      clFixH().run[Future](cm) must beEqualTo(User("joe", 27)).awaitFor(timeout)
      clColl(Map("coll" -> "joe", "collect" -> "jim")).run[Future](cm) must beEqualTo(User("coll: joe,collect: jim", 27)).awaitFor(timeout)
      serMatchH().run[Future](cm) must beEqualTo(User("joe", 27)).awaitFor(timeout)
      serSendH().run[Future](cm) must beEqualTo(User("joe", 27)).awaitFor(timeout)
    }

    "methods" >> {
      m0().run[Future](cm) must beEqualTo(User("foo", 27)).awaitFor(timeout)
      m1().run[Future](cm) must beEqualTo(User("foo", 27)).awaitFor(timeout)
      m2(User("jim", 42)).run[Future](cm) must beEqualTo(User("jim", 42)).awaitFor(timeout)
      m3().run[Future](cm) must beEqualTo(User("foo", 27)).awaitFor(timeout)
      m4(User("jim", 42)).run[Future](cm) must beEqualTo(User("jim", 42)).awaitFor(timeout)
      m5(List("because")).run[Future](cm) must beEqualTo(User("foo", 27)).awaitFor(timeout)
    }

    step {
      server.shutdown.unsafeRunSync()
      Await.ready(system.terminate, timeout)
    }
  }
} 
Example 8
Source File: SecurityServiceSpec.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.services

import cats.data.OptionT
import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.api.services.IdentityService
import com.mohiva.play.silhouette.api.util.Credentials
import com.mohiva.play.silhouette.impl.exceptions.InvalidPasswordException
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import de.frosner.broccoli.auth.{Account, AuthConfiguration, AuthMode, Role}
import org.mockito.Mock
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
import org.specs2.specification.mutable.ExecutionEnvironment

import scala.concurrent.Future
import scala.concurrent.duration.Duration

class SecurityServiceSpec extends Specification with Mockito with ExecutionEnvironment {

  def configWithAccounts(accounts: Seq[Account]): AuthConfiguration =
    AuthConfiguration(
      mode = AuthMode.Conf,
      session = AuthConfiguration.Session(timeout = Duration(1, "hour"), allowMultiLogin = true),
      cookie = AuthConfiguration.Cookie(secure = true),
      conf = AuthConfiguration.Conf(
        accounts = accounts
          .map(
            a =>
              AuthConfiguration.ConfAccount(
                a.name,
                "",
                a.instanceRegex,
                a.role
            ))
          .toList),
      allowedFailedLogins = 3
    )

  val identityService = mock[IdentityService[Account]]

  val account = Account("frank", "^test.*", Role.Administrator)

  override def is(implicit executionEnv: ExecutionEnv): Any =
    "An authentication check" should {

      "succeed if the credentials provider authenticates" in {
        val login = LoginInfo(CredentialsProvider.ID, account.name)
        val credentials = Credentials(account.name, "pass")

        val credentialsProvider = mock[CredentialsProvider]
        credentialsProvider.authenticate(credentials) returns Future.successful(login)

        SecurityService(configWithAccounts(List(account)), credentialsProvider, identityService)
          .authenticate(credentials) must beSome(login).await
      }

      "fail if the credentials provider fails to authenticate" in {
        val credentials = Credentials(account.name, "pass")

        val credentialsProvider = mock[CredentialsProvider]
        credentialsProvider.authenticate(credentials) returns Future.failed(new InvalidPasswordException("foo"))

        SecurityService(configWithAccounts(List(account)), credentialsProvider, identityService)
          .authenticate(credentials) must beNone.await
      }

      "succeed if the number of failed logins is equal to the allowed ones" in {
        val credentials = Credentials(account.name, "pass")
        val failedCredentials = credentials.copy(password = "foo")
        val login = LoginInfo(CredentialsProvider.ID, credentials.identifier)

        val credentialsProvider = mock[CredentialsProvider]
        credentialsProvider.authenticate(failedCredentials) returns Future.failed(new InvalidPasswordException("foo"))
        credentialsProvider.authenticate(credentials) returns Future.successful(login)

        val service = SecurityService(configWithAccounts(List(account)), credentialsProvider, identityService)
        val failedAttempts = for (attemptNo <- 1 to service.allowedFailedLogins) {
          service.authenticate(failedCredentials) must beNone.await
        }
        service.authenticate(credentials) must beSome(login).await
      }

      "fail if the number of failed logins is greater than the allowed number" in {
        val credentials = Credentials(account.name, "password")
        val failedCredentials = credentials.copy(password = "foo")
        val login = LoginInfo(CredentialsProvider.ID, credentials.identifier)

        val credentialsProvider = mock[CredentialsProvider]
        credentialsProvider.authenticate(failedCredentials) returns Future.failed(new InvalidPasswordException("foo"))
        credentialsProvider.authenticate(credentials) returns Future.successful(login)

        val service = SecurityService(configWithAccounts(List(account)), credentialsProvider, identityService)
        val failedAttempts = for (attemptNo <- 0 to service.allowedFailedLogins) {
          service.authenticate(failedCredentials) must beNone.await
        }
        service.authenticate(credentials) must beNone.await
      }

    }
} 
Example 9
Source File: BroccoliMessageHandlerSpec.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.websocket

import cats.data.EitherT
import cats.instances.future._
import de.frosner.broccoli.auth.Account
import de.frosner.broccoli.instances.NomadInstances
import de.frosner.broccoli.models._
import de.frosner.broccoli.nomad
import de.frosner.broccoli.services.InstanceService
import org.scalacheck.Gen
import org.specs2.ScalaCheck
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification

import scala.concurrent.Future

class BroccoliMessageHandlerSpec
    extends Specification
    with ScalaCheck
    with Mockito
    with nomad.ModelArbitraries
    with ModelArbitraries {

  "The Broccoli Message Handler" should {
    "send back instance tasks" in { implicit ee: ExecutionEnv =>
      prop {
        (account: Account,
         id: String,
         tasks: List[AllocatedTask],
         periodicRunTasks: Map[String, List[AllocatedTask]]) =>
          val instances = mock[NomadInstances]
          val instanceTasks = InstanceTasks(id, tasks, periodicRunTasks)
          instances.getInstanceTasks(account)(id) returns EitherT.pure[Future, InstanceError](instanceTasks)

          val outgoingMessage = new BroccoliMessageHandler(instances, mock[InstanceService])
            .processMessage(account)(IncomingMessage.GetInstanceTasks(id))

          outgoingMessage must beEqualTo(OutgoingMessage.GetInstanceTasksSuccess(instanceTasks)).await
      }.setGen2(Gen.identifier)
    }

    "send back an error if instance tasks failed" in { implicit ee: ExecutionEnv =>
      prop { (account: Account, id: String, error: InstanceError) =>
        val instances = mock[NomadInstances]
        instances.getInstanceTasks(account)(id) returns EitherT.leftT[Future, InstanceTasks](error)

        val outgoingMessage = new BroccoliMessageHandler(instances, mock[InstanceService])
          .processMessage(account)(IncomingMessage.GetInstanceTasks(id))

        outgoingMessage must beEqualTo(OutgoingMessage.GetInstanceTasksError(id, error)).await
      }.setGen2(Gen.identifier)
    }
  }
} 
Example 10
Source File: NomadHttpClientIntegrationSpec.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.nomad

import cats.instances.future._
import com.netaporter.uri.Uri
import com.netaporter.uri.dsl._
import de.frosner.broccoli.nomad.models.{Allocation, Job, WithId}
import de.frosner.broccoli.test.contexts.WSClientContext
import de.frosner.broccoli.test.contexts.docker.BroccoliDockerContext
import de.frosner.broccoli.test.contexts.docker.BroccoliTestService.{Broccoli, Nomad}
import org.scalacheck.Gen
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import org.specs2.specification.mutable.ExecutionEnvironment
import play.api.libs.json.Json
import play.api.libs.ws.WSClient

import scala.collection.immutable
import scala.concurrent.blocking
import scala.concurrent.duration._

class NomadHttpClientIntegrationSpec
    extends Specification
    with WSClientContext
    with BroccoliDockerContext
    with ExecutionEnvironment {

  
  override def broccoliDockerConfig: BroccoliDockerContext.Configuration =
    BroccoliDockerContext.Configuration.services(Broccoli, Nomad)

  private val broccoliApi = "http://localhost:9000/api/v1"

  override def is(implicit executionEnv: ExecutionEnv): Any =
    "The NomadHttpClient" should {
      "get allocations for a running nomad job" >> { wsClient: WSClient =>
        // Generate a random identifier for the instance
        val identifier = Gen.resize(10, Gen.identifier).sample.get
        val client = new NomadHttpClient(Uri.parse("http://localhost:4646"), wsClient)
        (for {
          // Create and start a simple instance to look at it's allocations
          _ <- wsClient
            .url(broccoliApi / "instances")
            .post(
              Json.obj("templateId" -> "http-server",
                       "parameters" -> Json.obj(
                         "id" -> identifier
                       )))
            .map(response => {
              // Ensure that the
              response.status must beEqualTo(201)
              response
            })
          _ <- wsClient
            .url(broccoliApi / "instances" / identifier)
            .post(Json.obj("status" -> "running"))
            .map(response => {
              response.status must beEqualTo(200)
              // Wait until the service is up
              blocking(Thread.sleep(1.seconds.toMillis))
              response
            })
          allocations <- client.getAllocationsForJob(shapeless.tag[Job.Id](identifier)).value
        } yield {
          allocations must beRight(
            (v: WithId[immutable.Seq[Allocation]]) => (v.jobId === identifier) and (v.payload must have length 1))
        }).await(5, broccoliDockerConfig.startupPatience + 2.seconds)
      }
    }
} 
Example 11
Source File: NetworkSpec.scala    From scala-stellar-sdk   with Apache License 2.0 5 votes vote down vote up
package stellar.sdk

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification

import scala.concurrent.duration._

class NetworkSpec(implicit ee: ExecutionEnv) extends Specification with ArbitraryInput with Mockito {

  "test network" should {
    "identify itself" >> {
      TestNetwork.passphrase mustEqual "Test SDF Network ; September 2015"
      BigInt(1, TestNetwork.networkId).toString(16).toUpperCase mustEqual
        "CEE0302D59844D32BDCA915C8203DD44B33FBB7EDC19051EA37ABEDF28ECD472"
    }

    "provide network info" >> {
      TestNetwork.info() must not(throwAn[Exception]).awaitFor(10.seconds)
    }
  }

  "public network" should {
    "identify itself" >> {
      PublicNetwork.passphrase mustEqual "Public Global Stellar Network ; September 2015"
      BigInt(1, PublicNetwork.networkId).toString(16).toUpperCase mustEqual
        "7AC33997544E3175D266BD022439B22CDB16508C01163F26E5CB2A3E1045A979"
    }
  }

  "any network" should {
    "provide access to the master account" >> {
      val networkAccountId = "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H"
      TestNetwork.masterAccount.accountId mustEqual networkAccountId
      KeyPair.fromSecretSeed(TestNetwork.masterAccount.secretSeed).accountId  mustEqual networkAccountId
    }
  }
} 
Example 12
Source File: FederationLookupSpec.scala    From scala-stellar-sdk   with Apache License 2.0 5 votes vote down vote up
package stellar.sdk

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import stellar.sdk.model.response.FederationResponse

import scala.concurrent.duration._

class FederationLookupSpec(implicit ec: ExecutionEnv) extends Specification {

  "federation server lookup" should {
    "find result by name" >> {
      FederationServer("https://keybase.io/_/api/1.0/stellar/federation.json")
        .byName("jem*keybase.io") must beSome(
        FederationResponse(
          address = "jem*keybase.io",
          account = KeyPair.fromAccountId("GBRAZP7U3SPHZ2FWOJLHPBO3XABZLKHNF6V5PUIJEEK6JEBKGXWD2IIE")
        )).awaitFor(10.seconds)
    }
  }

} 
Example 13
Source File: OAuthFailedSpec.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando.kanadi

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer
import com.typesafe.config.ConfigFactory
import io.circe.Json
import org.mdedetrich.webmodels.{FlowId, OAuth2Token, OAuth2TokenProvider}
import org.specs2.Specification
import org.specs2.concurrent.ExecutionEnv
import org.specs2.execute.Skipped
import org.specs2.matcher.FutureMatchers
import org.specs2.specification.core.SpecStructure
import org.zalando.kanadi.api.{Events, Subscriptions}
import org.zalando.kanadi.models._

import scala.concurrent.Future
import scala.concurrent.duration._

class OAuthFailedSpec(implicit ec: ExecutionEnv) extends Specification with FutureMatchers with Config {

  val config = ConfigFactory.load()

  implicit val system       = ActorSystem()
  implicit val http         = Http()
  implicit val materializer = ActorMaterializer()
  val failingOauth2TokenProvider = Some(
    OAuth2TokenProvider(() => Future.successful(OAuth2Token("Failing token")))
  )

  val subscriptionsClient =
    Subscriptions(nakadiUri, failingOauth2TokenProvider)
  val eventsClient = Events(nakadiUri, failingOauth2TokenProvider)

  override def is: SpecStructure = s2"""
    Call to subscriptions list should fail with invalid token   $oAuthCallSubscriptions
    Call to publishEvents should fail with invalid token        $oAuthPublishEvents
  """

  def oAuthCallSubscriptions = Skipped("No way for current Nakadi docker image to detect \"wrong\" tokens")

  def oAuthPublishEvents = Skipped("No way for current Nakadi docker image to detect \"wrong\" tokens")
} 
Example 14
Source File: DomainInfoItSpec.scala    From scala-stellar-sdk   with Apache License 2.0 5 votes vote down vote up
package stellar.sdk

import okhttp3.HttpUrl
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import stellar.sdk.model.domain.{DomainInfo, IssuerDocumentation, Validator}

import scala.concurrent.duration._

class DomainInfoItSpec(implicit ee: ExecutionEnv) extends Specification {

  "known stellar.toml files" should {
    "parse correctly" >> {
      // #domain_info_example
      DomainInfo.forDomain("stellar.org") must beSome(
        DomainInfo(
          version = Some("2.0.0"),
          accounts = List(
            KeyPair.fromAccountId("GB6NVEN5HSUBKMYCE5ZOWSK5K23TBWRUQLZY3KNMXUZ3AQ2ESC4MY4AQ"),
            KeyPair.fromAccountId("GATL3ETTZ3XDGFXX2ELPIKCZL7S5D2HY3VK4T7LRPD6DW5JOLAEZSZBA"),
            KeyPair.fromAccountId("GCVLWV5B3L3YE6DSCCMHLCK7QIB365NYOLQLW3ZKHI5XINNMRLJ6YHVX"),
            KeyPair.fromAccountId("GCVJDBALC2RQFLD2HYGQGWNFZBCOD2CPOTN3LE7FWRZ44H2WRAVZLFCU"),
            KeyPair.fromAccountId("GAMGGUQKKJ637ILVDOSCT5X7HYSZDUPGXSUW67B2UKMG2HEN5TPWN3LQ"),
            KeyPair.fromAccountId("GDUY7J7A33TQWOSOQGDO776GGLM3UQERL4J3SPT56F6YS4ID7MLDERI4"),
            KeyPair.fromAccountId("GCPWKVQNLDPD4RNP5CAXME4BEDTKSSYRR4MMEL4KG65NEGCOGNJW7QI2"),
            KeyPair.fromAccountId("GDKIJJIKXLOM2NRMPNQZUUYK24ZPVFC6426GZAEP3KUK6KEJLACCWNMX"),
            KeyPair.fromAccountId("GAX3BRBNB5WTJ2GNEFFH7A4CZKT2FORYABDDBZR5FIIT3P7FLS2EFOZZ"),
            KeyPair.fromAccountId("GBEVKAYIPWC5AQT6D4N7FC3XGKRRBMPCAMTO3QZWMHHACLHTMAHAM2TP"),
            KeyPair.fromAccountId("GCKJZ2YVECFGLUDJ5T7NZMJPPWERBNYHCXT2MZPXKELFHUSYQR5TVHJQ"),
            KeyPair.fromAccountId("GBA6XT7YBQOERXT656T74LYUVJ6MEIOC5EUETGAQNHQHEPUFPKCW5GYM"),
            KeyPair.fromAccountId("GD2D6JG6D3V52ZMPIYSVHYFKVNIMXGYVLYJQ3HYHG5YDPGJ3DCRGPLTP"),
            KeyPair.fromAccountId("GA2VRL65L3ZFEDDJ357RGI3MAOKPJZ2Z3IJTPSC24I4KDTNFSVEQURRA")
          ),
          issuerDocumentation = Some(IssuerDocumentation(
            name = Some("Stellar Development Foundation"),
            url = Some(HttpUrl.parse("https://www.stellar.org")),
            github = Some("stellar"),
            twitter = Some("StellarOrg"),
          )),
          validators = List(
            Validator(
              alias = Some("sdf1"),
              displayName = Some("SDF 1"),
              host = Some("core-live-a.stellar.org:11625"),
              publicKey = Some(KeyPair.fromAccountId("GCGB2S2KGYARPVIA37HYZXVRM2YZUEXA6S33ZU5BUDC6THSB62LZSTYH")),
              history = Some(HttpUrl.parse("http://history.stellar.org/prd/core-live/core_live_001/"))
            ),
            Validator(
              alias = Some("sdf2"),
              displayName = Some("SDF 2"),
              host = Some("core-live-b.stellar.org:11625"),
              publicKey = Some(KeyPair.fromAccountId("GCM6QMP3DLRPTAZW2UZPCPX2LF3SXWXKPMP3GKFZBDSF3QZGV2G5QSTK")),
              history = Some(HttpUrl.parse("http://history.stellar.org/prd/core-live/core_live_002/"))
            ),
            Validator(
              alias = Some("sdf3"),
              displayName = Some("SDF 3"),
              host = Some("core-live-c.stellar.org:11625"),
              publicKey = Some(KeyPair.fromAccountId("GABMKJM6I25XI4K7U6XWMULOUQIQ27BCTMLS6BYYSOWKTBUXVRJSXHYQ")),
              history = Some(HttpUrl.parse("http://history.stellar.org/prd/core-live/core_live_003/"))
            ),
          )
        )
      )
      // #domain_info_example
      .awaitFor(30.seconds)
    }
  }
} 
Example 15
Source File: FriendBotSpec.scala    From scala-stellar-sdk   with Apache License 2.0 5 votes vote down vote up
package stellar.sdk

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import stellar.sdk.model.op.AccountMergeOperation
import stellar.sdk.model.{Account, AccountId, NativeAmount, TimeBounds, Transaction}

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.util.Try

class FriendBotSpec(implicit ee: ExecutionEnv) extends Specification {

  "the test network" should {
    "allow account funding via friendbot" >> {
      // #friendbot_example
      val kp = KeyPair.random
      val response = TestNetwork.fund(kp)
      // #friendbot_example

      val r = Await.result(response, 1 minute)

      // roll it back in, to be a good testnet citizen
      implicit val n = TestNetwork
      val giveItBack = for {
        accn <- n.account(kp)
        friendbot <- response.map(_.transaction.transaction.source)
        response <- Transaction(accn,
          maxFee = NativeAmount(100),
          timeBounds = TimeBounds.Unbounded
        ).add(AccountMergeOperation(friendbot.id)).sign(kp).submit()
      } yield response
      Await.result(giveItBack, 1 minute)

      r.isSuccess must beTrue
    }

    "be used to serialise a transaction" >> {
      val accn = KeyPair.fromPassphrase("an account")
      val sequence = 1
      val txn = {
        // #new_transaction_example
        implicit val network = TestNetwork
        val account = Account(AccountId(accn.publicKey), sequence)
        Transaction(account, maxFee = NativeAmount(100), timeBounds = TimeBounds.Unbounded)
        // #new_transaction_example
      }
      Try(txn.encodeXDR) must beASuccessfulTry[String]
    }
  }

} 
Example 16
Source File: TransactionLedgerEntriesSpec.scala    From scala-stellar-sdk   with Apache License 2.0 5 votes vote down vote up
package stellar.sdk

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification
import stellar.sdk.model.ledger.{LedgerEntryChange, TransactionLedgerEntries}
import stellar.sdk.model.{Desc, Now}

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.util.Try

class TransactionLedgerEntriesSpec(ee: ExecutionEnv) extends Specification {

  import ee.ec

  val last100 = Await.result(PublicNetwork.transactions(cursor = Now, order = Desc), 1.minute).take(100).toList

  "transaction meta parsing" should {
    "parse the last 100 without any issues" >> {
      Try {
        last100.map(_.ledgerEntries)
      } must beSuccessfulTry[Seq[TransactionLedgerEntries]]
    }
  }

  "fee ledger entry parsing" should {
    "parse the last 100 without any issues" >> {
      Try {
        last100.flatMap(_.feeLedgerEntries)
      } must beSuccessfulTry[Seq[LedgerEntryChange]]
    }
  }
} 
Example 17
Source File: AlwaysPassAuthProviderSpec.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import org.specs2.concurrent.ExecutionEnv
import org.specs2.mutable.Specification

class AlwaysPassAuthProviderSpec(implicit ee: ExecutionEnv) extends Specification {
  val testTokenInfo = TokenInfo("", Scope.Empty, "token type", "user uid", realm = "/employees")

  "'Always pass' Authorization Provider" should {
    "accept any tokens and scopes and treat them as valid" in {
      val authProvider = new AlwaysPassAuthProvider(testTokenInfo)
      val scope = Scope(Set("any_scope"))
      val token = Some(OAuth2Token("6afe9886-0a0a-4ace-8bc7-fb96920fb764"))

      authProvider.valid(token, scope) must beEqualTo(AuthTokenValid(testTokenInfo)).await
    }
  }

} 
Example 18
Source File: TestUtils.scala    From codacy-analysis-cli   with GNU Affero General Public License v3.0 5 votes vote down vote up
package com.codacy.analysis.core.utils

import java.nio.file.attribute.PosixFilePermission
import java.nio.file.{Path, Paths}

import better.files.File
import com.codacy.plugins.api.results
import io.circe.Decoder
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.MatchResult

import scala.sys.process.Process

object TestUtils {

  implicit val categoryDecoder: Decoder[results.Pattern.Category.Value] =
    Decoder.decodeEnumeration(results.Pattern.Category)

  implicit val levelDecoder: Decoder[results.Result.Level.Value] =
    Decoder.decodeEnumeration(results.Result.Level)
  implicit val fileDecoder: Decoder[Path] = Decoder[String].map(Paths.get(_))
  implicit val executionEnv: ExecutionEnv = ExecutionEnv.fromGlobalExecutionContext

  def withClonedRepo[T](gitUrl: String, commitUUid: String)(block: (File, File) => MatchResult[T]): MatchResult[T] =
    (for {
      directory <- File.temporaryDirectory()
      file <- File.temporaryFile()
    } yield {
      directory
        .addPermission(PosixFilePermission.OWNER_READ)
        .addPermission(PosixFilePermission.GROUP_READ)
        .addPermission(PosixFilePermission.OTHERS_READ)
        .addPermission(PosixFilePermission.OWNER_EXECUTE)
        .addPermission(PosixFilePermission.GROUP_EXECUTE)
        .addPermission(PosixFilePermission.OTHERS_EXECUTE)
      Process(Seq("git", "clone", gitUrl, directory.pathAsString)).!
      Process(Seq("git", "reset", "--hard", commitUUid), directory.toJava).!
      block(file, directory)
    }).get()

  def withTemporaryGitRepo[T](fn: File => MatchResult[T]): MatchResult[T] = {
    (for {
      temporaryDirectory <- File.temporaryDirectory()
    } yield {
      Process(Seq("git", "init"), temporaryDirectory.toJava).!
      Process(Seq("git", "commit", "--allow-empty", "-m", "initial commit"), temporaryDirectory.toJava).!
      fn(temporaryDirectory)
    }).get

  }
} 
Example 19
Source File: AkkaServerProvider.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import org.specs2.concurrent.ExecutionEnv
import org.specs2.specification.BeforeAfterAll

import scala.concurrent.duration._
import scala.concurrent.Await
import scala.concurrent.Future
import akka.stream.Materializer

trait AkkaServerProvider extends BeforeAfterAll {

  
  def executionEnv: ExecutionEnv

  var testServerPort: Int            = _
  val defaultTimeout: FiniteDuration = 5.seconds

  // Create Akka system for thread and streaming management
  implicit val system       = ActorSystem()
  implicit val materializer = Materializer.matFromSystem

  lazy val futureServer: Future[Http.ServerBinding] = {
    // Using 0 (zero) means that a random free port will be used.
    // So our tests can run in parallel and won't mess with each other.
    Http().bindAndHandle(routes, "localhost", 0)
  }

  override def beforeAll(): Unit = {
    val portFuture = futureServer.map(_.localAddress.getPort)(executionEnv.executionContext)
    portFuture.foreach(port => testServerPort = port)(executionEnv.executionContext)
    Await.ready(portFuture, defaultTimeout)
  }

  override def afterAll(): Unit = {
    futureServer.foreach(_.unbind())(executionEnv.executionContext)
    val terminate = system.terminate()
    Await.ready(terminate, defaultTimeout)
  }
} 
Example 20
Source File: AhcWSClientSpec.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play.libs.ws.ahc

import akka.http.scaladsl.server.Route
import akka.stream.javadsl.Sink
import akka.util.ByteString
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.FutureMatchers
import org.specs2.mutable.Specification
import play.AkkaServerProvider
import play.libs.ws._

import scala.compat.java8.FutureConverters._
import scala.concurrent.Future
import scala.concurrent.duration._

class AhcWSClientSpec(implicit val executionEnv: ExecutionEnv)
    extends Specification
    with AkkaServerProvider
    with StandaloneWSClientSupport
    with FutureMatchers
    with XMLBodyWritables
    with XMLBodyReadables {

  override val routes: Route = {
    import akka.http.scaladsl.server.Directives._
    get {
      complete("<h1>Say hello to akka-http</h1>")
    } ~
      post {
        entity(as[String]) { echo =>
          complete(echo)
        }
      }
  }

  "play.libs.ws.ahc.StandaloneAhcWSClient" should {

    "get successfully" in withClient() { client =>
      def someOtherMethod(string: String) = {
        new InMemoryBodyWritable(akka.util.ByteString.fromString(string), "text/plain")
      }
      toScala(client.url(s"http://localhost:$testServerPort").post(someOtherMethod("hello world")))
        .map(response => response.getBody() must be_==("hello world"))
        .await(retries = 0, timeout = 5.seconds)
    }

    "source successfully" in withClient() { client =>
      val future = toScala(client.url(s"http://localhost:$testServerPort").stream())
      val result: Future[ByteString] = future.flatMap { response: StandaloneWSResponse =>
        toScala(response.getBodyAsSource.runWith(Sink.head[ByteString](), materializer))
      }
      val expected: ByteString = ByteString.fromString("<h1>Say hello to akka-http</h1>")
      result must be_==(expected).await(retries = 0, timeout = 5.seconds)
    }

    "round trip XML successfully" in withClient() { client =>
      val document = XML.fromString("""<?xml version="1.0" encoding='UTF-8'?>
                                      |<note>
                                      |  <from>hello</from>
                                      |  <to>world</to>
                                      |</note>""".stripMargin)
      document.normalizeDocument()

      toScala {
        client.url(s"http://localhost:$testServerPort").post(body(document))
      }.map { response =>
          import javax.xml.parsers.DocumentBuilderFactory
          val dbf = DocumentBuilderFactory.newInstance
          dbf.setNamespaceAware(true)
          dbf.setCoalescing(true)
          dbf.setIgnoringElementContentWhitespace(true)
          dbf.setIgnoringComments(true)
          dbf.newDocumentBuilder

          val responseXml = response.getBody(xml())
          responseXml.normalizeDocument()

          (responseXml.isEqualNode(document) must beTrue).and {
            response.getUri must beEqualTo(new java.net.URI(s"http://localhost:$testServerPort"))
          }
        }
        .await(retries = 0, timeout = 5.seconds)
    }
  }
} 
Example 21
Source File: CachingSpec.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play.api.libs.ws.ahc.cache

import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.server.Route
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.FutureMatchers
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
import org.specs2.specification.AfterAll
import play.AkkaServerProvider
import play.api.libs.ws.ahc._
import play.shaded.ahc.org.asynchttpclient._

import scala.concurrent.Future

class CachingSpec(implicit val executionEnv: ExecutionEnv)
    extends Specification
    with AkkaServerProvider
    with AfterAll
    with FutureMatchers
    with Mockito {

  val asyncHttpClient: AsyncHttpClient = {
    val config                           = AhcWSClientConfigFactory.forClientConfig()
    val ahcConfig: AsyncHttpClientConfig = new AhcConfigBuilder(config).build()
    new DefaultAsyncHttpClient(ahcConfig)
  }

  override val routes: Route = {
    import akka.http.scaladsl.server.Directives._
    path("hello") {
      respondWithHeader(RawHeader("Cache-Control", "public")) {
        val httpEntity = HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>")
        complete(httpEntity)
      }
    }
  }

  override def afterAll = {
    super.afterAll()
    asyncHttpClient.close()
  }

  "GET" should {

    "work once" in {
      val cache = mock[Cache]
      cache.get(any[EffectiveURIKey]()).returns(Future.successful(None))

      val cachingAsyncHttpClient = new CachingAsyncHttpClient(asyncHttpClient, new AhcHttpCache(cache))
      val ws                     = new StandaloneAhcWSClient(cachingAsyncHttpClient)

      ws.url(s"http://localhost:$testServerPort/hello")
        .get()
        .map { response =>
          response.body must be_==("<h1>Say hello to akka-http</h1>")
        }
        .await

      there.was(one(cache).get(EffectiveURIKey("GET", new java.net.URI(s"http://localhost:$testServerPort/hello"))))
    }
  }
} 
Example 22
Source File: FutureExtensionsSpec.scala    From wookiee   with Apache License 2.0 5 votes vote down vote up
package com.webtrends.harness.utils

import org.specs2.mutable.SpecificationWithJUnit

import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success}
import org.specs2.concurrent.ExecutionEnv

import scala.concurrent.duration.Duration

class FutureExtensionsSpec(implicit ee: ExecutionEnv) extends SpecificationWithJUnit {

  case class FutureException(message: String) extends Exception(message)

  import com.webtrends.harness.utils.FutureExtensions._
  val duration = Duration.fromNanos(10000000000L)

  "flatMapAll" should {
    "Successfully flatMap Success case" in {
      val f = Future.successful("").flatMapAll {
        case Success(_) => Future.successful("success")
        case Failure(_) => throw new Exception()
      }
      Await.result(f, duration) must be equalTo "success"
    }

    "Successfully flatMap Failure case" in {
      val f = Future.failed[String](new Exception()).flatMapAll {
        case Success(_) => Future.successful("")
        case Failure(_) => Future.successful("success")
      }
      Await.result(f, duration) must be equalTo "success"
    }

    "return failed future if exception is thrown in Success case" in {
      val f = Future.successful("").flatMapAll {
        case Success(_) => throw FutureException("Failed")
        case Failure(_) => Future.successful("success")
      }
      Await.result(f, duration) must throwAn[FutureException]
    }

    "return failed future if exception is thrown in Failure case" in {
      val f = Future.failed[String](new Exception()).flatMapAll {
        case Success(_) => Future.successful("success")
        case Failure(_) => throw FutureException("Failed")
      }
      Await.result(f, duration) must throwAn[FutureException]
    }
  }

  "mapAll" should {
    "Successfully map Success case" in {
      val f = Future.successful("").mapAll {
        case Success(_) => "success"
        case Failure(_) => throw new Exception()
      }
      Await.result(f, duration) must be equalTo "success"
    }

    "Successfully map Failure case" in {
      val f = Future.failed[String](new Exception()).mapAll {
        case Success(_) => throw new Exception()
        case Failure(_) => "success"
      }
      Await.result(f, duration) must be equalTo "success"
    }

    "Return failed future if exception is thrown in Success case" in {
      val f = Future.successful("").mapAll {
        case Success(_) => throw FutureException("Failed")
        case Failure(_) => "success"
      }
      Await.result(f, duration) must throwAn[FutureException]
    }

    "Return failed future if exception is thrown in Failure case" in {
      val f = Future.failed[String](new Exception()).mapAll {
        case Success(_) => "success"
        case Failure(_) => throw FutureException("Failed")
      }
      Await.result(f, duration) must throwAn[FutureException]
    }
  }
} 
Example 23
Source File: SubscriptionsSpec.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando.kanadi

import java.util.UUID

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer
import com.typesafe.config.ConfigFactory
import org.mdedetrich.webmodels.FlowId
import org.specs2.Specification
import org.specs2.concurrent.ExecutionEnv
import org.specs2.specification.core.SpecStructure
import org.specs2.specification.{AfterAll, BeforeAll}
import org.zalando.kanadi.api.{Category, EventType, EventTypes, Events, Subscription, Subscriptions}
import org.zalando.kanadi.models.{EventTypeName, SubscriptionId}

import scala.collection.parallel.mutable
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

class SubscriptionsSpec(implicit ec: ExecutionEnv) extends Specification with Config with BeforeAll with AfterAll {
  override def is: SpecStructure = sequential ^ s2"""
      Create enough subscriptions to ensure that pagination is used $createEnoughSubscriptionsToUsePagination
    """

  val config = ConfigFactory.load()

  implicit val system       = ActorSystem()
  implicit val http         = Http()
  implicit val materializer = ActorMaterializer()

  val eventTypeName         = EventTypeName(s"Kanadi-Test-Event-${UUID.randomUUID().toString}")
  val OwningApplication     = "KANADI"
  val consumerGroup: String = UUID.randomUUID().toString
  val subscriptionsClient =
    Subscriptions(nakadiUri, None)
  val eventsClient = Events(nakadiUri, None)
  val eventsTypesClient =
    EventTypes(nakadiUri, None)
  val subscriptionIds: mutable.ParSet[SubscriptionId] = mutable.ParSet.empty

  eventTypeName.pp
  s"Consumer Group: $consumerGroup".pp

  def createEventType = eventsTypesClient.create(EventType(eventTypeName, OwningApplication, Category.Business))

  override def beforeAll =
    Await.result(createEventType, 10 seconds)

  override def afterAll = {
    Await.result(
      for {
        res1 <- Future.sequence(subscriptionIds.toList.map(s => subscriptionsClient.delete(s)))
        res2 <- eventsTypesClient.delete(eventTypeName)
      } yield (res1, res2),
      10 seconds
    )
    ()
  }

  def createEnoughSubscriptionsToUsePagination = (name: String) => {
    implicit val flowId: FlowId = Utils.randomFlowId()
    flowId.pp(name)

    val createdSubscriptions = Future.sequence(for {
      _ <- 1 to 22
      subscription = subscriptionsClient.create(
        Subscription(None, s"$OwningApplication-${UUID.randomUUID().toString}", Some(List(eventTypeName))))
    } yield {
      subscription.foreach { s =>
        subscriptionIds += s.id.get
      }
      subscription
    })

    val retrievedSubscriptions = (for {
      subscriptions <- createdSubscriptions
      retrievedSubscription = Future.sequence(subscriptions.map { subscription =>
        subscriptionsClient.createIfDoesntExist(subscription)
      })
    } yield retrievedSubscription).flatMap(a => a)

    Await.result(createdSubscriptions, 10 seconds) mustEqual Await.result(retrievedSubscriptions, 10 seconds)
  }

}