Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions core-tests/shared/src/test/scala/zio/ZIOSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,14 @@ object ZIOSpec extends ZIOBaseSpec {
} yield assert(res._1)(equalTo(List(0, 2, 4, 6, 8))) && assert(res._2)(equalTo(List(1, 3, 5, 7, 9)))
}
),
suite("provideCustomLayer")(
testM("provides the part of the environment that is not part of the `ZEnv`") {
val loggingLayer: ZLayer[Any, Nothing, Logging] = Logging.live
val zio: ZIO[ZEnv with Logging, Nothing, Unit] = ZIO.unit
val zio2: ZIO[ZEnv, Nothing, Unit] = zio.provideCustomLayer(loggingLayer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really nice.

assertM(zio2)(anything)
}
),
suite("provideSomeLayer")(
testM("can split environment into two parts") {
val clockLayer: ZLayer[Any, Nothing, Clock] = Clock.live
Expand Down Expand Up @@ -3032,4 +3040,11 @@ object ZIOSpec extends ZIOBaseSpec {
} yield v1 + v2

def AsyncUnit[E] = IO.effectAsync[E, Unit](_(IO.unit))

type Logging = Has[Logging.Service]

object Logging {
trait Service
val live: ZLayer[Any, Nothing, Logging] = ZLayer.succeed(new Logging.Service {})
}
}
17 changes: 17 additions & 0 deletions core/shared/src/main/scala/zio/ZIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,23 @@ sealed trait ZIO[-R, +E, +A] extends Serializable with ZIOPlatformSpecific[R, E,
*/
final def provide(r: R)(implicit ev: NeedsEnv[R]): IO[E, A] = ZIO.provide(r)(self)

/**
* Provides the part of the environment that is not part of the `ZEnv`,
* leaving an effect that only depends on the `ZEnv`.
*
* {{{
* val loggingLayer: ZLayer[Any, Nothing, Logging] = ???
*
* val zio: ZIO[ZEnv with Logging, Nothing, Unit] = ???
*
* val zio2 = zio.provideCustomLayer(loggingLayer)
* }}}
*/
final def provideCustomLayer[E1 >: E, R1 <: Has[_]](
layer: ZLayer[ZEnv, E1, R1]
)(implicit ev: ZEnv with R1 <:< R, tagged: Tagged[R1]): ZIO[ZEnv, E1, A] =
provideSomeLayer[ZEnv](layer)

/**
* Provides a layer to the ZIO effect, which translates it to another level.
*/
Expand Down
17 changes: 17 additions & 0 deletions core/shared/src/main/scala/zio/ZManaged.scala
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,23 @@ final class ZManaged[-R, +E, +A] private (reservation: ZIO[R, E, Reservation[R,
def provide(r: R)(implicit ev: NeedsEnv[R]): Managed[E, A] =
provideSome(_ => r)

/**
* Provides the part of the environment that is not part of the `ZEnv`,
* leaving a managed effect that only depends on the `ZEnv`.
*
* {{{
* val loggingLayer: ZLayer[Any, Nothing, Logging] = ???
*
* val managed: ZManaged[ZEnv with Logging, Nothing, Unit] = ???
*
* val managed2 = managed.provideCustomLayer(loggingLayer)
* }}}
*/
def provideCustomLayer[E1 >: E, R1 <: Has[_]](
layer: ZLayer[ZEnv, E1, R1]
)(implicit ev: ZEnv with R1 <:< R, tagged: Tagged[R1]): ZManaged[ZEnv, E1, A] =
provideSomeLayer[ZEnv](layer)

/**
* Provides a layer to the `ZManaged`, which translates it to another level.
*/
Expand Down
17 changes: 17 additions & 0 deletions streams/shared/src/main/scala/zio/stream/ZStream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,23 @@ class ZStream[-R, +E, +A] private[stream] (private[stream] val structure: ZStrea
final def provide(r: R)(implicit ev: NeedsEnv[R]): Stream[E, A] =
ZStream(self.process.provide(r).map(_.provide(r)))

/**
* Provides the part of the environment that is not part of the `ZEnv`,
* leaving a stream that only depends on the `ZEnv`.
*
* {{{
* val loggingLayer: ZLayer[Any, Nothing, Logging] = ???
*
* val stream: ZStream[ZEnv with Logging, Nothing, Unit] = ???
*
* val stream2 = stream.provideCustomLayer(loggingLayer)
* }}}
*/
def provideCustomLayer[E1 >: E, R1 <: Has[_]](
layer: ZLayer[ZEnv, E1, R1]
)(implicit ev: ZEnv with R1 <:< R, tagged: Tagged[R1]): ZStream[ZEnv, E1, A] =
provideSomeLayer[ZEnv](layer)

/**
* An effectual version of `provide`, useful when the act of provision
* requires an effect.
Expand Down
9 changes: 9 additions & 0 deletions test-tests/shared/src/test/scala/zio/test/SpecSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package zio.test
import zio.test.Assertion.{ equalTo, isFalse, isTrue }
import zio.test.TestAspect.ifEnvSet
import zio.test.TestUtils._
import zio.test.environment.TestEnvironment
import zio.{ Has, Ref, UIO, ZIO, ZLayer, ZManaged }

object SpecSpec extends ZIOBaseSpec {
Expand Down Expand Up @@ -85,6 +86,14 @@ object SpecSpec extends ZIOBaseSpec {
} yield assert(passed)(isFalse)
}
),
suite("provideCustomLayer")(
testM("provides the part of the environment that is not part of the `TestEnvironment`") {
for {
_ <- ZIO.environment[TestEnvironment]
_ <- ZIO.environment[Module]
} yield assertCompletes
}.provideCustomLayer(layer)
),
suite("provideLayer")(
testM("does not have early initialization issues") {
for {
Expand Down
44 changes: 40 additions & 4 deletions test/shared/src/main/scala/zio/test/Spec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

package zio.test

import Spec._

import zio._
import zio.test.Spec._
import zio.test.environment.TestEnvironment

/**
* A `Spec[R, E, T]` is the backbone of _ZIO Test_. Every spec is either a
Expand Down Expand Up @@ -300,6 +300,42 @@ final case class Spec[-R, +E, +T](caseValue: SpecCase[R, E, T, Spec[R, E, T]]) {
final def provide(r: R)(implicit ev: NeedsEnv[R]): Spec[Any, E, T] =
provideM(ZIO.succeedNow(r))

/**
* Provides each test with the part of the environment that is not part of
* the `TestEnvironment`, leaving a spec that only depends on the
* `TestEnvironment`.
*
* {{{
* val loggingLayer: ZLayer[Any, Nothing, Logging] = ???
*
* val spec: ZSpec[TestEnvironment with Logging, Nothing] = ???
*
* val spec2 = spec.provideCustomLayer(loggingLayer)
* }}}
*/
def provideCustomLayer[E1 >: E, R1 <: Has[_]](
layer: ZLayer[TestEnvironment, E1, R1]
)(implicit ev: TestEnvironment with R1 <:< R, tagged: Tagged[R1]): Spec[TestEnvironment, E1, T] =
provideSomeLayer[TestEnvironment](layer)

/**
* Provides all tests with a shared version of the part of the environment
* that is not part of the `TestEnvironment`, leaving a spec that only
* depends on the `TestEnvironment`.
*
* {{{
* val loggingLayer: ZLayer[Any, Nothing, Logging] = ???
*
* val spec: ZSpec[TestEnvironment with Logging, Nothing] = ???
*
* val spec2 = spec.provideCustomLayerShared(loggingLayer)
* }}}
*/
def provideCustomLayerShared[E1 >: E, R1 <: Has[_]](
layer: ZLayer[TestEnvironment, E1, R1]
)(implicit ev: TestEnvironment with R1 <:< R, tagged: Tagged[R1]): Spec[TestEnvironment, E1, T] =
provideSomeLayerShared[TestEnvironment](layer)

/**
* Provides a layer to the spec, translating it up a level.
*/
Expand Down Expand Up @@ -374,9 +410,9 @@ final case class Spec[-R, +E, +T](caseValue: SpecCase[R, E, T, Spec[R, E, T]]) {
* {{{
* val clockLayer: ZLayer[Any, Nothing, Clock] = ???
*
* val spec: ZIO[Clock with Random, Nothing, Unit] = ???
* val spec: ZSpec[Clock with Random, Nothing] = ???
*
* val zio2 = zio.provideSomeLayer[Random](clockLayer)
* val spec2 = spec.provideSomeLayerShared[Random](clockLayer)
* }}}
*/
final def provideSomeLayerShared[R0 <: Has[_]]: Spec.ProvideSomeLayerShared[R0, R, E, T] =
Expand Down