Пример #1
0
 def setUp(self):
     self.res = ExponentiallyDecayingReservoir(15)
Пример #2
0
class TestExponentiallyDecayingReservoir(TestCase):

    def setUp(self):
        self.res = ExponentiallyDecayingReservoir(15)

    def test_sample_weight(self):
        for dt, w in [(0, 1),
                      (1800, 532048240601.79865),
                      (3600, 2.830753303274694e+23)]:
            self.assertEqual(w, self.res._sample_weight(dt))

    @patch('caliper.reservoir.datetime')
    def test_set_next_rescale(self, datetime_mock):
        now = datetime.now()
        datetime_mock.now.return_value = now

        self.res._set_next_rescale()
        self.assertEqual(now + timedelta(hours=1), self.res._next_rescale)


    def test_add_15_elements(self):
        for i in range(15):
            self.res.update(i)
        self.assertEqual(len(self.res), 15)

    def test_add_30_elements(self):
        for i in range(30):
            self.res.update(i)
        self.assertEqual(len(self.res), 30)
        self.assertEqual(len(self.res._res), 15)

    def test_add_to_full_reservoir(self):
        self.res._res = dict((i, (i, i)) for i in range(15))

        self.res._landmark = datetime.now() - timedelta(minutes=30)
        self.res._count = 15

        self.assertTrue(0 in self.res._res)

        # Python 2.6 only supports nested CMs through contextlib.nested,
        # which is deprecated in 3.x. Easiest solution is to make this
        # indent-hell. A better solution would be to split the tests up
        # into multiple cases that each test one assertion.
        with patch.object(self.res, '_rescale_if_needed') as _rin:
            with patch.object(self.res, '_rescale') as _rescale:
                with patch.object(self.res, '_sample_weight') as _sample_weight:
                    with patch('caliper.reservoir.random') as random:
                        random.return_value = 0.5
                        _sample_weight.return_value = 20

                        self.res.update(42)

                        _rin.assert_called_once_with()
                        _rescale.assert_not_called()
                        random.assert_called_once_with()

        for k, (v, w) in self.res._res.items():
            if v == 42:
                self.assertEqual(w, 20)
                self.assertEqual(k, 40)
                break
        else:
            self.assertTrue(False)

        self.assertEqual(len(self.res._res), 15)
        self.assertFalse(0 in self.res._res)

    def test_rescale(self):
        now = datetime.now()
        landmark = now - timedelta(seconds=3600)
        self.res._landmark = landmark

        self.res._res = dict((i, (i, 2 * i)) for i in range(15))
        self.res._count = 15

        # Python 2.6 only supports nested CMs through contextlib.nested,
        # which is deprecated in 3.x. Easiest solution is to make this
        # indent-hell. A better solution would be to split the tests up
        # into multiple cases that each test one assertion.
        with patch.object(self.res, '_set_next_rescale') as _set_next_resacle:
            with patch('caliper.reservoir.exp') as exp:
                with patch('caliper.reservoir.datetime') as datetime_mock:
                    datetime_mock.now.return_value = now
                    exp.return_value = 0.5

                    self.res._rescale()

                    datetime_mock.now.assert_called_once_with()
                    exp.assert_called_once_with(-0.015 * 3600)
                    _set_next_resacle.assert_called_once_with()

        expected = dict((0.5 * i, (i, i)) for i in range(15))
        self.assertEqual(self.res._res, expected)