Skip to content

Commit 721c92b

Browse files
committed
Update appengine imports for external_testcase_reader. (drive by add additional component filter for extra safety)
1 parent 0f590af commit 721c92b

File tree

3 files changed

+86
-15
lines changed

3 files changed

+86
-15
lines changed

src/clusterfuzz/_internal/cron/external_testcase_reader.py

+33-13
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@
2121

2222
from appengine.libs import form
2323
from appengine.libs import gcs
24-
from appengine.libs import helpers
2524
from clusterfuzz._internal.config import local_config
2625
from clusterfuzz._internal.issue_management.google_issue_tracker import \
2726
issue_tracker
27+
from clusterfuzz._internal.metrics import logs
2828

2929
ACCEPTED_FILETYPES = [
3030
'text/javascript', 'application/pdf', 'text/html', 'application/zip'
3131
]
3232
ISSUETRACKER_ACCEPTED_STATE = 'ACCEPTED'
3333
ISSUETRACKER_WONTFIX_STATE = 'NOT_REPRODUCIBLE'
34+
UPLOAD_REQUEST_COMPONENT_FILTER = 'componentid:1600865'
35+
CLUSTERFUZZ_COMPONENT_FILTER = 'componentid:1457062+'
3436

3537

3638
def get_vrp_uploaders(config):
@@ -125,7 +127,7 @@ def submit_testcase(issue_id, file, filename, filetype, cmds):
125127
elif filetype == 'application/zip':
126128
job = 'linux_asan_chrome_mp'
127129
else:
128-
raise TypeError
130+
return 0
129131
upload_info = gcs.prepare_blob_upload()._asdict()
130132

