-
Notifications
You must be signed in to change notification settings - Fork 88
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
Typed transitions #228
Typed transitions #228
Conversation
60fe275
to
be0a0e8
Compare
Unit Test Results 6 files ±0 76 suites +3 6m 35s ⏱️ +52s Results for commit ed7090d. ± Comparison against base commit ffd62cb. This pull request removes 14 and adds 9 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
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.
This is not really "boring Haskell" anymore but I like how this could make it easier to define generators for sequence of transitions and how it makes the State machine explicit and encoded in types. As long as we don't overdo it and keep it in this module and for this use case, I think it's an improvement.
I have to say, I exalt where this is taking the test code! I went through re-expressing the same properties as the ones we have in the I'd make a case for actually deprecating (a.k.a removing) the tests in TxSpec in favor of this new form, which gives us the same (if not more?) coverage. |
Tx -> | ||
OnChainHeadState st -> | ||
Maybe (OnChainTx Tx, SomeOnChainHeadState) | ||
Maybe (OnChainTx Tx, OnChainHeadState st') |
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.
I would like to have this named observeTransition
Not sure I want to commit that as this is venturing more and more in the lands of dependent-types... therefore adding complexity to the code for actually here little gain apart from a more descriptive module API. What motivated this change initially was an attempt at simplifying the underlying test-code where we do know exactly what transition we want to do. Thus, getting back an opaque 'SomeOnChainHeadState' forces some needless unwrapping via reify state. It ain't much, as we are really just talking about one case/pattern-match but still... that was the initial motivation. With this new approach, we can remove that extra pattern match on call-sites by using `transition` directly, with some type annotation as for the transition we expect and tada! Yet.. the definitions are a bit more complex now as I added a new type-class and some glue to make things work :/
can only apply/observe the same commit once.
Instead of writing the same 'is observed' property for each individual transitions.
… via QuickCheck. This is slightly involved but we get automatic coverage generation for free, telling us what transitions aren't covered by tests.
Enforced by code coverage! ``` observeTx All valid transitions for all possible states can be observed. +++ OK, passed 400 tests. Transition (400 in total): 19.0% StOpen -> StClosed 18.2% StClosed -> StIdle 17.0% StIdle -> StInitialized 16.0% StInitialized -> StIdle 15.0% StInitialized -> StInitialized 14.8% StInitialized -> StOpen ```
5ad0ed5
to
ed7090d
Compare
(Opening for the sake of discussion... the two last commits are probably salvageable but the first one is up to debate 😬).
📍 Make transitions visible at the type-level.
Not sure I want to commit that as this is venturing more and more in
the lands of dependent-types... therefore adding complexity to the
code for actually here little gain apart from a more descriptive
module API.
What motivated this change initially was an attempt at simplifying the
underlying test-code where we do know exactly what transition we want
to do. Thus, getting back an opaque 'SomeOnChainHeadState' forces some
needless unwrapping via reify state. It ain't much, as we are really
just talking about one case/pattern-match but still... that was the
initial motivation. With this new approach, we can remove that extra
pattern match on call-sites by using
transition
directly, with sometype annotation as for the transition we expect and tada! Yet.. the
definitions are a bit more complex now as I added a new type-class and
some glue to make things work :/
📍 write another property on commit transition.
can only apply/observe the same commit once.
📍 dry a bit the StateSpec: define forAllCommit.
📍 Add property tests for 'init' at the Direct.State level.
📍 Add property test for observing a CollectCom tx from the 'State' module perspective.
📍 Rename 'transition' -> 'observeTx'
📍 Minor cosmetic adjustments to StateSpec.
📍 Write a generic property for observing all possible transitions.
Instead of writing the same 'is observed' property for each individual transitions.
📍 Provide Eq / Show instances for Transition to enable generic coverage via QuickCheck.
This is slightly involved but we get automatic coverage generation for free, telling us what transitions aren't covered by tests.
📍 Move 'forAll2' to the test prelude.
📍 Add chain state tests for remaining transitions
Enforced by code coverage!
📍 Add classification for interesting scenarios to the generic state observation tests.
📍 Remove now redundant/obsolete tests from TxSpec.
📍 Also move the size specs to the chain state spec module.