tests.py 8.1 KB

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