How to use Double.shouldBeBetween method of io.kotest.matchers.doubles.Between class

Best Kotest code snippet using io.kotest.matchers.doubles.Between.Double.shouldBeBetween

DoubleMatchersTest.kt

Source:DoubleMatchersTest.kt Github

copy

Full Screen

1package com.sksamuel.kotest.matchers.doubles2import io.kotest.assertions.shouldFail3import io.kotest.assertions.throwables.shouldThrow4import io.kotest.core.spec.style.FreeSpec5import io.kotest.matchers.doubles.beGreaterThan6import io.kotest.matchers.doubles.beGreaterThanOrEqualTo7import io.kotest.matchers.doubles.beLessThan8import io.kotest.matchers.doubles.beLessThanOrEqualTo9import io.kotest.matchers.doubles.beNaN10import io.kotest.matchers.doubles.beNegativeInfinity11import io.kotest.matchers.doubles.bePositiveInfinity12import io.kotest.matchers.doubles.between13import io.kotest.matchers.doubles.gt14import io.kotest.matchers.doubles.gte15import io.kotest.matchers.doubles.lt16import io.kotest.matchers.doubles.lte17import io.kotest.matchers.doubles.negative18import io.kotest.matchers.doubles.positive19import io.kotest.matchers.doubles.shouldBeBetween20import io.kotest.matchers.doubles.shouldBeGreaterThan21import io.kotest.matchers.doubles.shouldBeGreaterThanOrEqual22import io.kotest.matchers.doubles.shouldBeLessThan23import io.kotest.matchers.doubles.shouldBeLessThanOrEqual24import io.kotest.matchers.doubles.shouldBeMultipleOf25import io.kotest.matchers.doubles.shouldBeNaN26import io.kotest.matchers.doubles.shouldBeNegative27import io.kotest.matchers.doubles.shouldBeNegativeInfinity28import io.kotest.matchers.doubles.shouldBePositive29import io.kotest.matchers.doubles.shouldBePositiveInfinity30import io.kotest.matchers.doubles.shouldBeZero31import io.kotest.matchers.doubles.shouldNotBeBetween32import io.kotest.matchers.doubles.shouldNotBeGreaterThan33import io.kotest.matchers.doubles.shouldNotBeGreaterThanOrEqual34import io.kotest.matchers.doubles.shouldNotBeLessThan35import io.kotest.matchers.doubles.shouldNotBeLessThanOrEqual36import io.kotest.matchers.doubles.shouldNotBeNaN37import io.kotest.matchers.doubles.shouldNotBeNegative38import io.kotest.matchers.doubles.shouldNotBeNegativeInfinity39import io.kotest.matchers.doubles.shouldNotBePositive40import io.kotest.matchers.doubles.shouldNotBePositiveInfinity41import io.kotest.matchers.doubles.shouldNotBeZero42import io.kotest.matchers.should43import io.kotest.matchers.shouldBe44import io.kotest.matchers.shouldNot45import io.kotest.matchers.shouldNotBe46import io.kotest.property.arbitrary.filterNot47import io.kotest.property.checkAll48import kotlin.Double.Companion.MAX_VALUE49import kotlin.Double.Companion.MIN_VALUE50import kotlin.Double.Companion.NEGATIVE_INFINITY51import kotlin.Double.Companion.NaN52import kotlin.Double.Companion.POSITIVE_INFINITY53import kotlin.math.absoluteValue54class DoubleMatchersTest : FreeSpec() {55 init {56 "Between matcher" - {57 "Every numeric double that is not Double.MAX_VALUE" - {58 "Should match between" - {59 "When it's equal to the first number of the range" - {60 "With tolerance" {61 checkAll(100, nonMinNorMaxValueDoubles) {62 it.shouldMatchBetween(it, it.slightlyGreater(), it.toleranceValue())63 }64 }65 "Without tolerance" {66 checkAll(100, nonMinNorMaxValueDoubles) {67 it.shouldMatchBetween(it, it.slightlyGreater(), 0.0)68 }69 }70 }71 "When it's between the first number of the range and the last one" - {72 "With tolerance" {73 checkAll(100, nonMinNorMaxValueDoubles) {74 it.shouldMatchBetween(it.slightlySmaller(), it.slightlyGreater(), it.toleranceValue())75 }76 }77 "Without tolerance" {78 checkAll(100, nonMinNorMaxValueDoubles) {79 it.shouldMatchBetween(it.slightlySmaller(), it.slightlyGreater(), 0.0)80 }81 }82 }83 "When it's equal to the last number of the range" - {84 "With tolerance" {85 checkAll(100, nonMinNorMaxValueDoubles) {86 it.shouldMatchBetween(it.slightlySmaller(), it, it.toleranceValue())87 }88 }89 "Without tolerance" {90 checkAll(100, nonMinNorMaxValueDoubles) {91 it.shouldMatchBetween(it.slightlySmaller(), it, 0.0)92 }93 }94 }95 }96 "Should not match between" - {97 "When it's smaller than the first number of the range" - {98 "With tolerance" {99 checkAll(100, nonMinNorMaxValueDoubles) {100 it.shouldNotMatchBetween(it.slightlyGreater(), it.muchGreater(), it.toleranceValue())101 }102 }103 "Without tolerance" {104 checkAll(100, nonMinNorMaxValueDoubles) {105 it.shouldNotMatchBetween(it.slightlyGreater(), it.muchGreater(), 0.0)106 }107 }108 }109 "When it's bigger than the last number of the range" - {110 "With tolerance" {111 checkAll(100, nonMinNorMaxValueDoubles) {112 it.shouldNotMatchBetween(it.muchSmaller(), it.slightlySmaller(), it.toleranceValue())113 }114 }115 "Without tolerance" {116 checkAll(100, nonMinNorMaxValueDoubles) {117 it.shouldNotMatchBetween(it.muchSmaller(), it.slightlySmaller(), 0.0)118 }119 }120 }121 }122 }123 }124 "Less than matcher" - {125 "Every numeric double" - {126 "Should be less than" - {127 "Numbers bigger than itself" {128 checkAll(100, nonMinNorMaxValueDoubles) {129 it shouldMatchLessThan it.slightlyGreater()130 it shouldMatchLessThan it.muchGreater()131 }132 }133 "Infinity" {134 checkAll(100, nonMinNorMaxValueDoubles) {135 it shouldMatchLessThan POSITIVE_INFINITY136 }137 }138 }139 "Should not be less than" - {140 "Itself" {141 checkAll(100, nonMinNorMaxValueDoubles) {142 it shouldNotMatchLessThan it143 }144 }145 "Numbers smaller than itself" {146 checkAll(100, nonMinNorMaxValueDoubles) {147 it shouldNotMatchLessThan it.slightlySmaller()148 it shouldNotMatchLessThan it.muchSmaller()149 }150 }151 "Negative Infinity" {152 checkAll(100, nonMinNorMaxValueDoubles) {153 it shouldNotMatchLessThan it154 }155 }156 "NaN" {157 checkAll(100, nonMinNorMaxValueDoubles) {158 it shouldNotMatchLessThan NaN159 }160 }161 }162 }163 "The non-numeric double" - {164 "NaN" - {165 "Should not be less than" - {166 "Any numeric double" {167 checkAll(100, nonMinNorMaxValueDoubles) {168 NaN shouldNotMatchLessThan it169 }170 }171 "Any non-numeric double" {172 nonNumericDoubles.forEach {173 NaN shouldNotMatchLessThan it174 }175 }176 }177 }178 "Positive Infinity" - {179 "Should not be less than" - {180 "Any numeric double" {181 checkAll(100, nonMinNorMaxValueDoubles) {182 POSITIVE_INFINITY shouldNotMatchLessThan it183 }184 }185 "Any non-numeric double" {186 nonNumericDoubles.forEach {187 POSITIVE_INFINITY shouldNotMatchLessThan it188 }189 }190 }191 }192 "Negative Infinity" - {193 "Should be less than" - {194 "Any numeric double" {195 checkAll(100, nonMinNorMaxValueDoubles) {196 NEGATIVE_INFINITY shouldMatchLessThan it197 }198 }199 "Positive Infinity" {200 NEGATIVE_INFINITY shouldMatchLessThan POSITIVE_INFINITY201 }202 }203 "Should not be less than" - {204 "Itself" {205 NEGATIVE_INFINITY shouldNotMatchLessThan NEGATIVE_INFINITY206 }207 "NaN" {208 NEGATIVE_INFINITY shouldNotMatchLessThan NaN209 }210 }211 }212 }213 }214 "Positive matcher" - {215 "Zero" - {216 "Should not be positive" {217 0.0.shouldNotMatchPositive()218 }219 }220 "Every positive number" - {221 "Should be positive" {222 checkAll(100, numericDoubles.filterNot { it == 0.0 }) {223 it.absoluteValue.shouldMatchPositive()224 }225 }226 }227 "Every non-positive number" - {228 "Should not be positive" {229 checkAll(100, numericDoubles) {230 (-it.absoluteValue).shouldNotMatchPositive()231 }232 }233 }234 "The non-numeric double" - {235 "Positive Infinity" - {236 "Should be positive" {237 POSITIVE_INFINITY.shouldMatchPositive()238 }239 }240 "Negative Infinity" - {241 "Should not be positive" {242 NEGATIVE_INFINITY.shouldNotMatchPositive()243 }244 }245 "NaN" - {246 "Should not be positive" {247 NaN.shouldNotMatchPositive()248 }249 }250 }251 }252 "Negative matcher" - {253 "Zero" - {254 "Should not be negative" {255 0.0.shouldNotMatchNegative()256 }257 }258 "Every negative number" - {259 "Should be negative" {260 checkAll(100, numericDoubles.filterNot { it == 0.0 }) {261 (-it.absoluteValue).shouldMatchNegative()262 }263 }264 }265 "Every non-negative number" - {266 "Should not be negative" {267 checkAll(100, numericDoubles) {268 it.absoluteValue.shouldNotMatchNegative()269 }270 }271 }272 "The non-numeric double" - {273 "Positive Infinity" - {274 "Should not be negative" {275 POSITIVE_INFINITY.shouldNotMatchNegative()276 }277 }278 "Negative Infinity" - {279 "Should be negative" {280 NEGATIVE_INFINITY.shouldMatchNegative()281 }282 }283 "NaN" - {284 "Should not be negative" {285 NaN.shouldNotMatchNegative()286 }287 }288 }289 }290 "MultipleOf matcher" - {291 "Matches a simple multiple" {292 300.0 shouldBeMultipleOf 1.0293 }294 "Fails due to precision problems" {295 shouldFail {296 3.6e300 shouldBeMultipleOf 1.2297 }298 }299 }300 "Less than or equal matcher" - {301 "Every numeric double" - {302 "Should be less than or equal" - {303 "Itself" {304 checkAll(100, nonMinNorMaxValueDoubles) {305 it shouldMatchLessThanOrEqual it306 }307 }308 "Numbers bigger than itself" {309 checkAll(100, nonMinNorMaxValueDoubles) {310 it shouldMatchLessThanOrEqual it.muchGreater()311 it shouldMatchLessThanOrEqual it.slightlyGreater()312 }313 }314 "Positive Infinity" {315 checkAll(100, nonMinNorMaxValueDoubles) {316 it shouldMatchLessThanOrEqual POSITIVE_INFINITY317 }318 }319 }320 "Should not be less than or equal" - {321 "Any number smaller than itself" {322 checkAll(100, nonMinNorMaxValueDoubles) {323 it shouldNotMatchLessThanOrEqual it.slightlySmaller()324 it shouldNotMatchLessThanOrEqual it.muchSmaller()325 }326 }327 "Negative Infinity" {328 checkAll(100, nonMinNorMaxValueDoubles) {329 it shouldNotMatchLessThanOrEqual NEGATIVE_INFINITY330 }331 }332 "NaN" {333 checkAll(100, nonMinNorMaxValueDoubles) {334 it shouldNotMatchLessThanOrEqual NaN335 }336 }337 }338 }339 "The non-numeric double" - {340 "NaN" {341 "Should not be less than or equal" - {342 "Any numeric double" {343 checkAll(100, nonMinNorMaxValueDoubles) {344 NaN shouldNotMatchLessThanOrEqual it345 }346 }347 "Positive Infinity" {348 NaN shouldNotMatchLessThanOrEqual POSITIVE_INFINITY349 }350 "Negative Infinity" {351 NaN shouldNotMatchLessThanOrEqual NEGATIVE_INFINITY352 }353 "Itself" {354 NaN shouldNotMatchLessThanOrEqual NaN355 }356 }357 }358 "Positive Infinity" - {359 "Should be less than or equal" - {360 "Positive Infinity" {361 POSITIVE_INFINITY shouldMatchLessThanOrEqual POSITIVE_INFINITY362 }363 }364 "Should not be less than or equal" - {365 "Any numeric double" {366 checkAll(100, nonMinNorMaxValueDoubles) {367 POSITIVE_INFINITY shouldNotMatchLessThanOrEqual it368 }369 }370 "Negative Infinity" {371 POSITIVE_INFINITY shouldNotMatchLessThanOrEqual NEGATIVE_INFINITY372 }373 "NaN" {374 POSITIVE_INFINITY shouldNotMatchLessThanOrEqual NaN375 }376 }377 }378 "Negative Infinity" - {379 "Should be less than or equal" - {380 "Any numeric double" {381 checkAll(100, nonMinNorMaxValueDoubles) {382 NEGATIVE_INFINITY shouldMatchLessThanOrEqual it383 }384 }385 "Positive Infinity" {386 NEGATIVE_INFINITY shouldMatchLessThanOrEqual POSITIVE_INFINITY387 }388 "Itself" {389 NEGATIVE_INFINITY shouldMatchLessThanOrEqual NEGATIVE_INFINITY390 }391 }392 "Should not be less than or equal" - {393 "NaN" {394 NEGATIVE_INFINITY shouldNotMatchLessThanOrEqual NaN395 }396 }397 }398 }399 }400 "Greater than matcher" - {401 "Every numeric double" - {402 "Should be greater than" - {403 "Numbers smaller than itself" {404 checkAll(100, nonMinNorMaxValueDoubles) {405 it shouldMatchGreaterThan it.slightlySmaller()406 it shouldMatchGreaterThan it.muchSmaller()407 }408 }409 "Negative infinity" {410 checkAll(100, nonMinNorMaxValueDoubles) {411 it shouldMatchGreaterThan NEGATIVE_INFINITY412 }413 }414 }415 "Should not be greater than" - {416 "Itself" {417 checkAll(100, nonMinNorMaxValueDoubles) {418 it shouldNotMatchGreaterThan it419 }420 }421 "Numbers greater than itself" {422 checkAll(100, nonMinNorMaxValueDoubles) {423 it shouldNotMatchGreaterThan it.slightlyGreater()424 it shouldNotMatchGreaterThan it.muchGreater()425 }426 }427 "NaN" {428 checkAll(100, nonMinNorMaxValueDoubles) {429 it shouldNotMatchGreaterThan NaN430 }431 }432 "Positive Infinity" {433 checkAll(100, nonMinNorMaxValueDoubles) {434 it shouldNotMatchGreaterThan POSITIVE_INFINITY435 }436 }437 }438 }439 "The non-numeric double" - {440 "NaN" - {441 "Should not be greater than" - {442 "Itself" {443 NaN shouldNotMatchGreaterThan NaN444 }445 "Any numeric double" {446 checkAll(100, numericDoubles) {447 NaN shouldNotMatchGreaterThan it448 }449 }450 "Positive Infinity" {451 NaN shouldNotMatchGreaterThan POSITIVE_INFINITY452 }453 "Negative Infinity" {454 NaN shouldNotMatchGreaterThan NEGATIVE_INFINITY455 }456 }457 }458 }459 }460 "Greater than or equal matcher" - {461 "Every numeric double" - {462 "Should be greater than or equal to" - {463 "Itself" {464 checkAll(100, nonMinNorMaxValueDoubles) {465 it shouldMatchGreaterThanOrEqual it466 }467 }468 "Numbers smaller than itself" {469 checkAll(100, nonMinNorMaxValueDoubles) {470 it shouldMatchGreaterThanOrEqual it.slightlySmaller()471 it shouldMatchGreaterThanOrEqual it.muchSmaller()472 }473 }474 "Negative Infinity" {475 checkAll(100, nonMinNorMaxValueDoubles) {476 it shouldMatchGreaterThanOrEqual NEGATIVE_INFINITY477 }478 }479 }480 "Should not be greater than or equal to" - {481 "Numbers bigger than itself" {482 checkAll(100, nonMinNorMaxValueDoubles) {483 it shouldNotMatchGreaterThanOrEqual it.slightlyGreater()484 it shouldNotMatchGreaterThanOrEqual it.muchGreater()485 }486 }487 "Positive Infinity" {488 checkAll(100, nonMinNorMaxValueDoubles) {489 it shouldNotMatchGreaterThanOrEqual POSITIVE_INFINITY490 }491 }492 "NaN" {493 checkAll(100, nonMinNorMaxValueDoubles) {494 it shouldNotMatchGreaterThanOrEqual NaN495 }496 }497 }498 }499 "The non-numeric double" - {500 "NaN" - {501 "Should not be greater than or equal to" - {502 "Itself" {503 NaN shouldNotMatchGreaterThanOrEqual NaN504 }505 "Any numeric double" {506 checkAll(100, numericDoubles) {507 NaN shouldNotMatchGreaterThanOrEqual it508 }509 }510 "Positive Infinity" {511 NaN shouldNotMatchGreaterThanOrEqual POSITIVE_INFINITY512 }513 "Negative Infinity" {514 NaN shouldNotMatchGreaterThanOrEqual NEGATIVE_INFINITY515 }516 }517 }518 "Positive Infinity" - {519 "Should be greater than or equal to" - {520 "Itself" {521 POSITIVE_INFINITY shouldMatchGreaterThanOrEqual POSITIVE_INFINITY522 }523 "Negative Infinity" {524 POSITIVE_INFINITY shouldMatchGreaterThanOrEqual NEGATIVE_INFINITY525 }526 "Any numeric double" {527 checkAll(100, numericDoubles) {528 POSITIVE_INFINITY shouldMatchGreaterThanOrEqual it529 }530 }531 }532 "Should not be greater than or equal to" - {533 "NaN" {534 POSITIVE_INFINITY shouldNotMatchGreaterThanOrEqual NaN535 }536 }537 }538 "Negative Infinity" - {539 "Should be greater than or equal to" - {540 "Itself" {541 NEGATIVE_INFINITY shouldMatchGreaterThanOrEqual NEGATIVE_INFINITY542 }543 }544 "Should not be greater than or equal to" - {545 "Any numeric double" {546 checkAll(100, numericDoubles) {547 NEGATIVE_INFINITY shouldNotMatchGreaterThanOrEqual it548 }549 }550 "Positive Infinity" {551 NEGATIVE_INFINITY shouldNotMatchGreaterThanOrEqual POSITIVE_INFINITY552 }553 "NaN" {554 NEGATIVE_INFINITY shouldNotMatchGreaterThanOrEqual NaN555 }556 }557 }558 }559 }560 "NaN matcher" - {561 "Every numeric double" - {562 "Should not be NaN" {563 checkAll(100, numericDoubles) {564 it.shouldNotMatchNaN()565 }566 }567 }568 "The non-numeric double" - {569 "NaN" - {570 "Should match NaN" {571 NaN.shouldMatchNaN()572 }573 }574 "Positive Infinity" - {575 "Should not match NaN" {576 POSITIVE_INFINITY.shouldNotMatchNaN()577 }578 }579 "Negative Infinity" - {580 "Should not match NaN" {581 NEGATIVE_INFINITY.shouldNotMatchNaN()582 }583 }584 }585 }586 "Positive Infinity matcher" - {587 "Any numeric double" - {588 "Should not match positive infinity" {589 checkAll(100, numericDoubles) {590 it.shouldNotMatchPositiveInfinity()591 }592 }593 }594 "The non-numeric double" - {595 "Positive Infinity" - {596 "Should match positive infinity" {597 POSITIVE_INFINITY.shouldMatchPositiveInfinity()598 }599 }600 "Negative Infinity" - {601 "Should not match positive infinity" {602 NEGATIVE_INFINITY.shouldNotMatchPositiveInfinity()603 }604 }605 "NaN" - {606 "Should not match positive infinity" {607 NaN.shouldNotMatchPositiveInfinity()608 }609 }610 }611 }612 "Negative Infinity matcher" - {613 "Any numeric double" - {614 "Should not match negative infinity" {615 checkAll(100, numericDoubles) {616 it.shouldNotMatchNegativeInfinity()617 }618 }619 }620 "The non-numeric double" - {621 "Negative Infinity" - {622 "Should match negative infinity" {623 NEGATIVE_INFINITY.shouldMatchNegativeInfinity()624 }625 }626 "Positive Infinity" - {627 "Should not match negative infinity" {628 POSITIVE_INFINITY.shouldNotMatchNegativeInfinity()629 }630 }631 "NaN" - {632 "Should not match negative infinity" {633 NaN.shouldNotMatchNegativeInfinity()634 }635 }636 }637 }638 "shouldBeZero" {639 (0.0).shouldBeZero()640 (-0.1).shouldNotBeZero()641 (0.1).shouldNotBeZero()642 MIN_VALUE.shouldNotBeZero()643 MAX_VALUE.shouldNotBeZero()644 NaN.shouldNotBeZero()645 POSITIVE_INFINITY.shouldNotBeZero()646 NEGATIVE_INFINITY.shouldNotBeZero()647 }648 }649 private fun shouldThrowAssertionError(message: String, vararg expression: () -> Any?) {650 expression.forEach {651 val exception = shouldThrow<AssertionError>(it)652 exception.message shouldBe message653 }654 }655 private fun Double.shouldMatchBetween(a: Double, b: Double, tolerance: Double) {656 this.shouldBeBetween(a, b, tolerance)657 this shouldBe between(a, b, tolerance)658 this.shouldThrowExceptionOnNotBetween(a, b, tolerance)659 }660 private fun Double.shouldNotMatchBetween(a: Double, b: Double, tolerance: Double) {661 this.shouldNotBeBetween(a, b, tolerance)662 this shouldNotBe between(a, b, tolerance)663 this.shouldThrowExceptionOnBetween(a, b, tolerance)664 }665 private fun Double.shouldThrowExceptionOnBetween(a: Double, b: Double, tolerance: Double) {666 when {667 this < a -> this.shouldThrowMinimumExceptionOnBetween(a, b, tolerance)668 this > b -> this.shouldThrowMaximumExceptionOnBetween(a, b, tolerance)669 else -> throw IllegalStateException()670 }671 }672 private fun Double.shouldThrowMinimumExceptionOnBetween(a: Double, b: Double, tolerance: Double) {673 val message = "$this should be bigger than $a"674 shouldThrowExceptionOnBetween(a, b, tolerance, message)675 }676 private fun Double.shouldThrowMaximumExceptionOnBetween(a: Double, b: Double, tolerance: Double) {677 val message = "$this should be smaller than $b"678 shouldThrowExceptionOnBetween(a, b, tolerance, message)679 }680 private fun Double.shouldThrowExceptionOnBetween(681 a: Double,682 b: Double,683 tolerance: Double,684 message: String = "$this should be smaller than $b and bigger than $a"685 ) {686 shouldThrowAssertionError(message,687 { this.shouldBeBetween(a, b, tolerance) },688 { this shouldBe between(a, b, tolerance) })689 }690 private fun Double.shouldThrowExceptionOnNotBetween(691 a: Double,692 b: Double,693 tolerance: Double,694 message: String = "$this should not be smaller than $b and should not be bigger than $a"695 ) {696 shouldThrowAssertionError(message,697 { this.shouldNotBeBetween(a, b, tolerance) },698 { this shouldNotBe between(a, b, tolerance) })699 }700 private infix fun Double.shouldMatchLessThan(x: Double) {701 this shouldBe lt(x)702 this shouldBeLessThan x703 this should beLessThan(x)704 this shouldThrowExceptionOnNotLessThan x705 }706 private infix fun Double.shouldThrowExceptionOnNotLessThan(x: Double) {707 shouldThrowAssertionError("$this should not be < $x",708 { this shouldNotBe lt(x) },709 { this shouldNotBeLessThan x },710 { this shouldNot beLessThan(x) })711 }712 private infix fun Double.shouldNotMatchLessThan(x: Double) {713 this shouldNotBe lt(x)714 this shouldNotBeLessThan x715 this shouldNot beLessThan(x)716 this shouldThrowExceptionOnLessThan x717 }718 private infix fun Double.shouldThrowExceptionOnLessThan(x: Double) {719 shouldThrowAssertionError("$this should be < $x",720 { this shouldBe lt(x) },721 { this shouldBeLessThan x },722 { this should beLessThan(x) }723 )724 }725 private fun Double.shouldMatchPositive() {726 this.shouldBePositive()727 this shouldBe positive()728 this.shouldThrowExceptionOnNotPositive()729 }730 private fun Double.shouldThrowExceptionOnNotPositive() {731 shouldThrowAssertionError("$this should not be > 0.0",732 { this shouldNotBe positive() },733 { this.shouldNotBePositive() }734 )735 }736 private fun Double.shouldNotMatchPositive() {737 this.shouldNotBePositive()738 this shouldNotBe positive()739 this.shouldThrowExceptionOnPositive()740 }741 private fun Double.shouldThrowExceptionOnPositive() {742 shouldThrowAssertionError("$this should be > 0.0",743 { this shouldBe positive() },744 { this.shouldBePositive() }745 )746 }747 private fun Double.shouldMatchNegative() {748 this.shouldBeNegative()749 this shouldBe negative()750 this.shouldThrowExceptionOnNotNegative()751 }752 private fun Double.shouldThrowExceptionOnNotNegative() {753 shouldThrowAssertionError("$this should not be < 0.0",754 { this shouldNotBe negative() },755 { this.shouldNotBeNegative() }756 )757 }758 private fun Double.shouldNotMatchNegative() {759 this.shouldNotBeNegative()760 this shouldNotBe negative()761 this.shouldThrowExceptionOnNegative()762 }763 private fun Double.shouldThrowExceptionOnNegative() {764 shouldThrowAssertionError("$this should be < 0.0",765 { this shouldBe negative() },766 { this.shouldBeNegative() }767 )768 }769 private infix fun Double.shouldMatchLessThanOrEqual(x: Double) {770 this should beLessThanOrEqualTo(x)771 this shouldBe lte(x)772 this shouldBeLessThanOrEqual x773 this shouldThrowExceptionOnNotLessThanOrEqual x774 }775 private infix fun Double.shouldThrowExceptionOnNotLessThanOrEqual(x: Double) {776 shouldThrowAssertionError("$this should not be <= $x",777 { this shouldNot beLessThanOrEqualTo(x) },778 { this shouldNotBe lte(x) },779 { this shouldNotBeLessThanOrEqual x }780 )781 }782 private infix fun Double.shouldNotMatchLessThanOrEqual(x: Double) {783 this shouldNot beLessThanOrEqualTo(x)784 this shouldNotBe lte(x)785 this shouldNotBeLessThanOrEqual x786 this shouldThrowExceptionOnLessThanOrEqual x787 }788 private infix fun Double.shouldThrowExceptionOnLessThanOrEqual(x: Double) {789 shouldThrowAssertionError("$this should be <= $x",790 { this should beLessThanOrEqualTo(x) },791 { this shouldBe lte(x) },792 { this shouldBeLessThanOrEqual x }793 )794 }795 private infix fun Double.shouldMatchGreaterThan(x: Double) {796 this should beGreaterThan(x)797 this shouldBe gt(x)798 this shouldBeGreaterThan x799 this shouldThrowExceptionOnNotGreaterThan x800 }801 private infix fun Double.shouldThrowExceptionOnNotGreaterThan(x: Double) {802 shouldThrowAssertionError("$this should not be > $x",803 { this shouldNot beGreaterThan(x) },804 { this shouldNotBeGreaterThan (x) },805 { this shouldNotBe gt(x) })806 }807 private infix fun Double.shouldNotMatchGreaterThan(x: Double) {808 this shouldNot beGreaterThan(x)809 this shouldNotBe gt(x)810 this shouldNotBeGreaterThan x811 this shouldThrowExceptionOnGreaterThan (x)812 }813 private infix fun Double.shouldThrowExceptionOnGreaterThan(x: Double) {814 shouldThrowAssertionError("$this should be > $x",815 { this should beGreaterThan(x) },816 { this shouldBe gt(x) },817 { this shouldBeGreaterThan x })818 }819 private infix fun Double.shouldMatchGreaterThanOrEqual(x: Double) {820 this should beGreaterThanOrEqualTo(x)821 this shouldBe gte(x)822 this shouldBeGreaterThanOrEqual x823 this shouldThrowExceptionOnNotGreaterThanOrEqual (x)824 }825 private infix fun Double.shouldThrowExceptionOnNotGreaterThanOrEqual(x: Double) {826 shouldThrowAssertionError("$this should not be >= $x",827 { this shouldNot beGreaterThanOrEqualTo(x) },828 { this shouldNotBe gte(x) },829 { this shouldNotBeGreaterThanOrEqual x })830 }831 private infix fun Double.shouldNotMatchGreaterThanOrEqual(x: Double) {832 this shouldNot beGreaterThanOrEqualTo(x)833 this shouldNotBe gte(x)834 this shouldNotBeGreaterThanOrEqual x835 this shouldThrowExceptionOnGreaterThanOrEqual (x)836 }837 private infix fun Double.shouldThrowExceptionOnGreaterThanOrEqual(x: Double) {838 shouldThrowAssertionError("$this should be >= $x",839 { this should beGreaterThanOrEqualTo(x) },840 { this shouldBe gte(x) },841 { this shouldBeGreaterThanOrEqual x })842 }843 private fun Double.shouldMatchNaN() {844 this should beNaN()845 this.shouldBeNaN()846 this.shouldThrowExceptionOnNotBeNaN()847 }848 private fun Double.shouldThrowExceptionOnNotBeNaN() {849 shouldThrowAssertionError("$this should not be NaN",850 { this.shouldNotBeNaN() },851 { this shouldNot beNaN() })852 }853 private fun Double.shouldNotMatchNaN() {854 this shouldNot beNaN()855 this.shouldNotBeNaN()856 this.shouldThrowExceptionOnBeNaN()857 }858 private fun Double.shouldThrowExceptionOnBeNaN() {859 shouldThrowAssertionError("$this should be NaN",860 { this.shouldBeNaN() },861 { this should beNaN() })862 }863 private fun Double.shouldMatchPositiveInfinity() {864 this should bePositiveInfinity()865 this.shouldBePositiveInfinity()866 this.shouldThrowExceptionOnNotBePositiveInfinity()867 }868 private fun Double.shouldThrowExceptionOnNotBePositiveInfinity() {869 shouldThrowAssertionError("$this should not be POSITIVE_INFINITY",870 { this shouldNot bePositiveInfinity() },871 { this.shouldNotBePositiveInfinity() })872 }873 private fun Double.shouldNotMatchPositiveInfinity() {874 this shouldNot bePositiveInfinity()875 this.shouldNotBePositiveInfinity()876 this.shouldThrowExceptionOnBePositiveInfinity()877 }878 private fun Double.shouldThrowExceptionOnBePositiveInfinity() {879 shouldThrowAssertionError("$this should be POSITIVE_INFINITY",880 { this should bePositiveInfinity() },881 { this.shouldBePositiveInfinity() })882 }883 private fun Double.shouldMatchNegativeInfinity() {884 this should beNegativeInfinity()885 this.shouldBeNegativeInfinity()886 this.shouldThrowExceptionOnNotBeNegativeInfinity()887 }888 private fun Double.shouldThrowExceptionOnNotBeNegativeInfinity() {889 shouldThrowAssertionError("$this should not be NEGATIVE_INFINITY",890 { this shouldNot beNegativeInfinity() },891 { this.shouldNotBeNegativeInfinity() })892 }893 private fun Double.shouldNotMatchNegativeInfinity() {894 this shouldNot beNegativeInfinity()895 this.shouldNotBeNegativeInfinity()896 this.shouldThrowExceptionOnBeNegativeInfinity()897 }898 private fun Double.shouldThrowExceptionOnBeNegativeInfinity() {899 shouldThrowAssertionError("$this should be NEGATIVE_INFINITY",900 { this should beNegativeInfinity() },901 { this.shouldBeNegativeInfinity() })902 }903}...

