def test_replica_value(self): """Test that the value of a replica is calculated correctly. Replica value is calculated by the following formula (from the paper): NOR / replica.size + NOR_FSTI / FSTI + 1 / (now - repl_last_req_time) """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4 replica = self._make_replica('replica_1', size=200) node = self._make_instance('node_1', 1000, sim) repl_stats = Mock(nor=0, lrt=0) repl_stats.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = repl_stats self.assertAlmostEqual(node._RV(replica), 0.25) repl_stats.nor = 20 self.assertAlmostEqual(node._RV(replica), 0.35) replica._size = 50 self.assertAlmostEqual(node._RV(replica), 0.65) repl_stats.nor_fsti.return_value = 15 self.assertAlmostEqual(node._RV(replica), 2.15) repl_stats.lrt = 3 self.assertAlmostEqual(node._RV(replica), 2.90) sim.now = 8 self.assertAlmostEqual(node._RV(replica), 2.10)
def test_group_value(self): """Test that the value of a replica group is calculated correctly. Group value is always negative, so that it is less important than any new replica. """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4 node = self._make_instance('node_1', 1000, sim) replica_group = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=400), ] stats_1 = Mock(nor=0, lrt=0) stats_1.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = stats_1 stats_2 = Mock(nor=0, lrt=0) stats_2.nor_fsti.return_value = 0 node._replica_stats['replica_2'] = stats_2 self.assertAlmostEqual(node._GV(replica_group), -1.0)
def test_store_if_valuable_enough_free_space(self): """Test that _store_if_valuable method stores a new replica when there is enough free space. """ sim = Mock() sim.fsti = 10 sim.now = 4 replicas = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=300), ] replicas = OrderedDict((r.name, r) for r in replicas) node = self._make_instance('node_1', 1000, sim, replicas) # make sure replica is considered less valuable than the group, so that # if it gets stored, it is because of enough free space on the node node._RV = Mock(return_value=7) node._GV = Mock(return_value=10) new_replica = self._make_replica('new_replica', size=500) node._store_if_valuable(new_replica) self.assertEqual(len(node._replicas), 3) self.assertIn('new_replica', node._replicas)
def test_group_value_zero_denominator(self): """Test that the value of a replica group is calculated correctly in cases of a zero denominator. This can happen if the current simulation time is exactly equal to replica's last requested time (e.g. when sorting replicas by importance) and this replica is the only one in replica group. """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4.0 node = self._make_instance('node_1', 1000, sim) replica_group = [self._make_replica('replica_1', size=200)] stats_1 = Mock(nor=0, lrt=4.0) stats_1.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = stats_1 try: result = node._GV(replica_group) except ZeroDivisionError: self.fail("Incorrect handling of a zero denominator.") else: self.assertEqual(result, float('inf'))
def test_store_if_valuable_limited_space_replica_more_important(self): """Test that _store_if_valuable method stores a new replica when there is not enough free space, but this replica is valued high enough. """ sim = Mock() sim.fsti = 10 sim.now = 4 replicas = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=300), self._make_replica('replica_3', size=400), ] replicas = OrderedDict((r.name, r) for r in replicas) node = self._make_instance('node_1', 1000, sim, replicas) node._RV = Mock(return_value=15) node._GV = Mock(return_value=8) new_replica = self._make_replica('new_replica', size=501) node._store_if_valuable(new_replica) self.assertEqual(len(node._replicas), 2) self.assertIn('new_replica', node._replicas) self.assertNotIn('replica_1', node._replicas) self.assertNotIn('replica_2', node._replicas)
def test_copy_replica_enough_space(self): """Test that _copy_replica correctly stores a replica when there is enough free space. """ sim = Mock() sim.fsti = 10 sim.now = 4 replicas = [ self._make_replica('replica_1', size=100), self._make_replica('replica_2', size=800), self._make_replica('replica_3', size=500), ] replicas = OrderedDict((r.name, r) for r in replicas) node = self._make_instance('node_1', 2000, sim, replicas) # make smaller replicas more valuable node._RV = Mock(side_effect=lambda r: 1000 - r.size) new_replica = self._make_replica('new_replica', size=400) node._copy_replica(new_replica) self.assertEqual(len(node._replicas), 4) self.assertIn('new_replica', node._replicas) self.assertIn('new_replica', node._replica_stats) self.assertEqual(node.free_capacity, 200) self.assertEqual( list(node._replicas.keys()), ['replica_1', 'replica_2', 'replica_3', 'new_replica'] )
def test_group_value(self): """Test that the value of a replica group is calculated correctly. Group value is simply the sum of numbers of requests for each replica in the group. """ sim = Mock(spec=self._make_sim()) sim.fsti = 1.50 sim.now = 4 node = self._make_instance('node_1', 1000, sim) replica_group = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=400), self._make_replica('replica_3', size=900), ] stats_1 = Mock(nor=6, lrt=3.50) stats_1.nor_fsti.return_value = 5 node._replica_stats['replica_1'] = stats_1 stats_2 = Mock(nor=0, lrt=0.04) stats_2.nor_fsti.return_value = 0 node._replica_stats['replica_2'] = stats_2 stats_3 = Mock(nor=11, lrt=2.40) stats_3.nor_fsti.return_value = 4 node._replica_stats['replica_3'] = stats_3 self.assertAlmostEqual(node._GV(replica_group), 17)
def test_request_replica_replica_not_present(self): """Test request_replica method when node does not have the requested replica. """ sim = Mock() sim.fsti = 10 sim.now = 4 event_send_repl_req = Mock(name='SendReplicaRequest') sim.event_send_replica_request.return_value = event_send_repl_req event_send_repl = Mock(name='SendReplica') sim.event_send_replica.return_value = event_send_repl replica_1 = self._make_replica('replica_1', size=100) replicas = OrderedDict(replica_1=replica_1) parent = self._make_instance('parent', 5000, sim, replicas) node = self._make_instance('node_1', 5000, sim) node.set_parent(parent) node._store_if_valuable = Mock(wraps=node._store_if_valuable) requester = self._make_instance('req_node', 5000, sim) g = node.request_replica('replica_1', requester) event = next(g) # check that correct event was yielded (send replica reques) self.assertIs(event, event_send_repl_req) self.assertEqual( sim.event_send_replica_request.call_args, ((node, parent, 'replica_1'), {}) ) # simulate response (replica receive event after some delay) and see # what we get sim.now += 10 event = g.send(replica_1) self.assertEqual( node._store_if_valuable.call_args, ((replica_1,), {}) ) self.assertIs(event, event_send_repl) self.assertEqual( sim.event_send_replica.call_args, ((node, requester, replica_1), {}) ) # check that requested replica's stats have been updated as well stats = node._replica_stats['replica_1'] self.assertEqual(stats.nor, 1) self.assertEqual(stats.nor_fsti(sim.now), 1) self.assertEqual(stats.lrt, 4) # the time replica was requested with self.assertRaises(StopIteration): next(g) # no more events yielded
def test_group_value(self): """Test that the value of a replica group is calculated correctly. Group value is calculated by the following formula (from the paper): sum(NOR) / sum(sizes) + sum(NOR_FSTI) / FSTI + 1 / (now - avg(last_req_time)) """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4 node = self._make_instance('node_1', 1000, sim) replica_group = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=400), self._make_replica('replica_3', size=900), ] stats_1 = Mock(nor=0, lrt=0) stats_1.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = stats_1 stats_2 = Mock(nor=0, lrt=0) stats_2.nor_fsti.return_value = 0 node._replica_stats['replica_2'] = stats_2 stats_3 = Mock(nor=0, lrt=0) stats_3.nor_fsti.return_value = 0 node._replica_stats['replica_3'] = stats_3 self.assertAlmostEqual(node._GV(replica_group), 0.25) stats_1.nor = 15 self.assertAlmostEqual(node._GV(replica_group), 0.26) stats_2.nor = 45 self.assertAlmostEqual(node._GV(replica_group), 0.29) replica_group[2]._size = 2400 self.assertAlmostEqual(node._GV(replica_group), 0.27) stats_1.nor_fsti.return_value = 5 self.assertAlmostEqual(node._GV(replica_group), 0.77) stats_2.nor_fsti.return_value = 20 self.assertAlmostEqual(node._GV(replica_group), 2.77) stats_1.lrt = 1 stats_2.lrt = 2 stats_3.lrt = 3 self.assertAlmostEqual(node._GV(replica_group), 3.02) sim.now = 7 self.assertAlmostEqual(node._GV(replica_group), 2.72)
def test_request_replica_replica_received_during_waiting(self): """Test request_replica method when replica is received (because of an earlier request) while the node is still waiting for this same replica. """ sim = Mock() sim.fsti = 10 sim.now = 4 event_send_repl_req = Mock(name='SendReplicaRequest') sim.event_send_replica_request.return_value = event_send_repl_req event_send_repl = Mock(name='SendReplica') sim.event_send_replica.return_value = event_send_repl replica_1 = self._make_replica('replica_1', size=100) replicas = OrderedDict(replica_1=replica_1) parent = self._make_instance('parent', 5000, sim, replicas) node = self._make_instance('node_1', 5000, sim) node.set_parent(parent) node._store_if_valuable = Mock(wraps=node._store_if_valuable) requester = self._make_instance('req_node', 5000, sim) g = node.request_replica('replica_1', requester) event = next(g) # simulate early arrival of a replica node._copy_replica(replica_1) sim.now += 10 stats_1 = node._replica_stats[replica_1.name] stats_1.new_request_made = Mock(wraps=stats_1.new_request_made) event = g.send(replica_1) self.assertFalse(node._store_if_valuable.called) self.assertEqual(stats_1.new_request_made.call_count, 1) self.assertEqual( stats_1.new_request_made.call_args, ((4,), {}) # the last time replica was requested ) self.assertIs(event, event_send_repl) self.assertEqual( sim.event_send_replica.call_args, ((node, requester, replica_1), {}) ) with self.assertRaises(StopIteration): next(g) # no more events yielded
def test_copy_replica_already_exists(self): """Test that _copy_replica raises an error if replica already exists. """ sim = Mock() sim.fsti = 10 sim.now = 4 replica = self._make_replica('replica', size=120) node = self._make_instance( 'node_1', 500, sim, OrderedDict(replica=replica)) replica_clone = deepcopy(replica) with self.assertRaises(ValueError): node._copy_replica(replica_clone)
def test_delete_replica_non_existent(self): """Test that _delete_replica raises ValueError for non-existent replicas. """ sim = Mock() sim.fsti = 10 sim.now = 4 replicas = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=300), self._make_replica('replica_3', size=400), ] replicas = OrderedDict((r.name, r) for r in replicas) node = self._make_instance('node_1', 1000, sim, replicas) with self.assertRaises(ValueError): node._delete_replica('non-existent')
def test_copy_replica_not_enough_space(self): """Test that _copy_replica raises ValueError if there is not enough free space. """ sim = Mock() sim.fsti = 10 sim.now = 4 replicas = [ self._make_replica('replica_1', size=100), self._make_replica('replica_2', size=350), ] replicas = OrderedDict((r.name, r) for r in replicas) node = self._make_instance('node_1', 500, sim, replicas) new_replica = self._make_replica('new_replica', size=51) with self.assertRaises(ValueError): node._copy_replica(new_replica)
def test_replica_value_stats_exist(self): """Test that the value of a replica with existing stats is calculated correctly. Replica value is just a time when it was last requested. """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4.77 replica = self._make_replica('replica_1', size=200) node = self._make_instance('node_1', 1000, sim) repl_stats = Mock(nor=0, lrt=2.57) repl_stats.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = repl_stats self.assertEqual(node._RV(replica), 2.57)
def test_replica_value_no_stats(self): """Test that the value of a replica with no stats is calculated correctly. Replica does not have any stats yet in cases when it has just been retrieved from a parent node and is a candidate for storing a copy of it on the node that requested it. When replica does not yet have any stats, its value is the default NOR value (0). """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4.77 replica = self._make_replica('replica_1', size=200) node = self._make_instance('node_1', 1000, sim) self.assertEqual(node._RV(replica), 0.0)
def test_delete_replica_replica_exists(self): """Test that _delete_replica correctly deletes an existing replica. """ sim = Mock() sim.fsti = 10 sim.now = 4 replicas = [ self._make_replica('replica_1', size=200), self._make_replica('replica_2', size=300), self._make_replica('replica_3', size=400), ] replicas = OrderedDict((r.name, r) for r in replicas) node = self._make_instance('node_1', 1000, sim, replicas) node._delete_replica('replica_3') self.assertEqual(len(node._replicas), 2) self.assertNotIn('replica_3', node._replicas) self.assertNotIn('replica_3', node._replica_stats) self.assertEqual(node.free_capacity, 500)
def test_request_replica_replica_present(self): """Test request_replica method when node has a copy of the requested replica. """ sim = Mock() sim.fsti = 10 sim.now = 4 event_send_repl = Mock(name='SendReplica') sim.event_send_replica.return_value = event_send_repl replica_1 = self._make_replica('replica_1', size=100) replica_2 = self._make_replica('replica_2', size=350) replicas = OrderedDict([ (replica_1.name, replica_1), (replica_2.name, replica_2), ]) node = self._make_instance('node_1', 5000, sim, replicas) node._replica_stats['replica_1']._nor = 10 requester = self._make_instance('req_node', 5000, sim) g = node.request_replica('replica_1', requester) event = next(g) # check that correct event was yielded (send replica) self.assertIs(event, event_send_repl) self.assertEqual( sim.event_send_replica.call_args, ((node, requester, replica_1), {}) ) # check that requested replica's stats have been updated as well stats = node._replica_stats['replica_1'] self.assertEqual(stats.nor, 11) self.assertEqual(stats.nor_fsti(sim.now), 1) self.assertEqual(stats.lrt, sim.now) with self.assertRaises(StopIteration): next(g) # no more events yielded
def test_replica_value_stats_exist(self): """Test that the value of a replica with existing stats is calculated correctly. Replica does not have any stats yet in cases when it has just been retrieved from a parent node and is a candidate for storing a copy of it on the node that requested it. Replica value is just the number of time it has been requested. """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4.77 replica = self._make_replica('replica_1', size=200) node = self._make_instance('node_1', 1000, sim) repl_stats = Mock(nor=6, lrt=2.57) repl_stats.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = repl_stats self.assertEqual(node._RV(replica), 6)
def test_replica_value_zero_denominator(self): """Test that _RV correctly handles cases with a denominator of zero. This can happen if the current simulation time is exactly equal to replica's last requested time (e.g. when sorting replicas by importance). """ sim = Mock(spec=self._make_sim()) sim.fsti = 10 sim.now = 4 replica = self._make_replica('replica_1', size=200) node = self._make_instance('node_1', 1000, sim) repl_stats = Mock(nor=0, lrt=4) repl_stats.nor_fsti.return_value = 0 node._replica_stats['replica_1'] = repl_stats try: result = node._RV(replica) except ZeroDivisionError: self.fail("Incorrect handling of a zero denominator.") else: self.assertEqual(result, float('inf'))