Issues (30)

tests/test_add.py (2 issues)

1
import unittest, os
2
from mock import Mock, patch, call, sentinel
3
from tests.ditest import DependencyInjectionTestBase
4
5
6
class AddTests(DependencyInjectionTestBase):
7
8
    def setUp(self):
9
        super(AddTests, self).setUp()
10
        self.config.dryrun = False
11
        self.repo.byLocation.return_value = None
12
        self.query.copiesOf.return_value = []
13
        self.img = Mock()
14
        self.lastProvenance = None
15
        def locAt(loc, provenance):
16
            self.lastProvenance = provenance
17
            self.lastPath = loc
18
            return self.img
19
        self.fileFactory.locatedAt.side_effect = locAt
20
        patcher = patch('niprov.adding.datetime')
21
        self.datetime = patcher.start()
22
        self.addCleanup(patcher.stop)
23
24
    def add(self, path, **kwargs):
25
        from niprov.adding import add
26
        with patch('niprov.adding.inheritFrom') as self.inheritFrom:
27
            return add(path, dependencies=self.dependencies, **kwargs)
28
29
    def assertNotCalledWith(self, m, *args, **kwargs):
30
        c = call(*args, **kwargs)
31
        assert c not in m.call_args_list, "Unexpectedly found call: "+str(c)
32
33
    def test_Returns_provenance_and_informs_listener(self):
34
        new = '/p/f2'
35
        image = self.add(new)
36
        self.listener.fileAdded.assert_called_with(self.img)
37
        self.assertEqual(image, self.img)
38
39
    def test_Sets_transient_flag_if_provided(self):
40
        image = self.add('/p/f1', transient=True)
41
        self.assertEqual(self.lastProvenance['transient'],True)
42
43
    def test_Creates_ImageFile_object_with_factory(self):
44
        image = self.add('p/afile.f')
45
        self.assertIs(self.img, image)
46
47
    def test_Calls_inspect(self):
48
        image = self.add('p/afile.f')
49
        self.img.inspect.assert_called_with()
50
51
    def test_If_inspect_raises_exceptions_tells_listener_and_doesnt_save(self):
52
        self.img.inspect.side_effect = IOError
53
        image = self.add('p/afile.f')
54
        assert not self.repo.add.called
55
        assert not self.repo.update.called
56
        self.listener.fileError.assert_called_with(self.img.path)
57
        self.assertEqual(self.img.status, 'failed')
58
59
    def test_If_dryrun_doesnt_talk_to_repo_and_status_is_test(self):
60
        self.config.dryrun = True
61
        image = self.add('p/afile.f')
62
        assert not self.repo.add.called
63
        assert not self.repo.update.called
64
        assert not self.img.inspect.called
65
66
    def test_accepts_optional_provenance(self):
67
        image = self.add('p/afile.f', provenance={'fob':'bez'})
68
        self.assertEqual(self.lastProvenance['fob'],'bez')
69
70
    def test_If_file_doesnt_exists_raises_error(self):
71
        self.filesys.fileExists.return_value = False
72
        self.assertRaises(IOError, self.add, self.img.location.path)
73
        self.filesys.fileExists.assert_called_with(self.img.location.path)
74
75
    def test_For_nonexisting_transient_file_behaves_normal(self):
76
        self.filesys.fileExists.return_value = False
77
        self.add('p/afile.f', transient=True)
78
79
    def test_Doesnt_inspect_transient_files(self):
80
        self.add('p/afile.f', transient=True)
81
        assert not self.img.inspect.called
82
83
    def test_Adds_timestamp(self):
84
        image = self.add('p/afile.f')
85
        self.assertEqual(self.lastProvenance['added'],self.datetime.now())
86
87
    def test_Adds_uid(self):
88
        with patch('niprov.adding.shortuuid') as shortuuid:
89
            shortuuid.uuid.return_value = 'abcdefghijklmn'
90
            image = self.add('p/afile.f')
91
            self.assertEqual(self.lastProvenance['id'],'abcdef')
92
93
    def test_If_config_attach_set_calls_attach_on_file(self):
94
        self.config.attach = False
95
        self.add('p/afile.f')
96
        assert not self.img.attach.called, "Shouldnt attach if not configured."
97
        self.config.attach = True
98
        self.config.attach_format = 'abracadabra'
99
        self.add('p/afile.f', transient=True)