Full Screen

Full Screen

RateLimitedDispatcherTest.kt

Source:RateLimitedDispatcherTest.kt Github

copy

Full Screen

1package ru.fix.stdlib.ratelimiter2import io.kotest.assertions.assertSoftly3import io.kotest.assertions.throwables.shouldThrow4import io.kotest.matchers.booleans.shouldBeFalse5import io.kotest.matchers.booleans.shouldBeTrue6import io.kotest.matchers.collections.shouldContain7import io.kotest.matchers.doubles.shouldBeBetween8import io.kotest.matchers.nulls.shouldNotBeNull9import io.kotest.matchers.shouldBe10import io.kotest.matchers.types.shouldBeInstanceOf11import kotlinx.coroutines.CoroutineScope12import kotlinx.coroutines.async13import kotlinx.coroutines.delay14import kotlinx.coroutines.future.await15import kotlinx.coroutines.future.future16import kotlinx.coroutines.runBlocking17import mu.KLogging18import org.awaitility.Awaitility.await19import org.junit.jupiter.api.Test20import org.junit.jupiter.api.TestInstance21import org.junit.jupiter.api.assertTimeoutPreemptively22import org.junit.jupiter.api.parallel.Execution23import org.junit.jupiter.api.parallel.ExecutionMode24import ru.fix.aggregating.profiler.AggregatingProfiler25import ru.fix.aggregating.profiler.NoopProfiler26import ru.fix.aggregating.profiler.Profiler27import ru.fix.aggregating.profiler.ProfilerReport28import ru.fix.dynamic.property.api.AtomicProperty29import ru.fix.dynamic.property.api.DynamicProperty30import java.lang.Thread.sleep31import java.time.Duration32import java.util.concurrent.*33import java.util.concurrent.CompletableFuture.completedFuture34import java.util.concurrent.atomic.AtomicBoolean35import java.util.concurrent.atomic.AtomicInteger36@TestInstance(TestInstance.Lifecycle.PER_METHOD)37@Execution(ExecutionMode.CONCURRENT)38class RateLimitedDispatcherTest {39 private companion object : KLogging() {40 const val DISPATCHER_NAME = "dispatcher-name"41 const val DISPATCHER_METRICS_PREFIX = "RateLimiterDispatcher.$DISPATCHER_NAME"42 }43 @Test44 fun `dispatch async operation with user defined async result type, operation invoked and it's result returned`() {45 class UserAsyncResult {46 fun whenComplete(callback: () -> Unit) {47 callback()48 }49 }50 val dispatcher = createDispatcher()51 val asyncResultInstance = UserAsyncResult()52 fun userAsyncOperation(): UserAsyncResult {53 return asyncResultInstance54 }55 val delayedSubmission = dispatcher.compose(56 { userAsyncOperation() },57 { asyncResult, callback -> asyncResult.whenComplete { callback.onAsyncResultCompleted() } }58 )59 (asyncResultInstance === delayedSubmission.get()).shouldBeTrue()60 dispatcher.close()61 }62 @Test63 fun `dispatch async operation with successfull CompletableFuture, operation invoked and it's result returned`() {64 val dispatcher = createDispatcher()65 val operationResult = Object()66 fun userAsyncOperation(): CompletableFuture<Any> {67 return completedFuture(operationResult)68 }69 val delayedSubmissionFuture = dispatcher.compose { userAsyncOperation() }70 (operationResult === delayedSubmissionFuture.get()).shouldBeTrue()71 dispatcher.close()72 }73 @Test74 fun `dispatch async operation with exceptional CompletableFuture, operation invoked and it's result returned`() {75 val dispatcher = createDispatcher()76 val asyncOperationException = Exception("some error")77 fun userAsyncOperation(): CompletableFuture<Any> {78 return CompletableFuture<Any>().apply {79 completeExceptionally(asyncOperationException)80 }81 }82 val delayedSubmissionFuture = dispatcher.compose { userAsyncOperation() }83 await().atMost(Duration.ofSeconds(10)).until {84 delayedSubmissionFuture.isCompletedExceptionally85 }86 val actualException = shouldThrow<Exception> { delayedSubmissionFuture.get() }87 actualException.cause.shouldNotBeNull()88 actualException.cause.shouldBe(asyncOperationException)89 dispatcher.close()90 }91 @Test92 fun `if windows size is 0, then restricted only by limiter `() {93 `async operations are restricted by limiter limit `(0)94 }95 @Test96 fun `if window size is not empty and quite big, restricted by limiter`() {97 `async operations are restricted by limiter limit `(100_000)98 }99 private fun `async operations are restricted by limiter limit `(windowSize: Int) {100 val RATE_PER_SECOND = 500101 val ITERATIONS = 5 * RATE_PER_SECOND102 val report = `submit series of operations`(103 ratePerSecond = RATE_PER_SECOND,104 interations = ITERATIONS,105 windowSize = DynamicProperty.of(windowSize))106 val operationReport = report.profilerCallReports.single { it.identity.name == "operation" }107 logger.info("Throughput " + operationReport.stopThroughputAvg)108 operationReport.stopThroughputAvg.shouldBeBetween(109 RATE_PER_SECOND.toDouble(),110 RATE_PER_SECOND.toDouble(),111 RATE_PER_SECOND.toDouble() * 0.25)112 }113 private fun `submit series of operations`(114 ratePerSecond: Int,115 interations: Int,116 windowSize: DynamicProperty<Int>): ProfilerReport {117 val profiler = AggregatingProfiler()118 val dispatcher = createDispatcher(119 rateLimitRequestPerSecond = ratePerSecond,120 window = windowSize,121 profiler = profiler122 )123 val counter = AtomicInteger(0)124 val profilerReporter = profiler.createReporter()125 val profiledCall = profiler.profiledCall("operation")126 val features = List(interations) {127 dispatcher.compose {128 profiledCall.profile<CompletableFuture<Int>> {129 completedFuture(counter.incrementAndGet())130 }131 }132 }133 logger.info("Submit $interations operations.")134 features.forEach { it.join() }135 counter.get().shouldBe(interations)136 features.map { it.join() }.toSet().containsAll((1..interations).toList())137 val report = profilerReporter.buildReportAndReset()138 dispatcher.close()139 return report;140 }141 @Test142 fun `when window of uncompleted operations is full no new operation is dispatched`() {143 val dispatcher = TrackableDispatcher()144 dispatcher.windowProperty.set(10)145 dispatcher.submitTasks(1..11)146 sleep(4000)147 dispatcher.isSubmittedTaskInvoked(1..10).shouldBeTrue()148 dispatcher.isSubmittedTaskInvoked(11).shouldBeFalse()149 dispatcher.completeTask(4)150 await().atMost(Duration.ofSeconds(10)).until {151 dispatcher.isSubmittedTaskInvoked(11)152 }153 dispatcher.completeAllAndClose()154 }155 @Test156 fun `'queue_wait', 'acquire_limit', 'acquire_window', 'supplied_operation', 'queue_size', 'active_async_operations' metrics gathered during execution`() {157 val RATE_PER_SECOND = 500158 val ITERATIONS = 5 * RATE_PER_SECOND159 val report = `submit series of operations`(160 ratePerSecond = RATE_PER_SECOND,161 interations = ITERATIONS,162 windowSize = DynamicProperty.of(100))163 report.profilerCallReports.single { it.identity.name == "$DISPATCHER_METRICS_PREFIX.queue_wait" }164 .stopSum.shouldBe(ITERATIONS)165 report.profilerCallReports.single { it.identity.name == "$DISPATCHER_METRICS_PREFIX.acquire_window" }166 .stopSum.shouldBe(ITERATIONS)167 report.profilerCallReports.single { it.identity.name == "$DISPATCHER_METRICS_PREFIX.acquire_limit" }168 .stopSum.shouldBe(ITERATIONS)169 report.profilerCallReports.single { it.identity.name == "$DISPATCHER_METRICS_PREFIX.supply_operation" }170 .stopSum.shouldBe(ITERATIONS)171 report.indicators.map { it.key.name }.shouldContain("$DISPATCHER_METRICS_PREFIX.queue_size")172 report.indicators.map { it.key.name }.shouldContain("$DISPATCHER_METRICS_PREFIX.active_async_operations")173 logger.info(report.toString())174 }175 @Test176 fun `indicators 'queue_size' and 'active_async_operations' adjusted according to number of queued and active operations`() {177 val profiler = AggregatingProfiler()178 val reporter = profiler.createReporter()179 val trackableDispatcher = TrackableDispatcher(profiler)180 trackableDispatcher.windowProperty.set(10)181 trackableDispatcher.submitTasks(1..12)182 await().atMost(1, TimeUnit.SECONDS).until {183 trackableDispatcher.isSubmittedTaskInvoked(1..10)184 }185 reporter.buildReportAndReset().assertSoftly {186 indicators.mapKeys { it.key.name }.assertSoftly {187 it["$DISPATCHER_METRICS_PREFIX.queue_size"] shouldBe 1188 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 10189 }190 profilerCallReports.single { it.identity.name == "$DISPATCHER_METRICS_PREFIX.acquire_window" }191 .activeCallsCountMax shouldBe 1192 }193 trackableDispatcher.completeTasks(1..10)194 await().atMost(1, TimeUnit.SECONDS).until {195 trackableDispatcher.isSubmittedTaskInvoked(11..12)196 }197 reporter.buildReportAndReset().indicators.mapKeys { it.key.name }.assertSoftly {198 it["$DISPATCHER_METRICS_PREFIX.queue_size"] shouldBe 0199 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 2200 }201 trackableDispatcher.completeTasks(11..12)202 reporter.buildReportAndReset().indicators.mapKeys { it.key.name }.assertSoftly {203 it["$DISPATCHER_METRICS_PREFIX.queue_size"] shouldBe 0204 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 0205 }206 trackableDispatcher.completeAllAndClose()207 }208 @Test209 fun `WHEN many fast CompletableFuture tasks completed THEN 'active_async_operations' is 0`() {210 val report = `submit series of operations`(500, 4000, DynamicProperty.of(1000))211 logger.info { report }212 report.indicators.mapKeys { it.key.name }.assertSoftly {213 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 0214 }215 }216 @Test217 fun `WHEN completed futures arrived THEN indicators are correctly adjusted`() {218 val profiler = AggregatingProfiler()219 val reporter = profiler.createReporter()220 val trackableDispatcher = TrackableDispatcher(profiler)221 trackableDispatcher.windowProperty.set(5)222 trackableDispatcher.submitCompletedTasks(1..4)223 trackableDispatcher.submitTasks(5..6)224 await().atMost(1, TimeUnit.SECONDS).until {225 trackableDispatcher.isSubmittedTaskInvoked(1..6)226 }227 reporter.buildReportAndReset().indicators.mapKeys { it.key.name }.assertSoftly {228 it["$DISPATCHER_METRICS_PREFIX.queue_size"] shouldBe 0229 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 2230 }231 trackableDispatcher.submitCompletedTasks(7..10)232 await().atMost(1, TimeUnit.SECONDS).until {233 trackableDispatcher.isSubmittedTaskInvoked(7..10)234 }235 reporter.buildReportAndReset().indicators.mapKeys { it.key.name }.assertSoftly {236 it["$DISPATCHER_METRICS_PREFIX.queue_size"] shouldBe 0237 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 2238 }239 trackableDispatcher.completeTasks(5..6)240 reporter.buildReportAndReset().indicators.mapKeys { it.key.name }.assertSoftly {241 it["$DISPATCHER_METRICS_PREFIX.queue_size"] shouldBe 0242 it["$DISPATCHER_METRICS_PREFIX.active_async_operations"] shouldBe 0243 }244 trackableDispatcher.completeAllAndClose()245 }246 @Test247 fun `increasing window size allows to submit new operations up to the new limit`() {248 val trackableDispatcher = TrackableDispatcher()249 trackableDispatcher.windowProperty.set(10)250 trackableDispatcher.submitTasks(1..11)251 sleep(4000)252 trackableDispatcher.isSubmittedTaskInvoked(1..10).shouldBeTrue()253 trackableDispatcher.isSubmittedTaskInvoked(11).shouldBeFalse()254 trackableDispatcher.windowProperty.set(11)255 trackableDispatcher.submitTask(12)256 trackableDispatcher.completeTask(1)257 await().atMost(Duration.ofSeconds(10)).until {258 trackableDispatcher.isSubmittedTaskInvoked(1..12)259 }260 trackableDispatcher.completeAllAndClose();261 }262 @Test263 fun `decreasing window size reduces limit`() {264 val trackableDispatcher = TrackableDispatcher()265 trackableDispatcher.windowProperty.set(10)266 trackableDispatcher.submitTasks(1..10)267 sleep(4000)268 trackableDispatcher.isSubmittedTaskInvoked(1..10).shouldBeTrue()269 trackableDispatcher.completeTasks(1..10)270 trackableDispatcher.windowProperty.set(4)271 trackableDispatcher.submitTasks(11..15)272 sleep(4000)273 trackableDispatcher.isSubmittedTaskInvoked(11..14).shouldBeTrue()274 trackableDispatcher.isSubmittedTaskInvoked(15).shouldBeFalse()275 trackableDispatcher.completeTask(11)276 await().atMost(Duration.ofSeconds(10)).until {277 trackableDispatcher.isSubmittedTaskInvoked(15)278 }279 trackableDispatcher.completeAllAndClose();280 }281 /**282 * When dispatcher closingTimeout is enough for pending tasks to complete283 * such tasks will complete normally284 */285 @Test286 fun `on shutdown fast tasks complete normally`() {287 val dispatch = createDispatcher(closingTimeout = 5_000)288 assertTimeoutPreemptively(Duration.ofSeconds(10)) {289 val blockingTaskIsStarted = CountDownLatch(1)290 dispatch.compose {291 blockingTaskIsStarted.countDown()292 //Due to blocking nature of dispatch.close we hae to use sleep293 Thread.sleep(1000)294 completedFuture(true)295 }296 val futures = List(3) {297 dispatch.compose {298 completedFuture(true)299 }300 }301 blockingTaskIsStarted.await()302 dispatch.close()303 CompletableFuture.allOf(*futures.toTypedArray()).exceptionally { null }.join()304 futures.forEach { future: CompletableFuture<*> ->305 future.isDone.shouldBeTrue()306 future.isCompletedExceptionally.shouldBeFalse()307 }308 }309 }310 @Test311 fun `on shutdown slow tasks complete exceptionally`() {312 val dispatch = createDispatcher(closingTimeout = 0)313 assertTimeoutPreemptively(Duration.ofSeconds(5)) {314 val blockingTaskIsStarted = CountDownLatch(1)315 dispatch.compose {316 blockingTaskIsStarted.countDown()317 //Due to blocking nature of dispatch.close we hae to use sleep318 Thread.sleep(1000)319 completedFuture(true)320 }321 val futures = ArrayList<CompletableFuture<*>>()322 for (i in 1..3) {323 futures.add(dispatch.compose {324 completedFuture(true)325 })326 }327 blockingTaskIsStarted.await()328 dispatch.close()329 CompletableFuture.allOf(*futures.toTypedArray()).exceptionally { null }.join()330 futures.forEach { future: CompletableFuture<*> ->331 future.isDone.shouldBeTrue()332 future.isCompletedExceptionally.shouldBeTrue()333 shouldThrow<ExecutionException> { future.get() }334 .cause.shouldBeInstanceOf<RejectedExecutionException>()335 }336 }337 }338 @Test339 fun `task, submitted in closed dispatcher, is rejected with exception`() {340 val dispatcher = createDispatcher()341 dispatcher.close()342 val result = dispatcher.compose {343 completedFuture(true)344 }345 await().atMost(Duration.ofSeconds(2)).until {346 result.isCompletedExceptionally347 }348 shouldThrow<ExecutionException> { result.get() }349 .cause.shouldBeInstanceOf<RejectedExecutionException>()350 }351 fun createDispatcher(352 rateLimitRequestPerSecond: Int = 500,353 window: DynamicProperty<Int> = DynamicProperty.of(0),354 closingTimeout: Int = 5000,355 profiler: Profiler = NoopProfiler()) =356 RateLimitedDispatcher(357 DISPATCHER_NAME,358 ConfigurableRateLimiter("rate-limiter-name", rateLimitRequestPerSecond),359 profiler,360 window,361 DynamicProperty.of(closingTimeout.toLong())362 )363 inner class TrackableDispatcher(364 profiler: Profiler = NoopProfiler()365 ) {366 val windowProperty = AtomicProperty(0)367 val dispatcher = createDispatcher(profiler = profiler, window = windowProperty)368 val submittedTasksResults = HashMap<Int, CompletableFuture<Any?>>()369 val isSubmittedTaskInvoked = HashMap<Int, AtomicBoolean>()370 fun submitCompletedTasks(tasks: IntRange) {371 for (task in tasks) {372 submitCompletedTask(task)373 }374 }375 fun submitTasks(tasks: IntRange) {376 for (task in tasks) {377 submitTask(task)378 }379 }380 fun submitCompletedTask(taskIndex: Int) = submitTask(taskIndex, completedFuture(taskIndex))381 fun submitTask(taskIndex: Int) = submitTask(taskIndex, CompletableFuture())382 private fun submitTask(taskIndex: Int, future: CompletableFuture<Any?>) {383 submittedTasksResults[taskIndex] = future384 isSubmittedTaskInvoked[taskIndex] = AtomicBoolean(false)385 dispatcher.compose {386 isSubmittedTaskInvoked[taskIndex]!!.set(true)387 future388 }389 }390 fun completeTask(taskIndex: Int) {391 submittedTasksResults[taskIndex]!!.complete(taskIndex)392 }393 fun completeTasks(range: IntRange) {394 for (task in range) {395 submittedTasksResults[task]!!.complete(task)396 }397 }398 fun isSubmittedTaskInvoked(index: Int) = isSubmittedTaskInvoked[index]!!.get()399 fun isSubmittedTaskInvoked(range: IntRange) = range.all { isSubmittedTaskInvoked[it]!!.get() }400 fun completeAllAndClose() {401 submittedTasksResults.forEach { (_, future) -> future.complete(true) }402 await().atMost(Duration.ofSeconds(10)).until {403 isSubmittedTaskInvoked.all { it.value.get() }404 }405 dispatcher.close()406 }407 }408 @Test409 fun `invoke suspend function wrapped to completable future`() {410 val dispatcher = createDispatcher()411 val suspendFunctionInvoked = AtomicBoolean(false)412 suspend fun mySuspendFunction(): String{413 delay(1000)414 suspendFunctionInvoked.set(true)415 return "suspend-function-result"416 }417 runBlocking {418 val result = dispatcher.compose { future { mySuspendFunction() } }.await()419 suspendFunctionInvoked.get().shouldBeTrue()420 result.shouldBe("suspend-function-result")421 }422 }423}...

Full Screen

Full Screen

Between.kt

Source:Between.kt Github

copy

Full Screen

1package io.kotest.matchers.doubles2import io.kotest.matchers.Matcher3import io.kotest.matchers.MatcherResult4import io.kotest.matchers.shouldBe5import io.kotest.matchers.shouldNotBe6import kotlin.math.abs7/**8 * Asserts that this [Double] is in the interval [[a]-[tolerance] , [b]+[tolerance]]9 *10 * Verifies that this [Double] is greater than or equal to ([a] - [tolerance]) and less than or equal to ([b] + [tolerance])11 *12 * Opposite of [Double.shouldNotBeBetween]13 *14 * ```15 * 0.5.shouldBeBetween(0.2, 0.7, 0.0) // Assertion passes16 * 0.5.shouldBeBetween(0.2, 0.3, 0.0) // Assertion fails17 * 0.5.shouldBeBetween(0.2, 0.3, 0.2) // Assertion passes18 * 0.5.shouldBeBetween(0.2, 0.3, 0.1) // Assertion fails19 * ```20 */21fun Double.shouldBeBetween(a: Double, b: Double, tolerance: Double) = this shouldBe between(a, b, tolerance)22/**23 * Asserts that this [Double] is NOT in the interval [[a]-[tolerance] , [b]+[tolerance]]24 *25 * Verifies that this [Double] is not:26 * - Greater than or equal to ([a] - [tolerance])27 * - Less than or equal to ([b] + [tolerance])28 *29 * If and only if both the assertions are true, which means that this [Double] is in the interval, this assertion fails.30 *31 * Opposite of [Double.shouldBeBetween]32 *33 *34 * ```35 * 0.5.shouldNotBeBetween(0.2, 0.7, 0.0) // Assertion fails36 * 0.5.shouldNotBeBetween(0.2, 0.3, 0.0) // Assertion passes37 * 0.5.shouldNotBeBetween(0.2, 0.3, 0.2) // Assertion fails38 * 0.5.shouldNotBeBetween(0.2, 0.3, 0.1) // Assertion passes39 * ```40 */41fun Double.shouldNotBeBetween(a: Double, b: Double, tolerance: Double) = this shouldNotBe between(a, b, tolerance)42/**43 * Matcher that matches doubles and intervals44 *45 * Verifies that a specific [Double] is in the interval [[a] - [tolerance] , [b] + [tolerance]].46 *47 * For example:48 *49 * 0.5 is in the interval [0.4 , 0.6], because 0.4 <= 0.5 <= 0.6.50 *51 * This matcher also includes the bonds of the interval, so:52 *53 * 0.5 is in the interval [0.5, 0.6] because 0.5 <= 0.5 <= 0.6.54 *55 * The parameter [tolerance] is used to allow a slightly wider range, to include possible imprecision, and can be 0.0.56 *57 * 0.5 is in the interval [0.6, 0.7] when there's a tolerance of 0.1, because (0.6 - 0.1) <= 0.5 <= (0.7 + 0.1)58 *59 * ```60 * 0.5 shouldBe between(0.1, 1.0, 0.0) // Assertion passes61 * 0.5 shouldNotBe between(1.0, 2.0, 0.1) // Assertion passes62 * ```63 *64 * @see [Double.shouldBeBetween]65 * @see [Double.shouldNotBeBetween]66 */67fun between(a: Double, b: Double, tolerance: Double): Matcher<Double> = object : Matcher<Double> {68 override fun test(value: Double): MatcherResult {69 val differenceToMinimum = value - a70 val differenceToMaximum = b - value71 if (differenceToMinimum < 0 && abs(differenceToMinimum) > tolerance) {72 return MatcherResult(false, "$value should be bigger than $a", "$value should not be bigger than $a")73 }74 if (differenceToMaximum < 0 && abs(differenceToMaximum) > tolerance) {75 return MatcherResult(false, "$value should be smaller than $b", "$value should not be smaller than $b")76 }77 return MatcherResult(true,78 "$value should be smaller than $b and bigger than $a",79 "$value should not be smaller than $b and should not be bigger than $a")80 }81}...

Full Screen

Full Screen

OrNullTest.kt

Source:OrNullTest.kt Github

copy

Full Screen

1package com.sksamuel.kotest.property.arbitrary2import io.kotest.assertions.retry3import io.kotest.assertions.throwables.shouldThrow4import io.kotest.core.spec.style.FunSpec5import io.kotest.inspectors.forAll6import io.kotest.matchers.doubles.plusOrMinus7import io.kotest.matchers.ints.shouldBeBetween8import io.kotest.matchers.shouldBe9import io.kotest.property.Arb10import io.kotest.property.RandomSource11import io.kotest.property.Sample12import io.kotest.property.arbitrary.constant13import io.kotest.property.arbitrary.int14import io.kotest.property.arbitrary.long15import io.kotest.property.arbitrary.orNull16import io.kotest.property.forAll17import kotlin.time.Duration.Companion.seconds18class OrNullTest : FunSpec({19 test("Arb.orNull() should add null values to those generated") {20 val iterations = 100021 val classifications =22 forAll(iterations, Arb.int().orNull()) { num ->23 classify(num == null, "null", "non-null")24 true25 }.classifications()26 classifications["null"]?.shouldBeBetween(300, 600)27 classifications["non-null"]?.shouldBeBetween(300, 600)28 }29 test("null probability values can be specified") {30 retry(3, timeout = 2.seconds, delay = 0.1.seconds) {31 listOf(0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 1.0)32 .forAll { p: Double ->33 val nullCount = Arb.long().orNull(nullProbability = p).samples(RandomSource.default())34 .map(Sample<Long?>::value)35 .take(1000)36 .filter { it == null }37 .count()38 (nullCount.toDouble() / 1000) shouldBe (p plusOrMinus 0.05)39 }40 }41 }42 test("invalid null probability raise an IllegalArgumentException") {43 listOf(1.01, -0.1, 4.9, 99.9)44 .forAll { illegalVal ->45 shouldThrow<IllegalArgumentException> { Arb.long().orNull(nullProbability = illegalVal) }46 }47 }48 test("functions can be supplied to determine null frequency") {49 listOf(true, false).forAll { isNextNull: Boolean ->50 val allNull = Arb.int().orNull(isNextNull = { isNextNull }).samples(RandomSource.default())51 .map(Sample<Int?>::value)52 .take(100)53 .all { it == null }54 allNull shouldBe isNextNull55 }56 }57 test("orNull has a shrink to null"){58 val iterations = 100059 val rs = RandomSource.default()60 val classifications =61 forAll(iterations, Arb.constant(Arb.int().orNull())) { orNullArb ->62 val sample = orNullArb.sample(rs)63 val hasNullShrink = sample.shrinks.children.value.map{it.value()}.any{it == null}64 classify(hasNullShrink, "nullShrink", "noNullShrink")65 true66 }.classifications()67 classifications["nullShrink"]?.shouldBeBetween(800, 1000)68 classifications["noNullShrink"]?.shouldBeBetween(0, 200)69 }70})...

Full Screen

Full Screen

Double.shouldBeBetween

Using AI Code Generation

copy

Full Screen

1Double . shouldBeBetween ( 0.0 , 10.0 )2Double . shouldBeBetween ( 0.0 , 10.0 , 0.1 )3Int . shouldBeBetween ( 0 , 10 )4Int . shouldBeBetween ( 0 , 10 , 1 )5Long . shouldBeBetween ( 0L , 10L )6Long . shouldBeBetween ( 0L , 10L , 1L )7Short . shouldBeBetween ( 0.toShort () , 10.toShort () )8Short . shouldBeBetween ( 0.toShort () , 10.toShort () , 1.toShort () )9"abc" . shouldBeBetween ( "a" , "z" )10"abc" . shouldBeBetween ( "a" , "z" , true )11"abc" . shouldBeBetween ( "a" , "z" , true , true )12UInt . shouldBeBetween ( 0U , 10U )13UInt . shouldBeBetween ( 0U , 10U , 1U )

Full Screen

Full Screen

Double.shouldBeBetween

Using AI Code Generation

copy

Full Screen

1Double . shouldBeBetween ( 1.0 , 5.0 , 2.0 )2Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 )3Double . shouldBeBetween ( 1.0 , 5.0 , 2.0 , 3.0 )4Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 , 3.0 )5Double . shouldBeBetween ( 1.0 , 5.0 , 2.0 , 6.0 , 3.0 )6Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 , 2.0 , 3.0 )7Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 , 2.0 , 3.0 , 4.0 )8Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 , 2.0 , 3.0 , 4.0 , 5.0 )9Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 )10Double . shouldBeBetween ( 1.0 , 5.0 , 6.0 , 2.0 , 3.0 ,

Full Screen

Full Screen

Double.shouldBeBetween

Using AI Code Generation

copy

Full Screen

1 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)2 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)3 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)4 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)5 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)6 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)7 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)8 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)9 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)10 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)11 io.kotest.matchers.doubles.shouldBeBetween(1.0, 2.0)

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Kotest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful