pureconfig.error.ConfigReaderFailures Scala Examples

The following examples show how to use pureconfig.error.ConfigReaderFailures. 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: RefTypeConfigConvertSpec.scala    From refined   with MIT License 5 votes vote down vote up
package eu.timepit.refined.pureconfig

import com.typesafe.config.ConfigValueType
import eu.timepit.refined.api.Refined
import eu.timepit.refined.auto._
import eu.timepit.refined.numeric.Positive
import org.scalacheck.Prop._
import org.scalacheck.Properties
import pureconfig._
import pureconfig.error.{CannotConvert, ConfigReaderFailures, ConvertFailure, WrongType}
import pureconfig.generic.auto._

class RefTypeConfigConvertSpec extends Properties("RefTypeConfigConvert") {

  type PosInt = Int Refined Positive
  case class Config(value: PosInt)

  property("load success") = secure {
    loadConfigWithValue("1") ?=
      Right(Config(1))
  }

  property("load failure (predicate)") = secure {
    val expected1 = Left(
      ConfigReaderFailures(
        ConvertFailure(
          reason = CannotConvert(
            value = "0",
            toType =
              "eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Greater[shapeless.nat._0]]",
            because = "Predicate failed: (0 > 0)."
          ),
          location = None,
          path = "value"
        )
      )
    )

    // Allow "scala.Int" instead of just "Int" in the toType parameter.
    // For some reason Scala 2.12 with sbt 1.1.2 uses the former.
    val expected2 = Left(
      ConfigReaderFailures(
        ConvertFailure(
          reason = CannotConvert(
            value = "0",
            toType =
              "eu.timepit.refined.api.Refined[scala.Int,eu.timepit.refined.numeric.Greater[shapeless.nat._0]]",
            because = "Predicate failed: (0 > 0)."
          ),
          location = None,
          path = "value"
        )
      )
    )

    val actual = loadConfigWithValue("0")
    (actual ?= expected1) ||
    (actual ?= expected2)
  }

  property("load failure (wrong type)") = secure {
    loadConfigWithValue("abc") =?
      Left(
        ConfigReaderFailures(
          ConvertFailure(
            reason = WrongType(
              foundType = ConfigValueType.STRING,
              expectedTypes = Set(ConfigValueType.NUMBER)
            ),
            location = None,
            path = "value"
          )
        )
      )
  }

  property("roundtrip success") = secure {
    val config = Config(1)
    val configValue = ConfigConvert[Config].to(config)
    ConfigConvert[Config].from(configValue) ?=
      Right(config)
  }

  def loadConfigWithValue(value: String): Either[ConfigReaderFailures, Config] =
    ConfigSource.string(s"value = $value").load[Config]
} 
Example 2
Source File: TemplateConfig.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.templates

import com.typesafe.config.{ConfigObject, ConfigValue}
import de.frosner.broccoli.models.{ParameterType, ParameterValue}
import pureconfig.ConfigReader
import pureconfig.error.{ConfigReaderFailures, ThrowableFailure}

import scala.collection.JavaConversions._
import scala.util.{Failure, Success, Try}

object TemplateConfig {

  implicit val configReader: ConfigReader[TemplateInfo] = new ConfigReader[TemplateInfo] {
    override def from(configOrig: ConfigValue): Either[ConfigReaderFailures, TemplateInfo] =
      Try {
        val confObj = configOrig.asInstanceOf[ConfigObject]
        val config = confObj.toConfig
        val description = Try(config.getString("description")).toOption
        val parameters = config
          .getObject("parameters")
          .map {
            case (paramName, paramConfig) =>
              val paramValueObj = paramConfig.asInstanceOf[ConfigObject].toConfig
              val maybeName = Try(paramValueObj.getString("name")).toOption
              val maybeSecret = Try(paramValueObj.getBoolean("secret")).toOption
              // Don't wrap the call as we want it to fail in case the wrong type or no type is supplied
              val paramType = ParameterType.withName(paramValueObj.getString("type"))
              val maybeOrderIndex = Try(paramValueObj.getInt("order-index")).toOption
              val maybeDefault = Try(paramValueObj.getValue("default")).toOption.map { paramValueConf =>
                ParameterValue.fromConfigValue(
                  paramName,
                  paramType,
                  paramValueConf
                ) match {
                  case Success(paramDefault) => paramDefault
                  case Failure(ex)           => throw ex
                }
              }
              (paramName, Parameter(maybeName, maybeDefault, maybeSecret, paramType, maybeOrderIndex))
          }
          .toMap
        TemplateInfo(description, parameters)
      } match {
        case Success(e)  => Right(e)
        case Failure(ex) =>
          // TODO: Improve this error throwing.
          Left(ConfigReaderFailures(ThrowableFailure(ex, None, "")))
      }
  }

