def test_wire_frame_implements_str(): pkt_1 = NetworkPacket(data=AppData(100)) pkt_2 = NetworkPacket(data=AppData(200)) frame_1 = WireFrame(pkt_1, header_size=10, preamble=1, duration=2) assert str(frame_1) == f'WireFrame[D=2,HDR=10,PR=1 | {pkt_1}]' frame_2 = WireFrame(pkt_2) assert str(frame_2) == f'WireFrame[D=0,HDR=0,PR=0 | {pkt_2}]'
def test_wired_transceiver_sends_data_up_when_rx_completed(): sim, sender, switch = Mock(), Mock(), Mock() sim.stime = 0 iface = WiredTransceiver(sim) sim.schedule.reset_mock() # clear sim.schedule(0, iface.start) call pkt = NetworkPacket(data=AppData(size=100)) frame = WireFrame(pkt, duration=0.5, header_size=20, preamble=0.01) switch_rev_conn = Mock() switch.connections.set = Mock(return_value=switch_rev_conn) iface.connections.set('up', switch, rname='iface') sender_conn = iface.connections.set('peer', sender, rname='peer') assert iface.rx_ready and not iface.rx_busy iface.handle_message(frame, sender=sender, connection=sender_conn) assert not iface.rx_ready and iface.rx_busy sim.schedule.assert_called_once_with( frame.duration, iface.handle_rx_end, args=(frame, ), ) sim.schedule.reset_mock() sim.stime += frame.duration iface.handle_rx_end(frame) sim.schedule.assert_called_once_with(0, switch.handle_message, args=(pkt, ), kwargs={ 'sender': iface, 'connection': switch_rev_conn, }) assert iface.rx_ready and not iface.rx_busy
def test_wire_frame_init_and_properties(): pkt_1 = NetworkPacket(data=AppData(100)) pkt_2 = NetworkPacket(data=AppData(200)) frame_1 = WireFrame(pkt_1, header_size=10, preamble=0.2, duration=1.5) assert frame_1.packet == pkt_1 assert frame_1.duration == 1.5 assert frame_1.header_size == 10 assert frame_1.preamble == 0.2 assert frame_1.size == 10 + pkt_1.size frame_2 = WireFrame(packet=pkt_2) assert frame_2.packet == pkt_2 assert frame_2.duration == 0 assert frame_2.header_size == 0 assert frame_2.preamble == 0 assert frame_2.size == 0
def test_wired_transceiver_ignores_frames_not_from_peer(): sim, sender, switch = Mock(), Mock(), Mock() sim.stime = 0 iface = WiredTransceiver(sim) sim.schedule.reset_mock() # clear sim.schedule(0, iface.start) call pkt = NetworkPacket(data=AppData(size=100)) frame = WireFrame(pkt, duration=0.5, header_size=20, preamble=0.01) iface.connections.set('up', switch, reverse=False) sender_conn = iface.connections.set('wrong_name', sender, reverse=False) iface.handle_message(frame, sender=sender, connection=sender_conn) sim.schedule.assert_not_called() assert iface.rx_ready
def test_wired_transceiver_drops_received_message_if_not_connected_to_switch(): sim, sender = Mock(), Mock() sim.stime = 0 iface = WiredTransceiver(sim) sender_conn = iface.connections.set('peer', sender, rname='peer') pkt = NetworkPacket(data=AppData(size=100)) frame = WireFrame(pkt, duration=0.5, header_size=20, preamble=0.01) iface.handle_message(frame, sender=sender, connection=sender_conn) sim.stime += frame.duration sim.schedule.reset_mock() iface.handle_rx_end(frame) sim.schedule.assert_not_called()
def test_wired_interface_forwards_frames_from_wire_to_transceiver(): sim, queue, transceiver, peer = Mock(), Mock(), Mock(), Mock() iface = WiredInterface(sim, 13, queue, transceiver) peer_conn = iface.connections.set('wire', peer, rname='wire') frame = WireFrame(NetworkPacket(data=AppData(size=100))) iface.handle_message(frame, connection=peer_conn, sender=peer) int_peer_conn = iface.connections['_peer'] sim.schedule.assert_called_once_with(0, transceiver.handle_message, args=(frame, ), kwargs={ 'connection': int_peer_conn.reverse, 'sender': iface })
def test_wired_transceiver_records_rx_statistics(bitrate, data_sizes, header_size, preamble, intervals): sim, sender = Mock(), Mock() sim.stime = 0 iface = WiredTransceiver(sim, bitrate, header_size, preamble) sender_conn = iface.connections.set('peer', sender, rname='peer') packets = [NetworkPacket(data=AppData(size=sz)) for sz in data_sizes] durations = [(sz + header_size) / bitrate + preamble for sz in data_sizes] frames = [ WireFrame(pkt, dt, header_size, preamble) for pkt, dt in zip(packets, durations) ] t, timestamps = 0, [] for interval, duration in zip(intervals, durations): t_arrival = t + interval t_departure = t_arrival + duration t = t_departure timestamps.append((t_arrival, t_departure)) # Simulating receive sequence for (t_arrival, t_departure), frame in zip(timestamps, frames): sim.stime = t_arrival iface.handle_message(frame, sender=sender, connection=sender_conn) sim.stime = t_departure iface.handle_rx_end(frame) # Check RX statistics: expected_busy_trace = [(0, 0)] for t_arrival, t_departure in timestamps: expected_busy_trace.append((t_arrival, 1)) expected_busy_trace.append((t_departure, 0)) assert iface.num_received_frames == len(frames) assert iface.num_received_bits == sum(frame.size for frame in frames) assert iface.rx_busy_trace.as_tuple() == tuple(expected_busy_trace)
def test_wired_interface_integration_receives_frame(): sim, user, peer = Mock(), Mock(), Mock() sim.stime = 10 from pycsmaca.simulations.modules.queues import Queue queue = Queue(sim) transceiver = WiredTransceiver(sim, 1000, 22, 0.1, 0.05) iface = WiredInterface(sim, 0, queue=queue, transceiver=transceiver) user_rev_conn = Mock() user.connections.set = Mock(return_value=user_rev_conn) iface.connections.set('user', user, rname='iface') wire_rev_conn = Mock() peer.connections.set = Mock(return_value=wire_rev_conn) wire_conn = iface.connections.set('wire', peer, rname='wire') packet = NetworkPacket(data=AppData(size=242)) duration = (packet.size + transceiver.header_size ) / transceiver.bitrate + transceiver.preamble frame = WireFrame(packet, duration, transceiver.header_size, transceiver.preamble) transceiver_peer_conn = iface.connections['_peer'].reverse _receiver_conn = iface.connections['_receiver'] # 1) Simulate like a frame came from the peer: iface.handle_message(frame, connection=wire_conn, sender=peer) sim.schedule.assert_called_with(0, transceiver.handle_message, args=(frame, ), kwargs={ 'connection': transceiver_peer_conn, 'sender': iface, }) sim.schedule.reset_mock() # 2) Execute transceiver frame reception start, update time and # execute transceiver frame reception end. Then make sure that # packet was scheduled for sending up to the interface via 'up': transceiver.handle_message(frame, transceiver_peer_conn, iface) sim.schedule.assert_called_with(duration, transceiver.handle_rx_end, args=(frame, )) sim.schedule.reset_mock() sim.stime += duration transceiver.handle_rx_end(frame) sim.schedule.assert_called_with(0, iface.handle_message, args=(packet, ), kwargs={ 'connection': _receiver_conn, 'sender': transceiver, }) sim.schedule.reset_mock() # 3) Execute interface packet reception, make sure it is delivered to user: iface.handle_message(packet, _receiver_conn, transceiver) sim.schedule.assert_called_with(0, user.handle_message, args=(packet, ), kwargs={ 'connection': user_rev_conn, 'sender': iface, }) sim.schedule.reset_mock()
def test_wired_transceiver_is_full_duplex(bitrate, header_size, preamble, size): sim, peer, queue, switch = Mock(), Mock(), Mock(), Mock() sim.stime = 0 eth = WiredTransceiver(sim, header_size=header_size, bitrate=bitrate, preamble=preamble, ifs=0) peer_conn = eth.connections.set('peer', peer, reverse=False) queue_conn = eth.connections.set('queue', queue, reverse=False) eth.connections.set('up', switch, reverse=False) inp_pkt = NetworkPacket(data=AppData(size=size)) out_pkt_1 = NetworkPacket(data=AppData(size=size)) out_pkt_2 = NetworkPacket(data=AppData(size=size)) duration = (header_size + size) / bitrate + preamble frame = WireFrame(inp_pkt, duration=duration, header_size=header_size, preamble=preamble) # 1) Transceiver starts transmitting `out_pkt_1`: sim.stime = 0 eth.start() eth.handle_message(out_pkt_1, queue_conn, queue) assert eth.tx_busy assert eth.rx_ready sim.schedule.assert_any_call(duration, eth.handle_tx_end) sim.schedule.assert_any_call(0, peer.handle_message, args=ANY, kwargs=ANY) sim.schedule.reset_mock() # 2) Then, after 2/3 of the packet was transmitted, a packet arrives: sim.stime = 2 * duration / 3 eth.handle_message(frame, peer_conn, peer) assert eth.tx_busy assert eth.rx_busy sim.schedule.assert_called_with(duration, eth.handle_rx_end, args=(frame, )) sim.schedule.reset_mock() # 3) After duration, call handle_tx_end and handle_ifs_end: sim.stime = duration eth.handle_tx_end() eth.handle_ifs_end() assert eth.tx_ready assert eth.rx_busy sim.schedule.reset_mock() # 4) After another 1/3 duration start new TX (during RX this time): sim.stime = 4 / 3 * duration eth.handle_message(out_pkt_2, queue_conn, queue) assert eth.tx_busy assert eth.rx_busy sim.schedule.assert_any_call(duration, eth.handle_tx_end) sim.schedule.assert_any_call(0, peer.handle_message, args=ANY, kwargs=ANY) sim.schedule.reset_mock() # 5) After 5/3 duration, RX ends, but TX still goes on: sim.stime = 5 / 3 * duration eth.handle_rx_end(frame) assert eth.tx_busy assert eth.rx_ready sim.schedule.assert_called_with(0, switch.handle_message, args=ANY, kwargs=ANY)