-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement
head
and headOption
operators
The `headOption` operator returns the first element in `Source` wrapped in `Some` or `None` in case when source is empty or failed e.g.: Source.empty[Int].headOption() // None Source.fromValues(1, 2).headOption() // Some(1) The `head` operator returns the first element in `Source` or throws `NoSuchElementException` in case when it is either empty or `receive()` operation fails without error. In case when `receive()` fails with exception then this exception is re-thrown e.g.: Source.empty[Int].head() // throws NoSuchElementException("cannot obtain head from the empty source") Source.fromValues(1, 2).head() // 1 Note that neither `head` nor `headOption` are idempotent operations.
- Loading branch information
1 parent
7d7897a
commit 0df1526
Showing
3 changed files
with
162 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
core/src/test/scala/ox/channels/SourceOpsHeadOptionTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package ox.channels | ||
|
||
import org.scalatest.OptionValues | ||
import org.scalatest.flatspec.AnyFlatSpec | ||
import org.scalatest.matchers.should.Matchers | ||
import ox.* | ||
|
||
class SourceOpsHeadOptionTest extends AnyFlatSpec with Matchers with OptionValues { | ||
behavior of "Source.headOption" | ||
|
||
it should "return None for the empty source" in supervised { | ||
Source.empty[Int].headOption() shouldBe None | ||
} | ||
|
||
it should "return None for the failed source" in supervised { | ||
Source | ||
.failed(new RuntimeException("source is broken")) | ||
.headOption() shouldBe None | ||
} | ||
|
||
it should "return Some element for the non-empty source" in supervised { | ||
Source.fromValues(1, 2).headOption().value shouldBe 1 | ||
} | ||
|
||
it should "be not idempotent operation" in supervised { | ||
val s = Source.fromValues(1, 2) | ||
s.headOption().value shouldBe 1 | ||
s.headOption().value shouldBe 2 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ox.channels | ||
|
||
import org.scalatest.flatspec.AnyFlatSpec | ||
import org.scalatest.matchers.should.Matchers | ||
import ox.* | ||
|
||
class SourceOpsHeadTest extends AnyFlatSpec with Matchers { | ||
behavior of "Source.head" | ||
|
||
it should "throw NoSuchElementException for the empty source" in supervised { | ||
the[NoSuchElementException] thrownBy { | ||
Source.empty[Int].head() | ||
} should have message "cannot obtain head from an empty source" | ||
} | ||
|
||
it should "re-throw exception that was thrown during element retrieval" in supervised { | ||
the[RuntimeException] thrownBy { | ||
Source | ||
.failed(new RuntimeException("source is broken")) | ||
.head() | ||
} should have message "source is broken" | ||
} | ||
|
||
it should "throw NoSuchElementException for source failed without exception" in supervised { | ||
the[NoSuchElementException] thrownBy { | ||
Source.failed[Int]().head() | ||
} should have message "getting head failed" | ||
} | ||
|
||
it should "return first value from non empty source" in supervised { | ||
Source.fromValues(1, 2).head() shouldBe 1 | ||
} | ||
|
||
it should "be not idempotent operation" in supervised { | ||
val s = Source.fromValues(1, 2) | ||
s.head() shouldBe 1 | ||
s.head() shouldBe 2 | ||
} | ||
} |