  final case class TemplateInfo(description: Option[String], parameters: Map[String, Parameter])

  final case class Parameter(name: Option[String],
                             default: Option[ParameterValue],
                             secret: Option[Boolean],
                             `type`: ParameterType,
                             orderIndex: Option[Int])

} 
Example 3
Source File: package.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.scalaz

import com.typesafe.config.ConfigValue
import pureconfig.{ ConfigConvert, ConfigReader, ConfigWriter }
import pureconfig.error.{ ConfigReaderFailure, ConfigReaderFailures, FailureReason }

import scalaz.{ Contravariant, Equal, InvariantFunctor, MonadError, Semigroup, Show }


package object instances {

  implicit val configReaderInstance: MonadError[ConfigReader, ConfigReaderFailures] =
    new MonadError[ConfigReader, ConfigReaderFailures] {
      def point[A](a: => A): ConfigReader[A] =
        ConfigReader.fromFunction { _ => Right(a) }

      def bind[A, B](fa: ConfigReader[A])(f: A => ConfigReader[B]): ConfigReader[B] =
        fa.flatMap(f)

      def raiseError[A](e: ConfigReaderFailures): ConfigReader[A] =
        ConfigReader.fromFunction { _ => Left(e) }

      def handleError[A](fa: ConfigReader[A])(f: ConfigReaderFailures => ConfigReader[A]): ConfigReader[A] =
        ConfigReader.fromFunction { cv =>
          fa.from(cv) match {
            case Left(failures) => f(failures).from(cv)
            case r @ Right(_) => r
          }
        }
    }

  implicit val configWriterInstance: Contravariant[ConfigWriter] =
    new Contravariant[ConfigWriter] {
      def contramap[A, B](fa: ConfigWriter[A])(f: B => A): ConfigWriter[B] =
        fa.contramap(f)
    }

  implicit val configConvertInstance: InvariantFunctor[ConfigConvert] =
    new InvariantFunctor[ConfigConvert] {
      def xmap[A, B](ma: ConfigConvert[A], f: A => B, g: B => A): ConfigConvert[B] =
        ma.xmap(f, g)
    }

  implicit val configValueEqual: Equal[ConfigValue] = Equal.equalA
  implicit val failureReasonEqual: Equal[FailureReason] = Equal.equalA
  implicit val configReaderFailureEqual: Equal[ConfigReaderFailure] = Equal.equalA
  implicit val configReaderFailuresEqual: Equal[ConfigReaderFailures] = Equal.equalA

  implicit val failureReasonShow: Show[FailureReason] = Show.showFromToString
  implicit val configReaderFailureShow: Show[ConfigReaderFailure] = Show.showFromToString
  implicit val configReaderFailuresShow: Show[ConfigReaderFailures] = Show.showFromToString

  implicit val configReaderFailuresSemigroup: Semigroup[ConfigReaderFailures] =
    Semigroup.instance(_ ++ _)

  implicit val configValueSemigroup: Semigroup[ConfigValue] =
    Semigroup.instance((a, b) => b.withFallback(a))
} 
Example 4
Source File: ScalazLawsSuite.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.scalaz

