tests.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import contextlib
  2. import tempfile
  3. from hashlib import sha1
  4. from unittest.mock import MagicMock, patch
  5. from django.core.files import File as DjangoFile
  6. from django.core.files.uploadedfile import SimpleUploadedFile
  7. from model_bakery import baker
  8. from difs.tasks import ChecksumMismatched, difs_create_file_from_chunks
  9. from files.models import File
  10. from glitchtip.test_utils.test_case import GlitchTipTestCase
  11. class DebugInformationFileModelTestCase(GlitchTipTestCase):
  12. def test_is_proguard(self):
  13. dif = baker.make("difs.DebugInformationFile")
  14. self.assertEqual(dif.is_proguard_mapping(), False)
  15. dif = baker.make("difs.DebugInformationFile", data={"symbol_type": "proguard"})
  16. self.assertEqual(dif.is_proguard_mapping(), True)
  17. class DifsAssembleAPITestCase(GlitchTipTestCase):
  18. def setUp(self):
  19. self.create_user_and_project()
  20. self.url = f"/api/0/projects/{self.organization.slug}/{self.project.slug}/files/difs/assemble/" # noqa
  21. self.checksum = "0892b6a9469438d9e5ffbf2807759cd689996271"
  22. self.chunks = [
  23. "efa73a85c44d64e995ade0cc3286ea47cfc49c36",
  24. "966e44663054d6c1f38d04c6ff4af83467659bd7",
  25. ]
  26. self.data = {
  27. self.checksum: {
  28. "name": "test",
  29. "debug_id": "a959d2e6-e4e5-303e-b508-670eb84b392c",
  30. "chunks": self.chunks,
  31. }
  32. }
  33. def test_difs_assemble_with_dif_existed(self):
  34. file = baker.make("files.File", checksum=self.checksum)
  35. baker.make(
  36. "difs.DebugInformationFile",
  37. project=self.project,
  38. file=file,
  39. )
  40. expected_response = {self.checksum: {"state": "ok", "missingChunks": []}}
  41. response = self.client.post(self.url, self.data, format="json")
  42. self.assertEqual(response.data, expected_response)
  43. def test_difs_assemble_with_missing_chunks(self):
  44. baker.make("files.FileBlob", checksum=self.chunks[0])
  45. data = {
  46. self.checksum: {
  47. "name": "test",
  48. "debug_id": "a959d2e6-e4e5-303e-b508-670eb84b392c",
  49. "chunks": self.chunks,
  50. }
  51. }
  52. expected_response = {
  53. self.checksum: {"state": "not_found", "missingChunks": [self.chunks[1]]}
  54. }
  55. response = self.client.post(self.url, data, format="json")
  56. self.assertEqual(response.data, expected_response)
  57. def test_difs_assemble_without_missing_chunks(self):
  58. for chunk in self.chunks:
  59. baker.make("files.FileBlob", checksum=chunk)
  60. expected_response = {self.checksum: {"state": "created", "missingChunks": []}}
  61. response = self.client.post(self.url, self.data, format="json")
  62. self.assertEqual(response.data, expected_response)
  63. class DsymsAPIViewTestCase(GlitchTipTestCase):
  64. def setUp(self):
  65. self.create_user_and_project()
  66. self.url = f"/api/0/projects/{self.organization.slug}/{self.project.slug}/files/dsyms/" # noqa
  67. self.uuid = "afb116cf-efec-49af-a7fe-281ac680d8a0"
  68. self.checksum = "da39a3ee5e6b4b0d3255bfef95601890afd80709"
  69. @contextlib.contextmanager
  70. def patch(self):
  71. proguard_file = MagicMock()
  72. proguard_file.read.return_value = b""
  73. uploaded_zip_file = MagicMock()
  74. uploaded_zip_file.namelist.return_value = iter([f"proguard/{self.uuid}.txt"])
  75. uploaded_zip_file.open.return_value.__enter__.return_value = (
  76. proguard_file # noqa
  77. )
  78. with patch("zipfile.is_zipfile", return_value=True), patch(
  79. "zipfile.ZipFile"
  80. ) as ZipFile:
  81. ZipFile.return_value.__enter__.return_value = uploaded_zip_file
  82. yield
  83. def test_post(self):
  84. """
  85. It should return the expected response
  86. """
  87. upload_file = SimpleUploadedFile(
  88. "example.zip", b"random_content", content_type="multipart/form-data"
  89. )
  90. data = {"file": upload_file}
  91. with self.patch():
  92. response = self.client.post(self.url, data)
  93. expected_response = [
  94. {
  95. "id": response.data[0]["id"],
  96. "debugId": self.uuid,
  97. "cpuName": "any",
  98. "objectName": "proguard-mapping",
  99. "symbolType": "proguard",
  100. "headers": {"Content-Type": "text/x-proguard+plain"},
  101. "size": 0,
  102. "sha1": self.checksum,
  103. "dateCreated": response.data[0]["dateCreated"],
  104. "data": {"features": ["mapping"]},
  105. }
  106. ]
  107. self.assertEqual(response.status_code, 200)
  108. self.assertEqual(len(response.data), 1)
  109. self.assertEqual(response.data, expected_response)
  110. def test_post_existing_file(self):
  111. """
  112. It should success and return the expected response
  113. """
  114. baker.make("files.FileBlob", checksum=self.checksum)
  115. fileobj = baker.make("files.File", checksum=self.checksum)
  116. dif = baker.make(
  117. "difs.DebugInformationFile", file=fileobj, project=self.project
  118. )
  119. upload_file = SimpleUploadedFile(
  120. "example.zip", b"random_content", content_type="multipart/form-data"
  121. )
  122. data = {"file": upload_file}
  123. with self.patch():
  124. response = self.client.post(self.url, data)
  125. expected_response = [
  126. {
  127. "id": dif.id,
  128. "debugId": self.uuid,
  129. "cpuName": "any",
  130. "objectName": "proguard-mapping",
  131. "symbolType": "proguard",
  132. "headers": {"Content-Type": "text/x-proguard+plain"},
  133. "size": 0,
  134. "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
  135. "dateCreated": response.data[0]["dateCreated"],
  136. "data": {"features": ["mapping"]},
  137. }
  138. ]
  139. self.assertEqual(response.status_code, 200)
  140. self.assertEqual(len(response.data), 1)
  141. self.assertEqual(response.data, expected_response)
  142. def test_post_invalid_zip_file(self):
  143. upload_file = SimpleUploadedFile(
  144. "example.zip", b"random_content", content_type="multipart/form-data"
  145. )
  146. data = {"file": upload_file}
  147. response = self.client.post(self.url, data)
  148. expected_response = {"error": "Invalid file type uploaded"}
  149. self.assertEqual(response.data, expected_response)
  150. self.assertEqual(response.status_code, 400)
  151. class DifsTasksTestCase(GlitchTipTestCase):
  152. def setUp(self):
  153. self.create_user_and_project()
  154. def create_file_blob(self, name, content):
  155. bin = content.encode("utf-8")
  156. tmp = tempfile.NamedTemporaryFile()
  157. tmp.write(bin)
  158. tmp.flush()
  159. checksum = sha1(bin).hexdigest()
  160. fileblob = baker.make("files.FileBlob", checksum=checksum)
  161. fileblob.blob.save(name, DjangoFile(tmp))
  162. tmp.close()
  163. return fileblob
  164. def test_difs_create_file_from_chunks(self):
  165. fileblob1 = self.create_file_blob("1", "1")
  166. fileblob2 = self.create_file_blob("2", "2")
  167. checksum = sha1(b"12").hexdigest()
  168. chunks = [fileblob1.checksum, fileblob2.checksum]
  169. difs_create_file_from_chunks("12", checksum, chunks)
  170. file = File.objects.filter(checksum=checksum).first()
  171. self.assertEqual(file.checksum, checksum)
  172. def test_difs_create_file_from_chunks_with_mismatched_checksum(self):
  173. fileblob1 = self.create_file_blob("1", "1")
  174. fileblob2 = self.create_file_blob("2", "2")
  175. checksum = sha1(b"123").hexdigest()
  176. chunks = [fileblob1.checksum, fileblob2.checksum]
  177. with self.assertRaises(ChecksumMismatched):
  178. difs_create_file_from_chunks("123", checksum, chunks)