mirror of
https://github.com/urbit/shrub.git
synced 2024-12-24 11:24:21 +03:00
b3901ab42f
git-subtree-dir: pkg/arvo git-subtree-mainline:9c8f40bf6c
git-subtree-split:c20e2a185f
77 lines
1.7 KiB
Plaintext
77 lines
1.7 KiB
Plaintext
:: Wrap tests in stateful philters
|
|
::
|
|
/+ ph
|
|
=, ph
|
|
|%
|
|
::
|
|
:: A philter is similar to a test in structure, but they don't
|
|
:: terminate and have a ++stay arm for saving their state.
|
|
::
|
|
:: They may be wrappped around a test with +wrap-philter.
|
|
::
|
|
++ philter
|
|
|* o=mold
|
|
|%
|
|
++ output
|
|
$~ [& ~ %wait ~]
|
|
$: thru=?
|
|
events=(list ph-event)
|
|
$= next
|
|
$% [%wait ~]
|
|
[%cont self=form]
|
|
==
|
|
==
|
|
++ form
|
|
$_ ^?
|
|
|%
|
|
++ stay *o
|
|
++ run |~(ph-input *output)
|
|
--
|
|
--
|
|
::
|
|
:: Run the inner test wrapped in the outer philter. The philter may
|
|
:: respond to any event that the test didn't consume. One use is to
|
|
:: mock outside services, like an Ethereum node or LetsEncrypt.
|
|
::
|
|
++ wrap-philter
|
|
|* [o=mold i=mold]
|
|
|= [outer=_*form:(philter o) inner=_*form:(ph i)]
|
|
^+ *form:(ph ,[o i])
|
|
|= input=ph-input
|
|
=/ res-i=_*output:(ph i)
|
|
(inner input)
|
|
?. thru.res-i
|
|
:+ thru.res-i events.res-i
|
|
?- -.next.res-i
|
|
%wait [%wait ~]
|
|
%cont [%cont ..$(inner self.next.res-i)]
|
|
%fail [%fail ~]
|
|
%done [%done stay:outer value.next.res-i]
|
|
==
|
|
=/ res-o=_*output:(philter o)
|
|
(run:outer input)
|
|
^+ *output:(ph ,[o i])
|
|
:+ thru.res-o (welp events.res-i events.res-o)
|
|
?- -.next.res-i
|
|
%wait
|
|
?- -.next.res-o
|
|
%wait [%wait ~]
|
|
%cont [%cont ..$(outer self.next.res-o)]
|
|
==
|
|
::
|
|
%cont
|
|
=. inner self.next.res-i
|
|
?- -.next.res-o
|
|
%wait [%cont ..$]
|
|
%cont [%cont ..$(outer self.next.res-o)]
|
|
==
|
|
::
|
|
%fail [%fail ~]
|
|
%done
|
|
?- -.next.res-o
|
|
%wait [%done stay:outer value.next.res-i]
|
|
%cont [%done stay:self.next.res-o value.next.res-i]
|
|
==
|
|
==
|
|
--
|