test_datadownloads_dataarchive.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import os
  2. from collections import OrderedDict
  3. from django.core.files import File
  4. from django.test import TestCase
  5. from django.utils import timezone
  6. from misago.conf import settings
  7. from misago.users.datadownloads.dataarchive import FILENAME_MAX_LEN, DataArchive, trim_long_filename
  8. from misago.users.testutils import AuthenticatedUserTestCase
  9. DATA_DOWNLOADS_WORKING_DIR = settings.MISAGO_USER_DATA_DOWNLOADS_WORKING_DIR
  10. TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
  11. TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, 'avatar.png')
  12. class DataArchiveTests(AuthenticatedUserTestCase):
  13. def test_enter_without_dirs(self):
  14. """data archive doesn't touch filesystem on init"""
  15. archive = DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR)
  16. self.assertEqual(archive.user, self.user)
  17. self.assertEqual(archive.working_dir_path, DATA_DOWNLOADS_WORKING_DIR)
  18. self.assertIsNone(archive.tmp_dir_path)
  19. self.assertIsNone(archive.data_dir_path)
  20. def test_context_life_cycle(self):
  21. """object creates valid tmp directory on enter and cleans on exit"""
  22. tmp_dir_path = None
  23. data_dir_path = None
  24. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  25. self.assertTrue(os.path.exists(archive.tmp_dir_path))
  26. self.assertTrue(os.path.exists(archive.data_dir_path))
  27. working_dir = str(DATA_DOWNLOADS_WORKING_DIR)
  28. tmp_dir_path = str(archive.tmp_dir_path)
  29. data_dir_path = str(archive.data_dir_path)
  30. self.assertTrue(tmp_dir_path.startswith(working_dir))
  31. self.assertTrue(data_dir_path.startswith(working_dir))
  32. self.assertTrue(data_dir_path.startswith(working_dir))
  33. self.assertTrue(data_dir_path.startswith(tmp_dir_path))
  34. self.assertIsNone(archive.tmp_dir_path)
  35. self.assertIsNone(archive.data_dir_path)
  36. self.assertFalse(os.path.exists(tmp_dir_path))
  37. self.assertFalse(os.path.exists(data_dir_path))
  38. def test_add_text_str(self):
  39. """add_dict method creates text file with string"""
  40. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  41. data_to_write = "Hello, łorld!"
  42. file_path = archive.add_text('testfile', data_to_write)
  43. self.assertTrue(os.path.isfile(file_path))
  44. valid_output_path = os.path.join(archive.data_dir_path, 'testfile.txt')
  45. self.assertEqual(file_path, valid_output_path)
  46. with open(file_path, 'r') as fp:
  47. saved_data = fp.read().strip()
  48. self.assertEqual(saved_data, data_to_write)
  49. def test_add_text_int(self):
  50. """add_dict method creates text file with int"""
  51. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  52. data_to_write = 1234
  53. file_path = archive.add_text('testfile', data_to_write)
  54. self.assertTrue(os.path.isfile(file_path))
  55. valid_output_path = os.path.join(archive.data_dir_path, 'testfile.txt')
  56. self.assertEqual(file_path, valid_output_path)
  57. with open(file_path, 'r') as fp:
  58. saved_data = fp.read().strip()
  59. self.assertEqual(saved_data, str(data_to_write))
  60. def test_add_dict(self):
  61. """add_dict method creates text file from dict"""
  62. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  63. data_to_write = {'first': "łorld!", 'second': "łup!"}
  64. file_path = archive.add_dict('testfile', data_to_write)
  65. self.assertTrue(os.path.isfile(file_path))
  66. valid_output_path = os.path.join(archive.data_dir_path, 'testfile.txt')
  67. self.assertEqual(file_path, valid_output_path)
  68. with open(file_path, 'r') as fp:
  69. saved_data = fp.read().strip()
  70. # order of dict items in py<3.6 is non-deterministic
  71. # making testing for exact match a mistake
  72. self.assertIn("first: łorld!", saved_data)
  73. self.assertIn("second: łup!", saved_data)
  74. def test_add_dict_ordered(self):
  75. """add_dict method creates text file form ordered dict"""
  76. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  77. data_to_write = OrderedDict((('first', "łorld!"), ('second', "łup!")))
  78. file_path = archive.add_dict('testfile', data_to_write)
  79. self.assertTrue(os.path.isfile(file_path))
  80. valid_output_path = os.path.join(archive.data_dir_path, 'testfile.txt')
  81. self.assertEqual(file_path, valid_output_path)
  82. with open(file_path, 'r') as fp:
  83. saved_data = fp.read().strip()
  84. self.assertEqual(saved_data, "first: łorld!\nsecond: łup!")
  85. def test_add_model_file(self):
  86. """add_model_file method adds model file"""
  87. with open(TEST_AVATAR_PATH, 'rb') as avatar:
  88. self.user.avatar_tmp = File(avatar)
  89. self.user.save()
  90. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  91. file_path = archive.add_model_file(self.user.avatar_tmp)
  92. self.assertTrue(os.path.isfile(file_path))
  93. data_dir_path = str(archive.data_dir_path)
  94. self.assertTrue(str(file_path).startswith(data_dir_path))
  95. def test_add_model_file_empty(self):
  96. """add_model_file method is noop if model field is empty"""
  97. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  98. file_path = archive.add_model_file(self.user.avatar_tmp)
  99. self.assertIsNone(file_path)
  100. self.assertFalse(os.listdir(archive.data_dir_path))
  101. def test_add_model_file_prefixed(self):
  102. """add_model_file method adds model file with prefix"""
  103. with open(TEST_AVATAR_PATH, 'rb') as avatar:
  104. self.user.avatar_tmp = File(avatar)
  105. self.user.save()
  106. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  107. file_path = archive.add_model_file(self.user.avatar_tmp, prefix="prefix")
  108. self.assertTrue(os.path.isfile(file_path))
  109. data_dir_path = str(archive.data_dir_path)
  110. self.assertTrue(str(file_path).startswith(data_dir_path))
  111. filename = os.path.basename(self.user.avatar_tmp.name)
  112. target_filename = 'prefix-{}'.format(filename)
  113. self.assertTrue(str(file_path).endswith(target_filename))
  114. def test_make_final_path_no_kwargs(self):
  115. """make_final_path returns data_dir_path if no kwargs are set"""
  116. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  117. final_path = archive.make_final_path()
  118. self.assertEqual(final_path, archive.data_dir_path)
  119. def test_make_final_path_directory(self):
  120. """make_final_path returns path including directory name"""
  121. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  122. final_path = archive.make_final_path(directory='test-directory')
  123. valid_path = os.path.join(archive.data_dir_path, 'test-directory')
  124. self.assertEqual(final_path, valid_path)
  125. def test_make_final_path_date(self):
  126. """make_final_path returns path including date segments"""
  127. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  128. now = timezone.now().date()
  129. final_path = archive.make_final_path(date=now)
  130. valid_path = os.path.join(
  131. archive.data_dir_path,
  132. now.strftime('%Y'),
  133. now.strftime('%m'),
  134. now.strftime('%d')
  135. )
  136. self.assertEqual(final_path, valid_path)
  137. def test_make_final_path_datetime(self):
  138. """make_final_path returns path including date segments"""
  139. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  140. now = timezone.now()
  141. final_path = archive.make_final_path(date=now)
  142. valid_path = os.path.join(
  143. archive.data_dir_path,
  144. now.strftime('%Y'),
  145. now.strftime('%m'),
  146. now.strftime('%d')
  147. )
  148. self.assertEqual(final_path, valid_path)
  149. def test_make_final_path_both_kwargs(self):
  150. """make_final_path raises value error if both date and directory are set"""
  151. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  152. expected_message = "date and directory arguments are mutually exclusive"
  153. with self.assertRaisesMessage(ValueError, expected_message):
  154. archive.make_final_path(date=timezone.now(), directory='test')
  155. def test_get_file(self):
  156. """get_file returns django file"""
  157. django_file = None
  158. with open(TEST_AVATAR_PATH, 'rb') as avatar:
  159. self.user.avatar_tmp = File(avatar)
  160. self.user.save()
  161. with DataArchive(self.user, DATA_DOWNLOADS_WORKING_DIR) as archive:
  162. archive.add_model_file(self.user.avatar_tmp)
  163. django_file = archive.get_file()
  164. archive_path = archive.file_path
  165. self.assertIsNotNone(archive_path)
  166. self.assertEqual(django_file.name, archive.file_path)
  167. self.assertFalse(django_file.closed)
  168. self.assertIsNone(archive.file)
  169. self.assertIsNone(archive.file_path)
  170. self.assertTrue(django_file.closed)
  171. class TrimLongFilenameTests(TestCase):
  172. def test_trim_short_filename(self):
  173. """trim_too_long_filename returns short filename as it is"""
  174. filename = 'filename.jpg'
  175. trimmed_filename = trim_long_filename(filename)
  176. self.assertEqual(trimmed_filename, filename)
  177. def test_trim_too_long_filename(self):
  178. """trim_too_long_filename trims filename if its longer than allowed"""
  179. filename = 'filename'
  180. extension = '.jpg'
  181. long_filename = '{}{}'.format(filename * 10, extension)
  182. trimmed_filename = trim_long_filename(long_filename)
  183. self.assertEqual(len(trimmed_filename), FILENAME_MAX_LEN)
  184. self.assertTrue(trimmed_filename.startswith(filename))
  185. self.assertTrue(trimmed_filename.endswith(extension))