import com.typesafe.config.ConfigValue
import org.scalacheck.{ Prop, Properties }
import org.scalatest.funsuite.AnyFunSuite
import org.scalatestplus.scalacheck.Checkers
import pureconfig.error.ConfigReaderFailures
import pureconfig.module.scalaz.arbitrary._
import pureconfig.module.scalaz.equal._
import pureconfig.module.scalaz.instances._
import pureconfig.{ ConfigConvert, ConfigReader, ConfigWriter }
import scalaz.scalacheck.ScalazProperties._
import scalaz.std.anyVal.intInstance

class ScalazLawsSuite extends AnyFunSuite with Checkers {
  import ScalazLawsSuite._

  test("contravariant.laws[ConfigWriter]") {
    check(properties2prop(contravariant.laws[ConfigWriter]))
  }

  test("invariantFunctor.laws[ConfigConvert]") {
    check(properties2prop(invariantFunctor.laws[ConfigConvert]))
  }

  test("monadError.laws[ConfigReader, ConfigReaderFailures]") {
    check(properties2prop(monadError.laws[ConfigReader, ConfigReaderFailures]))
  }

  test("semigroup.laws[ConfigReaderFailures]") {
    check(properties2prop(semigroup.laws[ConfigReaderFailures]))
  }

  test("semigroup.laws[ConfigValue]") {
    check(properties2prop(semigroup.laws[ConfigValue]))
  }
}

object ScalazLawsSuite {
  def properties2prop(ps: Properties): Prop = Prop.all(ps.properties.map(_._2).toSeq: _*)
} 
Example 5
Source File: Cron4sSuite.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.cron4s

import java.util.{ Map => JMap }
import com.typesafe.config.ConfigFactory
import _root_.cron4s.expr.CronExpr
import _root_.cron4s.Cron
import pureconfig.BaseSuite
import pureconfig.error.{ CannotConvert, ConfigReaderFailures, ConvertFailure }
import pureconfig.generic.auto._
import pureconfig.syntax._

class Cron4sSuite extends BaseSuite {

  case class Config(schedule: CronExpr)

  "reading valid cron expressons" should "parse the expression" in {
    val conf = ConfigFactory.parseString(s"""{schedule: "10-35 2,4,6 * ? * *"}""")

    conf.to[Config].right.value shouldEqual Config(Cron.unsafeParse("10-35 2,4,6 * ? * *"))
  }

  "reading invalid cron expressions" should "get a CannotConvert error" in {
    val conf = ConfigFactory.parseString(s"""{schedule: "10-65 * * * * *"}""")

    val errors = ConfigReaderFailures(
      ConvertFailure(
        CannotConvert("10-65 * * * * *", "CronExpr", "blank expected at position 3 but found '-'"),
        stringConfigOrigin(1),
        "schedule"))

    conf.to[Config].left.value shouldEqual errors
  }

  "writing a cron expression" should "generate a valid configuration" in {
    val exprStr = "10-35 2,4,6 * ? * *"
    val cfg = Config(Cron.unsafeParse(exprStr))

    cfg.toConfig.unwrapped().asInstanceOf[JMap[String, String]].get("schedule") shouldEqual exprStr
  }

} 
Example 6
Source File: SttpSuite.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.sttp

import sttp.model.Uri
import sttp.model.Uri._
import com.typesafe.config.ConfigFactory
import pureconfig.BaseSuite
import pureconfig.error.{ CannotConvert, ConfigReaderFailures, ConvertFailure }
import pureconfig.generic.auto._
import pureconfig.syntax._

class SttpSuite extends BaseSuite {

  case class AppConfig(uri: Uri)

  behavior of "sttp module"

  it should "read uri" in {
    val config = ConfigFactory.parseString("""{uri = "https://sttp.readthedocs.io"}""")

    config.to[AppConfig].right.value shouldBe AppConfig(uri"https://sttp.readthedocs.io")
  }

  it should "handle error when reading uri" in {
    val config = ConfigFactory.parseString("""{uri = "sttp.readthedocs.io"}""")

    val failure =
      ConvertFailure(
        reason = CannotConvert(
          value = "sttp.readthedocs.io",
          toType = "sttp.model.Uri",
          because = "missing scheme"),
        origin = stringConfigOrigin(1),
        path = "uri")

    config.to[AppConfig].left.value shouldBe ConfigReaderFailures(failure)
  }

} 
Example 7
Source File: NoValidCoproductOptionFound.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.generic.error

