-
Notifications
You must be signed in to change notification settings - Fork 90
feat: Add NestedHandlerTest to validate Nested behavior and enhance A… #1493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
1ae5fd3
857eefc
f6a102e
a8bdff0
991e6a7
1261545
d397522
9ba69f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| package kyo.kernel | ||
|
|
||
| import kyo.* | ||
| import kyo.kernel.* | ||
| import kyo.kernel.internal.* | ||
|
|
||
| class ArrowEffectNestedTest extends Test: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this belongs in ArrowEffect as a nested Suite?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. Let's avoid creating ad-hoc test classes, test files should have corresponding source files. |
||
|
|
||
| given [A, B]: CanEqual[A, B] = CanEqual.derived | ||
|
|
||
| sealed trait TestEffect extends ArrowEffect[Const[Int], Const[Int]] | ||
|
|
||
| def suspend(i: Int): Int < TestEffect = | ||
| ArrowEffect.suspend[Any](Tag[TestEffect], i) | ||
|
|
||
| val tag: Tag[TestEffect] = Tag[TestEffect] | ||
|
|
||
| def flatten[A, B, C](v: A < B < C): A < (B & C) = v.map(a => a) | ||
|
|
||
| "handle on Nested (unsafeGet path)" - { | ||
ahoy-jon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < S = | ||
| ArrowEffect.handle(tag, v): | ||
| [C] => (input, cont) => cont(input * 10) | ||
|
|
||
| "unwraps Nested and returns inner suspension" in { | ||
| val comp: Int < TestEffect = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
| val result: Int < TestEffect < Any = handle(nested) | ||
|
|
||
| assert(result == nested, "handleSimple should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult = handle(flattened) | ||
|
|
||
| assert(finalResult.eval == 50) | ||
| } | ||
| } | ||
|
|
||
| "handleFirst on Nested" - { | ||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < (S & TestEffect) = | ||
| ArrowEffect.handleFirst(tag, v)( | ||
| [C] => (input, cont) => cont(input * 10), | ||
| identity | ||
| ) | ||
|
|
||
| "done callback receives unwrapped value" in { | ||
| val comp = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
|
|
||
| val result = handle(nested) | ||
|
|
||
| assert(result == nested, "handleFirst should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult: Int < TestEffect = handle(flattened) | ||
| assert(finalResult.evalNow == Maybe(50)) | ||
| } | ||
| } | ||
|
|
||
| "handleLoop (stateless) on Nested" - { | ||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < S = | ||
| ArrowEffect.handleLoop(Tag[TestEffect], v): | ||
| [C] => (input, cont) => Loop.continue(cont(input * 10)) | ||
|
|
||
| "unwraps Nested and handles inner suspension" in { | ||
| val comp: Int < TestEffect = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
|
|
||
| val result = handle(nested) | ||
| assert(result == nested, "handleLoop should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult: Int < Any = handle(flattened) | ||
|
|
||
| assert(finalResult.eval == 50) | ||
| } | ||
| } | ||
|
|
||
| "handleLoop (stateful) on Nested" - { | ||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < S = | ||
| ArrowEffect.handleLoop(tag, 0, v)( | ||
| [C] => (input, state, cont) => Loop.continue(state + 1, cont((input + state) * 10)) | ||
| ) | ||
|
|
||
| "unwraps Nested and handles inner suspension" in { | ||
| val comp: Int < TestEffect = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
|
|
||
| val result = handle(nested) | ||
| assert(result == nested, "handleLoop should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult: Int < Any = handle(flattened) | ||
|
|
||
| assert(finalResult.eval == 50) | ||
| } | ||
|
|
||
| } | ||
|
|
||
| "handleLoop (stateful + done) on Nested" - { | ||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < S = | ||
| ArrowEffect.handleLoop(tag, 0, v)( | ||
| [C] => (input, state, cont) => Loop.continue(state + 1, cont(input * 10)), | ||
| (state, v) => v | ||
| ) | ||
|
|
||
| "unwraps Nested and handles inner suspension" in { | ||
| val comp: Int < TestEffect = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
|
|
||
| val result = handle(nested) | ||
| assert(result == nested, "handleLoop should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult: Int < Any = handle(flattened) | ||
|
|
||
| assert(finalResult.eval == 50) | ||
| } | ||
| } | ||
|
|
||
| "handleCatching on Nested" - { | ||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < S = | ||
| ArrowEffect.handleCatching(tag, v)( | ||
| [C] => (input, cont) => cont(input * 10), | ||
| recover = e => throw e | ||
| ) | ||
|
|
||
| "unwraps Nested and handles inner suspension" in { | ||
| val comp: Int < TestEffect = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
|
|
||
| val result = handle(nested) | ||
| assert(result == nested, "handleLoop should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult: Int < Any = handle(flattened) | ||
|
|
||
| assert(finalResult.eval == 50) | ||
| } | ||
| } | ||
|
|
||
| "handlePartial on Nested" - { | ||
|
|
||
| def handle[A, S](v: A < (S & TestEffect)): A < (S & TestEffect) = | ||
| ArrowEffect.handlePartial(tag, tag, v, Context.empty)( | ||
| stop = | ||
| false, | ||
| [C] => (input, cont) => cont(input * 10), | ||
| [C] => (input, cont) => cont(input * 10) | ||
| ) | ||
|
|
||
| "unwraps Nested and handles inner suspension" in { | ||
| val comp: Int < TestEffect = suspend(5) | ||
| val nested: Int < TestEffect < Any = Nested(comp) | ||
|
|
||
| val result = handle(nested) | ||
| assert(result == nested, "handlePartial should return the nested computation") | ||
|
|
||
| val flattened = flatten(result) | ||
| val finalResult = handle(flattened) | ||
| assert(finalResult.evalNow == Maybe(50)) | ||
| } | ||
| } | ||
|
|
||
| end ArrowEffectNestedTest | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package kyo.kernel.internal | ||
|
|
||
| import kyo.* | ||
|
|
||
| class NestedHandlerTest extends Test: | ||
| "bug #1412 - handler on Nested" - { | ||
| "Var.update through lift/flatten/run" in { | ||
| var executed = false | ||
|
|
||
| val comp: Unit < Var[Int] = Var.update[Int] { x => | ||
| executed = true | ||
| x + 1 | ||
| }.unit | ||
|
|
||
| val lifted: Unit < Var[Int] < Any = Nested(comp) // Kyo.lift(comp) | ||
|
|
||
| def flatten[A, B, C](v: A < B < C): A < (B & C) = v.map(a => a) | ||
|
|
||
| val step1 = Var.run(0)(lifted) | ||
| val step2 = flatten(step1) | ||
| val step3 = Var.run(0)(step2) | ||
|
|
||
| step3.eval | ||
| assert(executed, "Var.update body should have been executed") | ||
| } | ||
|
|
||
| "details" in { | ||
| given [A, B]: CanEqual[A, B] = CanEqual.derived | ||
|
|
||
| val update: Int < Var[Int] = Var.update[Int](_ + 1) | ||
| val nested: Int < Var[Int] < Any = Nested(update) | ||
| val handled: Int < Var[Int] < Any = Var.run(0)(nested) | ||
|
|
||
| assert(handled == nested, "Var.run should return the nested computation") | ||
| } | ||
| } | ||
|
|
||
| end NestedHandlerTest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice catch!