Completed
Pull Request — master (#147)
by Jasper
01:33
created

MongoRepoTests.test_knowsByLocation()   A

Complexity

Conditions 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
import unittest
2
from mock import Mock, patch, sentinel
3
from datetime import timedelta
4
from tests.ditest import DependencyInjectionTestBase
5
6
7
class MongoRepoTests(DependencyInjectionTestBase):
8
9
    def setUp(self):
10
        super(MongoRepoTests, self).setUp()
11
        self.pictureCache.getBytes.return_value = None
12
        self.db = Mock()
13
        self.db.provenance.find_one.return_value = {}
14
        self.db.provenance.find.return_value = {}
15
        self.pymongo = None
16
17
    def setupRepo(self):
18
        from niprov.mongo import MongoRepository
19
        with patch('niprov.mongo.pymongo') as self.pymongo:
20
            self.repo = MongoRepository(dependencies=self.dependencies)
21
        self.repo.db = self.db
22
23
    def test_Connection(self):
24
        from niprov.mongo import MongoRepository
25
        with patch('niprov.mongo.pymongo') as pymongo:
26
            repo = MongoRepository(dependencies=self.dependencies)
27
        pymongo.MongoClient.assert_called_with(self.config.database_url)
28
        self.assertEqual(pymongo.MongoClient().get_default_database(), repo.db)
29
30
    def test_byLocation_returns_img_from_record_with_path(self):
31
        self.setupRepo()
32
        p = '/p/f1'
33
        out = self.repo.byLocation(p)
34
        self.db.provenance.find_one.assert_called_with({'location':p})
35
        self.fileFactory.fromProvenance.assert_called_with(
36
            self.db.provenance.find_one())
37
        self.assertEqual(self.fileFactory.fromProvenance(), out)
38
39
    def test_getSeries(self):
40
        self.setupRepo()
41
        img = Mock()
42
        out = self.repo.getSeries(img)
43
        self.db.provenance.find_one.assert_called_with(
44
            {'seriesuid':img.getSeriesId()})
45
        self.fileFactory.fromProvenance.assert_called_with(
46
            self.db.provenance.find_one())
47
        self.assertEqual(self.fileFactory.fromProvenance(), out)
48
49
    def test_getSeries_returns_None_right_away_if_no_series_id(self):
50
        self.setupRepo()
51
        img = Mock()
52
        img.getSeriesId.return_value = None
53
        out = self.repo.getSeries(img)
54
        assert not self.db.provenance.find_one.called
55
        self.assertEqual(None, out)
56
57
    def test_Add(self):
58
        self.setupRepo()
59
        img = Mock()
60
        img.provenance = {'a':1, 'b':2}
61
        self.repo.add(img)
62
        self.db.provenance.insert_one.assert_called_with({'a':1, 'b':2})
63
64
    def test_update(self):
65
        self.setupRepo()
66
        img = Mock()
67
        img.provenance = {'a':1, 'b':2}
68
        self.repo.update(img)
69
        self.db.provenance.update.assert_called_with(
70
            {'location':img.location.toString()}, {'a':1, 'b':2})
71
72
    def test_all(self):
73
        self.fileFactory.fromProvenance.side_effect = lambda p: 'img_'+p
74
        self.db.provenance.find.return_value = ['p1', 'p2']
75
        self.setupRepo()
76
        out = self.repo.all()
77
        self.db.provenance.find.assert_called_with()
78
        self.fileFactory.fromProvenance.assert_any_call('p1')
79
        self.fileFactory.fromProvenance.assert_any_call('p2')
80
        self.assertEqual(['img_p1', 'img_p2'], out)
81
82
    def test_updateApproval(self):
83
        self.setupRepo()
84 View Code Duplication
        img = Mock()
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
85
        p = '/p/f1'
86
        newStatus = 'oh-oh'
87
        self.repo.updateApproval(p, newStatus)
88
        self.db.provenance.update.assert_called_with(
89
            {'location':p}, {'$set': {'approval': newStatus}})
90
91
    def test_latest(self):
92
        self.fileFactory.fromProvenance.side_effect = lambda p: 'img_'+p
93
        self.db.provenance.find.return_value = Mock()
94
        self.db.provenance.find.return_value.sort.return_value.limit.return_value = ['px','py']
95
        self.setupRepo()
96
        out = self.repo.latest()
97
        self.db.provenance.find.assert_called_with()
98
        self.db.provenance.find().sort.assert_called_with('added', -1)
99
        self.db.provenance.find().sort().limit.assert_called_with(20)
100
        self.fileFactory.fromProvenance.assert_any_call('px')
101
        self.fileFactory.fromProvenance.assert_any_call('py')
102
        self.assertEqual(['img_px', 'img_py'], out)
103
104
    def test_statistics(self):
105
        self.db.provenance.aggregate.return_value = [sentinel.stats,]
106
        self.setupRepo()
107
        out = self.repo.statistics()
108
        self.db.provenance.aggregate.assert_called_with(
109
           [{'$group':
110
                 {
111
                   '_id': None,
112
                   'totalsize': { '$sum': '$size' },
113
                   'count': { '$sum': 1 }
114
                 }
115
            }])
116
        self.assertEqual(sentinel.stats, out)
117
118
    def test_statistics_if_no_records(self):
119
        self.db.provenance.aggregate.return_value = []
120
        self.setupRepo()
121
        out = self.repo.statistics()
122
        self.assertEqual({'count':0}, out)
123
124
    def test_byId(self):
125
        self.setupRepo()
126
        ID = 'abc123'
127
        out = self.repo.byId(ID)
128
        self.db.provenance.find_one.assert_called_with({'id':ID})
129
        self.fileFactory.fromProvenance.assert_called_with(
130
            self.db.provenance.find_one())
131
        self.assertEqual(self.fileFactory.fromProvenance(), out)
132
133
    def test_If_db_returns_None_should_return_None_for_byId_byLocation(self):
134
        self.setupRepo()
135
        self.db.provenance.find_one.return_value = None
136
        out = self.repo.byId('abc123')
137
        assert not self.fileFactory.fromProvenance.called
138
        self.assertEqual(None, out)
139
140
    def test_byLocations(self):
141
        self.fileFactory.fromProvenance.side_effect = lambda p: 'img_'+p
142
        self.db.provenance.find.return_value = ['p1', 'p2']
143
        self.setupRepo()
144
        out = self.repo.byLocations(['l1','l2'])
145
        self.db.provenance.find.assert_called_with({'location':{'$in':['l1','l2']}})
146
        self.fileFactory.fromProvenance.assert_any_call('p1')
147
        self.fileFactory.fromProvenance.assert_any_call('p2')
148
        self.assertEqual(['img_p1', 'img_p2'], out)
149
150
    def test_byParents(self):
151
        self.fileFactory.fromProvenance.side_effect = lambda p: 'img_'+p
152
        self.db.provenance.find.return_value = ['p1', 'p2']
153
        self.setupRepo()
154
        out = self.repo.byParents(['x1','x2'])
155
        self.db.provenance.find.assert_called_with({'parents':{'$in':['x1','x2']}})
156
        self.fileFactory.fromProvenance.assert_any_call('p1')
157
        self.fileFactory.fromProvenance.assert_any_call('p2')
158
        self.assertEqual(['img_p1', 'img_p2'], out)
159
160
    def test_Converts_timedelta_to_float_when_serializing(self):
161
        self.setupRepo()
162
        img = Mock()
163
        img.provenance = {'a':1, 'duration':timedelta(seconds=67.89)}
164
        self.repo.add(img)
165
        self.db.provenance.insert_one.assert_called_with(
166
            {'a':1, 'duration':67.89})
167 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
168
    def test_Converts_duration_to_timedelta_when_deserializing(self):
169
        self.setupRepo()
170
        self.db.provenance.find_one.return_value = {'a':3, 'duration':89.01}
171
        out = self.repo.byLocation('/p/f1')
172
        self.fileFactory.fromProvenance.assert_called_with(
173
            {'a':3, 'duration':timedelta(seconds=89.01)})
174
175
    def test_Obtains_optional_snapshot_data_from_cache_when_serializing(self):
176
        self.pictureCache.getBytes.return_value = sentinel.snapbytes
177 View Code Duplication
        with patch('niprov.mongo.bson') as bson:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
178
            bson.Binary.return_value = sentinel.snapbson
179
            self.setupRepo()
180
            img = Mock()
181
            img.provenance = {'a':1}
182
            self.repo.add(img)
183
            self.pictureCache.getBytes.assert_called_with(for_=img)
184
            bson.Binary.assert_called_with(sentinel.snapbytes)
185
            self.db.provenance.insert_one.assert_called_with({'a':1, 
186
                '_snapshot-data':sentinel.snapbson})
187
188
    def test_If_no_snapshot_doesnt_add_data_field(self):
189
        self.pictureCache.getBytes.return_value = None
190
        with patch('niprov.mongo.bson') as bson:
191
            self.setupRepo()
192
            img = Mock()
193
            img.provenance = {'a':1}
194
            self.repo.add(img)
195
            assert not bson.Binary.called
196
            self.db.provenance.insert_one.assert_called_with({'a':1})
197
198
    def test_If_snapshotdata_hands_them_to_pictureCache_on_deserializing(self):
199
        img = Mock()
200
        self.fileFactory.fromProvenance.return_value = img
201
        self.setupRepo()
202
        self.db.provenance.find_one.return_value = {'a':3}
203
        out = self.repo.byLocation('/p/f1')
204
        assert not self.pictureCache.keep.called
205
        self.db.provenance.find_one.return_value = {'a':3, 
206
                                                    '_snapshot-data':'y7yUyS'}
207
        out = self.repo.byLocation('/p/f1')
208
        self.pictureCache.keep.assert_called_with('y7yUyS', for_=img)
209
210
    def test_Query(self):
211
        self.db.provenance.find.return_value = ['record1']
212
        self.setupRepo()
213
        q = Mock()
214
        field1 = Mock()
215
        field1.name = 'color'
216
        field1.value = 'red'
217
        field1.all = False
218
        q.getFields.return_value = [field1]
219
        out = self.repo.inquire(q)
220
        self.db.provenance.find.assert_called_with({'color':'red'})
221
        self.fileFactory.fromProvenance.assert_called_with('record1')
222
223
    def test_Ensures_text_index_for_search(self):
224
        self.setupRepo()
225
        self.repo.search('')
226
        searchfields = ['location','user','subject','project','protocol',
227
                  'transformation','technique','modality']
228
        indexspec = [(field, 'text') for field in searchfields]
229
        self.db.provenance.create_index.assert_called_with(indexspec, 
230
                                                           name='textsearch')
231
232
    def test_Search(self):
233
        self.db.provenance.find.return_value = ['r1','r2']
234
        self.setupRepo()
235
        self.repo.search('xyz')
236
        self.db.provenance.find.assert_called_with({'$text':{'$search': 'xyz'}})
237 View Code Duplication
        self.fileFactory.fromProvenance.assert_any_call('r1')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
238
        self.fileFactory.fromProvenance.assert_any_call('r2')
239
240
    def test_Query_for_ALL_field(self):
241
        self.db.provenance.distinct.return_value = ['r1','r2']
242
        self.setupRepo()
243
        q = Mock()
244
        field1 = Mock()
245
        field1.name = 'color'
246
        field1.all = True
247
        q.getFields.return_value = [field1]
248
        out = self.repo.inquire(q)
249
        self.db.provenance.distinct.assert_called_with('color')
250
        assert not self.fileFactory.fromProvenance.called
251
252