import com.typesafe.config.{ ConfigRenderOptions, ConfigValue }
import pureconfig.error.{ ConfigReaderFailures, FailureReason }


final case class NoValidCoproductOptionFound(value: ConfigValue, optionFailures: Seq[(String, ConfigReaderFailures)]) extends FailureReason {
  def description = {
    val baseDescription = s"No valid coproduct option found for '${value.render(ConfigRenderOptions.concise())}'."
    baseDescription + (
      if (optionFailures.isEmpty) ""
      else {
        "\n" + optionFailures.map {
          case (optionName, failures) =>
            s"Can't use coproduct option '$optionName':\n" + failures.prettyPrint(1)
        }.mkString("\n")
      })
  }
} 
Example 8
Source File: package.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.cats

import cats._
import com.typesafe.config.{ Config, ConfigFactory, ConfigValue }
import pureconfig._
import pureconfig.error.{ ConfigReaderFailure, ConfigReaderFailures }

package object instances {

  implicit val configReaderInstance: ApplicativeError[ConfigReader, ConfigReaderFailures] =
    new ApplicativeError[ConfigReader, ConfigReaderFailures] {
      def pure[A](x: A): ConfigReader[A] =
        ConfigReader.fromFunction { _ => Right(x) }

      def ap[A, B](ff: ConfigReader[A => B])(fa: ConfigReader[A]): ConfigReader[B] =
        ff.zip(fa).map { case (f, a) => f(a) }

      def raiseError[A](e: ConfigReaderFailures): ConfigReader[A] =
        ConfigReader.fromFunction { _ => Left(e) }

      def handleErrorWith[A](fa: ConfigReader[A])(f: ConfigReaderFailures => ConfigReader[A]): ConfigReader[A] =
        ConfigReader.fromFunction { cv =>
          fa.from(cv) match {
            case Left(failures) => f(failures).from(cv)
            case r @ Right(_) => r
          }
        }
    }

  implicit val configWriterCatsInstance: ContravariantSemigroupal[ConfigWriter] =
    new ContravariantSemigroupal[ConfigWriter] {
      def contramap[A, B](fa: ConfigWriter[A])(f: B => A): ConfigWriter[B] =
        fa.contramap(f)

      def product[A, B](fa: ConfigWriter[A], fb: ConfigWriter[B]) =
        ConfigWriter.fromFunction[(A, B)] {
          case (a, b) =>
            fb.to(b).withFallback(fa.to(a))
        }
    }

  implicit val configConvertCatsInstance: InvariantSemigroupal[ConfigConvert] =
    new InvariantSemigroupal[ConfigConvert] {
      def imap[A, B](fa: ConfigConvert[A])(f: A => B)(g: B => A): ConfigConvert[B] =
        fa.xmap(f, g)

      def product[A, B](fa: ConfigConvert[A], fb: ConfigConvert[B]): ConfigConvert[(A, B)] = {
        val reader = fa.zip(fb)
        val writer = ConfigWriter.fromFunction[(A, B)] {
          case (a, b) =>
            fb.to(b).withFallback(fa.to(a))
        }

        ConfigConvert.fromReaderAndWriter(
          Derivation.Successful(reader),
          Derivation.Successful(writer))
      }
    }

  implicit val configValueEq: Eq[ConfigValue] = Eq.fromUniversalEquals
  implicit val configEq: Eq[Config] = Eq.fromUniversalEquals
  implicit val configReaderFailureEq: Eq[ConfigReaderFailure] = Eq.fromUniversalEquals
  implicit val configReaderFailuresEq: Eq[ConfigReaderFailures] = Eq.fromUniversalEquals

  implicit val configReaderFailuresSemigroup: Semigroup[ConfigReaderFailures] =
    Semigroup.instance(_ ++ _)

  implicit val configValueCatsSemigroup: Semigroup[ConfigValue] =
    Semigroup.instance((a, b) => b.withFallback(a))

  implicit val configCatsMonoid: Monoid[Config] =
    Monoid.instance(ConfigFactory.empty, (a, b) => b.withFallback(a))

  implicit val configObjectSourceCatsMonoid: Monoid[ConfigObjectSource] =
    Monoid.instance(ConfigSource.empty, (a, b) => b.withFallback(a))
} 
Example 9
Source File: package.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.cats

