예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
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)
예제 #4
0
    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'))
예제 #5
0
    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)
예제 #6
0
    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']
        )
예제 #7
0
    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)
예제 #8
0
    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
예제 #9
0
    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)
예제 #10
0
    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
예제 #11
0
    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)
예제 #12
0
    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')
예제 #13
0
    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)
예제 #14
0
    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)
예제 #15
0
    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)
예제 #16
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)
예제 #17
0
    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
예제 #18
0
    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)
예제 #19
0
    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'))