aboutsummaryrefslogtreecommitdiffstats
path: root/spec/rtnode_spec.moon
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-09-04 12:11:06 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commit75ac21597024def4c3c1dee34c19402b16f81cd2 (patch)
tree2adf180550bc395a51145d124b03d203559d43a6 /spec/rtnode_spec.moon
parentonly increment tick if IO was triggered (diff)
downloadalive-75ac21597024def4c3c1dee34c19402b16f81cd2.tar.gz
alive-75ac21597024def4c3c1dee34c19402b16f81cd2.zip
reroll RTNode tests
Diffstat (limited to 'spec/rtnode_spec.moon')
-rw-r--r--spec/rtnode_spec.moon195
1 files changed, 105 insertions, 90 deletions
diff --git a/spec/rtnode_spec.moon b/spec/rtnode_spec.moon
index 6ac7d15..f757067 100644
--- a/spec/rtnode_spec.moon
+++ b/spec/rtnode_spec.moon
@@ -1,37 +1,94 @@
import do_setup from require 'spec.test_setup'
import RTNode, Scope, SimpleRegistry from require 'alv'
-import T, Input, Op, Constant, IOStream from require 'alv.base'
+import T, Input, Op, Constant from require 'alv.base'
+
+class IOOp extends Op
+ new: (...) =>
+ super ...
+ @is_dirty = true
+
+ poll: => @is_dirty
+
+make_op = (Class, inputs={}) ->
+ with Class!
+ \setup inputs
setup do_setup
-class DirtyIO extends IOStream
- new: => super T.dirty_io
- dirty: => true
+describe 'RTNode', ->
+ describe 'constructor', ->
+ it 'takes result, children', ->
+ result = Constant.num 3
+
+ a = RTNode!
+ b = RTNode!
+ children = { a, b }
-op_with_inputs = (inputs) ->
- with Op!
- \setup inputs if inputs
+ node = RTNode :result, :children
-dirty_op = ->
- result = DirtyIO!
- input = Input.hot result
- result, input, op_with_inputs { input }
+ assert.is.equal result, node.result
+ assert.is.same children, node.children
-node_with_sideinput = (result, input) ->
- RTNode :result, side_inputs: { [result]: input }
+ it 'takes op and detects io_ops', ->
+ op = make_op Op
+ rtn = RTNode :op
+ assert.is.equal op, rtn.op
+ assert.is.same {}, rtn.io_ops
-describe 'RTNode', ->
- it 'wraps result, children', ->
- result = Constant.num 3
+ op = make_op IOOp
+ rtn = RTNode :op
+ assert.is.equal op, rtn.op
+ assert.is.same { op }, rtn.io_ops
+
+ describe 'detects Op inputs', ->
+ it '(hot -> side_input)', ->
+ sig = T.num\mk_sig!
+ inp = Input.hot sig
+ rtn = RTNode op: make_op Op, { inp }
+ assert.is.same { [sig]: inp }, rtn.side_inputs
+
+ it '(cold -> discard)', ->
+ rtn = RTNode op: make_op Op, { Input.cold T.num\mk_sig! }
+ assert.is.same {}, rtn.side_inputs
+
+ it "(childrens' results -> discard)", ->
+ child = RTNode op: make_op(Op), result: T.num\mk_sig 123
+ parent = RTNode children: { child }, op: make_op Op, { Input.hot child.result }
+ assert.is.same {}, parent.side_inputs
+
+ describe 'lifts up', ->
+ it 'side_inputs from children', ->
+ expected_inputs = {}
+ children = {}
+
+ for i=1,3
+ result = T.num\mk_sig!
+ input = Input.hot result
+ table.insert children, RTNode op: make_op Op, { input }
+ expected_inputs[result] = input
+
+ mid_rtn = RTNode children: children
+ out_rtn = RTNode children: { mid_rtn }
+
+ assert.is.same expected_inputs, mid_rtn.side_inputs
+ assert.is.same expected_inputs, out_rtn.side_inputs
+
+ it 'io_ops from children', ->
+ a_op = make_op IOOp
+ a_rtn = RTNode op: a_op
+
+ b_op = make_op IOOp
+ b_rtn = RTNode op: b_op
- a = RTNode!
- b = RTNode!
- children = { a, b }
+ c_op = make_op Op
+ c_rtn = RTNode op: c_op
- node = RTNode :result, :children
+ mid_rtn = RTNode children: { a_rtn, b_rtn, c_rtn }
+ out_op = make_op IOOp
+ out_rtn = RTNode children: { mid_rtn }, op: out_op
- assert.is.equal result, node.result
- assert.is.same children, node.children
+ assert.is.same { a_op, b_op }, mid_rtn.io_ops
+ assert.is.same { a_op, b_op, out_op }, out_rtn.io_ops
it ':type gets type and assets value', ->
node = RTNode result: Constant.num 2
@@ -43,7 +100,7 @@ describe 'RTNode', ->
it ':is_const', ->
result = Constant.num 2
pure = RTNode :result
- impure = node_with_sideinput result, {}
+ impure = RTNode op: make_op Op, { Input.hot T.num\mk_sig! }
assert.is.true pure\is_const!
assert.is.false impure\is_const!
@@ -55,7 +112,7 @@ describe 'RTNode', ->
it ':make_ref', ->
result = T.num\mk_sig 2
input = Input.hot result
- op = op_with_inputs { input }
+ op = make_op IOOp, { input }
thick = RTNode :result, :op, children: { RTNode!, RTNode! }
ref = thick\make_ref!
@@ -63,66 +120,35 @@ describe 'RTNode', ->
assert.is.equal thick.result, ref.result
assert.is.same thick.side_inputs, ref.side_inputs
assert.is.same {}, ref.children
+ assert.is.same {}, ref.io_ops
assert.is.nil ref.op
- it 'lifts up inputs from op', ->
- event = T.bang\mk_evt!
- event_input = Input.hot event
-
- value = T.num\mk_sig 4
- value_input = Input.hot value
-
- op = op_with_inputs { event_input, value_input }
- node = RTNode :op, result: value
-
- assert.is.equal op, node.op
- assert.is.same { [event]: event_input, [value]: value_input },
- node.side_inputs
-
- it 'does not lift up op inputs that are also children', ->
- child_result, child_input, child_op = dirty_op!
- result = T.num\mk_sig 4
- child = RTNode op: child_op, :result
-
- event = T.bang\mk_evt!
- event_input = Input.hot event
- input = Input.hot child
-
- op = op_with_inputs { event_input, input }
- node = RTNode :op, children: { child }
-
- assert.is.same { [event]: event_input, [child_result]: child_input },
- node.side_inputs
-
- it 'does not lift up op inputs that are cold', ->
- bang = T.bang\mk_const true
- bang_input = Input.hot bang
+ describe ':poll_io', ->
+ it 'polls all io_ops in tree', ->
+ child = RTNode op: make_op IOOp
+ node = RTNode children: { child }, op: make_op IOOp
- num = T.num\mk_const 2
- num_input = Input.cold num
+ sc = spy.on child.op, 'poll'
+ sn = spy.on node.op, 'poll'
+ node\poll_io!
- sym = T.sym\mk_sig 'hello'
- sym_input = Input.hot sym
+ assert.spy(sc).was_called_with match.ref child.op
+ assert.spy(sn).was_called_with match.ref node.op
- op = op_with_inputs { bang_input, num_input, sym_input }
- node = RTNode :op
+ it 'returns whether any ops were dirty', ->
+ child = RTNode op: make_op IOOp
+ node = RTNode children: { child }, op: make_op IOOp
- assert.is.same { [sym]: sym_input }, node.side_inputs
+ assert.is.true node\poll_io!
- it 'lifts up side_inputs from children', ->
- event_value = T.bang\mk_evt!
- event_input = Input.hot event_value
- event = RTNode op: op_with_inputs { event_input }
- assert.is.same { [event_value]: event_input }, event.side_inputs
+ child.op.is_dirty = false
+ assert.is.true node\poll_io!
- value_value = T.num\mk_sig 4
- value_input = Input.hot value_value
- value = RTNode op: op_with_inputs { value_input }
- assert.is.same { [value_value]: value_input }, value.side_inputs
+ node.op.is_dirty = false
+ assert.is.false node\poll_io!
- node = RTNode children: { event, value }
- assert.is.same { [event_value]: event_input, [value_value]: value_input },
- node.side_inputs
+ child.op.is_dirty = true
+ assert.is.true node\poll_io!
describe ':tick', ->
local a_value, a_child, a_input
@@ -130,11 +156,11 @@ describe 'RTNode', ->
before_each ->
a_value = T.num\mk_evt!
a_input = Input.hot a_value
- a_child = node_with_sideinput a_value, a_input
+ a_child = RTNode op: make_op Op, { a_input }
b_value = T.num\mk_evt!
b_input = Input.hot b_value
- b_child = node_with_sideinput b_value, b_input
+ b_child = RTNode op: make_op Op, { b_input }
it 'updates children when a side_input is dirty', ->
a_value\set 1
@@ -168,7 +194,7 @@ describe 'RTNode', ->
assert.is.true a_input\dirty!
assert.is.false b_input\dirty!
- op = op_with_inputs a: Input.hot a_value
+ op = make_op Op, { a: Input.hot a_value }
s = spy.on op, 'tick'
node = RTNode :op, children: { a_child, b_child }
@@ -181,21 +207,10 @@ describe 'RTNode', ->
assert.is.true a_input\dirty!
assert.is.false b_input\dirty!
- op = op_with_inputs { Input.hot b_value }
+ op = make_op Op, { Input.hot b_value }
s = spy.on op, 'tick'
node = RTNode :op, children: { a_child, b_child }
node\tick!
assert.spy(s).was_not_called!
-
- describe ':poll_io', ->
- it 'polls IOs referenced in side_inputs', ->
- io, input, op = dirty_op!
- node = RTNode :op
-
- s = spy.on io, 'poll'
- assert.is.same { [io]: input }, node.side_inputs
- node\poll_io!
-
- assert.spy(s).was_called_with match.ref io