import scala.collection.JavaConverters._

import com.typesafe.config.{ Config, ConfigValue, ConfigValueFactory }
import org.scalacheck.Arbitrary.{ arbitrary => arb }
import org.scalacheck.{ Arbitrary, Cogen, Gen }
import pureconfig._
import pureconfig.error.{ ConfigReaderFailures, ConvertFailure }

package object arbitrary {

  private[this] val MaxConfigDepth = 3
  private[this] val MaxCollSize = 3

  private[this] def genAnyMapForConfig(maxDepth: Int): Gen[Map[String, Any]] = {
    Gen.choose(0, MaxCollSize).flatMap { sz =>
      Gen.mapOfN(sz, for { k <- Gen.alphaStr; v <- Gen.lzy(genAnyForConfig(maxDepth - 1)) } yield (k, v))
    }
  }

  private[this] def genAnyForConfig(maxDepth: Int): Gen[Any] = {
    val genScalar: Gen[Any] = Gen.oneOf(
      Gen.oneOf(true, false),
      Gen.choose(Int.MinValue, Int.MaxValue),
      Gen.choose(Double.MinValue, Double.MaxValue),
      Gen.alphaStr)

    def genList(maxDepth: Int): Gen[List[Any]] = Gen.choose(0, MaxCollSize).flatMap { sz =>
      Gen.listOfN(sz, Gen.lzy(genAnyForConfig(maxDepth - 1)))
    }

    if (maxDepth == 0) genScalar
    else Gen.frequency(
      3 -> genScalar,
      1 -> genList(maxDepth).map(_.asJava),
      1 -> genAnyMapForConfig(maxDepth).map(_.asJava))
  }

  implicit val arbConfigValue: Arbitrary[ConfigValue] = Arbitrary {
    genAnyForConfig(MaxConfigDepth).map(ConfigValueFactory.fromAnyRef)
  }

  implicit val arbConfig: Arbitrary[Config] = Arbitrary {
    genAnyMapForConfig(MaxConfigDepth).map(_.asJava).map(ConfigValueFactory.fromMap(_).toConfig)
  }

  implicit val cogenConfigValue: Cogen[ConfigValue] =
    Cogen[String].contramap[ConfigValue](_.render)

  implicit val arbConfigReaderFailures: Arbitrary[ConfigReaderFailures] = Arbitrary {
    Gen.const(ConfigReaderFailures(ConvertFailure(EmptyTraversableFound("List"), None, "")))
  }

  implicit val cogenConfigReaderFailures: Cogen[ConfigReaderFailures] =
    Cogen[String].contramap[ConfigReaderFailures](_.toString)

  implicit val arbConfigObjectSource: Arbitrary[ConfigObjectSource] = Arbitrary {
    Gen.either(arb[ConfigReaderFailures], arb[Config]).map(ConfigObjectSource(_))
  }

  implicit def arbConfigReader[A: Arbitrary]: Arbitrary[ConfigReader[A]] = Arbitrary {
    arb[ConfigValue => ConfigReader.Result[A]].map(ConfigReader.fromFunction)
  }

  implicit def arbConfigWriter[A: Cogen]: Arbitrary[ConfigWriter[A]] = Arbitrary {
    arb[A => ConfigValue].map(ConfigWriter.fromFunction)
  }

  implicit def arbConfigConvert[A: Arbitrary: Cogen]: Arbitrary[ConfigConvert[A]] = Arbitrary {
    for { reader <- arb[ConfigReader[A]]; writer <- arb[ConfigWriter[A]] }
      yield ConfigConvert.fromReaderAndWriter(Derivation.Successful(reader), Derivation.Successful(writer))
  }
} 
Example 10
Source File: CollectionConvertersSuite.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig

