diff --git a/backend/build.sbt b/backend/build.sbt index 87b27c74..0a222c75 100644 --- a/backend/build.sbt +++ b/backend/build.sbt @@ -6,7 +6,6 @@ ThisBuild / scalaVersion := "3.8.1" ThisBuild / evictionErrorLevel := Level.Debug ThisBuild / semanticdbEnabled := true -ThisBuild / semanticdbVersion := scalafixSemanticdb.revision val utils = (project in file("utils")) .settings(Settings.common) @@ -214,5 +213,5 @@ val root = (project in file(".")) `edsl` ) .settings( - run / aggregate := false, + run / aggregate := false ) diff --git a/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/JsonOptic.scala b/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/JsonOptic.scala index df9bcabf..0df6ffe6 100644 --- a/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/JsonOptic.scala +++ b/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/JsonOptic.scala @@ -50,13 +50,17 @@ final case class JsonOptic private[optics] (private val jsonPath: Seq[PathPart]) def prune: Json => Json = { json => if (validate(json)) - jsonPath.init.foldRight[Json => Json] { json => - jsonPath.last.fold( - f => json.withObject(jo => Json.fromJsonObject(jo.remove(f))), - i => json.withArray(ja => Json.fromValues(ja.take(i) ++ ja.drop(i + 1))), - if (json.isArray) Json.Null else json - ) - }((part, f) => modifyPart(Json.Null)(part)(f))(json) + jsonPath.lastOption.fold(json) { lastPart => + jsonPath + .dropRight(1) + .foldRight[Json => Json] { innerJson => + lastPart.fold( + f => innerJson.withObject(jo => Json.fromJsonObject(jo.remove(f))), + i => innerJson.withArray(ja => Json.fromValues(ja.take(i) ++ ja.drop(i + 1))), + if (innerJson.isArray) Json.Null else innerJson + ) + }((part, f) => modifyPart(Json.Null)(part)(f))(json) + } else json } @@ -82,7 +86,9 @@ final case class JsonOptic private[optics] (private val jsonPath: Seq[PathPart]) jsonPath.foldRight[Json => Json](op)((part, f) => modifyPart(Json.Null)(part)(f)) def modifyOpt(op: Option[Json] => Json): Json => Json = - jsonPath.init.foldRight[Json => Json](modifyPart(jsonPath.last)(op))((part, f) => modifyPart(Json.Null)(part)(f)) + jsonPath.lastOption.fold[Json => Json](identity) { lastPart => + jsonPath.dropRight(1).foldRight[Json => Json](modifyPart(lastPart)(op))((part, f) => modifyPart(Json.Null)(part)(f)) + } def modifyObjectValues(op: Json => Json): Json => Json = { json => getOpt(json) diff --git a/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/package.scala b/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/package.scala index b0901d01..582e4141 100644 --- a/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/package.scala +++ b/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/optics/package.scala @@ -27,7 +27,7 @@ package object optics { else { val itemsToAdd = index - ja.length + 1 Json.fromValues( - ja ++ Vector.tabulate(itemsToAdd)(idx => if (idx == itemsToAdd - 1) mod(None) else Json.Null) + ja ++ Vector.tabulate(itemsToAdd)(idx => if (idx === itemsToAdd - 1) mod(None) else Json.Null) ) } } diff --git a/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/package.scala b/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/package.scala index 01c17423..d106fdb8 100644 --- a/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/package.scala +++ b/backend/circe-utils/src/main/scala/ru/tinkoff/tcb/utils/circe/package.scala @@ -52,7 +52,10 @@ package object circe { if (baseArr.length >= patchArr.length) Json.fromValues((baseArr zip patchArr).map(mrgPair.tupled)) - else Json.fromValues(baseArr.zipAll(patchArr, Json.Null, patchArr.last).map(mrgPair.tupled)) + else + Json.fromValues( + baseArr.zipAll(patchArr, Json.Null, patchArr.lastOption.getOrElse(Json.Null)).map(mrgPair.tupled) + ) case (p, JsonNull()) if arraySubvalues => p case (_, p) => p } diff --git a/backend/circe-utils/src/test/scala/ru/tinkoff/tcb/utils/circe/optics/OpticSpec.scala b/backend/circe-utils/src/test/scala/ru/tinkoff/tcb/utils/circe/optics/OpticSpec.scala index c813de3a..9437ff26 100644 --- a/backend/circe-utils/src/test/scala/ru/tinkoff/tcb/utils/circe/optics/OpticSpec.scala +++ b/backend/circe-utils/src/test/scala/ru/tinkoff/tcb/utils/circe/optics/OpticSpec.scala @@ -150,7 +150,7 @@ class OpticSpec extends RefSpec with Matchers { val optic = JLens \ "value" - optic.modify(_.withNumber(jn => Json.fromInt(jn.toInt.get * 2)))(target) shouldBe + optic.modify(_.withNumber(jn => jn.toInt.fold(Json.Null)(n => Json.fromInt(n * 2))))(target) shouldBe json"""{"value": 4}""" } @@ -159,7 +159,7 @@ class OpticSpec extends RefSpec with Matchers { val optic = (JLens \ "value").traverse - optic.modify(_.withNumber(jn => Json.fromInt(jn.toInt.get * 2)))(target) shouldBe + optic.modify(_.withNumber(jn => jn.toInt.fold(Json.Null)(n => Json.fromInt(n * 2))))(target) shouldBe json"""{"value": [2, 4, 6]}""" } } @@ -171,7 +171,7 @@ class OpticSpec extends RefSpec with Matchers { val optic = JLens \ "value" optic.modifyOpt { - case Some(json) => json.withNumber(jn => Json.fromInt(jn.toInt.get * 2)) + case Some(json) => json.withNumber(jn => jn.toInt.fold(Json.Null)(n => Json.fromInt(n * 2))) case None => Json.fromInt(2) }(target) shouldBe json"""{"value": 4}""" @@ -183,7 +183,7 @@ class OpticSpec extends RefSpec with Matchers { val optic = JLens \ "value" optic.modifyOpt { - case Some(json) => json.withNumber(jn => Json.fromInt(jn.toInt.get * 2)) + case Some(json) => json.withNumber(jn => jn.toInt.fold(Json.Null)(n => Json.fromInt(n * 2))) case None => Json.fromInt(2) }(target) shouldBe json"""{"value": 2}""" @@ -196,7 +196,8 @@ class OpticSpec extends RefSpec with Matchers { val optic = JLens \ "outer" - optic.modifyObjectValues(_.withNumber(jn => Json.fromInt(jn.toInt.get * 2)))(target) shouldBe + optic + .modifyObjectValues(_.withNumber(jn => jn.toInt.fold(Json.Null)(n => Json.fromInt(n * 2))))(target) shouldBe json"""{"outer": {"inner": 84}}""" } } @@ -208,7 +209,7 @@ class OpticSpec extends RefSpec with Matchers { val optic = JLens \ "outer" optic.modifyFields { case (key, value) => - key -> value.withNumber(jn => Json.fromInt(jn.toInt.get * 2)) + key -> value.withNumber(jn => jn.toInt.fold(Json.Null)(n => Json.fromInt(n * 2))) }(target) shouldBe json"""{"outer": {"inner": 84}}""" } } diff --git a/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/dataaccess/UpdateResult.scala b/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/dataaccess/UpdateResult.scala index f5d7c10e..01769af2 100644 --- a/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/dataaccess/UpdateResult.scala +++ b/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/dataaccess/UpdateResult.scala @@ -2,8 +2,8 @@ package ru.tinkoff.tcb.dataaccess final case class UpdateResult(matched: Long, modified: Long) { val successful: Boolean = matched > 0 || modified > 0 - val noMatch: Boolean = matched == 0 - val noOp: Boolean = modified == 0 + val noMatch: Boolean = matched === 0L + val noOp: Boolean = modified === 0L val unsuccessful: Boolean = noMatch && noOp } diff --git a/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/Fields.scala b/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/Fields.scala index 7ddc25f3..bfcc2cc5 100644 --- a/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/Fields.scala +++ b/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/Fields.scala @@ -34,7 +34,7 @@ object Fields extends AutoDerivation[Fields] { implicit def enumEntry[T <: EnumEntry]: Fields[T] = mk(Nil) implicit def strEnum[T <: StringEnumEntry]: Fields[T] = mk(Nil) - def join[T](caseClass: CaseClass[Fields, T]): Fields[T] = + override def join[T](caseClass: CaseClass[Fields, T]): Fields[T] = mk( caseClass.parameters .foldLeft(List.newBuilder[String])((acc, fld) => @@ -44,5 +44,5 @@ object Fields extends AutoDerivation[Fields] { .result() ) - def split[T](sealedTrait: SealedTrait[Fields, T]): Fields[T] = mk(Nil) + override def split[T](sealedTrait: SealedTrait[Fields, T]): Fields[T] = mk(Nil) } diff --git a/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/RootOptionFields.scala b/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/RootOptionFields.scala index d6ec45db..25a22bb5 100644 --- a/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/RootOptionFields.scala +++ b/backend/dataAccess/src/main/scala/ru/tinkoff/tcb/generic/RootOptionFields.scala @@ -35,7 +35,7 @@ object RootOptionFields extends AutoDerivation[RootOptionFields] { implicit def refn[T, R, F[_, _]](implicit rt: RefType[F], rof: RootOptionFields[T]): RootOptionFields[F[T, R]] = mk(rof.fields) - def join[T](caseClass: CaseClass[RootOptionFields, T]): RootOptionFields[T] = + override def join[T](caseClass: CaseClass[RootOptionFields, T]): RootOptionFields[T] = mk( caseClass.parameters .foldLeft(Set.newBuilder[String])((acc, fld) => @@ -45,5 +45,5 @@ object RootOptionFields extends AutoDerivation[RootOptionFields] { .result() ) - def split[T](sealedTrait: SealedTrait[RootOptionFields, T]): RootOptionFields[T] = mk(Set.empty) + override def split[T](sealedTrait: SealedTrait[RootOptionFields, T]): RootOptionFields[T] = mk(Set.empty) } diff --git a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/RoundRobinSpec.scala b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/RoundRobinSpec.scala index 965acc8b..c706704d 100644 --- a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/RoundRobinSpec.scala +++ b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/RoundRobinSpec.scala @@ -13,7 +13,7 @@ class RoundRobinSpec extends AnyFunSuite with Matchers with TryValues { implicit private val regexEquality: Equality[Regex] = (a: Regex, b: Any) => b match { - case rb: Regex => a.regex == rb.regex + case rb: Regex => a.regex === rb.regex case _ => false } diff --git a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/BsonEnumSpec.scala b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/BsonEnumSpec.scala index 56cb9b09..9b8ebc20 100644 --- a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/BsonEnumSpec.scala +++ b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/BsonEnumSpec.scala @@ -2,17 +2,18 @@ package ru.tinkoff.tcb.bson.enumeratum import oolong.bson.* import org.mongodb.scala.bson.* +import org.scalatest.TryValues import org.scalatest.funspec.AnyFunSpec import org.scalatest.matchers.should.Matchers -class BsonEnumSpec extends AnyFunSpec with Matchers { +class BsonEnumSpec extends AnyFunSpec with Matchers with TryValues { describe("BSON serdes") { describe("deserialisation") { it("should work with valid values") { val bsonValue: BsonValue = BsonString("A") - BsonDecoder[Dummy].fromBson(bsonValue).get shouldBe Dummy.A + BsonDecoder[Dummy].fromBson(bsonValue).success.value shouldBe Dummy.A } it("should fail with invalid values") { diff --git a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerHelpers.scala b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerHelpers.scala index 9676c510..45dc9e49 100644 --- a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerHelpers.scala +++ b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerHelpers.scala @@ -3,10 +3,11 @@ package ru.tinkoff.tcb.bson.enumeratum.values import enumeratum.values.* import oolong.bson.* import org.mongodb.scala.bson.* +import org.scalatest.TryValues import org.scalatest.funspec.AnyFunSpec import org.scalatest.matchers.should.Matchers -trait EnumBsonHandlerHelpers { this: AnyFunSpec & Matchers => +trait EnumBsonHandlerHelpers { this: AnyFunSpec & Matchers & TryValues => def testWriter[EntryType <: ValueEnumEntry[ValueType], ValueType]( enumKind: String, `enum`: ValueEnum[ValueType, EntryType], @@ -28,7 +29,7 @@ trait EnumBsonHandlerHelpers { this: AnyFunSpec & Matchers => val reader = providedReader.getOrElse(EnumHandler.reader(`enum`)) describe(enumKind) { it("should read valid values") { - `enum`.values.foreach(entry => reader.fromBson(entry.value.bson).get shouldBe entry) + `enum`.values.foreach(entry => reader.fromBson(entry.value.bson).success.value shouldBe entry) } it("should fail to read with invalid values") { reader.fromBson(BsonInt32(Int.MaxValue)) shouldBe Symbol("failure") diff --git a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerSpec.scala b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerSpec.scala index 0a8a27ae..97da324a 100644 --- a/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerSpec.scala +++ b/backend/dataAccess/src/test/scala/ru/tinkoff/tcb/bson/enumeratum/values/EnumBsonHandlerSpec.scala @@ -1,10 +1,11 @@ package ru.tinkoff.tcb.bson.enumeratum.values import oolong.bson.given +import org.scalatest.TryValues import org.scalatest.funspec.AnyFunSpec import org.scalatest.matchers.should.Matchers -class EnumBsonHandlerSpec extends AnyFunSpec with Matchers with EnumBsonHandlerHelpers { +class EnumBsonHandlerSpec extends AnyFunSpec with Matchers with TryValues with EnumBsonHandlerHelpers { describe(".reader") { testReader("IntEnum", BsonLibraryItem) diff --git a/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGenerator.scala b/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGenerator.scala index 4ba33008..1a235352 100644 --- a/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGenerator.scala +++ b/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGenerator.scala @@ -105,7 +105,7 @@ final class MarkdownGenerator(baseUri: Uri) { } yield () private[interpreter] def stepsPrinterW: FunctionK[Step, W] = new (Step ~> W) { - def apply[A](fa: Step[A]): W[A] = + override def apply[A](fa: Step[A]): W[A] = fa match { case Describe(text, pos) => Vector(p(text)).tell diff --git a/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/model/Check.scala b/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/model/Check.scala index fe6078ac..a35c521e 100644 --- a/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/model/Check.scala +++ b/backend/edsl/src/main/scala/ru/tinkoff/tcb/mockingbird/edsl/model/Check.scala @@ -72,7 +72,7 @@ object Check { * null value * @group CheckJson */ - final case object CheckJsonNull extends CheckJson + case object CheckJsonNull extends CheckJson /** * Any valid JSON. diff --git a/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteTest.scala b/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteTest.scala index 31968612..f1f18ee4 100644 --- a/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteTest.scala +++ b/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteTest.scala @@ -24,6 +24,8 @@ import ru.tinkoff.tcb.mockingbird.edsl.model.Check.* import ru.tinkoff.tcb.mockingbird.edsl.model.ValueMatcher.syntax.* class AsyncScalaTestSuiteTest extends AsyncScalaTestSuite with Matchers with AsyncMockFactory with BeforeAndAfterEach { + given Eq[Uri] = Eq.fromUniversalEquals + val eset = new ExampleSet[HttpResponseR] { override def name: String = "" } @@ -65,9 +67,9 @@ class AsyncScalaTestSuiteTest extends AsyncScalaTestSuite with Matchers with Asy sttpbackend_ = HttpClientFutureBackend.stub().whenRequestMatchesPartial { case Request(POST, uri, StringBody(`body`, _, _), hs, _, _, _) - if uri == uri"http://some.domain.com:8090/api/handler?service=world" - && hs.exists(h => h.name == "x-token" && h.value == "asd5453qwe") - && hs.exists(h => h.name == "Content-Type" && h.value == "application/json") => + if uri === uri"http://some.domain.com:8090/api/handler?service=world" + && hs.exists(h => h.name === "x-token" && h.value === "asd5453qwe") + && hs.exists(h => h.name === "Content-Type" && h.value === "application/json") => new Response[String]( body = "got request", code = StatusCode.Ok, diff --git a/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteWholeTest.scala b/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteWholeTest.scala index e61bebbb..8006faf8 100644 --- a/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteWholeTest.scala +++ b/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/AsyncScalaTestSuiteWholeTest.scala @@ -26,6 +26,8 @@ class AsyncScalaTestSuiteWholeTest with AsyncMockFactory with BeforeAndAfterAll { + given Eq[sttp.model.Method] = Eq.fromUniversalEquals + val eset = new CatsFacts[HttpResponseR]() var sttpbackend_ : WebSocketBackendStub[Future] = @@ -58,8 +60,8 @@ class AsyncScalaTestSuiteWholeTest sttpbackend_ = HttpClientFutureBackend .stub() .whenRequestMatches { req => - req.method == GET && req.uri.toString() == s"https://localhost.example:9977/fact" && - req.headers.exists(h => h.name == "X-CSRF-TOKEN" && h.value == "unEENxJqSLS02rji2GjcKzNLc0C0ySlWih9hSxwn") + req.method === GET && req.uri.toString() === s"https://localhost.example:9977/fact" && + req.headers.exists(h => h.name === "X-CSRF-TOKEN" && h.value === "unEENxJqSLS02rji2GjcKzNLc0C0ySlWih9hSxwn") } .thenRespond( new Response( diff --git a/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGeneratorSuite.scala b/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGeneratorSuite.scala index af973d23..15bbd630 100644 --- a/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGeneratorSuite.scala +++ b/backend/edsl/src/test/scala/ru/tinkoff/tcb/mockingbird/edsl/interpreter/MarkdownGeneratorSuite.scala @@ -1,5 +1,6 @@ package ru.tinkoff.tcb.mockingbird.edsl.interpreter +import org.scalatest.OptionValues import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import pl.muninn.scalamdtag.* @@ -11,7 +12,7 @@ import ru.tinkoff.tcb.mockingbird.edsl.model.Check.* import ru.tinkoff.tcb.mockingbird.edsl.model.ValueMatcher.syntax.* import ru.tinkoff.tcb.mockingbird.examples.CatsFacts -class MarkdownGeneratorSuite extends AnyFunSuite with Matchers { +class MarkdownGeneratorSuite extends AnyFunSuite with Matchers with OptionValues { val eset = new ExampleSet[MarkdownGenerator.HttpResponseR] { override def name: String = "" } @@ -36,7 +37,7 @@ class MarkdownGeneratorSuite extends AnyFunSuite with Matchers { val mds = eset.describe(text).foldMap(mdg.stepsPrinterW).written mds should have length 1 - mds.head.md shouldBe ("\n".concat(text).concat("\n")) + mds.headOption.value.md shouldBe ("\n".concat(text).concat("\n")) } test("sendHttp produces curl command") { @@ -58,7 +59,7 @@ class MarkdownGeneratorSuite extends AnyFunSuite with Matchers { .written mds should have length 1 - val obtains = mds.head.md + val obtains = mds.headOption.value.md val expected = raw"""``` |curl \ diff --git a/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/BasicHttpStub.scala b/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/BasicHttpStub.scala index 11be8a99..0ee29955 100644 --- a/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/BasicHttpStub.scala +++ b/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/BasicHttpStub.scala @@ -105,7 +105,11 @@ class BasicHttpStub[HttpResponseR] extends ExampleSet[HttpResponseR] { ).some, ) ) - idEphemeral = parser.parse(r.body.get).toOption.flatMap((JLens \ "id").getOpt).flatMap(_.asString).get + idEphemeral = r.body + .flatMap(b => parser.parse(b).toOption) + .flatMap((JLens \ "id").getOpt) + .flatMap(_.asString) + .getOrElse(throw new NoSuchElementException("Expected 'id' field in response")) _ <- describe("And creating a stub in the `countdown` scope with `times` equal to 2.") resp <- sendHttp( diff --git a/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/HttpStubWithState.scala b/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/HttpStubWithState.scala index 54bc40a0..d376c756 100644 --- a/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/HttpStubWithState.scala +++ b/backend/examples/src/main/scala/ru/tinkoff/tcb/mockingbird/examples/HttpStubWithState.scala @@ -268,8 +268,13 @@ class HttpStubWithState[HttpResponseR] extends ExampleSet[HttpResponseR] { ).some ) ) - o1v1 = checked.body.flatMap(b => parser.parse(b).toOption).get - o1v1created = (JLens \ "meta" \ "created").getOpt(o1v1).flatMap(_.asString).get + o1v1 = checked.body + .flatMap(b => parser.parse(b).toOption) + .getOrElse(throw new NoSuchElementException("Expected JSON response body")) + o1v1created = (JLens \ "meta" \ "created") + .getOpt(o1v1) + .flatMap(_.asString) + .getOrElse(throw new NoSuchElementException("Expected meta.created in response")) _ <- describe("And now retrieve the state") resp <- sendHttp( method = Post, @@ -328,8 +333,13 @@ class HttpStubWithState[HttpResponseR] extends ExampleSet[HttpResponseR] { ).some ) ) - o1v2 = checked.body.flatMap(b => parser.parse(b).toOption).get - o1v2modified = (JLens \ "meta" \ "modified").getOpt(o1v2).flatMap(_.asString).get + o1v2 = checked.body + .flatMap(b => parser.parse(b).toOption) + .getOrElse(throw new NoSuchElementException("Expected JSON response body")) + o1v2modified = (JLens \ "meta" \ "modified") + .getOpt(o1v2) + .flatMap(_.asString) + .getOrElse(throw new NoSuchElementException("Expected meta.modified in response")) _ <- describe("And again, we request the state of object `o1`") resp <- sendHttp( method = Post, diff --git a/backend/examples/src/test/scala/ru/tinkoff/tcb/mockingbird/examples/BaseSuite.scala b/backend/examples/src/test/scala/ru/tinkoff/tcb/mockingbird/examples/BaseSuite.scala index 2974f6ef..38dd17e0 100644 --- a/backend/examples/src/test/scala/ru/tinkoff/tcb/mockingbird/examples/BaseSuite.scala +++ b/backend/examples/src/test/scala/ru/tinkoff/tcb/mockingbird/examples/BaseSuite.scala @@ -14,11 +14,9 @@ import sttp.model.Uri import ru.tinkoff.tcb.mockingbird.edsl.interpreter.AsyncScalaTestSuite trait BaseSuite extends AsyncScalaTestSuite with TestContainerForAll { - private var httpHost: Uri = scala.compiletime.uninitialized - @annotation.nowarn("msg=is never used") - private var grpcHost: String = scala.compiletime.uninitialized + private var httpHost: Option[Uri] = None - override def baseUri = httpHost + override def baseUri = httpHost.getOrElse(throw new IllegalStateException("httpHost not initialized")) override val containerDef: DockerComposeContainer.Def = DockerComposeContainer.Def( @@ -34,10 +32,8 @@ trait BaseSuite extends AsyncScalaTestSuite with TestContainerForAll { val host = containers.getServiceHost("mockingbird", 8228) val httpPort = containers.getServicePort("mockingbird", 8228) - val grpcPort = containers.getServicePort("mockingbird", 9000) - httpHost = uri"http://$host:$httpPort" - grpcHost = s"$host:$grpcPort" + httpHost = Some(uri"http://$host:$httpPort") val sb = HttpClientSyncBackend() val resp = quickRequest diff --git a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/Mockingbird.scala b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/Mockingbird.scala index e7ca1bed..c60c9893 100644 --- a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/Mockingbird.scala +++ b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/Mockingbird.scala @@ -61,6 +61,10 @@ object Mockingbird { private def zioLog: Logging[UIO] = new ZUniversalLogging(this.getClass.getName) + @SuppressWarnings(Array("org.wartremover.warts.Null")) + private def defaultKeyManagerFactory(): KeyManagerFactory = + KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm).tap(_.init(null, Array())) + private def mongoLayer = ZLayer { for { config <- ZIO.service[MongoConfig] @@ -127,10 +131,8 @@ object Mockingbird { .some ) } - keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm).tap { kmf => - kmf.init(null, Array()) - } - trustManager = TrustSomeHostsManager.of(pc.insecureHosts.to(Set)) + keyManagerFactory = defaultKeyManagerFactory() + trustManager = TrustSomeHostsManager.of(pc.insecureHosts.to(Set)) sslContext = SSLContext.getInstance("TLS").tap { sslc => sslc.init(keyManagerFactory.getKeyManagers, Array(trustManager), new SecureRandom) } diff --git a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/TrustSomeHostsManager.scala b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/TrustSomeHostsManager.scala index 9ed56dfe..126d0bd3 100644 --- a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/TrustSomeHostsManager.scala +++ b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/TrustSomeHostsManager.scala @@ -48,6 +48,7 @@ class TrustSomeHostsManager(delegate: X509ExtendedTrustManager, insecureHosts: S } object TrustSomeHostsManager { + @SuppressWarnings(Array("org.wartremover.warts.Null")) def of(insecureHosts: Set[String]): TrustSomeHostsManager = boundary { val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm) diff --git a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/UIHttp.scala b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/UIHttp.scala index 4d2a36be..a02c4c9c 100644 --- a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/UIHttp.scala +++ b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/UIHttp.scala @@ -48,7 +48,7 @@ class UIHttp { ): ServerEndpoint[Any, F] = ServerEndpoint.public( staticResourcesGetEndpoint(prefix).mapIn(si => si.copy(path = si.path.appended("index.html")))(si => - si.copy(path = si.path.init) + si.copy(path = si.path.dropRight(1)) ), (m: MonadError[F]) => Resources.get(classLoader, resourcePrefix, options)(m) ) diff --git a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/exec/package.scala b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/exec/package.scala index 2461007a..643c973e 100644 --- a/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/exec/package.scala +++ b/backend/mockingbird-api/src/main/scala/ru/tinkoff/tcb/mockingbird/api/exec/package.scala @@ -64,7 +64,7 @@ package object exec { .map(_.map(part => part.copy[String](body = new String(part.body, StandardCharsets.UTF_8))))( _.map(part => part.copy(body = part.body.getBytes(StandardCharsets.UTF_8))) ) - .map[RequestBody](MultipartRequestBody(_))(MultipartRequestBody.subset.getOption(_).get.value) + .map[RequestBody](MultipartRequestBody(_))(MultipartRequestBody.subset.getOption(_).fold(Seq.empty)(_.value)) ) .out(headers) .out(statusCode) diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/circe/bson/package.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/circe/bson/package.scala index fdd9d5cc..8c1d44f6 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/circe/bson/package.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/circe/bson/package.scala @@ -57,7 +57,7 @@ package object bson { final override def onNumber(value: JsonNumber): Either[Throwable, BsonValue] = { val asDouble = value.toDouble - if (java.lang.Double.compare(asDouble, -0.0) == 0) { + if (java.lang.Double.compare(asDouble, -0.0) === 0) { Right(BsonDecimal128(Decimal128.NEGATIVE_ZERO)) } else value.toLong match { @@ -110,5 +110,5 @@ package object bson { (value: BsonValue) => bsonToJson(value).toTry implicit final lazy val jsonBsonWriter: BsonEncoder[Json] = - (value: Json) => jsonToBson(value).toTry.get + (value: Json) => jsonToBson(value).fold(throw _, identity) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/instances/jsonNumber.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/instances/jsonNumber.scala index 122acee0..057f4e28 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/instances/jsonNumber.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/instances/jsonNumber.scala @@ -4,5 +4,11 @@ import io.circe.JsonNumber object jsonNumber { implicit val jsonNumberOrdering: scala.math.Ordering[JsonNumber] = - (lhs: JsonNumber, rhs: JsonNumber) => lhs.toBigDecimal.get.compare(rhs.toBigDecimal.get) + (lhs: JsonNumber, rhs: JsonNumber) => + (lhs.toBigDecimal, rhs.toBigDecimal) match { + case (Some(l), Some(r)) => l.compare(r) + case (None, None) => 0 + case (None, _) => -1 + case (_, None) => 1 + } } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/AdminApiHandler.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/AdminApiHandler.scala index d7494532..a26f1421 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/AdminApiHandler.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/AdminApiHandler.scala @@ -53,6 +53,7 @@ import ru.tinkoff.tcb.utils.id.SID import ru.tinkoff.tcb.utils.refinedchimney.* import ru.tinkoff.tcb.utils.xml.* +@SuppressWarnings(Array("org.wartremover.warts.Equals")) final class AdminApiHandler( stubDAO: HttpStubDAO[Task], scenarioDAO: ScenarioDAO[Task], @@ -75,14 +76,13 @@ final class AdminApiHandler( for { service1 <- ZIO.foreach(body.path)(serviceDAO.getServiceFor).map(_.flatten) service2 <- ZIO.foreach(body.pathPattern)(serviceDAO.getServiceFor).map(_.flatten) - _ <- ZIO.when(service1.isEmpty && service2.isEmpty)( - ZIO.fail( + service <- ZIO + .fromOption(service1.orElse(service2)) + .orElseFail( ValidationError( Vector(s"Can't find service for ${body.path.orElse(body.pathPattern.map(_.regex)).getOrElse("")}") ) ) - ) - service = service1.orElse(service2).get candidatesQuery = { val baseQ = query[HttpStub](hs => hs.method == lift(body.method) && @@ -163,7 +163,7 @@ final class AdminApiHandler( vr = Scenario.validationRules(sourceNames, destNames)(scenario) _ <- ZIO.when(vr.nonEmpty)(ZIO.fail(ValidationError(vr))) res <- scenarioDAO.insert(scenario) - _ <- labelDAO.ensureLabels(service.get.suffix, scenario.labels.to(Vector)) + _ <- ZIO.foreachDiscard(service)(s => labelDAO.ensureLabels(s.suffix, scenario.labels.to(Vector))) } yield if (res > 0) OperationResult("success", scenario.id) else OperationResult("nothing inserted") def createService(body: CreateServiceRequest): RIO[WLD, OperationResult[String]] = @@ -312,14 +312,13 @@ final class AdminApiHandler( for { service1 <- ZIO.foreach(body.path.map(_.value))(serviceDAO.getServiceFor).map(_.flatten) service2 <- ZIO.foreach(body.pathPattern)(serviceDAO.getServiceFor).map(_.flatten) - _ <- ZIO.when(service1.isEmpty && service2.isEmpty)( - ZIO.fail( + service <- ZIO + .fromOption(service1.orElse(service2)) + .orElseFail( ValidationError( Vector(s"Can't find a service for ${body.path.orElse(body.pathPattern.map(_.regex)).getOrElse("")}") ) ) - ) - service = service1.orElse(service2).get candidatesQuery = { val baseQ = query[HttpStub](hs => hs.id != lift(id) && @@ -564,9 +563,7 @@ final class AdminApiHandler( service: Option[NonEmptyString] ): RIO[WLD, Vector[SourceDTO]] = { var queryDoc = BsonDocument() - if (service.isDefined) { - queryDoc = BsonDocument("service" -> service.get.bson) - } + service.foreach(svc => queryDoc = BsonDocument("service" -> svc.bson)) sourceDAO .findChunkProjection[SourceDTO](queryDoc, 0, Int.MaxValue, BsonDocument("created" -> -1) :: Nil) } @@ -673,7 +670,7 @@ final class AdminApiHandler( ) _ <- sourceDAO.deleteById(name) // TODO: delete in transaction _ <- ZIO - .foreachDiscard(source.get.shutdown.map(_.toVector).getOrElse(Vector.empty))(rm.execute) + .foreachDiscard(source.fold(Vector.empty)(_.shutdown.map(_.toVector).getOrElse(Vector.empty)))(rm.execute) .catchSomeDefect { case NonFatal(ex) => ZIO.fail(ex) } @@ -687,9 +684,7 @@ final class AdminApiHandler( service: Option[NonEmptyString] ): RIO[WLD, Vector[DestinationDTO]] = { var queryDoc = BsonDocument() - if (service.isDefined) { - queryDoc = BsonDocument("service" -> service.get.bson) - } + service.foreach(svc => queryDoc = BsonDocument("service" -> svc.bson)) destinationDAO.findChunkProjection[DestinationDTO]( queryDoc, 0, diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/PublicApiHandler.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/PublicApiHandler.scala index 740cc15f..f42fd17e 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/PublicApiHandler.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/PublicApiHandler.scala @@ -138,12 +138,12 @@ final class PublicApiHandler( ) ) } - _ <- ZIO.when(stub.scope == Scope.Countdown)( + _ <- ZIO.when(stub.scope === Scope.Countdown)( stubDAO.updateById(stub.id, Document("$inc" -> Document("times" -> -1.bson))) ) - _ <- ZIO.when(stub.callback.isDefined)( + _ <- ZIO.foreachDiscard(stub.callback)(cb => engine - .recurseCallback(state, stub.callback.get, data, xdata) + .recurseCallback(state, cb, data, xdata) .catchSomeDefect { case NonFatal(ex) => ZIO.fail(ex) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/StubResolver.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/StubResolver.scala index f68788d9..ff65ea87 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/StubResolver.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/api/StubResolver.scala @@ -26,6 +26,7 @@ import ru.tinkoff.tcb.utils.id.SID import ru.tinkoff.tcb.utils.regex.* import ru.tinkoff.tcb.utils.sandboxing.GraalJsSandbox +@SuppressWarnings(Array("org.wartremover.warts.Equals")) final class StubResolver( stubDAO: HttpStubDAO[Task], stateDAO: PersistentStateDAO[Task], diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/dal/LabelDAO.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/dal/LabelDAO.scala index 84345565..7fc3e89f 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/dal/LabelDAO.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/dal/LabelDAO.scala @@ -24,6 +24,7 @@ trait LabelDAO[F[_]] extends MongoDAO[F, Label] { object LabelDAO +@SuppressWarnings(Array("org.wartremover.warts.Equals")) class LabelDAOImpl(collection: MongoCollection[BsonDocument]) extends DAOBase[Label](collection) with LabelDAO[Task] { def createIndexes: Task[Unit] = createIndex( diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcExractor.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcExractor.scala index 5b213217..b14a9aed 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcExractor.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcExractor.scala @@ -183,10 +183,12 @@ object GrpcExractor { ) } + @SuppressWarnings(Array("org.wartremover.warts.Equals")) private def isProto3OptionalField(field: DescriptorProtos.FieldDescriptorProto, oneOfFields: Set[String]): Boolean = GrpcLabel.withValue(field.getLabel.toString.split("_").last.toLowerCase) == GrpcLabel.Optional && oneOfFields(s"_${field.getName}") + @SuppressWarnings(Array("org.wartremover.warts.Equals")) private def getGrpcField( field: DescriptorProtos.FieldDescriptorProto, label: GrpcLabel, @@ -203,8 +205,9 @@ object GrpcExractor { ) } + @SuppressWarnings(Array("org.wartremover.warts.Equals")) private def getGrpcType(field: DescriptorProtos.FieldDescriptorProto): GrpcType = - if (!primitiveTypes.isDefinedAt(field.getType.name()) || field.getTypeName != "") GrpcType.Custom + if (!primitiveTypes.isDefinedAt(field.getType.name()) || field.getTypeName.nonEmpty) GrpcType.Custom else GrpcType.Primitive private def getFieldType(field: DescriptorProtos.FieldDescriptorProto, custom: Boolean): String = diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcRequestHandler.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcRequestHandler.scala index eafa896a..4c6b8dc4 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcRequestHandler.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcRequestHandler.scala @@ -43,6 +43,7 @@ trait GrpcRequestHandler { def exec(stream: Stream[StatusException, Array[Byte]]): ZStream[WLD & RequestContext, Throwable, Array[Byte]] } +@SuppressWarnings(Array("org.wartremover.warts.Equals")) class GrpcRequestHandlerImpl( stateDAO: PersistentStateDAO[Task], stubDAO: GrpcStubDAO[Task], @@ -116,7 +117,7 @@ class GrpcRequestHandlerImpl( .map(_.keys.map(_.path).filter(_.startsWith("_")).toVector) .filter(_.nonEmpty) .cata(_.traverse(stateDAO.createIndexForDataField), ZIO.unit) - _ <- ZIO.when(stub.scope == Scope.Countdown)( + _ <- ZIO.when(stub.scope === Scope.Countdown)( stubDAO.updateById(stub.id, Document("$inc" -> Document("times" -> -1.bson))) ) } yield (stub, data, bytes) @@ -130,7 +131,7 @@ class GrpcRequestHandlerImpl( ): Stream[Throwable, Array[Byte]] = stubResponse match { case FillResponse(rdata, delay) => ZStream.fromZIO { - ZIO.when(delay.isDefined)(ZIO.sleep(Duration.fromScala(delay.get))) *> + ZIO.foreachDiscard(delay)(d => ZIO.sleep(Duration.fromScala(d))) *> ZIO .attemptBlocking( methodDescription.responseSchema @@ -140,7 +141,7 @@ class GrpcRequestHandlerImpl( case FillStreamResponse(rdataArr, delay, streamDelay) => ZStream .fromIterableZIO { - ZIO.when(delay.isDefined)(ZIO.sleep(Duration.fromScala(delay.get))) *> + ZIO.foreachDiscard(delay)(d => ZIO.sleep(Duration.fromScala(d))) *> ZIO.foreach(rdataArr) { rdata => ZIO.attemptBlocking( methodDescription.responseSchema @@ -148,13 +149,13 @@ class GrpcRequestHandlerImpl( ) } } - .tap(_ => ZIO.when(streamDelay.isDefined)(ZIO.sleep(Duration.fromScala(streamDelay.get)))) + .tap(_ => ZIO.foreachDiscard(streamDelay)(d => ZIO.sleep(Duration.fromScala(d)))) case NoBodyResponse(delay) => - ZStream.fromZIO(ZIO.when(delay.isDefined)(ZIO.sleep(Duration.fromScala(delay.get)))).drain + ZStream.fromZIO(ZIO.foreachDiscard(delay)(d => ZIO.sleep(Duration.fromScala(d)))).drain case RepeatResponse(rdata, repeats, delay, streamDelay) => ZStream .unwrap { - ZIO.when(delay.isDefined)(ZIO.sleep(Duration.fromScala(delay.get))) *> + ZIO.foreachDiscard(delay)(d => ZIO.sleep(Duration.fromScala(d))) *> ZIO .attemptBlocking( methodDescription.responseSchema @@ -162,7 +163,7 @@ class GrpcRequestHandlerImpl( ) .map(bytes => ZStream.repeatWithSchedule(bytes, Schedule.recurs(repeats.value - 1))) } - .tap(_ => ZIO.when(streamDelay.isDefined)(ZIO.sleep(Duration.fromScala(streamDelay.get)))) + .tap(_ => ZIO.foreachDiscard(streamDelay)(d => ZIO.sleep(Duration.fromScala(d)))) case _: GProxyResponse => ZStream.fail(ValidationError(Vector("Found proxy-stub during processing fill-stubs"))) } @@ -174,7 +175,7 @@ class GrpcRequestHandlerImpl( ZIO .foreach(methodDescription.proxyUrl) { proxyUrl => val bytesStream = stream.mapZIO { case (proxyStub, _, bytes) => - ZIO.when(proxyStub.delay.isDefined)(ZIO.sleep(Duration.fromScala(proxyStub.delay.get))).as(bytes) + ZIO.foreachDiscard(proxyStub.delay)(d => ZIO.sleep(Duration.fromScala(d))).as(bytes) } val binaryResp = methodDescription.connectionType match { diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcStubResolver.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcStubResolver.scala index d87680a2..f6fa9c7f 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcStubResolver.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/GrpcStubResolver.scala @@ -31,6 +31,7 @@ trait GrpcStubResolver { )(scope: Scope): RIO[WLD, Option[(GrpcStub, Json, Option[PersistentState])]] } +@SuppressWarnings(Array("org.wartremover.warts.Equals")) class GrpcStubResolverImpl( stubDAO: GrpcStubDAO[Task], stateDAO: PersistentStateDAO[Task], @@ -95,7 +96,7 @@ class GrpcStubResolverImpl( ) res = candidates.find(_._2.size == 1) orElse candidates.find(_._1.state.isEmpty) } yield res.map { case (stub, states) => - (stub, pairs.find(_._2.id == stub.id).map(_._1).get, states.headOption) + (stub, pairs.find(_._2.id == stub.id).map(_._1).getOrElse(Json.Null), states.headOption) } private def parseJson(methodDescription: GrpcMethodDescription, bytes: Array[Byte]): URIO[WLD, Option[Json]] = diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/ProtobufSchemaResolver.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/ProtobufSchemaResolver.scala index ac3c028b..26bfcb8d 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/ProtobufSchemaResolver.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/grpc/ProtobufSchemaResolver.scala @@ -25,7 +25,7 @@ class ProtobufSchemaResolverImpl extends ProtobufSchemaResolver { private val log = MDCLogging.`for`[Tracing](this) - def parseDefinitionFrom(bytes: Array[Byte]): ZIO[Tracing, IOException, GrpcProtoDefinition] = { + override def parseDefinitionFrom(bytes: Array[Byte]): ZIO[Tracing, IOException, GrpcProtoDefinition] = { val managed = ZManaged.acquireReleaseWith(ZIO.attemptBlockingIO(Files.createTempDirectory("temp"))) { path => log.info("Deleting files in path", path.toString) *> ZIO.attemptBlockingIO { diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Extractor.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Extractor.scala index e60f4add..ab7b001d 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Extractor.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Extractor.scala @@ -48,7 +48,7 @@ object XmlExtractor { * Path inside CDATA */ final case class JsonCDataExtractor(prefix: SXpath, path: JsonOptic) extends XmlExtractor { - def apply(node: NodeSeq): Option[Json] = + override def apply(node: NodeSeq): Option[Json] = prefix.toZoom .bind(node) .run[Option] diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcMethodDescription.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcMethodDescription.scala index 31f34ac1..f212fd7f 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcMethodDescription.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcMethodDescription.scala @@ -80,7 +80,7 @@ object GrpcMethodDescription { extension (pp: PackagePrefix.Type) { def :+(nested: String): PackagePrefix.Type = - PackagePrefix(pp.unwrap ++ nested.dropWhile(_ == '.') ++ ".") + PackagePrefix(pp.unwrap ++ nested.dropWhile(_ === '.') ++ ".") def resolve(n: String): NormalizedTypeName.Type = if (n.startsWith(".")) NormalizedTypeName.fromString(n) @@ -90,7 +90,7 @@ object GrpcMethodDescription { object NormalizedTypeName extends Newtype[String] { def fromString(name: String): NormalizedTypeName.Type = - this.unsafeMake(s".${name.dropWhile(_ == '.')}") + this.unsafeMake(s".${name.dropWhile(_ === '.')}") } def makeDictTypes(p: PackagePrefix.Type, ms: Seq[GrpcRootMessage]): Vector[(NormalizedTypeName.Type, GrpcRootMessage)] = @@ -103,6 +103,7 @@ object GrpcMethodDescription { b :+ (p.resolve(name) -> m) } + @SuppressWarnings(Array("org.wartremover.warts.Equals")) def validate(methodDescription: GrpcMethodDescription)( requestClass: String, requestSchema: GrpcProtoDefinition, diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcStub.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcStub.scala index 9b2bd07e..3627a703 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcStub.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/GrpcStub.scala @@ -64,9 +64,11 @@ object GrpcStub { case Right(fieldName) => for { fs <- fields.get - field <- ZIO.getOrFailWith(ValidationError(Vector(s"Field $fieldName not found")))(fs.find(_.name == fieldName)) + field <- ZIO.getOrFailWith(ValidationError(Vector(s"Field $fieldName not found")))( + fs.find(_.name === fieldName) + ) _ <- - if (primitiveTypes.values.exists(_ == field.typeName)) fields.set(List.empty) + if (primitiveTypes.values.exists(_ === field.typeName)) fields.set(List.empty) else types.get(NormalizedTypeName.fromString(field.typeName)) match { case Some(message) => @@ -89,5 +91,5 @@ object GrpcStub { private val stateNonEmpty: Rule[GrpcStub] = _.state.exists(_.isEmpty).valueOrZero(Vector("The state predicate cannot be empty")) - val validationRules: Rule[GrpcStub] = Vector(stateNonEmpty).reduce(_ |+| _) + val validationRules: Rule[GrpcStub] = stateNonEmpty } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStub.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStub.scala index 2d12bdb1..1d61967a 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStub.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStub.scala @@ -5,6 +5,7 @@ import scala.util.matching.Regex import com.github.dwickern.macros.NameOf.* import eu.timepit.refined.* +import eu.timepit.refined.cats.* import io.circe.Decoder import io.circe.Encoder import io.circe.Json @@ -92,7 +93,8 @@ object HttpStub extends CallbackChecker { private val responseCodes204and304: Rule[HttpStub] = stub => stub.response match { case StubCode(rc) - if rc == refineV[HttpStatusCodeRange].unsafeFrom(204) || rc == refineV[HttpStatusCodeRange].unsafeFrom(304) => + if rc === refineV[HttpStatusCodeRange] + .unsafeFrom(204) || rc === refineV[HttpStatusCodeRange].unsafeFrom(304) => stub.response match { case EmptyResponse(_, _, _) => Vector.empty case _ => @@ -102,12 +104,10 @@ object HttpStub extends CallbackChecker { } def validationRules(destinations: Set[SID[DestinationConfiguration]]): Rule[HttpStub] = - Vector( - pathOrPattern, - (h: HttpStub) => checkCallback(h.callback, destinations), - stateNonEmpty, - persistNonEmpty, - jsonProxyReq, + pathOrPattern |+| + ((h: HttpStub) => checkCallback(h.callback, destinations)) |+| + stateNonEmpty |+| + persistNonEmpty |+| + jsonProxyReq |+| responseCodes204and304 - ).reduce(_ |+| _) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubRequest.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubRequest.scala index e326f7ff..1457d93d 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubRequest.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubRequest.scala @@ -42,7 +42,7 @@ sealed trait HttpStubRequest derives BsonDecoder, BsonEncoder { def checkHeaders(hs: Map[String, String]): Boolean = headers.forall { case (k, v) => hs.exists { case (kx, vx) => - k.toLowerCase == kx.toLowerCase && v == vx + k.toLowerCase === kx.toLowerCase && v === vx } } @@ -235,7 +235,7 @@ sealed trait RequestPart derives BsonDecoder, BsonEncoder { def checkHeaders(hs: Map[String, String]): Boolean = headers.forall { case (k, v) => hs.exists { case (kx, vx) => - k.toLowerCase == kx.toLowerCase && v == vx + k.toLowerCase === kx.toLowerCase && v === vx } } @@ -281,7 +281,7 @@ final case class AnyContentPart(headers: Map[String, String]) extends RequestPar } final case class RawPart(headers: Map[String, String], body: String) extends RequestPart { - override def checkBody(value: String): Boolean = value == body + override def checkBody(value: String): Boolean = value === body override def extractJson(body: String): Option[Json] = None @@ -305,6 +305,7 @@ final case class JsonPart(headers: Map[String, String], body: Json) extends Requ } final case class XMLPart(headers: Map[String, String], body: XMLString.Type) extends RequestPart { + @SuppressWarnings(Array("org.wartremover.warts.Equals")) override def checkBody(value: String): Boolean = Try(SafeXML.loadString(value)).exists(_ == body.unwrap) override def extractJson(body: String): Option[Json] = None diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubResponse.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubResponse.scala index dacf4eac..59caa031 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubResponse.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/HttpStubResponse.scala @@ -64,13 +64,11 @@ object HttpStubResponse { given Schema[HttpStubResponse] = Schema.derived val headers: Property[HttpStubResponse, Map[String, String]] = - Vector( - EmptyResponse.prism >> EmptyResponse.headers, - RawResponse.prism >> RawResponse.headers, - JsonResponse.prism >> JsonResponse.headers, - XmlResponse.prism >> XmlResponse.headers, - BinaryResponse.prism >> BinaryResponse.headers - ).reduce[Property[HttpStubResponse, Map[String, String]]](_ orElse _) + (EmptyResponse.prism >> EmptyResponse.headers) orElse + (RawResponse.prism >> RawResponse.headers) orElse + (JsonResponse.prism >> JsonResponse.headers) orElse + (XmlResponse.prism >> XmlResponse.headers) orElse + (BinaryResponse.prism >> BinaryResponse.headers) val jsonBody: Property[HttpStubResponse, Json] = JsonResponse.prism >> JsonResponse.body diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ResponseSpec.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ResponseSpec.scala index 28b49e02..27f9c138 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ResponseSpec.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ResponseSpec.scala @@ -51,14 +51,15 @@ object ResponseSpec { } final case class RawResponseSpec(code: Option[Int], body: Option[String]) extends ResponseSpec { - override def checkBody(data: String): Boolean = body.forall(_ == data) + override def checkBody(data: String): Boolean = body.forall(_ === data) } final case class JsonResponseSpec(code: Option[Int], body: Option[Json]) extends ResponseSpec { - override def checkBody(data: String): Boolean = parse(data).map(jx => body.forall(_ == jx)).getOrElse(false) + override def checkBody(data: String): Boolean = parse(data).map(jx => body.forall(_ === jx)).getOrElse(false) } final case class XmlResponseSpec(code: Option[Int], body: Option[XMLString.Type]) extends ResponseSpec { + @SuppressWarnings(Array("org.wartremover.warts.Equals")) override def checkBody(data: String): Boolean = Try(SafeXML.loadString(data)).toOption.exists(nx => body.forall(_.unwrap == nx)) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scenario.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scenario.scala index f3e985de..14fb9a6a 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scenario.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scenario.scala @@ -92,12 +92,10 @@ object Scenario extends CallbackChecker { sources: Set[SID[SourceConfiguration]], destinations: Set[SID[DestinationConfiguration]] ): Rule[Scenario] = - Vector( - destOutp, - (s: Scenario) => checkCallback(s.callback, destinations), - checkSourceId(sources), - checkDestinationId(destinations), - stateNonEmpty, + destOutp |+| + ((s: Scenario) => checkCallback(s.callback, destinations)) |+| + checkSourceId(sources) |+| + checkDestinationId(destinations) |+| + stateNonEmpty |+| persistNonEmpty - ).reduce(_ |+| _) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ScenarioInput.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ScenarioInput.scala index 6bf5ca1b..57586e45 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ScenarioInput.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/ScenarioInput.scala @@ -55,7 +55,7 @@ object ScenarioInput { } final case class RawInput(payload: String) extends ScenarioInput { - override def checkMessage(message: String): Boolean = message == payload + override def checkMessage(message: String): Boolean = message === payload override def extractJson(message: String): Option[Json] = None diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scope.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scope.scala index ca2233b5..137b2695 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scope.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/model/Scope.scala @@ -19,10 +19,12 @@ object Scope extends Enum[Scope] with BsonEnum[Scope] with TapirCodecEnumeratum val values = findValues + implicit val scopeEq: cats.Eq[Scope] = cats.Eq.fromUniversalEquals + implicit val scopeLoggable: Loggable[Scope] = Loggable.stringValue.contramap(_.toString) implicit val scopeBsonEncoder: BsonEncoder[Scope] = BsonEncoder[Int].beforeWrite(_.priority) implicit val scopeBsonDecoder: BsonDecoder[Scope] = - BsonDecoder[Int].afterReadTry(p => values.find(_.priority == p).toTry(new Exception(s"No Scope with priority $p"))) + BsonDecoder[Int].afterReadTry(p => values.find(_.priority === p).toTry(new Exception(s"No Scope with priority $p"))) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/resource/ResourceManager.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/resource/ResourceManager.scala index 5e2ef3a3..be872d70 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/resource/ResourceManager.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/resource/ResourceManager.scala @@ -39,8 +39,9 @@ final class ResourceManager( ZIO.foreachDiscard(errs)(recover) case CompoundError(errs) => val recoverable = errs.filter(recover.isDefinedAt) - val fatal = errs.find(!recover.isDefinedAt(_)) - ZIO.foreachDiscard(recoverable)(recover) *> log.errorCause("Fatal error", fatal.get) *> ZIO.die(fatal.get) + val fatalOpt = errs.find(!recover.isDefinedAt(_)) + ZIO.foreachDiscard(recoverable)(recover) *> + fatalOpt.fold[URIO[WLD, Unit]](ZIO.unit)(f => log.errorCause("Fatal error", f) *> ZIO.die(f)) case thr if recover.isDefinedAt(thr) => recover(thr) case thr => @@ -60,8 +61,9 @@ final class ResourceManager( ZIO.foreachDiscard(errs)(recover) case CompoundError(errs) => val recoverable = errs.filter(recover.isDefinedAt) - val fatal = errs.find(!recover.isDefinedAt(_)) - ZIO.foreachDiscard(recoverable)(recover) *> log.errorCause("Fatal error", fatal.get) *> ZIO.die(fatal.get) + val fatalOpt = errs.find(!recover.isDefinedAt(_)) + ZIO.foreachDiscard(recoverable)(recover) *> + fatalOpt.fold[URIO[WLD, Unit]](ZIO.unit)(f => log.errorCause("Fatal error", f) *> ZIO.die(f)) case thr if recover.isDefinedAt(thr) => recover(thr) case thr => @@ -94,8 +96,9 @@ final class ResourceManager( ZIO.foreachDiscard(errs)(recover) case CompoundError(errs) => val recoverable = errs.filter(recover.isDefinedAt) - val fatal = errs.find(!recover.isDefinedAt(_)) - ZIO.foreachDiscard(recoverable)(recover) *> log.errorCause("Fatal error", fatal.get) *> ZIO.die(fatal.get) + val fatalOpt = errs.find(!recover.isDefinedAt(_)) + ZIO.foreachDiscard(recoverable)(recover) *> + fatalOpt.fold[URIO[WLD, Unit]](ZIO.unit)(f => log.errorCause("Fatal error", f) *> ZIO.die(f)) case thr if recover.isDefinedAt(thr) => recover(thr) case thr => diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioEngine.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioEngine.scala index 2ecbfcdc..a133d5cd 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioEngine.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioEngine.scala @@ -97,22 +97,23 @@ final class ScenarioEngine( .filter(_.nonEmpty) .fold(ZIO.attempt(()))(_.traverse_(stateDAO.createIndexForDataField)) dests <- fetcher.getDestinations - _ <- ZIO.when(scenario.destination.isDefined && !dests.exists(_.name == scenario.destination.get))( - ZIO.fail(ScenarioExecError(s"Destination with the name ${scenario.destination.get} is not configured")) - ) - destOut = scenario.destination.flatMap(dn => dests.find(_.name == dn)) zip scenario.output - _ <- ZIO.when(destOut.isDefined) { - val (dest, out) = destOut.get + _ <- ZIO.foreachDiscard(scenario.destination) { destName => + ZIO.when(!dests.exists(_.name === destName))( + ZIO.fail(ScenarioExecError(s"Destination with the name $destName is not configured")) + ) + } + destOut = scenario.destination.flatMap(dn => dests.find(_.name === dn)) zip scenario.output + _ <- ZIO.foreachDiscard(destOut) { case (dest, out) => sendTo(dest, out, data, xdata) } - _ <- ZIO.when(scenario.scope == Scope.Countdown)( + _ <- ZIO.when(scenario.scope === Scope.Countdown)( scenarioDAO.updateById(scenario.id, Document("$inc" -> Document("times" -> -1.bson))) ) - _ <- ZIO.when(scenario.callback.isDefined)(recurseCallback(state, scenario.callback.get, data, xdata)) + _ <- ZIO.foreachDiscard(scenario.callback)(recurseCallback(state, _, data, xdata)) } yield () } - def recurseCallback( + override def recurseCallback( state: PersistentState, callback: Callback, data: Json, @@ -121,19 +122,18 @@ final class ScenarioEngine( callback match { case MessageCallback(destinationId, output, callback, delay) => for { - _ <- ZIO.when(delay.isDefined)(ZIO.sleep(Duration.fromScala(delay.get))) + _ <- ZIO.foreachDiscard(delay)(d => ZIO.sleep(Duration.fromScala(d))) _ <- log.info("Executing MessageCallback with destinationId={}", destinationId) dests <- fetcher.getDestinations - _ <- ZIO.when(!dests.exists(_.name == destinationId))( - ZIO.fail(CallbackError(s"Destination with the name $destinationId is not configured")) + destination <- ZIO.getOrFailWith(CallbackError(s"Destination with the name $destinationId is not configured"))( + dests.find(_.name === destinationId) ) - destination = dests.find(_.name == destinationId).get _ <- sendTo(destination, output, data, xdata) - _ <- ZIO.when(callback.isDefined)(recurseCallback(state, callback.get, data, xdata)) + _ <- ZIO.foreachDiscard(callback)(recurseCallback(state, _, data, xdata)) } yield () case HttpCallback(request, responseMode, persist, callback, delay) => for { - _ <- ZIO.when(delay.isDefined)(ZIO.sleep(Duration.fromScala(delay.get))) + _ <- ZIO.foreachDiscard(delay)(d => ZIO.sleep(Duration.fromScala(d))) requestUrl = request.url.value.substitute(data, xdata) _ <- log.info("Executing HttpCallback to {}", requestUrl) res <- @@ -165,15 +165,13 @@ final class ScenarioEngine( .flatten data1 = jsonBody.cata(j => data.mapObject(("req" -> j) +: _), data) xdata1 = xmlBody.getOrElse(xdata) - _ <- ZIO.when(persist.isDefined) { - stateDAO.upsertBySpec(state.id, persist.get.fill(data1).fill(xdata1)) - } - _ <- ZIO.when(callback.isDefined)(recurseCallback(state, callback.get, data1, xdata1)) + _ <- ZIO.foreachDiscard(persist)(p => stateDAO.upsertBySpec(state.id, p.fill(data1).fill(xdata1))) + _ <- ZIO.foreachDiscard(callback)(recurseCallback(state, _, data1, xdata1)) } yield () } private def sendTo(dest: DestinationConfiguration, out: ScenarioOutput, data: Json, xdata: Node): RIO[WLD, Unit] = - ZIO.when(out.delay.isDefined)(ZIO.sleep(Duration.fromScala(out.delay.get))) *> basicRequest + ZIO.foreachDiscard(out.delay)(d => ZIO.sleep(Duration.fromScala(d))) *> basicRequest .pipe(rt => dest.request.body.fold { rt.body( diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioResolver.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioResolver.scala index db84e020..60bff06b 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioResolver.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/scenario/ScenarioResolver.scala @@ -25,6 +25,7 @@ import ru.tinkoff.tcb.utils.circe.optics.JsonOptic import ru.tinkoff.tcb.utils.id.SID import ru.tinkoff.tcb.utils.sandboxing.GraalJsSandbox +@SuppressWarnings(Array("org.wartremover.warts.Equals")) class ScenarioResolver( scenarioDAO: ScenarioDAO[Task], stateDAO: PersistentStateDAO[Task], @@ -82,7 +83,7 @@ class ScenarioResolver( log.error("More than one stateless scenario found") *> ZIO.fail(ScenarioSearchError("More than one stateless scenario found")) ) - res = scenarios2.find(_._2.size == 1) orElse scenarios2.find(_._1.state.isEmpty) + res = scenarios2.find(_._2.size === 1) orElse scenarios2.find(_._1.state.isEmpty) } yield res.map { case (scenario, states) => scenario -> states.headOption }).catchSome { case EarlyReturn => ZIO.none } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EphemeralCleaner.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EphemeralCleaner.scala index df06ed25..0ab6931f 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EphemeralCleaner.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EphemeralCleaner.scala @@ -17,6 +17,7 @@ import ru.tinkoff.tcb.mockingbird.model.HttpStub import ru.tinkoff.tcb.mockingbird.model.Scenario import ru.tinkoff.tcb.mockingbird.model.Scope +@SuppressWarnings(Array("org.wartremover.warts.Equals")) final class EphemeralCleaner( stubDAO: HttpStubDAO[Task], scenarioDAO: ScenarioDAO[Task], diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EventSpawner.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EventSpawner.scala index a84b133c..44d0949a 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EventSpawner.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/mockingbird/stream/EventSpawner.scala @@ -82,7 +82,7 @@ final class EventSpawner( for { response <- request.send(httpBackend) - reInit = triggers.exists(sp => sp.code.forall(_ == response.code.code) && sp.checkBody(response.body.merge)) + reInit = triggers.exists(sp => sp.code.forall(_ === response.code.code) && sp.checkBody(response.body.merge)) body <- ZIO .fromEither(response.body) .mapError[Exception](err => @@ -130,9 +130,12 @@ final class EventSpawner( Stream.eval(recover(thr)) ++ Stream.sleep[[X] =>> RIO[WLD, X]](eventConfig.fetchInterval) ++ fetchStream case CompoundError(errs) => val recoverable = errs.filter(recover.isDefinedAt) - val fatal = errs.find(!recover.isDefinedAt(_)) + val fatalOpt = errs.find(!recover.isDefinedAt(_)) - Stream.evalSeq(ZIO.foreach(recoverable)(recover)) ++ Stream.raiseError[[X] =>> RIO[WLD, X]](fatal.get).as(()) + Stream.evalSeq(ZIO.foreach(recoverable)(recover)) ++ + fatalOpt.fold[Stream[[X] =>> RIO[WLD, X], Unit]](Stream.empty)(f => + Stream.raiseError[[X] =>> RIO[WLD, X]](f).as(()) + ) case thr => Stream.raiseError[[X] =>> RIO[WLD, X]](thr).as(()) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/form/FormPredicate.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/form/FormPredicate.scala index 1890be8d..f640d023 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/form/FormPredicate.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/form/FormPredicate.scala @@ -25,6 +25,7 @@ abstract class FormPredicate extends (Map[String, List[String]] => Boolean) { override def hashCode(): Int = definition.hashCode() + @SuppressWarnings(Array("org.wartremover.warts.Equals")) override def equals(obj: Any): Boolean = obj match { case sp: FormPredicate => sp.definition == definition case _ => false diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/json/JsonPredicate.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/json/JsonPredicate.scala index bba48138..a76b1060 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/json/JsonPredicate.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/json/JsonPredicate.scala @@ -31,6 +31,7 @@ abstract class JsonPredicate extends (Json => Boolean) { override def hashCode(): Int = definition.hashCode() + @SuppressWarnings(Array("org.wartremover.warts.Equals")) override def equals(obj: Any): Boolean = obj match { case jp: JsonPredicate => jp.definition == definition case _ => false @@ -85,8 +86,8 @@ object JsonPredicate { private val mkPredicate: (Keyword.Json, Json) => ValidatedNel[(Keyword, Json), Json => Boolean] = (kwd, jv) => (kwd, jv) match { - case (Equals, value) => Validated.valid(_ == value) - case (NotEq, value) => Validated.valid(_ != value) + case (Equals, value) => Validated.valid(j => j === value) + case (NotEq, value) => Validated.valid(j => j =!= value) case (Greater, JsonNumber(jnum)) => Validated.valid(_.asNumber.exists(_ > jnum)) case (Gte, JsonNumber(jnum)) => Validated.valid(_.asNumber.exists(_ >= jnum)) case (Less, JsonNumber(jnum)) => Validated.valid(_.asNumber.exists(_ < jnum)) @@ -94,8 +95,8 @@ object JsonPredicate { case (Rx, JsonString(str)) => Validated.valid(_.asString.exists(_.matches(str))) case (Size, JsonNumber(jnum)) if jnum.toInt.isDefined => Validated.valid { - case JsonString(str) => str.length == jnum.toInt.get - case JsonVector(vec) => vec.length == jnum.toInt.get + case JsonString(str) => jnum.toInt.exists(str.length === _) + case JsonVector(vec) => jnum.toInt.exists(vec.length === _) case _ => false } case (Exists, JsonBoolean(true)) => Validated.valid(!_.isNull) diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/xml/XmlPredicate.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/xml/XmlPredicate.scala index d246d661..4428c0fa 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/xml/XmlPredicate.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/predicatedsl/xml/XmlPredicate.scala @@ -34,6 +34,7 @@ abstract class XmlPredicate extends (NodeSeq => Boolean) { override def hashCode(): Int = definition.hashCode() + @SuppressWarnings(Array("org.wartremover.warts.Equals")) override def equals(obj: Any): Boolean = obj match { case xp: XmlPredicate => xp.definition == definition case _ => false @@ -94,11 +95,11 @@ object XmlPredicate { (kwd, jv) => (kwd, jv) match { case (Equals, JsonString(str)) => - Validated.valid(_.exists(_.text == str)) + Validated.valid(_.exists(_.text === str)) case (Equals, JsonNumber(jnum)) => Validated.valid(_.exists(n => jnum.toBigDecimal.contains(BigDecimal(n.text)))) case (NotEq, JsonString(str)) => - Validated.valid(_.exists(_.text != str)) + Validated.valid(_.exists(n => n.text =!= str)) case (NotEq, JsonNumber(jnum)) => Validated.valid(_.exists(n => !jnum.toBigDecimal.contains(BigDecimal(n.text)))) case (Greater, JsonNumber(jnum)) => @@ -112,11 +113,11 @@ object XmlPredicate { case (Rx, JsonString(str)) => Validated.valid(_.exists(_.text.matches(str))) case (Size, JsonNumber(jnum)) if jnum.toInt.isDefined => - Validated.valid(_.exists(_.text.length == jnum.toInt.get)) + Validated.valid(_.exists(n => jnum.toInt.exists(n.text.length === _))) case (Exists, JsonBoolean(true)) => Validated.valid(_.isDefined) case (Exists, JsonBoolean(false)) => Validated.valid(_.isEmpty) case (Cdata, JsonDocument(JObject("==" -> JsonString(value)))) => - Validated.valid(_.exists(_.text == value)) + Validated.valid(_.exists(_.text === value)) case (Cdata, JsonDocument(JObject("~=" -> JsonString(value)))) => Validated.valid(_.exists(_.text.matches(value))) case (JCdata, spec) => diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/id/IDCompanion.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/id/IDCompanion.scala index 42df33e3..1df401db 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/id/IDCompanion.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/id/IDCompanion.scala @@ -1,5 +1,6 @@ package ru.tinkoff.tcb.utils.id +import cats.Eq import com.softwaremill.tagging.* import glass.Equivalent import io.circe.* @@ -40,4 +41,6 @@ trait IDCompanion[I] { implicit def idLoggable[T](implicit il: Loggable[I]): Loggable[I @@ T] = il.narrow implicit def idConfigReader[T](implicit cr: ConfigReader[I]): ConfigReader[I @@ T] = cr.map(apply) + + implicit def eqForID[T](implicit ei: Eq[I]): Eq[I @@ T] = (a, b) => ei.eqv(a, b) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/sandboxing/conversion/package.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/sandboxing/conversion/package.scala index 26b4444a..f08fa589 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/sandboxing/conversion/package.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/sandboxing/conversion/package.scala @@ -17,6 +17,7 @@ import org.graalvm.polyglot.proxy.* package object conversion { object GValue extends Newtype[AnyRef] + @SuppressWarnings(Array("org.wartremover.warts.Null")) val circe2js: Json.Folder[GValue.Type] = new Json.Folder[GValue.Type] { override def onNull: GValue.Type = GValue(null) @@ -34,6 +35,7 @@ package object conversion { }) override def onObject(value: JsonObject): GValue.Type = GValue(new ProxyObject { + @SuppressWarnings(Array("org.wartremover.warts.Null")) override def getMember(key: String): AnyRef = value.apply(key).map(_.foldWith(circe2js).unwrap).orNull override def getMemberKeys: AnyRef = new ProxyArray { private val keys = value.keys.toVector @@ -41,7 +43,7 @@ package object conversion { override def set(index: Long, value: Value): Unit = throw new UnsupportedOperationException() override def getSize: Long = keys.size } - override def hasMember(key: String): Boolean = value.keys.exists(_ == key) + override def hasMember(key: String): Boolean = value.keys.exists(_ === key) override def putMember(key: String, value: Value): Unit = throw new UnsupportedOperationException() }) } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/json/package.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/json/package.scala index 80151481..0b2a8211 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/json/package.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/json/package.scala @@ -23,6 +23,7 @@ package object json { private object JORxs extends OneOrMore(JORx) + @SuppressWarnings(Array("org.wartremover.warts.Null")) private object JOptic { def unapply(defn: String): Option[(Option[String], JsonOptic)] = defn match { @@ -121,8 +122,9 @@ package object json { } private val castToString: PartialFunction[Json, Json] = { - case JsonBoolean(b) => Json.fromString(b.toString) - case JsonNumber(n) if n.toBigDecimal.isDefined => Json.fromString(n.toBigDecimal.get.bigDecimal.toPlainString) + case JsonBoolean(b) => Json.fromString(b.toString) + case JsonNumber(n) if n.toBigDecimal.isDefined => + Json.fromString(n.toBigDecimal.map(_.bigDecimal.toPlainString).getOrElse("")) } private object JNum { diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/xml/package.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/xml/package.scala index b1d6f54b..370085ae 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/xml/package.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/transformation/xml/package.scala @@ -121,16 +121,16 @@ package object xml { case jp if jt.isDefinedAt(jp) => (zoom ==> Replace(_.map(_.transform { case Text(_) => Text(jt(jp).foldWith(json2StringFolder)) }.result))) .transform[Try](acc) - .map(_.head) + .map(_.headOption.getOrElse(acc)) .getOrElse(acc) case xp if nt.isDefinedAt(xp) => (zoom ==> Replace(_.map(_.transform { case Text(_) => Text(nt(xp)) }.result))) .transform[Try](acc) - .map(_.head) + .map(_.headOption.getOrElse(acc)) .getOrElse(acc) case _ => acc } } - .pipe(_.child.head) + .pipe(_.child.headOption.getOrElse(n)) } } diff --git a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/xml/SafeXML.scala b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/xml/SafeXML.scala index 1e8f5494..7effb9fe 100644 --- a/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/xml/SafeXML.scala +++ b/backend/mockingbird/src/main/scala/ru/tinkoff/tcb/utils/xml/SafeXML.scala @@ -53,7 +53,7 @@ object SafeXML extends XMLLoader[Elem] { newAdapter.scopeStack = TopScope :: newAdapter.scopeStack parser.parse(source, newAdapter) - newAdapter.scopeStack = newAdapter.scopeStack.tail + newAdapter.scopeStack = newAdapter.scopeStack.drop(1) newAdapter.rootElem.asInstanceOf[Elem] } diff --git a/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/MappersSpec.scala b/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/MappersSpec.scala index b44b05f4..c6e0b536 100644 --- a/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/MappersSpec.scala +++ b/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/MappersSpec.scala @@ -2,6 +2,7 @@ package ru.tinkoff.tcb.protobuf import com.github.os72.protobuf.dynamic.DynamicSchema import zio.test.* +import zio.test.Assertion.* import ru.tinkoff.tcb.mockingbird.grpc.GrpcExractor.toDynamicSchema import ru.tinkoff.tcb.mockingbird.grpc.GrpcExractor.toGrpcProtoDefinition @@ -43,7 +44,7 @@ object MappersSpec extends ZIOSpecDefault { content <- Utils.getProtoDescriptionFromResource("requests.proto") schema = DynamicSchema.parseFrom(content) protoDefinition = schema.toGrpcProtoDefinition - } yield assertTrue(getAllTypes(protoDefinition) == allTypesInRequests) + } yield assert(getAllTypes(protoDefinition))(equalTo(allTypesInRequests)) }, test("Mappers from DynamicSchema to GrpcProtoDefinition and back are consistent") { for { @@ -51,7 +52,7 @@ object MappersSpec extends ZIOSpecDefault { schema = DynamicSchema.parseFrom(content) protoDefinition = schema.toGrpcProtoDefinition protoDefinitionAgain = protoDefinition.toDynamicSchema.toGrpcProtoDefinition - } yield assertTrue(protoDefinition == protoDefinitionAgain) + } yield assert(protoDefinition)(equalTo(protoDefinitionAgain)) }, test("Mappers from nested DynamicSchema to GrpcProtoDefinition and back are consistent") { for { @@ -59,7 +60,7 @@ object MappersSpec extends ZIOSpecDefault { schema = DynamicSchema.parseFrom(content) protoDefinition = schema.toGrpcProtoDefinition protoDefinitionAgain = protoDefinition.toDynamicSchema.toGrpcProtoDefinition - } yield assertTrue(protoDefinition == protoDefinitionAgain) + } yield assert(protoDefinition)(equalTo(protoDefinitionAgain)) } ) diff --git a/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/SerializationOptionalFieldsSpec.scala b/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/SerializationOptionalFieldsSpec.scala index 67f922f8..989ea9f6 100644 --- a/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/SerializationOptionalFieldsSpec.scala +++ b/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/protobuf/SerializationOptionalFieldsSpec.scala @@ -37,7 +37,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2DefaultVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An optional field in proto2 syntax: the field has default value") { for { @@ -47,7 +47,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2DefaultVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An optional field in proto2 syntax: the field has another value") { for { @@ -57,7 +57,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2AnotherVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An required field in proto2 syntax: the field is absent") { for { @@ -72,7 +72,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2DefaultVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An required field in proto2 syntax: the field has another value") { for { @@ -82,7 +82,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2AnotherVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An optional field in proto3 syntax: the field is absent") { for { @@ -91,7 +91,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { expected <- parseJson(s"""{ | "field1": "$field1Val" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An optional field in proto3 syntax: the field has default value") { for { @@ -101,7 +101,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2DefaultVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An optional field in proto3 syntax: the field has another value") { for { @@ -111,7 +111,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2AnotherVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An regular field in proto3 syntax: the field is absent") { for { @@ -121,7 +121,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2DefaultVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An regular field in proto3 syntax: the field has default value") { for { @@ -131,7 +131,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2DefaultVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, test("An regular field in proto3 syntax: the field has another value") { for { @@ -141,7 +141,7 @@ object SerializationOptionalFieldsSpec extends ZIOSpecDefault { | "field1": "$field1Val", | "field2": "$field2AnotherVal" |}""".stripMargin) - } yield assertTrue(obtain == expected) + } yield assert(obtain)(equalTo(expected)) }, ) diff --git a/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/utils/transformation/xml/XmlTransformationSpec.scala b/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/utils/transformation/xml/XmlTransformationSpec.scala index a53e68d9..11cb6956 100644 --- a/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/utils/transformation/xml/XmlTransformationSpec.scala +++ b/backend/mockingbird/src/test/scala/ru/tinkoff/tcb/utils/transformation/xml/XmlTransformationSpec.scala @@ -7,6 +7,7 @@ import advxml.transform.XmlZoom import advxml.xpath.* import io.circe.Json import io.circe.syntax.* +import org.scalatest.OptionValues import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers @@ -15,7 +16,7 @@ import ru.tinkoff.tcb.utils.resource.readStr import ru.tinkoff.tcb.utils.sandboxing.GraalJsSandbox import ru.tinkoff.tcb.utils.xml.SafeXML -class XmlTransformationSpec extends AnyFunSuite with Matchers { +class XmlTransformationSpec extends AnyFunSuite with Matchers with OptionValues { test("Fill template from Node") { val template: Node = ${{/root/tag1}}${{/root/tag2}} @@ -120,8 +121,8 @@ class XmlTransformationSpec extends AnyFunSuite with Matchers { val schema = Map( - XmlZoom.fromXPath("/root/inner").toOption.get -> "${comment}", - XmlZoom.fromXPath("/root/second").toOption.get -> "${/data/value}" + XmlZoom.fromXPath("/root/inner").toOption.value -> "${comment}", + XmlZoom.fromXPath("/root/second").toOption.value -> "${/data/value}" ) val sut = target.patchFromValues(source, xSource, schema).useAsIs diff --git a/backend/project/Dependencies.scala b/backend/project/Dependencies.scala index d13b77b9..7dd044ce 100644 --- a/backend/project/Dependencies.scala +++ b/backend/project/Dependencies.scala @@ -30,7 +30,7 @@ object Dependencies { val zio = Seq( "dev.zio" %% "zio" % Versions.zio, "dev.zio" %% "zio-managed" % Versions.zio, - "dev.zio" %% "zio-interop-cats" % "23.1.0.1", + "dev.zio" %% "zio-interop-cats" % "23.1.0.13", //"dev.zio" %% "zio-interop-twitter" % "21.2.0.2.2", "dev.zio" %% "zio-test" % Versions.zio % Test, "dev.zio" %% "zio-test-sbt" % Versions.zio % Test @@ -74,7 +74,8 @@ object Dependencies { ).map("com.dimafeng" %% _ % "0.44.1" % Test) lazy val refined = Seq( - "eu.timepit" %% "refined" % "0.11.3" + "eu.timepit" %% "refined" % "0.11.3", + "eu.timepit" %% "refined-cats" % "0.11.3" ) lazy val protobuf = Seq( diff --git a/backend/project/Settings.scala b/backend/project/Settings.scala index 716498ee..55a70e38 100644 --- a/backend/project/Settings.scala +++ b/backend/project/Settings.scala @@ -56,12 +56,29 @@ object Settings { wartremoverDependencies ~= (_.filterNot(_.name == "wartremover-contrib")), wartremoverDependencies += "org.wartremover" % "wartremover-contrib_3" % ContribWart.ContribVersion, wartremoverErrors ++= Seq( + Wart.ArrayEquals, + Wart.CaseClassPrivateApply, + Wart.EitherProjectionPartial, + Wart.Enumeration, + Wart.Equals, Wart.ExplicitImplicitTypes, Wart.FinalCaseClass, - //Wart.IterableOps, + Wart.JavaConversions, + Wart.JavaSerializable, + Wart.IterableOps, Wart.LeakingSealed, + Wart.NonUnitStatements, + Wart.Null, + Wart.OptionPartial, + Wart.Product, + Wart.PublicInference, + Wart.Serializable, + Wart.StringPlusAny, + Wart.TripleQuestionMark, + Wart.TryPartial, ContribWart.DiscardedFuture, - //ContribWart.MissingOverride + ContribWart.MissingOverride, + ContribWart.RefinedClasstag, ), dockerize := ciEnabled, testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework"), diff --git a/backend/project/Versions.scala b/backend/project/Versions.scala index a4d58096..a9ba8e31 100644 --- a/backend/project/Versions.scala +++ b/backend/project/Versions.scala @@ -6,6 +6,6 @@ object Versions { val micrometer = "1.8.5" val glass = "0.3.0" val sttp = "4.0.0-M13" - val zio = "2.0.19" + val zio = "2.1.24" val circe = "0.14.10" } diff --git a/backend/utils/src/main/scala/ru/tinkoff/tcb/utils/string/package.scala b/backend/utils/src/main/scala/ru/tinkoff/tcb/utils/string/package.scala index e2a69514..9cc3128b 100644 --- a/backend/utils/src/main/scala/ru/tinkoff/tcb/utils/string/package.scala +++ b/backend/utils/src/main/scala/ru/tinkoff/tcb/utils/string/package.scala @@ -10,8 +10,8 @@ package object string { */ def camel2Underscore: String = text.drop(1).foldLeft(text.headOption.map(ch => s"${ch.toLower}") getOrElse "") { - case (acc, c) if c.isUpper => acc + "_" + c.toLower - case (acc, c) => acc + c + case (acc, c) if c.isUpper => acc + "_" + c.toLower.toString + case (acc, c) => acc + c.toString } /**