def test_no_invert_invert(circuit): """_not__not_name has no special meaning.""" edzed.Not('src').connect(edzed.Const(True)) edzed.FuncBlock('F', func=lambda x: x).connect('_not_src') edzed.FuncBlock('T', func=lambda x: x).connect('_not__not_src') with pytest.raises(Exception, match="not found"): init(circuit)
def test_invert(circuit): """Shortcut '_not_blk' creates an inverter block connected to blk.""" src = edzed.Input('src', allowed=(True, False), initdef=False) id1 = edzed.FuncBlock('identity1', func=lambda x: x).connect('src') id2 = edzed.FuncBlock('identity2', func=lambda x: x).connect('_not_src') # verify that _not_src shortcut may be used multiple times id3 = edzed.FuncBlock('identity3', func=lambda x: x).connect('_not_src') # _not_src does not exist yet assert sum(1 for blk in circuit.getblocks()) == 4 with pytest.raises(KeyError): circuit.findblock('_not_src') init(circuit) # _not_src was just created automatically by finalize() assert sum(1 for blk in circuit.getblocks()) == 5 invert = circuit.findblock('_not_src') for value in (True, False, True, False): src.put(value) invert.eval_block() id1.eval_block() id2.eval_block() id3.eval_block() assert id1.output is value assert id2.output is id3.output is not value
def test_debug(circuit): """Test set_debug().""" def blocks_set(): return [i for i, blk in enumerate(blocks) if blk.debug] blocks = [ edzed.FuncBlock('F1', func=lambda: None), # CBlock edzed.FuncBlock('F2', func=lambda: None), # CBlock edzed.Timer('T1'), # SBlock edzed.Timer('T2'), # SBlock ] assert blocks_set() == [] assert circuit.set_debug(True, '*') == 4 # check real block count without duplicates assert circuit.set_debug(True, '*', *blocks, 'F1', 'F1') == 4 assert blocks_set() == [0, 1, 2, 3] assert circuit.set_debug(False, blocks[0]) == 1 assert blocks_set() == [1, 2, 3] assert circuit.set_debug(False, 'F2') == 1 assert blocks_set() == [2, 3] assert circuit.set_debug(True, edzed.CBlock) == 2 assert blocks_set() == [0, 1, 2, 3] assert circuit.set_debug(False, '?2') == 2 assert blocks_set() == [0, 2]
def test_getblocks(circuit): """Test getblocks() and findblock().""" # 1 Const, 2 CBlocks and 2 SBlocks edzed.Const(0) f1 = edzed.FuncBlock('F1', func=lambda: None) # CBlock f2 = edzed.FuncBlock('F2', func=lambda: None) # CBlock t1 = edzed.Timer('T1') # SBlock t2 = edzed.Timer('T2') # SBlock assert circuit.findblock('F1') is f1 assert circuit.findblock('T2') is t2 assert set(circuit.getblocks()) == {f1, f2, t1, t2} assert not set(circuit.getblocks( btype=edzed.Const)) # Const blocks are not registered assert set(circuit.getblocks(btype=edzed.CBlock)) == {f1, f2} assert set(circuit.getblocks(btype=edzed.SBlock)) == {t1, t2}
def test_input_groups(circuit): """Input group is a sequence of input values.""" d4 = edzed.FuncBlock( '4 digits', func=lambda f4: 1000*f4[0] + 100*f4[1] + 10*f4[2] + f4[3] ).connect(f4=[edzed.Const(3), 5, 7, 9]) init(circuit) d4.eval_block() assert d4.output == 3579
async def test_instability_2(circuit): """Test a stable circuit that becomes instable.""" ctrl = edzed.Input('ctrl', initdef=False) edzed.FuncBlock('xor', func=lambda a, b: bool(a) != bool(b)).connect(ctrl, 'xor') simtask = asyncio.create_task(circuit.run_forever()) await circuit.wait_init() assert ctrl.output is not edzed.UNDEF # so far so good, but now create an instability ctrl.put(True) with pytest.raises(edzed.EdzedCircuitError, match="instability"): await asyncio.wait_for(simtask, timeout=1.0)
def test_missing_funcblock_inputs(circuit): """Incorrect number of inputs are an error.""" errblks = [ edzed.FuncBlock( 'test1', comment='2 expected, 3 given', func=lambda a1, a2: None ).connect(1, 2, 3), edzed.FuncBlock( 'test2', comment='2 expected, 1 given', func=lambda a1, a2: None ).connect(1), edzed.FuncBlock( 'test3', comment='a1 name missing', func=lambda a1, a2: None ).connect(a2=2), edzed.FuncBlock( 'test4', comment='a3 name unexpected', func=lambda a1, a2: None ).connect(a1=1, a2=2, a3=3), ] circuit.finalize() for blk in errblks: with pytest.raises(TypeError, match="does not match the connected inputs"): blk.start()
def test_named_inputs(circuit): """ Named inputs are ordered by name. This test also covers that no unnamed inputs is a special case in FuncBlock. """ d4 = edzed.FuncBlock( '4 digits', func=lambda a, b, c, d: 1000*a + 100*b + 10*c + d ).connect(d=9, c=edzed.Const(1), a=2, b=edzed.Const(0)) init(circuit) d4.eval_block() assert d4.output == 2019
def test_unnamed_inputs(circuit): """ Unnamed inputs are processed in order as they are connected. Const blocks are created on the fly. """ d4 = edzed.FuncBlock( '4 digits', func=lambda a, b, c, d: 1000*a + 100*b + 10*c + d ).connect(1, 9, 8, edzed.Const(4)) init(circuit) d4.eval_block() assert d4.output == 1984