100
        assert not self.img.attach.called, "Shouldnt attach to transient file."
101
        self.add('p/afile.f')
102
        self.img.attach.assert_called_with('abracadabra')
103
104
    def test_If_file_unknown_adds_it(self):                             # A
105
        self.repo.byLocation.return_value = None
106
        self.repo.getSeries.return_value = None
107
        image = self.add('p/afile.f')
108
        self.repo.add.assert_any_call(self.img)
109
110
    def test_If_file_is_version_but_not_series(self):                    # B
111
        previousVersion = Mock()
112
        self.repo.byLocation.return_value = previousVersion
113
        self.repo.getSeries.return_value = None
114
        img = self.add('p/afile.f')
115
        self.img.keepVersionsFromPrevious.assert_called_with(previousVersion)
116
        self.repo.update.assert_any_call(self.img)
117
118
    def test_If_file_is_version_and_series(self):                        # C
119
        previousVersion = Mock()
120
        series = Mock()
121
        self.repo.byLocation.return_value = previousVersion
122
        self.repo.getSeries.return_value = series
123
        image = self.add('p/afile.f')
124
        self.img.keepVersionsFromPrevious.assert_called_with(previousVersion)
125
        self.repo.update.assert_any_call(self.img)
126 View Code Duplication
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
127
    def test_If_file_not_version_but_series_and_not_in_there_yet(self):   # D1
128
        series = Mock()
129
        series.hasFile.return_value = False
130
        series.mergeWith.return_value = series
131
        self.repo.byLocation.return_value = None
132
        self.repo.getSeries.return_value = series
133
        image = self.add('p/afile.f')
134
        series.mergeWith.assert_called_with(self.img)
135
        self.repo.update.assert_any_call(series)
136 View Code Duplication
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
137
    def test_If_file_not_version_but_series_has_file(self):               # D2
138
        series = Mock()
139
        series.hasFile.return_value = True
140
        self.repo.byLocation.return_value = None
141
        self.repo.getSeries.return_value = series
142
        image = self.add('p/afile.f')
143
        assert not series.mergeWith.called
144
        self.img.keepVersionsFromPrevious.assert_called_with(series)
145
        self.repo.update.assert_any_call(self.img)
146
147
    def test_copiesOf_not_called_before_inspect(self):
148
        def testIfInspectedAndReturnEptyList(img):
149
            img.inspect.assert_called_with()
150
            return []
151
        self.query.copiesOf.side_effect = testIfInspectedAndReturnEptyList
152
        image = self.add('p/afile.f')
153
154
    def test_getSeries_not_called_before_inspect(self):
155
        self.repo.getSeries.side_effect = lambda img: img.inspect.assert_called_with()
156
        image = self.add('p/afile.f')
157
158
    def test_copiesOf_not_called_if_parent_available(self):
159
        image = self.add('p/afile.f', provenance={'parents':[sentinel.parent]})
160
        assert not self.query.copiesOf.called
161
162
    def test_Found_copy_set_as_parent_inherits_and_flags_and_informs_listener(self):
163
        self.img.provenance = {}
164
        copy = Mock()
165
        copy.provenance = {'location':'copy-location'}
166
        self.query.copiesOf.return_value = [self.img, copy]
167
        out = self.add('p/afile.f')
168
        self.inheritFrom.assert_called_with(self.img.provenance, copy.provenance)
169
        self.listener.usingCopyAsParent.assert_called_with(copy)
170
        self.assertEqual(copy.location.toString(), out.provenance['parents'][0])
171
        self.assertEqual(True, out.provenance['copy-as-parent'])
172
173
    def test_If_only_copy_is_same_location_ignores_it(self):
174
        self.img.provenance = {}
175
        self.query.copiesOf.return_value = [self.img]
176
        out = self.add('p/afile.f')
177
        assert not self.inheritFrom.called
178
        assert not self.listener.usingCopyAsParent.called
179
        self.assertNotIn('parents', out.provenance)
180
        self.assertNotIn('copy-as-parent', out.provenance)
181
182
    def test_Adds_niprov_version(self):
183
        with patch('niprov.adding.pkg_resources') as pkgres:
184
            dist = Mock()
185
            dist.version = '5.4.1'
186
            pkgres.get_distribution.return_value = dist
187
            image = self.add('p/afile.f')
188
        self.assertEqual(self.lastProvenance['version-added'], 5.41)
189
190
        
191
192