import scala.collection.JavaConverters._
import scala.collection.immutable.{ HashSet, ListSet, Queue, TreeSet }

import com.typesafe.config.{ ConfigFactory, ConfigValueFactory, ConfigValueType }
import pureconfig.error.{ ConfigReaderFailures, ConvertFailure, WrongType }

class CollectionConvertersSuite extends BaseSuite {
  implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 100)

  behavior of "ConfigConvert"

  checkArbitrary[HashSet[String]]

  checkArbitrary[List[Float]]
  checkRead[List[Int]](
    // order of keys maintained
    ConfigValueFactory.fromMap(Map("2" -> 1, "0" -> 2, "1" -> 3).asJava) -> List(2, 3, 1),
    ConfigValueFactory.fromMap(Map("3" -> 2, "1" -> 4).asJava) -> List(4, 2),
    ConfigValueFactory.fromMap(Map("1" -> 1, "a" -> 2).asJava) -> List(1))

  checkFailures[List[Int]](
    ConfigValueFactory.fromMap(Map("b" -> 1, "a" -> 2).asJava) -> ConfigReaderFailures(
      ConvertFailure(WrongType(ConfigValueType.OBJECT, Set(ConfigValueType.LIST)), emptyConfigOrigin, "")),
    ConfigValueFactory.fromMap(Map().asJava) -> ConfigReaderFailures(
      ConvertFailure(WrongType(ConfigValueType.OBJECT, Set(ConfigValueType.LIST)), emptyConfigOrigin, "")))

  checkArbitrary[ListSet[Int]]

  checkArbitrary[Map[String, Int]]
  checkFailures[Map[String, Int]](
    // nested map should fail
    ConfigFactory.parseString("conf.a=1").root() -> ConfigReaderFailures(
      ConvertFailure(WrongType(ConfigValueType.OBJECT, Set(ConfigValueType.NUMBER)), stringConfigOrigin(1), "conf")),
    // wrong value type should fail
    ConfigFactory.parseString("{ a=b }").root() -> ConfigReaderFailures(
      ConvertFailure(WrongType(ConfigValueType.STRING, Set(ConfigValueType.NUMBER)), stringConfigOrigin(1), "a")))

  checkArbitrary[Queue[Boolean]]

  checkArbitrary[Set[Double]]
  checkRead[Set[Int]](
    ConfigValueFactory.fromMap(Map("1" -> 4, "2" -> 5, "3" -> 6).asJava) -> Set(4, 5, 6))

  checkArbitrary[Stream[String]]

  checkArbitrary[TreeSet[Int]]

  checkArbitrary[Vector[Short]]

  checkArbitrary[Option[Int]]

  checkArbitrary[Array[Int]]
} 
Example 11
Source File: BaseFeature.scala    From cornichon   with Apache License 2.0 5 votes vote down vote up
package com.github.agourlay.cornichon.dsl

import java.util.concurrent.ConcurrentLinkedDeque

import com.github.agourlay.cornichon.core.{ Config, Done, FeatureDef, Step }
import com.github.agourlay.cornichon.matchers.Matcher
import com.github.agourlay.cornichon.resolver.Mapper
import monix.execution.Scheduler
import pureconfig.error.{ ConvertFailure, KeyNotFound }

import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer
import scala.concurrent.Future

trait BaseFeature {

  protected[cornichon] val beforeFeature: ListBuffer[() => Unit] = ListBuffer.empty
  protected[cornichon] val afterFeature: ListBuffer[() => Unit] = ListBuffer.empty

  protected[cornichon] val beforeEachScenario: ListBuffer[Step] = ListBuffer.empty
  protected[cornichon] val afterEachScenario: ListBuffer[Step] = ListBuffer.empty

  private[cornichon] lazy val config = BaseFeature.config
  lazy val executeScenariosInParallel: Boolean = config.executeScenariosInParallel

  lazy val seed: Option[Long] = None

