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
|
|
|
|