44import datetime
55import hashlib
66import os
7+ from contextlib import nullcontext
78from typing import Tuple
9+ from unittest .mock import patch
810
911from django .conf import settings
1012from django .contrib .auth import get_user_model
1618from api_app .choices import Classification
1719from api_app .connectors_manager .models import ConnectorConfig
1820from api_app .playbooks_manager .models import PlaybookConfig
21+ from tests .mock_utils import if_mock_connections
1922
2023from .. import CustomViewSetTestCase
2124
@@ -101,7 +104,8 @@ def test_ask_analysis_availability__run_all_analyzers(self):
101104 response = self .client .post ("/api/ask_analysis_availability" , data , format = "json" )
102105 self .assertEqual (response .status_code , 200 )
103106
104- def test_analyze_file__pcap (self ):
107+ @if_mock_connections (patch ("intel_owl.tasks.job_pipeline.apply_async" ))
108+ def test_analyze_file__pcap (self , mock_apply_async = None ):
105109 # set a fake API key or YARAify_File_Scan will be skipped as not configured
106110 models .PluginConfig .objects .create (
107111 owner = self .user ,
@@ -144,6 +148,10 @@ def test_analyze_file__pcap(self):
144148 list (job .analyzers_to_execute .all ().values_list ("name" , flat = True )),
145149 )
146150
151+ if mock_apply_async is not None :
152+ mock_apply_async .assert_called_once ()
153+ self .assertEqual (mock_apply_async .call_args .kwargs ["args" ], [job_id ])
154+
147155 def test_analyze_file__exe (self ):
148156 data = self .analyze_file_data .copy ()
149157 response = self .client .post ("/api/analyze_file" , data , format = "multipart" )
@@ -232,7 +240,8 @@ def test_analyze_observable__ip(self):
232240 self .assertEqual (data ["observable_classification" ], job .analyzable .classification , msg = msg )
233241 self .assertEqual (self .observable_md5 , job .analyzable .md5 , msg = msg )
234242
235- def test_analyze_observable__guess_optional (self ):
243+ @if_mock_connections (patch ("intel_owl.tasks.job_pipeline.apply_async" ))
244+ def test_analyze_observable__guess_optional (self , mock_apply_async = None ):
236245 data = self .analyze_observable_ip_data .copy ()
237246 observable_classification = data .pop ("observable_classification" ) # let the server calc it
238247
@@ -252,16 +261,22 @@ def test_analyze_observable__guess_optional(self):
252261 self .assertEqual (observable_classification , job .analyzable .classification , msg = msg )
253262 self .assertEqual (self .observable_md5 , job .analyzable .md5 , msg = msg )
254263
255- def test_analyze_multiple_observables (self ):
264+ if mock_apply_async is not None :
265+ mock_apply_async .assert_called_once ()
266+ self .assertEqual (mock_apply_async .call_args .kwargs ["args" ], [job_id ])
267+
268+ @if_mock_connections (patch ("intel_owl.tasks.job_pipeline.apply_async" ))
269+ def test_analyze_multiple_observables (self , mock_apply_async = None ):
256270 data = self .mixed_observable_data .copy ()
257271
258272 response = self .client .post ("/api/analyze_multiple_observables" , data , format = "json" )
259273 contents = response .json ()
260274 msg = (response .status_code , contents )
261275 self .assertEqual (response .status_code , 200 , msg = msg )
276+ if mock_apply_async is not None :
277+ self .assertEqual (mock_apply_async .call_count , len (data ["observables" ]))
262278
263279 content = contents ["results" ][0 ]
264-
265280 job_id = int (content ["job_id" ])
266281 job = models .Job .objects .get (pk = job_id )
267282 self .assertEqual (data ["observables" ][0 ][1 ], job .analyzable .name , msg = msg )
@@ -275,9 +290,10 @@ def test_analyze_multiple_observables(self):
275290 list (job .analyzers_to_execute .all ().values_list ("name" , flat = True )),
276291 msg = msg ,
277292 )
293+ if mock_apply_async is not None :
294+ self .assertEqual (mock_apply_async .call_args_list [0 ].kwargs ["args" ], [job_id ])
278295
279296 content = contents ["results" ][1 ]
280-
281297 job_id = int (content ["job_id" ])
282298 job = models .Job .objects .get (pk = job_id )
283299 self .assertEqual (data ["observables" ][1 ][1 ], job .analyzable .name , msg = msg )
@@ -286,6 +302,8 @@ def test_analyze_multiple_observables(self):
286302 list (job .analyzers_to_execute .all ().values_list ("name" , flat = True )),
287303 msg = msg ,
288304 )
305+ if mock_apply_async is not None :
306+ self .assertEqual (mock_apply_async .call_args_list [1 ].kwargs ["args" ], [job_id ])
289307 job .delete ()
290308
291309 def test_observable_no_analyzers_only_connector (self ):
@@ -527,7 +545,12 @@ def test_job_rescan__observable_playbook(self):
527545 "visualizers" : {},
528546 },
529547 )
530- response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
548+ # dont actually run the analyzers when mocking connections, they are tested in unit tests
549+ ctx = (
550+ patch ("intel_owl.tasks.job_pipeline.apply_async" ) if settings .MOCK_CONNECTIONS else nullcontext ()
551+ )
552+ with ctx as mock_apply_async :
553+ response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
531554 contents = response .json ()
532555 self .assertEqual (response .status_code , 202 , contents )
533556 new_job_id = int (contents ["id" ])
@@ -543,6 +566,9 @@ def test_job_rescan__observable_playbook(self):
543566 "visualizers" : {},
544567 },
545568 )
569+ if mock_apply_async is not None :
570+ mock_apply_async .assert_called_once ()
571+ self .assertEqual (mock_apply_async .call_args .kwargs ["args" ], [new_job_id ])
546572 an .delete ()
547573
548574 def test_job_rescan__sample_analyzers (self ):
@@ -567,7 +593,11 @@ def test_job_rescan__sample_analyzers(self):
567593 )
568594 job .analyzers_requested .set ([AnalyzerConfig .objects .get (name = "Strings_Info" )])
569595
570- response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
596+ ctx = (
597+ patch ("intel_owl.tasks.job_pipeline.apply_async" ) if settings .MOCK_CONNECTIONS else nullcontext ()
598+ )
599+ with ctx as mock_apply_async :
600+ response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
571601 contents = response .json ()
572602 self .assertEqual (response .status_code , 202 , contents )
573603 new_job_id = int (contents ["id" ])
@@ -579,6 +609,9 @@ def test_job_rescan__sample_analyzers(self):
579609 list (new_job .analyzers_requested .all ()),
580610 [AnalyzerConfig .objects .get (name = "Strings_Info" )],
581611 )
612+ if mock_apply_async is not None :
613+ mock_apply_async .assert_called_once ()
614+ self .assertEqual (mock_apply_async .call_args .kwargs ["args" ], [new_job_id ])
582615 self .assertEqual (
583616 new_job .runtime_configuration ,
584617 {
@@ -617,7 +650,11 @@ def test_job_rescan__sample_playbook(self):
617650 },
618651 )
619652
620- response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
653+ ctx = (
654+ patch ("intel_owl.tasks.job_pipeline.apply_async" ) if settings .MOCK_CONNECTIONS else nullcontext ()
655+ )
656+ with ctx as mock_apply_async :
657+ response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
621658 contents = response .json ()
622659 self .assertEqual (response .status_code , 202 , contents )
623660 new_job_id = int (contents ["id" ])
@@ -642,6 +679,9 @@ def test_job_rescan__sample_playbook(self):
642679 "visualizers" : {},
643680 },
644681 )
682+ if mock_apply_async is not None :
683+ mock_apply_async .assert_called_once ()
684+ self .assertEqual (mock_apply_async .call_args .kwargs ["args" ], [new_job_id ])
645685 job .delete ()
646686 an .delete ()
647687
@@ -665,14 +705,24 @@ def test_job_rescan__permission(self):
665705 "visualizers" : {},
666706 },
667707 )
668- # same user
669- response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
670- contents = response .json ()
671- self .assertEqual (response .status_code , 202 , contents )
672- # another user
673- self .client .logout ()
674- self .client .force_login (self .guest )
675- response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
676- contents = response .json ()
677- self .assertEqual (response .status_code , 403 , contents )
708+ ctx = (
709+ patch ("intel_owl.tasks.job_pipeline.apply_async" ) if settings .MOCK_CONNECTIONS else nullcontext ()
710+ )
711+ with ctx as mock_apply_async :
712+ response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
713+ contents = response .json ()
714+ self .assertEqual (response .status_code , 202 , contents )
715+ new_job_id = int (contents ["id" ])
716+ if mock_apply_async is not None :
717+ mock_apply_async .assert_called_once ()
718+ self .assertEqual (mock_apply_async .call_args .kwargs ["args" ], [new_job_id ])
719+ mock_apply_async .reset_mock ()
720+
721+ self .client .logout ()
722+ self .client .force_login (self .guest )
723+ response = self .client .post (f"/api/jobs/{ job .pk } /rescan" , format = "json" )
724+ contents = response .json ()
725+ self .assertEqual (response .status_code , 403 , contents )
726+ if mock_apply_async is not None :
727+ mock_apply_async .assert_not_called ()
678728 an .delete ()
0 commit comments