1- """Tests for ArtifactProcessor including error handling, retry logic, and message processing."""
2-
31from unittest .mock import Mock , patch
42
53import pytest
64
7- from sentry_kafka_schemas .schema_types .preprod_artifact_events_v1 import PreprodArtifactEvents
5+ from sentry_kafka_schemas .schema_types .preprod_artifact_events_v1 import (
6+ PreprodArtifactEvents ,
7+ )
88
99from launchpad .artifact_processor import ArtifactProcessor
1010from launchpad .constants import (
1616)
1717from launchpad .sentry_client import SentryClient , SentryClientError
1818from launchpad .service import ServiceConfig
19+ from launchpad .utils .objectstore .service import Client as ObjectstoreClient
1920from launchpad .utils .statsd import FakeStatsd
2021
2122
2223class TestArtifactProcessorErrorHandling :
23- """Test error handling and retry logic in ArtifactProcessor."""
24-
2524 def setup_method (self ):
2625 """Set up test fixtures."""
2726 mock_sentry_client = Mock (spec = SentryClient )
2827 mock_statsd = Mock ()
29- self .processor = ArtifactProcessor (mock_sentry_client , mock_statsd )
28+ mock_objectstore_client = Mock (spec = ObjectstoreClient )
29+ self .processor = ArtifactProcessor (mock_sentry_client , mock_statsd , mock_objectstore_client )
3030
3131 def test_retry_operation_success_on_first_attempt (self ):
3232 """Test that _retry_operation succeeds on first attempt."""
@@ -215,7 +215,11 @@ class TestArtifactProcessorMessageHandling:
215215 def test_process_message_ios (self , mock_process , mock_sentry_client ):
216216 """Test processing iOS artifact messages."""
217217 fake_statsd = FakeStatsd ()
218- service_config = ServiceConfig (sentry_base_url = "http://test.sentry.io" , projects_to_skip = [])
218+ service_config = ServiceConfig (
219+ sentry_base_url = "http://test.sentry.io" ,
220+ projects_to_skip = [],
221+ objectstore_base_url = "http://test.objectstore.io" ,
222+ )
219223
220224 # Create a payload for iOS artifact
221225 payload : PreprodArtifactEvents = {
@@ -230,20 +234,33 @@ def test_process_message_ios(self, mock_process, mock_sentry_client):
230234
231235 # Verify process_artifact was called with correct args
232236 mock_process .assert_called_once_with (
233- "test-org-123" , "test-project-ios" , "ios-test-123" , [PreprodFeature .SIZE_ANALYSIS ]
237+ "test-org-123" ,
238+ "test-project-ios" ,
239+ "ios-test-123" ,
240+ [PreprodFeature .SIZE_ANALYSIS ],
234241 )
235242
236243 # Verify metrics were recorded
237244 calls = fake_statsd .calls
238- assert ("increment" , {"metric" : "artifact.processing.started" , "value" : 1 , "tags" : None }) in calls
239- assert ("increment" , {"metric" : "artifact.processing.completed" , "value" : 1 , "tags" : None }) in calls
245+ assert (
246+ "increment" ,
247+ {"metric" : "artifact.processing.started" , "value" : 1 , "tags" : None },
248+ ) in calls
249+ assert (
250+ "increment" ,
251+ {"metric" : "artifact.processing.completed" , "value" : 1 , "tags" : None },
252+ ) in calls
240253
241254 @patch ("launchpad.artifact_processor.SentryClient" )
242255 @patch .object (ArtifactProcessor , "process_artifact" )
243256 def test_process_message_android (self , mock_process , mock_sentry_client ):
244257 """Test processing Android artifact messages."""
245258 fake_statsd = FakeStatsd ()
246- service_config = ServiceConfig (sentry_base_url = "http://test.sentry.io" , projects_to_skip = [])
259+ service_config = ServiceConfig (
260+ sentry_base_url = "http://test.sentry.io" ,
261+ projects_to_skip = [],
262+ objectstore_base_url = "http://test.objectstore.io" ,
263+ )
247264
248265 # Create a payload for Android artifact
249266 payload : PreprodArtifactEvents = {
@@ -266,15 +283,25 @@ def test_process_message_android(self, mock_process, mock_sentry_client):
266283
267284 # Verify metrics were recorded
268285 calls = fake_statsd .calls
269- assert ("increment" , {"metric" : "artifact.processing.started" , "value" : 1 , "tags" : None }) in calls
270- assert ("increment" , {"metric" : "artifact.processing.completed" , "value" : 1 , "tags" : None }) in calls
286+ assert (
287+ "increment" ,
288+ {"metric" : "artifact.processing.started" , "value" : 1 , "tags" : None },
289+ ) in calls
290+ assert (
291+ "increment" ,
292+ {"metric" : "artifact.processing.completed" , "value" : 1 , "tags" : None },
293+ ) in calls
271294
272295 @patch ("launchpad.artifact_processor.SentryClient" )
273296 @patch .object (ArtifactProcessor , "process_artifact" )
274297 def test_process_message_error (self , mock_process , mock_sentry_client ):
275298 """Test error handling in message processing."""
276299 fake_statsd = FakeStatsd ()
277- service_config = ServiceConfig (sentry_base_url = "http://test.sentry.io" , projects_to_skip = [])
300+ service_config = ServiceConfig (
301+ sentry_base_url = "http://test.sentry.io" ,
302+ projects_to_skip = [],
303+ objectstore_base_url = "http://test.objectstore.io" ,
304+ )
278305
279306 # Make process_artifact raise an exception
280307 mock_process .side_effect = RuntimeError ("Download failed: HTTP 404" )
@@ -292,7 +319,10 @@ def test_process_message_error(self, mock_process, mock_sentry_client):
292319
293320 # Verify process_artifact was called
294321 mock_process .assert_called_once_with (
295- "test-org" , "test-project" , "test-123" , [PreprodFeature .SIZE_ANALYSIS , PreprodFeature .BUILD_DISTRIBUTION ]
322+ "test-org" ,
323+ "test-project" ,
324+ "test-123" ,
325+ [PreprodFeature .SIZE_ANALYSIS , PreprodFeature .BUILD_DISTRIBUTION ],
296326 )
297327
298328 # Verify the metrics were called correctly
@@ -308,7 +338,9 @@ def test_process_message_project_skipped(self, mock_process, mock_sentry_client)
308338 """Test that projects in the skip list are not processed."""
309339 fake_statsd = FakeStatsd ()
310340 service_config = ServiceConfig (
311- sentry_base_url = "http://test.sentry.io" , projects_to_skip = ["skip-project-1" , "skip-project-2" ]
341+ sentry_base_url = "http://test.sentry.io" ,
342+ projects_to_skip = ["skip-project-1" , "skip-project-2" ],
343+ objectstore_base_url = "http://test.objectstore.io" ,
312344 )
313345
314346 # Create a payload for a project that should be skipped
@@ -334,7 +366,11 @@ def test_process_message_project_skipped(self, mock_process, mock_sentry_client)
334366 def test_process_message_project_not_skipped (self , mock_process , mock_sentry_client ):
335367 """Test that projects not in the skip list are processed normally."""
336368 fake_statsd = FakeStatsd ()
337- service_config = ServiceConfig (sentry_base_url = "http://test.sentry.io" , projects_to_skip = ["other-project" ])
369+ service_config = ServiceConfig (
370+ sentry_base_url = "http://test.sentry.io" ,
371+ projects_to_skip = ["other-project" ],
372+ objectstore_base_url = "http://test.objectstore.io" ,
373+ )
338374
339375 # Create a payload for a project that should NOT be skipped
340376 payload : PreprodArtifactEvents = {
@@ -357,5 +393,11 @@ def test_process_message_project_not_skipped(self, mock_process, mock_sentry_cli
357393
358394 # Verify normal metrics were recorded
359395 calls = fake_statsd .calls
360- assert ("increment" , {"metric" : "artifact.processing.started" , "value" : 1 , "tags" : None }) in calls
361- assert ("increment" , {"metric" : "artifact.processing.completed" , "value" : 1 , "tags" : None }) in calls
396+ assert (
397+ "increment" ,
398+ {"metric" : "artifact.processing.started" , "value" : 1 , "tags" : None },
399+ ) in calls
400+ assert (
401+ "increment" ,
402+ {"metric" : "artifact.processing.completed" , "value" : 1 , "tags" : None },
403+ ) in calls
0 commit comments