131133
data = {
@@ -158,18 +160,23 @@ def handle_testcases(tracker, config):
158160
# Handle bugs that were already submitted and still open.
159161
older_issues = tracker.find_issues_with_filters(
160162
keywords=[],
161-
query_filters=['componentid:1600865', 'status:accepted'],
163+
query_filters=[
164+
UPLOAD_REQUEST_COMPONENT_FILTER, CLUSTERFUZZ_COMPONENT_FILTER,
165+
'status:accepted'
166+
],
162167
only_open=True)
163168
for issue in older_issues:
164169
# Close out older bugs that may have failed to reproduce.
165170
if close_issue_if_not_reproducible(issue, config):
166-
helpers.log('Closing issue {issue_id} as it failed to reproduce',
167-
issue.id)
171+
logs.info(f'Closing issue {issue.id} as it failed to reproduce')
168172

169173
# Handle new bugs that may need to be submitted.
170174
issues = tracker.find_issues_with_filters(
171175
keywords=[],
172-
query_filters=['componentid:1600865', 'status:new'],
176+
query_filters=[
177+
UPLOAD_REQUEST_COMPONENT_FILTER, CLUSTERFUZZ_COMPONENT_FILTER,
178+
'status:new'
179+
],
173180
only_open=True)
174181
if len(issues) == 0:
175182
return
@@ -189,20 +196,33 @@ def handle_testcases(tracker, config):
189196
reporters_map[issue.reporter] = reporters_map.get(issue.reporter, 1) + 1
190197
if close_issue_if_invalid(issue, attachment_metadata, commandline_flags,
191198
vrp_uploaders):
192-
helpers.log('Closing issue {issue_id} as it is invalid', issue.id)
199+
logs.info(f'Closing issue {issue.id} as it is invalid')
193200
continue
194201

195202
# Submit valid testcases.
196203
attachment_metadata = attachment_metadata[0]
197204
attachment = tracker.get_attachment(
198205
attachment_metadata['attachmentDataRef']['resourceName'])
199-
submit_testcase(issue.id, attachment, attachment_metadata['filename'],
200-
attachment_metadata['contentType'], commandline_flags)
201-
comment_message = 'Testcase submitted to clusterfuzz'
202-
issue.status = ISSUETRACKER_ACCEPTED_STATE
203-
issue.assignee = 'clusterfuzz@chromium.org'
206+
submit_result = submit_testcase(
207+
issue.id, attachment, attachment_metadata['filename'],
208+
attachment_metadata['contentType'], commandline_flags)
209+
if submit_result and submit_result.status_code == 200:
210+
comment_message = 'Testcase submitted to clusterfuzz.'
211+
issue.status = ISSUETRACKER_ACCEPTED_STATE
212+
issue.assignee = 'clusterfuzz@chromium.org'
213+
logs.info(f'Submitted testcase file for issue {issue.id}')
214+
elif submit_result and submit_result.status_code != 200:
215+
comment_message = 'Testcase submission failed during upload.'
216+
issue.status = ISSUETRACKER_WONTFIX_STATE
217+
logs.info(f'Testcase submission failed with error code'
218+
f'{submit_result.status_code} for issue: {issue.id}')
219+
else:
220+
comment_message = (
221+
'Testcase submission failed due to unrecognized poc type.')
222+
issue.status = ISSUETRACKER_WONTFIX_STATE
223+
logs.info(f'Testcase submission failed due to poc type error'
224+
f'for issue: {issue.id}')
204225
issue.save(new_comment=comment_message, notify=True)
205-
helpers.log('Submitted testcase file for issue {issue_id}', issue.id)
206226

207227

208228
def main():

src/clusterfuzz/_internal/tests/appengine/handlers/cron/external_testcase_reader_test.py

+47
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,53 @@ def test_handle_testcases_no_issues(self, mock_close_issue_if_invalid,
129129
mock_submit_testcase.assert_not_called()
130130

131131

132+
@mock.patch.object(
133+
external_testcase_reader.gcs, 'prepare_blob_upload', autospec=True)
134+
@mock.patch.object(
135+
external_testcase_reader.form, 'generate_csrf_token', autospec=True)
136+
class ExternalTestcaseReaderSubmitTestcaseTest(unittest.TestCase):
137+
"""external_testcase_reader submit_testcase tests."""
138+
139+
@mock.patch.object(external_testcase_reader.requests, 'post', autospec=True)
140+
def test_submit_valid_testcase(self, mock_post, mock_csrf, mock_blob):
141+
"""Test a basic submit_testcase with a valid testcase."""
142+
html_file = mock.MagicMock()
143+
actual = external_testcase_reader.submit_testcase(
144+
123, html_file, 'filename', 'text/html', ['command1'])
145+
146+
self.assertNotEqual(0, actual)
147+
mock_post.assert_called()
148+
mock_csrf.assert_called()
149+
mock_blob.assert_called()
150+
151+
@mock.patch.object(external_testcase_reader.requests, 'post', autospec=True)
152+
def test_submit_unsupported_testcase(self, mock_post, mock_csrf, mock_blob):
153+
"""Test a basic submit_testcase with an unsupported testcase."""
154+
some_file = mock.MagicMock()
155+
actual = external_testcase_reader.submit_testcase(
156+
123, some_file, 'filename', 'invalid/type', ['command1'])
157+
158+
self.assertEqual(0, actual)
159+
mock_post.assert_not_called()
160+
mock_csrf.assert_not_called()
161+
mock_blob.assert_not_called()
162+
163+
@mock.patch.object(external_testcase_reader.requests, 'post', autospec=True)
164+
def test_submit_post_failure(self, mock_post, mock_csrf, mock_blob):
165+
"""Test a basic submit_testcase with an http post failure."""
166+
invalid_file = mock.MagicMock()
167+
invalid_response = mock.MagicMock()
168+
invalid_response.status_code = 400
169+
mock_post.return_value = invalid_response
170+
actual = external_testcase_reader.submit_testcase(
171+
123, invalid_file, 'filename', 'text/html', ['command1'])
172+
173+
self.assertEqual(400, actual.status_code)
174+
mock_post.assert_called()
175+
mock_csrf.assert_called()
176+
mock_blob.assert_called()
177+
178+
132179
class ExternalTestcaseReaderInvalidIssueTest(unittest.TestCase):
133180
"""external_testcase_reader close_issue_if_invalid tests."""
134181

src/python/bot/startup/run_cron.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,19 @@ def main():
4949
if os.path.exists(config_modules_path):
5050
sys.path.append(config_modules_path)
5151

52+
task = sys.argv[1]
53+
if task == 'external_testcase_reader':
54+
appengine_path = os.path.join(root_directory, 'src', 'appengine')
55+
if os.path.exists(appengine_path):
56+
sys.path.append(appengine_path)
57+
5258
try:
5359
# Run any module initialization code.
5460
import module_init
5561
module_init.init()
5662
except ImportError:
5763
pass
5864

59-
task = sys.argv[1]
60-
6165
task_module_name = f'clusterfuzz._internal.cron.{task}'
6266
with monitor.wrap_with_monitoring(), ndb_init.context():
6367
task_module = importlib.import_module(task_module_name)

0 commit comments

Comments
 (0)