  // Convenient implicits for the custom DSL
  implicit lazy val ec = Scheduler.Implicits.global

  def feature: FeatureDef

  def registerExtractors: Map[String, Mapper] = Map.empty

  def registerMatchers: List[Matcher] = Nil

  def beforeFeature(before: => Unit): Unit =
    beforeFeature += (() => before)

  def afterFeature(after: => Unit): Unit =
    (() => after) +=: afterFeature

  def beforeEachScenario(step: Step): Unit =
    beforeEachScenario += step

  def afterEachScenario(step: Step): Unit =
    step +=: afterEachScenario
}

// Protect and free resources
object BaseFeature {
  import pureconfig.generic.auto._
  import pureconfig.ConfigSource
  import pureconfig.error.{ ConfigReaderException, ConfigReaderFailures }

  lazy val config = ConfigSource.default.at("cornichon").load[Config] match {
    case Right(v)                                                                          => v
    case Left(ConfigReaderFailures(ConvertFailure(KeyNotFound("cornichon", _), _, _), _*)) => Config()
    case Left(failures)                                                                    => throw new ConfigReaderException[Config](failures)
  }

  private val hooks = new ConcurrentLinkedDeque[() => Future[_]]()

  def addShutdownHook(h: () => Future[_]): Unit =
    hooks.push(h)

  def shutDownGlobalResources(): Future[Done] = {
    import scala.concurrent.ExecutionContext.Implicits.global
    @tailrec
    def clearHooks(previous: Future[Any] = Future.successful[Any](())): Future[Any] =
      Option(hooks.poll()) match {
        case None => previous
        case Some(f) =>
          clearHooks {
            previous.flatMap { _ => f().recover { case _ => Done } }
          }
      }

    clearHooks().map(_ => Done)
  }
} 
Example 12
Source File: ProcessConfigReaderTest.scala    From stryker4s   with Apache License 2.0 5 votes vote down vote up
package stryker4s.config

import org.scalatest.EitherValues
import pureconfig.error.{ConfigReaderFailures, ConvertFailure, KeyNotFound}
import stryker4s.command.config.ProcessRunnerConfig
import stryker4s.run.process.Command
import stryker4s.scalatest.FileUtil
import stryker4s.testutil.Stryker4sSuite
import pureconfig.generic.auto._

class ProcessConfigReaderTest extends Stryker4sSuite with EitherValues {
  describe("ProcessConfig") {
    it("should read a process config") {
      val confPath = FileUtil.getResource("config/filledProcess.conf")

      val result = ConfigReader.readConfigOfType[ProcessRunnerConfig](confPath).getOrElse(fail())

      result.testRunner should equal(Command("gradle", "test"))
    }

    it("should read an empty config to errors") {
      val confPath = FileUtil.getResource("config/empty.conf")

      val result = ConfigReader.readConfigOfType[ProcessRunnerConfig](confPath)

      result.left.value should matchPattern {
        case ConfigReaderFailures(ConvertFailure(KeyNotFound("test-runner", _), _, _), _*) =>
      }
    }
  }
} 
Example 13
Source File: PureConfigModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.pureconfig

import cats.data.NonEmptyList
import cats.effect.Sync
import cats.syntax.either._
import pureconfig.error.{ConfigReaderFailure, ConfigReaderFailures, ConvertFailure}
import pureconfig.{ConfigReader, ConfigSource}

import scala.reflect.ClassTag


  def makeOrRaise[F[_]: Sync, A: ConfigReader: ClassTag](source: ConfigSource): F[A] = Sync[F].delay(source.loadOrThrow[A])

  private def convertFailures(failures: ConfigReaderFailures): NonEmptyList[String] = {
    NonEmptyList(failures.head, failures.tail.toList).map(formatFailure)
  }

  private def formatFailure(configReaderFailure: ConfigReaderFailure): String = {
    configReaderFailure match {
      case convertFailure: ConvertFailure =>
        s"Invalid configuration ${convertFailure.path}: ${convertFailure.description}"
      case configFailure =>
        s"Invalid configuration : ${configFailure.description}"
    }
  }

}