Completed
Pull Request — master (#32)
by Jace
03:15
created

TestUser.test_cleanup_empty_dirs()   A

Complexity

Conditions 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 11
rs 9.4285
1
#!/usr/bin/env python
2
3
"""Unit tests for the dtb.user module."""
4
5
import unittest
6
from unittest.mock import patch, Mock, call
7
8
import os
9
import tempfile
10
import shutil
11
12
from dtb.user import User, get_current
13
14
from dtb.test import FILES
15
16
FAKESONG = os.path.join(FILES, 'FakeSong.mp3')
17
FAKELINK = os.path.join(FILES, 'abc123.yml')
18
FAKEFILE = os.path.join(FILES, 'FakeFile.yml')
19
BROKENLINK = os.path.join(FILES, 'broken.yml')
20
21
22
class MockSong(Mock):
23
    """Mock Song class."""
24
25
    link = Mock()
26
27
28
class TestUser(unittest.TestCase):  # pylint: disable=R0904
29
    """Unit tests for the User class."""  # pylint: disable=C0103,W0212
30
31
    INFOS = [('PC', 'MrTemp'),
32
             ('PC', 'MrTemp2'),
33
             ('PC', 'MrTemp3')]
34
35
    @classmethod
36
    @patch('dtb.user.get_info', Mock(side_effect=INFOS))
37
    def setUpClass(cls):
38
        cls.root = tempfile.mkdtemp()
39
        cls.downloads = tempfile.mkdtemp()
40
        cls.name = 'TempUser'
41
        cls.user = User.new(cls.root, cls.name, downloads=cls.downloads)
42
        cls.user2 = User.new(cls.root, cls.name + '2')
43
        cls.user3 = User.new(cls.root, cls.name + '3')
44
        with open(os.path.join(cls.root, 'desktop.ini'), 'w'):
45
            pass  # create a "junk" file in the share directory
46
47
    @classmethod
48
    def tearDownClass(cls):
49
        shutil.rmtree(cls.root)
50
        shutil.rmtree(cls.downloads)
51
52
    def test_new_duplicate(self):
53
        """Verify a user cannot be created twice."""
54
        self.assertRaises(EnvironmentError, User.new, self.root, self.name)
55
56
    # https://github.com/jacebrowning/dropthebeat/issues/1
57
    def test_new_folder_exists(self):
58
        """Verify a user can be created when their friend directory exists."""
59
        name = 'FolderExists'
60
        os.mkdir(os.path.join(self.user.path, name))
61
        user = User.new(self.root, name)
62
        try:
63
            pass
64
        finally:
65
            user.delete()
66
67
    def test_add_old_format(self):
68
        """Verify a user can be added to an old format."""
69
        root = tempfile.mkdtemp()
70
        try:
71
            with patch('dtb.user.get_info', Mock(return_value=self.INFOS[0])):
72
                user = User.new(root, 'TempUser')
73
            open(user.path_info, 'w').close()  # blank the file
74
            with patch('dtb.user.get_info', Mock(return_value=self.INFOS[1])):
75
                user2 = User.add(root, 'TempUser')
76
            self.assertEqual(1, len(user2.info))
77
        finally:
78
            shutil.rmtree(root)
79
80
    def test_str(self):
81
        """Verify a user can be converted to a string."""
82
        text = str(os.path.join(self.root, self.name))
83
        self.assertEqual(text, str(self.user))
84
85
    def test_cmp(self):
86
        """Verify users can be compared."""
87
        self.assertEqual(self.user, self.user)
88
        self.assertNotEqual(self.user, self.user2)
89
90
    def test_name(self):
91
        """Verify a user's name is correct."""
92
        self.assertEqual(self.name, self.user.name)
93
94
    def test_root(self):
95
        """Verify a user's root path is correct."""
96
        self.assertEqual(self.root, self.user.root)
97
98
    def test_path_private(self):
99
        """Verify a user's private path is correct."""
100
        path = os.path.join(self.root, self.name, '.dtb')
101
        self.assertEqual(path, self.user.path_private)
102
        self.assertTrue(os.path.isdir(path))
103
104
    def test_path_drops(self):
105
        """Verify a user's drops path is correct."""
106
        path = os.path.join(self.root, self.name, '.dtb', 'drops')
107
        self.assertEqual(path, self.user.path_drops)
108
        self.assertTrue(os.path.isdir(path))
109
110
    def test_path_info(self):
111
        """Verify a user's info path is correct."""
112
        path = os.path.join(self.root, self.name, '.dtb', 'info.yml')
113
        self.assertEqual(path, self.user.path_info)
114
        self.assertTrue(os.path.isfile(path))
115
116
    def test_path_library(self):
117
        """Verify a user's library path is correct."""
118
        path = os.path.join(self.root, self.name, '.dtb', 'library.sqlite3')
119
        self.assertEqual(path, self.user.path_library)
120
        # TODO: add this test when library support is added
121
        # self.assertTrue(os.path.isfile(path))
122
123
    def test_path_reuests(self):
124
        """Verify a user's requests path is correct."""
125
        path = os.path.join(self.root, self.name, '.dtb', 'requests.yml')
126
        self.assertEqual(path, self.user.path_requests)
127
        self.assertTrue(os.path.isfile(path))
128
129
    def test_path_settings(self):
130
        """Verify a user's settings path is correct."""
131
        path = os.path.join(self.root, self.name, '.dtb', 'settings.yml')
132
        self.assertEqual(path, self.user.path_settings)
133
        self.assertTrue(os.path.isfile(path))
134
135
    @patch('dtb.user.get_info', Mock(return_value=INFOS[0]))
136
    def test_path_downloads(self):
137
        """Verify a user's downloads path is correct."""
138
        path = self.downloads
139
        self.assertEqual(path, self.user.path_downloads)
140
        self.assertTrue(os.path.isdir(path))
141
142
    @patch('dtb.user.get_info', Mock(return_value=INFOS[0]))
143
    def test_path_downloads_set(self):
144
        """Verify a user's downloads path can be set."""
145
        temp = tempfile.mkdtemp()
146
        try:
147
            self.user.path_downloads = temp
148
            self.assertEqual(temp, self.user.path_downloads)
149
        finally:
150
            shutil.rmtree(temp)
151
152
    @patch('dtb.user.get_info', Mock(return_value=INFOS[0]))
153
    def test_path_downloads_set_old_format(self):
154
        """Verify a user's downloads path can be set (from an old format)."""
155
        open(self.user.path_info, 'w').close()  # blank the file
156
        temp = tempfile.mkdtemp()
157
        try:
158
            self.user.path_downloads = temp
159
            self.assertEqual(temp, self.user.path_downloads)
160
        finally:
161
            shutil.rmtree(temp)
162
163
    def test_info(self):
164
        """Verify a user's info is correct."""
165
        self.assertEqual([('PC', 'MrTemp')], self.user.info)
166
167
    def test_friends(self):
168
        """Verify a user's friends are correct."""
169
        friends = list(self.user.friends)
170
        self.assertEqual(2, len(friends))
171
        self.assertIsInstance(friends[0], User)
172
173
    def test_incoming(self):
174
        """Verify a user's incoming songs are correct."""
175
        path = os.path.join(self.user.path, 'TempUser2', '_a_song')
176
        open(path, 'w').close()  # touch the file
177
        try:
178
            songs = list(self.user.incoming)
179
            self.assertEqual(1, len(songs))
180
            self.assertEqual('TempUser2', songs[0].friendname)
181
        finally:
182
            os.remove(path)
183
184
    def test_incoming_zero(self):
185
        """Verify there can be zero incoming songs."""
186
        songs = list(self.user.incoming)
187
        self.assertEqual(0, len(songs))
188
189
    def test_outgoing(self):
190
        """Verify a user's outgoing songs are correct."""
191
        path = os.path.join(self.user2.path, self.name, '_a_song')
192
        open(path, 'w').close()  # touch the file
193
        try:
194
            songs = list(self.user.outgoing)
195
            self.assertEqual(1, len(songs))
196
            self.assertEqual(self.user2.name, songs[0].friendname)
197
        finally:
198
            os.remove(path)
199
200
    def test_outgoing_zero(self):
201
        """Verify there can be zero incoming songs."""
202
        songs = list(self.user.outgoing)
203
        self.assertEqual(0, len(songs))
204
205
    def test_cleanup_unlinked(self):
206
        """Verify a user's directory can be cleaned."""
207
        path = os.path.join(self.user.path_drops, '_a_song')
208
        path2 = os.path.join(self.user2.path, self.name, '_a_song2')
209
        open(path, 'w').close()  # touch the file
210
        open(path2, 'w').close()  # touch the file
211
        try:
212
            self.assertEqual(1, len(os.listdir(self.user.path_drops)))
213
            self.user.cleanup()
214
            self.assertEqual(0, len(os.listdir(self.user.path_drops)))
215
        finally:
216
            os.remove(path2)
217
218
    # https://github.com/jacebrowning/dropthebeat/issues/5
219
    def test_cleanup_empty_dirs(self):
220
        """Verify empty directories are deleted during cleanup."""
221
        empty = os.path.join(self.user.path, 'empty')
222
        os.mkdir(empty)
223
        empty2 = os.path.join(self.root, 'empty')
224
        os.mkdir(empty2)
225
        self.assertTrue(os.path.exists(empty))
226
        self.assertTrue(os.path.exists(empty2))
227
        self.user.cleanup()
228
        self.assertFalse(os.path.exists(empty))
229
        self.assertFalse(os.path.exists(empty2))
230
231
    @patch('dtb.user.Song', MockSong)
232
    def test_recommend(self,):
233
        """Verify a user can recommend a song."""
234
        self.user.recommend(FAKESONG)
235
        path2 = os.path.join(self.user2.path, self.name)
236
        path3 = os.path.join(self.user3.path, self.name)
237
        self.assertEqual(2, len(MockSong.link.call_args_list))
238
        self.assertIn(call(path2), MockSong.link.call_args_list)
239
        self.assertIn(call(path3), MockSong.link.call_args_list)
240
241
    def test_request(self):
242
        """Verify a user can request a song."""
243
        # TODO: update this test when feature implemented
244
        self.assertRaises(NotImplementedError, self.user.request, None)
245
246
    def test_check(self):
247
        """Verify a user can be checked."""
248
        self.user.check()
249
250
    def test_check_file_error(self):
251
        """Verify a user fails the check with a missing files."""
252
        user = User.new(self.root, '_temp')
253
        try:
254
            os.remove(user.path_info)
255
            self.assertRaises(ValueError, user.check)
256
        finally:
257
            user.delete()
258
259
    def test_check_folder_error(self):
260
        """Verify a user fails the check with a missing folders."""
261
        user = User.new(self.root, '_temp')
262
        try:
263
            shutil.rmtree(user.path_drops)
264
            self.assertRaises(ValueError, user.check)
265
        finally:
266
            user.delete()
267
268
    def test_delete(self):
269
        """Verify a user can be deleted."""
270
        user = User.new(self.root, '_temp')
271
        self.assertTrue(os.path.isdir(user.path))
272
        user.delete()
273
        self.assertFalse(os.path.isdir(user.path))
274
275
    @patch('dtb.user.get_info', Mock(return_value=INFOS[0]))
276
    def test_get_current(self):
277
        """Verify the current user can be retrieved."""
278
        os.mkdir(os.path.join(self.root, 'empty'))
279
        user = get_current(self.root)
280
        self.assertEqual(self.user, user)
281
282
    def test_get_current_error(self):
283
        """Verify an error occurs when the user cannot be found."""
284
        self.assertRaises(EnvironmentError, get_current, self.root)
285
286
    # https://github.com/jacebrowning/dropthebeat/issues/3
287
    def test_multiple_computers(self):
288
        """Verify a user can use multiple computers."""
289
        infos = [('pc1', 'name'), ('pc2', 'name'), ('pc2', 'name')]
290
        root = tempfile.mkdtemp()
291
        downloads = tempfile.mkdtemp()
292
        try:
293
            with patch('dtb.user.get_info', Mock(side_effect=infos)):
294
                user = User.new(root, 'name', downloads=downloads)
295
                user2 = User.add(root, 'name')
296
                user3 = User.add(root, 'name')
297
                self.assertEqual(user, user2)
298
                self.assertEqual(user, user3)
299
        finally:
300
            shutil.rmtree(root)
301
302
303
if __name__ == '__main__':
304
    unittest.main()
305