Skip to content

Commit f3ce4f3

Browse files
move assemble test as well
1 parent fdb11f5 commit f3ce4f3

File tree

2 files changed

+232
-220
lines changed

2 files changed

+232
-220
lines changed

tests/sentry/preprod/test_tasks.py

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
from hashlib import sha1
2+
3+
from django.core.files.base import ContentFile
4+
5+
from sentry.models.files.file import File
6+
from sentry.models.files.fileblob import FileBlob
7+
from sentry.tasks.assemble import (
8+
AssembleTask,
9+
ChunkFileState,
10+
assemble_preprod_artifact,
11+
get_assemble_status,
12+
)
13+
from tests.sentry.tasks.test_assemble import BaseAssembleTest
14+
15+
16+
class AssemblePreprodArtifactTest(BaseAssembleTest):
17+
def test_assemble_preprod_artifact_success(self):
18+
content = b"test preprod artifact content"
19+
fileobj = ContentFile(content)
20+
total_checksum = sha1(content).hexdigest()
21+
22+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
23+
24+
assemble_preprod_artifact(
25+
org_id=self.organization.id,
26+
project_id=self.project.id,
27+
checksum=total_checksum,
28+
chunks=[blob.checksum],
29+
git_sha="abc123def456",
30+
build_configuration="release",
31+
)
32+
33+
status, details = get_assemble_status(
34+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, total_checksum
35+
)
36+
assert status == ChunkFileState.OK
37+
assert details is None
38+
39+
# Check that the file was created
40+
files = File.objects.filter(type="preprod.artifact")
41+
assert len(files) == 1
42+
assert files[0].checksum == total_checksum
43+
# Name should start with "preprod-artifact-" and be a UUID since file_name is no longer passed
44+
assert files[0].name.startswith("preprod-artifact-")
45+
46+
# Import models here to match the pattern in the source code
47+
from sentry.preprod.models import PreprodArtifact, PreprodBuildConfiguration
48+
49+
# Check that PreprodBuildConfiguration was created
50+
build_configs = PreprodBuildConfiguration.objects.filter(
51+
project=self.project, name="release"
52+
)
53+
assert len(build_configs) == 1
54+
55+
# Check that PreprodArtifact was created
56+
artifacts = PreprodArtifact.objects.filter(project=self.project)
57+
assert len(artifacts) == 1
58+
artifact = artifacts[0]
59+
assert artifact.file_id == files[0].id
60+
assert artifact.build_configuration == build_configs[0]
61+
assert artifact.state == PreprodArtifact.ArtifactState.UPLOADED
62+
63+
def test_assemble_preprod_artifact_without_build_configuration(self):
64+
content = b"test preprod artifact without build config"
65+
fileobj = ContentFile(content)
66+
total_checksum = sha1(content).hexdigest()
67+
68+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
69+
70+
assemble_preprod_artifact(
71+
org_id=self.organization.id,
72+
project_id=self.project.id,
73+
checksum=total_checksum,
74+
chunks=[blob.checksum],
75+
)
76+
77+
status, details = get_assemble_status(
78+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, total_checksum
79+
)
80+
assert status == ChunkFileState.OK
81+
82+
from sentry.preprod.models import PreprodArtifact
83+
84+
# Check that PreprodArtifact was created without build configuration
85+
artifacts = PreprodArtifact.objects.filter(project=self.project)
86+
assert len(artifacts) == 1
87+
artifact = artifacts[0]
88+
assert artifact.build_configuration is None
89+
assert artifact.extras is None
90+
91+
def test_assemble_preprod_artifact_generates_filename(self):
92+
content = b"test preprod artifact with generated filename"
93+
fileobj = ContentFile(content)
94+
total_checksum = sha1(content).hexdigest()
95+
96+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
97+
98+
assemble_preprod_artifact(
99+
org_id=self.organization.id,
100+
project_id=self.project.id,
101+
checksum=total_checksum,
102+
chunks=[blob.checksum],
103+
)
104+
105+
status, details = get_assemble_status(
106+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, total_checksum
107+
)
108+
assert status == ChunkFileState.OK
109+
110+
# Check that a file was created with generated name
111+
files = File.objects.filter(type="preprod.artifact")
112+
assert len(files) == 1
113+
# Name should start with "preprod-artifact-" and be a UUID
114+
assert files[0].name.startswith("preprod-artifact-")
115+
116+
def test_assemble_preprod_artifact_checksum_mismatch(self):
117+
content = b"test content"
118+
fileobj = ContentFile(content)
119+
wrong_checksum = "a" * 40 # Wrong checksum
120+
121+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
122+
123+
assemble_preprod_artifact(
124+
org_id=self.organization.id,
125+
project_id=self.project.id,
126+
checksum=wrong_checksum,
127+
chunks=[blob.checksum],
128+
)
129+
130+
status, details = get_assemble_status(
131+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, wrong_checksum
132+
)
133+
assert status == ChunkFileState.ERROR
134+
assert "Reported checksum mismatch" in details
135+
136+
def test_assemble_preprod_artifact_missing_chunks(self):
137+
missing_checksum = "nonexistent" + "0" * 32
138+
total_checksum = sha1(b"test").hexdigest()
139+
140+
assemble_preprod_artifact(
141+
org_id=self.organization.id,
142+
project_id=self.project.id,
143+
checksum=total_checksum,
144+
chunks=[missing_checksum],
145+
)
146+
147+
status, details = get_assemble_status(
148+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, total_checksum
149+
)
150+
assert status == ChunkFileState.ERROR
151+
assert "Not all chunks available for assembling" in details
152+
153+
def test_assemble_preprod_artifact_nonexistent_organization(self):
154+
content = b"test content"
155+
fileobj = ContentFile(content)
156+
total_checksum = sha1(content).hexdigest()
157+
158+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
159+
nonexistent_org_id = 99999
160+
161+
assemble_preprod_artifact(
162+
org_id=nonexistent_org_id,
163+
project_id=self.project.id,
164+
checksum=total_checksum,
165+
chunks=[blob.checksum],
166+
)
167+
168+
status, details = get_assemble_status(
169+
AssembleTask.PREPROD_ARTIFACT, nonexistent_org_id, total_checksum
170+
)
171+
assert status == ChunkFileState.ERROR
172+
assert details is not None
173+
174+
def test_assemble_preprod_artifact_nonexistent_project(self):
175+
content = b"test content"
176+
fileobj = ContentFile(content)
177+
total_checksum = sha1(content).hexdigest()
178+
179+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
180+
nonexistent_project_id = 99999
181+
182+
assemble_preprod_artifact(
183+
org_id=self.organization.id,
184+
project_id=nonexistent_project_id,
185+
checksum=total_checksum,
186+
chunks=[blob.checksum],
187+
)
188+
189+
status, details = get_assemble_status(
190+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, total_checksum
191+
)
192+
assert status == ChunkFileState.ERROR
193+
assert details is not None
194+
195+
def test_assemble_preprod_artifact_reuses_build_configuration(self):
196+
from sentry.preprod.models import PreprodBuildConfiguration
197+
198+
# Create an existing build configuration using get_or_create to match the source code pattern
199+
existing_config, _ = PreprodBuildConfiguration.objects.get_or_create(
200+
project=self.project, name="debug"
201+
)
202+
203+
content = b"test preprod artifact with existing config"
204+
fileobj = ContentFile(content)
205+
total_checksum = sha1(content).hexdigest()
206+
207+
blob = FileBlob.from_file_with_organization(fileobj, self.organization)
208+
209+
assemble_preprod_artifact(
210+
org_id=self.organization.id,
211+
project_id=self.project.id,
212+
checksum=total_checksum,
213+
chunks=[blob.checksum],
214+
build_configuration="debug",
215+
)
216+
217+
status, details = get_assemble_status(
218+
AssembleTask.PREPROD_ARTIFACT, self.organization.id, total_checksum
219+
)
220+
assert status == ChunkFileState.OK
221+
222+
# Should only have one build configuration with this name
223+
build_configs = PreprodBuildConfiguration.objects.filter(project=self.project, name="debug")
224+
assert len(build_configs) == 1
225+
assert build_configs[0].id == existing_config.id
226+
227+
from sentry.preprod.models import PreprodArtifact
228+
229+
# Check that the artifact uses the existing configuration
230+
artifacts = PreprodArtifact.objects.filter(project=self.project)
231+
assert len(artifacts) == 1
232+
assert artifacts[0].build_configuration == existing_config

0 commit comments

Comments
 (0)