def test_multiple_run_calls(callrpc_sg): """Make sure we can call run multiple times.""" sim = SensorGraphSimulator(callrpc_sg) sim.stop_condition('run_time 100 seconds') sim.run() # Make sure the sensor graph ran correctly last_input = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('system input 2')) last_output = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('unbuffered 2')) assert last_input.value == 100 assert last_output.value == 0 sim.run() # Make sure the sensor graph ran correctly last_input = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('system input 2')) last_output = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('unbuffered 2')) assert last_input.value == 200 assert last_output.value == 0
def test_stream_type_parsing(): """Make sure we can parse each type of stream.""" # Make sure parsing stream type works stream = DataStream.FromString('buffered 1') assert stream.stream_type == stream.BufferedType stream = DataStream.FromString(u'buffered 1') assert stream.stream_type == stream.BufferedType stream = DataStream.FromString('unbuffered 1') assert stream.stream_type == stream.UnbufferedType stream = DataStream.FromString(u'unbuffered 1') assert stream.stream_type == stream.UnbufferedType stream = DataStream.FromString('counter 1') assert stream.stream_type == stream.CounterType stream = DataStream.FromString(u'counter 1') assert stream.stream_type == stream.CounterType stream = DataStream.FromString('constant 1') assert stream.stream_type == stream.ConstantType stream = DataStream.FromString(u'constant 1') assert stream.stream_type == stream.ConstantType stream = DataStream.FromString('output 1') assert stream.stream_type == stream.OutputType stream = DataStream.FromString(u'output 1') assert stream.stream_type == stream.OutputType
def test_tick1(tick1_sg): """Make sure we receive tick_1 ticks in the simulation.""" assert tick1_sg.get_tick('user1') == 2 sim = SensorGraphSimulator(tick1_sg) sim.stop_condition('run_time 100 seconds') sim.run() # Make sure the sensor graph ran correctly last_input = tick1_sg.sensor_log.inspect_last( DataStream.FromString('system input 5')) last_output = tick1_sg.sensor_log.inspect_last( DataStream.FromString('counter 1')) assert last_input.value == 100 assert last_output.value == 100 sim.run() # Make sure the sensor graph ran correctly last_input = tick1_sg.sensor_log.inspect_last( DataStream.FromString('system input 5')) last_output = tick1_sg.sensor_log.inspect_last( DataStream.FromString('counter 1')) assert last_input.value == 200 assert last_output.value == 200
def test_seek_walker(): """Make sure we can seek a walker can count with an offset.""" model = DeviceModel() log = SensorLog(model=model) stream = DataStream.FromString('buffered 1') reading = IOTileReading(stream.encode(), 0, 1) log.push(stream, reading) log.push(stream, reading) log.push(DataStream.FromString('buffered 2'), reading) log.push(stream, reading) walk = log.create_walker(DataStreamSelector.FromString('buffered 1'), skip_all=False) assert walk.offset == 0 assert walk.count() == 3 walk.seek(1) assert walk.offset == 1 assert walk.count() == 2 # Make sure we can seek to a position corresponding to another stream walk.seek(2) assert walk.offset == 2 assert walk.count() == 1 # Make sure we can find a reading by reading ID walk = log.create_walker(DataStreamSelector.FromString('output 1'), skip_all=False) output1 = DataStream.FromString('output 1') output2 = DataStream.FromString('output 2') log.push(output1, IOTileReading(0, 0, 1, reading_id=1)) log.push(output1, IOTileReading(0, 0, 1, reading_id=2)) log.push(output2, IOTileReading(0, 0, 1, reading_id=3)) log.push(output1, IOTileReading(0, 0, 1, reading_id=4)) exact = walk.seek(2, target='id') assert exact is True assert walk.count() == 2 assert walk.offset == 1 exact = walk.seek(3, target='id') assert exact is False assert walk.count() == 1 assert walk.offset == 2 # Verify exceptions thrown by seek() with pytest.raises(UnresolvedIdentifierError): walk.seek(5, target='id') with pytest.raises(UnresolvedIdentifierError): walk.seek(5, target=u'id') with pytest.raises(UnresolvedIdentifierError): walk.seek(5, target='offset') with pytest.raises(ArgumentError): walk.seek(2, target="unsupported")
def test_on_block_dual(parser): """Make sure on with two conditions works.""" parser.parse_file(get_path(u'basic_on_dual.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() counter1 = log.create_walker(DataStreamSelector.FromString('counter 1')) sim = SensorGraphSimulator(sg) sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 0 sim.step(DataStream.FromString('input 2'), 1) for _i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 11 sim.step(DataStream.FromString('input 2'), 0) for _i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 11
def test_on_block(parser): """Make sure on count(stream), on value(stream) and on stream work.""" parser.parse_file(get_path(u'basic_on.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() counter1 = log.create_walker(DataStreamSelector.FromString('counter 1')) counter2 = log.create_walker(DataStreamSelector.FromString('counter 2')) counter3 = log.create_walker(DataStreamSelector.FromString('counter 3')) sim = SensorGraphSimulator(sg) sim.step(DataStream.FromString('input 1'), 8) assert counter1.count() == 0 assert counter2.count() == 0 assert counter3.count() == 0 for i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 10 assert counter2.count() == 5 assert counter3.count() == 5
def test_when_block_clock(parser): """Make sure we can compile when blocks (without identifiers).""" parser.parse_file(get_path(u'basic_when.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() assert sg.get_tick('fast') == 1 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert counter15.count() == 0 sim.step(DataStream.FromString('system input 1025'), 8) assert counter15.count() == 1 counter15.skip_all() sim.run() assert counter15.count() == 60 counter15.skip_all() sim.step(DataStream.FromString('system input 1026'), 8) sim.run() assert counter15.count() == 0
def test_stringification(): """Make sure we can stringify DataStream objects.""" stream1 = DataStream.FromString('system buffered 1') stream2 = DataStream.FromString('buffered 0xF') assert str(stream1) == str('system buffered 1') assert str(stream2) == str('buffered 15')
def test_system_parsing(): """Make sure we can parse the system prefix.""" stream = DataStream.FromString('buffered 1') assert stream.system is False stream = DataStream.FromString(u'buffered 1') assert stream.system is False stream = DataStream.FromString('system buffered 1') assert stream.system is True stream = DataStream.FromString(u'system buffered 1') assert stream.system is True
def test_complex_gate_optimization(complex_gate, complex_gate_opt): """Make sure the optimized version runs identically to the unoptimized.""" sg, sg_opt = complex_gate, complex_gate_opt sim1 = SensorGraphSimulator(sg) sim1.stop_condition("run_time 10 minutes") sg.load_constants() sim1.record_trace() sim1.run() sim2 = SensorGraphSimulator(sg_opt) sim2.stop_condition("run_time 10 minutes") sg_opt.load_constants() sim2.record_trace() sim2.run() assert len(sim1.trace) == 0 assert len(sim2.trace) == 0 sim1.step(DataStream.FromString("system input 1034"), 1) sim2.step(DataStream.FromString("system input 1034"), 1) sim1.run() sim2.run() print("Unoptimized Output") for x in sim1.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) print("\nOptimized Output") for x in sim2.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) assert len(sim1.trace) == 4 assert len(sim2.trace) == 4 assert sim1.trace == sim2.trace #Check that number of trigger streamer commands is same for optimized and unoptimized trigger_nodes = [ node for node in complex_gate.nodes if node.func_name == 'trigger_streamer' ] trigger_nodes_opt = [ node for node in complex_gate_opt.nodes if node.func_name == 'trigger_streamer' ] assert len(trigger_nodes) == len(trigger_nodes_opt)
def test_basic_sensorgraph(): """Make sure we can parse, load and run a basic sensor graph.""" model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node('(input 1 always && input 2 when count >= 1) => unbuffered 1 using copy_all_a') sg.process_input(DataStream.FromString('input 1'), IOTileReading(0, 1, 1), rpc_executor=None) sg.process_input(DataStream.FromString('input 2'), IOTileReading(0, 1, 1), rpc_executor=None) assert sg.sensor_log.inspect_last(DataStream.FromString('unbuffered 1')).value == 1
def test_stream_id_parsing(): """Make sure we can parse stream ids.""" stream = DataStream.FromString('buffered 1') assert stream.stream_id == 1 stream = DataStream.FromString('buffered 0x100') assert stream.stream_id == 0x100 stream = DataStream.FromString(u'buffered 1') assert stream.stream_id == 1 stream = DataStream.FromString(u'buffered 0x100') assert stream.stream_id == 0x100
def test_rpc_sim(callrpc_sg): """Make sure we can run a very simple sensor graph and have it work.""" sim = SensorGraphSimulator(callrpc_sg) sim.stop_condition('run_time 1000 seconds') sim.run() # Make sure the sensor graph ran correctly last_input = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('system input 2')) last_output = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('unbuffered 2')) assert last_input.value == 1000 assert last_output.value == 0
def test_walker_at_beginning(): """Make sure we can start a walker at the beginning of a stream.""" model = DeviceModel() log = SensorLog(model=model) stream = DataStream.FromString('buffered 1') reading = IOTileReading(stream.encode(), 0, 1) log.push(stream, reading) log.push(stream, reading) log.push(DataStream.FromString('buffered 2'), reading) walk = log.create_walker(DataStreamSelector.FromString('buffered 1'), skip_all=False) assert walk.offset == 0 assert walk.count() == 2
def test_counter_walker(): """Make sure counter walkers work correctly.""" model = DeviceModel() log = SensorLog(model=model) walk = log.create_walker(DataStreamSelector.FromString('counter 1')) stream = DataStream.FromString('counter 1') reading = IOTileReading(0, 1, 1) assert walk.count() == 0 log.push(stream, IOTileReading(0, 1, 1)) assert walk.count() == 1 assert walk.peek().value == 1 log.push(stream, IOTileReading(0, 1, 3)) assert walk.count() == 2 assert walk.peek().value == 3 val = walk.pop() assert walk.count() == 1 assert val.value == 3 val = walk.pop() assert walk.count() == 0 assert val.value == 3 with pytest.raises(StreamEmptyError): walk.pop()
def test_copy_constant_statement(parser): """Make sure we can copy constant values.""" parser.parse_file(get_path(u'basic_copy_constant.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output1 = log.create_walker(DataStreamSelector.FromString('output 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 10 seconds') sim.run() assert output1.count() == 1 assert output1.pop().value == 15 sim.step(DataStream.FromString('input 1'), 10) assert output1.count() == 1 assert output1.pop().value == 0x10
def test_storage_streaming_walkers(): """Make sure the storage and streaming walkers work simultaneously.""" model = DeviceModel() log = SensorLog(model=model) storage_walk = log.create_walker(DataStreamSelector.FromString('buffered 1')) output_walk = log.create_walker(DataStreamSelector.FromString('output 1')) storage1 = DataStream.FromString('buffered 1') storage2 = DataStream.FromString('buffered 2') output1 = DataStream.FromString('output 1') output2 = DataStream.FromString('output 2') assert storage_walk.offset == 0 assert output_walk.offset == 0 for i in range(0, 5000): reading = IOTileReading(0, 0, i) log.push(storage1, reading) log.push(storage2, reading) log.push(output1, reading) log.push(output2, reading) assert storage_walk.count() == (i + 1) assert output_walk.count() == (i + 1) assert storage_walk.offset == 0 assert output_walk.offset == 0 for i in range(0, 5000): reading1 = storage_walk.pop() reading2 = output_walk.pop() assert reading1.value == i assert reading1.stream == storage1.encode() assert reading2.value == i assert reading2.stream == output1.encode() assert storage_walk.offset == (2 * i) + 1 assert output_walk.offset == (2* i) + 1 log.clear() assert storage_walk.count() == 0 assert storage_walk.offset == 0 assert output_walk.count() == 0 assert output_walk.offset == 0
def test_user_tick_optimization(usertick_gate, usertick_gate_opt): """Make sure the optimized version runs identically to the unoptimized.""" sg, sg_opt = usertick_gate, usertick_gate_opt for node in sg_opt.nodes: print(node) sim1 = SensorGraphSimulator(sg) sim1.stop_condition("run_time 10 minutes") sg.load_constants() sim1.record_trace() sim1.run() sim2 = SensorGraphSimulator(sg_opt) sim2.stop_condition("run_time 10 minutes") sg_opt.load_constants() sim2.record_trace() sim2.run() assert len(sim1.trace) == 0 assert len(sim2.trace) == 0 sim1.step(DataStream.FromString("system input 1034"), 1) sim2.step(DataStream.FromString("system input 1034"), 1) sim1.run() sim2.run() print("Unoptimized Output") for x in sim1.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) print("\nOptimized Output") for x in sim2.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) assert len(sim1.trace) == 4 assert len(sim2.trace) == 4 assert sim1.trace == sim2.trace
def test_important_inputs(): """Make sure we support matching important inputs and outputs.""" imp_stream = DataStream.FromString('system input 1024') imp_store_stream = DataStream.FromString('system input 1536') assert imp_stream.important is True assert imp_store_stream.important is True assert imp_stream.associated_stream() == DataStream.FromString( 'system output 1024') assert imp_store_stream.associated_stream() == DataStream.FromString( 'system buffered 1536') random_stream = DataStream.FromString('unbuffered 1024') assert random_stream.important is False with pytest.raises(InternalError): random_stream.associated_stream()
def test_fill_stop(): """Make sure we can configure SensorLog into fill-stop mode.""" model = DeviceModel() log = SensorLog(model=model) storage = DataStream.FromString('buffered 1') output = DataStream.FromString('output 1') reading = IOTileReading(0, 0, 1) # Neither fill-stop for _i in range(0, 50000): log.push(storage, reading) for _i in range(0, 50000): log.push(output, reading) log.clear() log.set_rollover('storage', False) with pytest.raises(StorageFullError): for _i in range(0, 50000): log.push(storage, reading) for _i in range(0, 50000): log.push(output, reading) assert log.count() == (16128, 48720) log.clear() log.set_rollover('streaming', False) with pytest.raises(StorageFullError): for _i in range(0, 50000): log.push(storage, reading) with pytest.raises(StorageFullError): for _i in range(0, 50000): log.push(output, reading) assert log.count() == (16128, 48896)
def test_encoding(): """Test data stream and selector encoding.""" sel = DataStreamSelector.FromString(u'all system output') assert sel.encode() == 0x5FFF sel = DataStreamSelector.FromString(u'all user output') assert sel.encode() == 0x57FF sel = DataStreamSelector.FromString(u'all output') assert sel.encode() == 0xD7FF sel = DataStreamSelector.FromString(u'all combined output') assert sel.encode() == 0xDFFF stream = DataStream.FromString('output 1') assert stream.encode() == 0x5001 stream = DataStream.FromString('unbuffered 10') assert stream.encode() == 0x100a
def callrpc_sg(): model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node( '(system input 2 always && constant 1 always) => unbuffered 2 using call_rpc' ) log.push(DataStream.FromString('constant 1'), IOTileReading(0, 0, 0x000a8000)) return sg
def test_when_block_on_event(parser): """Make sure on connect and on disconnect work.""" parser.parse_file(get_path(u'basic_when_on.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() sim = SensorGraphSimulator(sg) # We should only get a reading in unbuffered 1 on connect and unbuffered 2 on disconnect with pytest.raises(StreamEmptyError): log.inspect_last(DataStream.FromString('unbuffered 2')) sim.step(DataStream.FromString('system input 1025'), 8) assert log.inspect_last(DataStream.FromString('unbuffered 1')).value == 0 with pytest.raises(StreamEmptyError): log.inspect_last(DataStream.FromString('unbuffered 2')) sim.step(DataStream.FromString('system input 1026'), 8) assert log.inspect_last(DataStream.FromString('unbuffered 2')).value == 0
def declare_stream(string_name): """Create a StreamDeclaration from a string name. This will encode the string name into a 16-bit stream identifier. Args: string_name (str): The human-readable name of the stream. Returns: int: The stream declaration. """ return DataStream.FromString(string_name).encode()
def test_latch_block(parser): """Make sure that we can compile and run latch blocks.""" parser.parse_file(get_path(u'basic_latch.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() assert sg.get_tick('fast') == 1 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert counter15.count() == 0 sim.step(DataStream.FromString('input 10'), 1) assert log.inspect_last(DataStream.FromString('constant 1')).value == 1 assert log.inspect_last(DataStream.FromString('constant 1024')).value == 1 counter15.skip_all() sim.run() assert counter15.count() == 60 counter15.skip_all() sim.step(DataStream.FromString('input 10'), 0) sim.run() assert counter15.count() == 0
def test_subtract_statement(parser): """Make sure we can copy data using subtract.""" parser.parse_file(get_path(u'basic_subtract.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output1 = log.create_walker(DataStreamSelector.FromString('unbuffered 1')) output2 = log.create_walker(DataStreamSelector.FromString('unbuffered 2')) output3 = log.create_walker(DataStreamSelector.FromString('unbuffered 3')) sg.process_input(DataStream.FromString('input 1'), IOTileReading(0, 0, 15), None) sg.process_input(DataStream.FromString('input 2'), IOTileReading(0, 0, 20), None) sg.process_input(DataStream.FromString('input 3'), IOTileReading(0, 0, 25), None) assert output1.count() == 1 assert output2.count() == 1 assert output3.count() == 1 val1 = output1.pop() val2 = output2.pop() val3 = output3.pop() assert val1.value == 5 assert val2.value == 10 assert val3.value == 25
def test_triggering_streamers(): model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node('(input 1 always) => output 1 using copy_all_a') sg.add_node('(input 1 always) => output 2 using copy_all_a') sg.add_streamer(parse_string_descriptor('streamer on output 1')) sg.add_streamer( parse_string_descriptor('manual streamer on output 2 with streamer 0')) triggered = sg.check_streamers() assert len(triggered) == 0 sg.process_input(DataStream.FromString('input 1'), IOTileReading(0, 1, 1), rpc_executor=None) triggered = sg.check_streamers() assert len(triggered) == 2
def test_constant_walker(): """Make sure constant walkers can be read any number of times.""" model = DeviceModel() log = SensorLog(model=model) walk = log.create_walker(DataStreamSelector.FromString('constant 1')) stream = DataStream.FromString('constant 1') reading = IOTileReading(0, 1, 1) log.push(stream, reading) assert walk.count() == 0xFFFFFFFF log.push(stream, reading) assert walk.count() == 0xFFFFFFFF val = walk.pop() assert walk.count() == 0xFFFFFFFF val = walk.pop() assert walk.count() == 0xFFFFFFFF
def test_storage_walker(): """Make sure the storage walker works.""" model = DeviceModel() log = SensorLog(model=model) walk = log.create_walker(DataStreamSelector.FromString('buffered 1')) stream = DataStream.FromString('buffered 1') storage_size = model.get('max_storage_buffer') erase_size = model.get('buffer_erase_size') for i in range(0, storage_size): reading = IOTileReading(0, stream.encode(), i) log.push(stream, reading) assert walk.count() == (i + 1) # Make sure the overwrite happens correctly old_count = walk.count() reading = IOTileReading(0, stream.encode(), storage_size) log.push(stream, reading) assert walk.count() == (old_count - erase_size + 1)
def test_unbuffered_walker(): """Make sure unbuffered walkers hold only 1 reading.""" model = DeviceModel() log = SensorLog(model=model) walk = log.create_walker(DataStreamSelector.FromString('unbuffered 1')) stream = DataStream.FromString('unbuffered 1') assert walk.count() == 0 log.push(stream, IOTileReading(0, 1, 1)) assert walk.count() == 1 assert walk.peek().value == 1 log.push(stream, IOTileReading(0, 1, 3)) assert walk.count() == 1 assert walk.peek().value == 3 val = walk.pop() assert walk.count() == 0 assert val.value == 3 with pytest.raises(StreamEmptyError): walk.pop()