1# -*- coding: utf-8 -*-
2
3import datetime
4from unittest import TestCase
5from flexmock import flexmock, flexmock_teardown
6
7from cachy import Repository
8from cachy.contracts.store import Store
9
10
11class RepositoryTestCase(TestCase):
12
13    def tearDown(self):
14        flexmock_teardown()
15
16    def test_get_returns_value_from_cache(self):
17        repo = self._get_repository()
18        repo.get_store().should_receive('get').once().with_args('foo').and_return('bar')
19
20        self.assertEqual('bar', repo.get('foo'))
21
22    def test_default_value_is_returned(self):
23        repo = self._get_repository()
24        repo.get_store().should_receive('get').and_return(None)
25
26        self.assertEqual('bar', repo.get('foo', 'bar'))
27        self.assertEqual('baz', repo.get('foo', lambda: 'baz'))
28
29    def test_set_default_cache_time(self):
30        repo = self._get_repository()
31        repo.set_default_cache_time(10)
32
33        self.assertEqual(10, repo.get_default_cache_time())
34
35    def test_has_method(self):
36        repo = self._get_repository()
37        repo.get_store().should_receive('get').with_args('foo').and_return(None)
38        repo.get_store().should_receive('get').with_args('bar').and_return('baz')
39
40        self.assertFalse(repo.has('foo'))
41        self.assertTrue(repo.has('bar'))
42
43    def test_pull(self):
44        repo = self._get_repository()
45        repo.get_store().should_receive('get').with_args('foo').and_return('bar')
46        repo.get_store().should_receive('forget').with_args('foo')
47
48        self.assertEqual('bar', repo.get('foo'))
49
50    def test_put(self):
51        repo = self._get_repository()
52        repo.get_store().should_receive('put').with_args('foo', 'bar', 10)
53
54        repo.put('foo', 'bar', 10)
55
56    def test_put_supports_datetime_as_minutes(self):
57        repo = self._get_repository()
58        repo.get_store().should_receive('put').with_args('foo', 'bar', 60)
59
60        repo.put('foo', 'bar', datetime.datetime.now() + datetime.timedelta(hours=1))
61
62    def test_put_with_minutes_to_zero_doesnt_store(self):
63        repo = self._get_repository()
64        repo.get_store().should_receive('put').never()
65
66        repo.put('foo', 'bar', datetime.datetime.now() - datetime.timedelta(hours=1))
67
68    def test_add(self):
69        repo = self._get_repository()
70        repo.get_store().should_receive('get').once().with_args('foo').and_return(None)
71        repo.get_store().should_receive('get').once().with_args('bar').and_return('baz')
72        repo.get_store().should_receive('put').once().with_args('foo', 'bar', 10)
73        repo.get_store().should_receive('put').never().with_args('bar', 'baz', 10)
74
75        self.assertTrue(repo.add('foo', 'bar', 10))
76        self.assertFalse(repo.add('bar', 'baz', 10))
77
78    def test_forever(self):
79        repo = self._get_repository()
80        repo.get_store().should_receive('forever').once().with_args('foo', 'bar')
81
82        repo.forever('foo', 'bar')
83
84    def test_remember_calls_put_and_returns_default(self):
85        repo = self._get_repository()
86        repo.get_store().should_receive('get').and_return(None)
87        repo.get_store().should_receive('put').once().with_args('foo', 'bar', 10)
88        result = repo.remember('foo', 10, lambda: 'bar')
89
90        self.assertEqual('bar', result)
91
92    def test_remember_forever_calls_forever_and_returns_default(self):
93        repo = self._get_repository()
94        repo.get_store().should_receive('get').and_return(None)
95        repo.get_store().should_receive('forever').once().with_args('foo', 'bar')
96        result = repo.remember_forever('foo', lambda: 'bar')
97
98        self.assertEqual('bar', result)
99
100    def test_repository_can_serve_as_a_decorator(self):
101        repo = self._get_repository()
102        repo.get_store().should_receive('get').and_return(None, 6, 6).one_by_one()
103        repo.get_store().should_receive('put').once()
104        calls = []
105
106        @repo
107        def test(i, m=3):
108            calls.append(i)
109
110            return i*3
111
112        test(2)
113        test(2)
114        test(2)
115
116        self.assertEqual(1, len(calls))
117
118    def test_repository_can_serve_as_a_decorator_with_key_and_minutes(self):
119        repo = flexmock(self._get_repository())
120        repo.should_receive('_get_key').with_args('my_key', (2,), {'m': 4}).and_return('foo')
121        repo.get_store().should_receive('get').and_return(None, 6, 6).one_by_one()
122        repo.get_store().should_receive('put').once()\
123            .with_args('foo', 6, 35)
124        calls = []
125
126        @repo(key='my_key', minutes=35)
127        def test(i, m=3):
128            calls.append(i)
129
130            return i*3
131
132        test(2, m=4)
133        test(2, m=4)
134        test(2, m=4)
135
136        self.assertEqual(1, len(calls))
137
138    def _get_repository(self):
139        repo = Repository(flexmock(Store()))
140
141        return repo
142