def __init__(self, arrival_mean, service_mean): # Parameters: self.arrival_mean = arrival_mean self.service_mean = service_mean # System state: self.queue_size = 0 self.server_busy = False # Statistics: self.system_size_trace = Trace() self.server_busy_trace = Trace() self.service_intervals = Statistic() self.arrivals = Intervals() self.departures = Intervals()
def test_intervals_creation_with_valid_data(timestamps): ints = Intervals(timestamps) _timestamps = asarray([0] + list(timestamps)) assert not ints.empty assert len(ints) == len(timestamps) assert ints.as_tuple() == tuple(_timestamps[1:] - _timestamps[:-1]) assert ints.last == timestamps[-1]
def test_random_source_provides_statistics(): """Validate that `RandomSource` provides statistics. """ intervals = (10, 12, 15, 17) data_size = (123, 453, 245, 321) class TestModel(Model): def __init__(self, sim): super().__init__(sim) self.source = RandomSource( sim, source_id=34, dest_addr=13, data_size=Mock(side_effect=data_size), interval=Mock(side_effect=(intervals + (1000, ))), ) self.network = DummyModel(sim, 'Network') self.source.connections['network'] = self.network ret = simulate(TestModel, stime_limit=sum(intervals)) assert ret.data.source.arrival_intervals.as_tuple() == intervals assert ret.data.source.data_size_stat.as_tuple() == data_size # Also check that we can not replace statistics: with pytest.raises(AttributeError): from pydesim import Intervals ret.data.source.arrival_intervals = Intervals() with pytest.raises(AttributeError): from pydesim import Statistic ret.data.source.data_size_stat = Statistic() # Check that source records the number of packets being sent: assert ret.data.source.num_packets_sent == 4
def __init__(self, sim): super().__init__(sim) self.__source_delays_data = {} self.__source_delays = ReadOnlyDict(self.__source_delays_data) self.__arrival_intervals = Intervals() self.__data_size_stat = Statistic() self.__num_packets_received = 0
def __init__(self, sim, arrival_mean): super().__init__(sim) self.__arrival_mean = arrival_mean # Statistics: self.intervals = Intervals() # Initialize: self._schedule_next_arrival()
def test_record_valid_data(): ints = Intervals() assert ints.as_tuple() == () ints.record(2) assert_almost_equal(ints.as_tuple(), (2, )) ints.record(3.4) assert_almost_equal(ints.as_tuple(), (2, 1.4))
def __init__(self, sim, arrival, index): super().__init__(sim) self.arrival = arrival self.index = index # Statistics: self.intervals = Intervals() self.num_generated = 0 self.delays = Statistic() # Initialize: self._schedule_next_arrival()
def __init__(self, sim, service_time, index=0): super().__init__(sim) self.service_time = service_time self.packet = None self.index = index # Statistics: self.service_intervals = Statistic() self.busy_trace = Trace() self.busy_trace.record(self.sim.stime, 0) self.departure_intervals = Intervals() self.departure_intervals.record(sim.stime) self.num_served = 0
def __init__(self, sim, capacity, index=0): super().__init__(sim) self.__capacity = capacity self.packets = deque() self.index = index # Statistics: self.size_trace = Trace() self.size_trace.record(self.sim.stime, 0) self.num_dropped = 0 self.arrival_intervals = Intervals() self.arrival_intervals.record(sim.stime) self.num_arrived = 0 self.wait_intervals = Statistic()
def test_controlled_source_provides_statistics(): """Validate that `ControlledSource` provides statistics. """ intervals = (10, 12, 15, 17) data_size = (123, 453, 245, 321) class SourceController(Model): def __init__(self, sim, src): super().__init__(sim) self.iterator = iter(intervals) self.src = src self.sim.schedule(next(self.iterator), self.handle_timeout) def handle_timeout(self): self.src.get_next() try: interval = next(self.iterator) except StopIteration: pass else: self.sim.schedule(interval, self.handle_timeout) class TestModel(Model): def __init__(self, sim): super().__init__(sim) self.source = ControlledSource( sim, source_id=34, dest_addr=13, data_size=Mock(side_effect=data_size), ) self.network = DummyModel(sim, 'Network') self.source.connections['network'] = self.network self.controller = SourceController(sim, self.source) ret = simulate(TestModel, stime_limit=sum(intervals)) assert ret.data.source.data_size_stat.as_tuple() == data_size assert ret.data.source.arrival_intervals.as_tuple() == intervals # Also check that we can not replace statistics: with pytest.raises(AttributeError): from pydesim import Intervals ret.data.source.arrival_intervals = Intervals() with pytest.raises(AttributeError): from pydesim import Statistic ret.data.source.data_size_stat = Statistic() # Check that source records the number of packets being sent: assert ret.data.source.num_packets_sent == 4
def __init__(self, sim, data_size, source_id, dest_addr): """Constructor. :param sim: `pydesim.Simulator` object; :param data_size: callable without arguments, iterable or constant; represents application data size distribution; :param source_id: this source ID (more like IP address, not MAC) :param dest_addr: destination MAC address. """ super().__init__(sim) self.__data_size = data_size self.__source_id = source_id self.__dest_addr = dest_addr # Attempt to build iterators for data size and intervals: try: self.__data_size_iter = iter(self.__data_size) except TypeError: self.__data_size_iter = None # Statistics: self.__arrival_intervals = Intervals() self.__data_size_stat = Statistic() self.__num_packets_sent = 0
def test_as_list(timestamps): ints = Intervals(timestamps) _timestamps = asarray([0] + list(timestamps)) assert ints.as_list() == list(_timestamps[1:] - _timestamps[:-1])
def test_statistic(data): ints = Intervals(data) stats = ints.statistic() assert_almost_equal(stats.as_tuple(), ints.as_tuple())
def test_record_in_past_raises_error(): ints = Intervals([10]) with pytest.raises(ValueError) as excinfo: ints.record(9.9) assert 'prohibited timestamps from past' in str(excinfo.value).lower()
def test_record_illegal_types_raises_error(value): ints = Intervals() with pytest.raises(TypeError) as excinfo: ints.record(value) assert 'only numeric values expected' in str(excinfo.value).lower()
def test_data_of_illegal_types_causes_type_error(timestamps): with pytest.raises(TypeError) as excinfo: Intervals(timestamps) assert 'only numeric values expected' in str(excinfo.value).lower()
def __init__(self, sim): super().__init__(sim) # Statistics: self.arrival_intervals = Intervals() self.arrival_intervals.record(self.sim.stime)
def test_intervals_accept_only_timestamps_in_future(): with pytest.raises(ValueError) as excinfo: Intervals([1, 2, 1.9, 3]) assert 'timestamps must be ascending' in str(excinfo.value).lower()
def test_intervals_copy_list_content_instead_of_pointer(): data = [1, 2] ints = Intervals(data) ints.record(3) assert ints.as_tuple() == (1, 1, 1) assert data == [1, 2]
def test_sink_module_records_statistics(): """Validate that `Sink` module records various statistics. In this test we check that `Sink` module records end-to-end delays per SourceID, inter-arrival intervals and packet sizes (last two statistics are recorded without splitting by SourceID). It also records the number of received packets. To do this, we define a sample simulation with dummy network layer, two sources and one sink. Each source generates three messages within given intervals and with given sizes. """ delays = [(5, 2, 234), (10, 3, 135)] intervals = [(10, 10, 200), (20, 400, 80)] sizes = [(1234, 1625, 1452), (2534, 2124, 2664)] sids = [23, 14] class DummyNetwork(Model): def __init__(self, sim): super().__init__(sim) def handle_message(self, app_data, **kwargs): self.connections['sink'].send(app_data) class TestModel(Model): def __init__(self, sim): super().__init__(sim) self.sink = Sink(sim) for ds, inter, sid, delay in zip(sizes, intervals, sids, delays): network = DummyNetwork(sim) source = RandomSource(sim, ds, inter, sid, 5) source.connections['network'] = network network.connections['sink'] = self.sink network.connections['sink'].delay = Mock(side_effect=delay) ret = simulate(TestModel) sink = ret.data.sink assert isinstance(sink.source_delays[sids[0]], Statistic) assert sink.source_delays[sids[0]].as_tuple() == delays[0] assert sink.source_delays[sids[1]].as_tuple() == delays[1] # To check `Sink` stores arrival intervals and packet sizes, we estimate # expected arrival times (received_at) and along with it order packet # sizes by their arrival time: indices = [0, 0] gen_times = [cumsum(ints) for ints in intervals] n = len(intervals[0]) received_at, received_sizes = [], [] while any(i < n for i in indices): next_arrivals = [(gen_times[i][j] + delays[i][j]) if j < n else inf for i, j in enumerate(indices)] i = int(argmin(next_arrivals)) received_at.append(next_arrivals[i]) received_sizes.append(sizes[i][indices[i]]) indices[i] += 1 # Since received_at stores arrival timestamps, compute arrival intervals: v = asarray(received_at) arrival_intervals = [v[0]] + list(v[1:] - v[:-1]) # Check that recorded data match the expected: assert isinstance(sink.arrival_intervals, Intervals) assert sink.arrival_intervals.as_tuple() == tuple(arrival_intervals) assert isinstance(sink.data_size_stat, Statistic) assert sink.data_size_stat.as_tuple() == tuple(received_sizes) assert sink.num_packets_received == len(received_sizes) # Check that statistics can not be overwritten: with pytest.raises(AttributeError): sink.arrival_intervals = Intervals() with pytest.raises(AttributeError): sink.data_size_stat = Statistic() with pytest.raises(TypeError): sink.source_delays[sids[0]] = Statistic()
def test_empty_intervals_instantiation(): ints = Intervals() assert ints.empty assert len(ints) == 0 assert ints.as_tuple() == () assert ints.last == 0
def __init__(self, sim): super().__init__(sim) # Statistics: self.departures = Intervals() self.departures.record(self.sim.stime)