Skip to content

Commit 9fb41a9

Browse files
authored
Add introspector report links to oss-fuzz-home (#2632)
* Add introspector report links * local gitignore * making it unconditional * debug * add logging * restore .gitingnore * gitignore * skip memoize * trying again template * fix template * cleanup * restore .gitignore * apply comments * lint * add mock for storage.read_data * adding mock for storage.exists and fixing assertEqual * diversify tests
1 parent ae4867a commit 9fb41a9

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

src/appengine/handlers/home.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,23 @@
1313
# limitations under the License.
1414
"""Home page handler."""
1515

16+
import json
17+
1618
from clusterfuzz._internal.base import external_users
1719
from clusterfuzz._internal.base import memoize
1820
from clusterfuzz._internal.base import utils
1921
from clusterfuzz._internal.datastore import data_handler
2022
from clusterfuzz._internal.datastore import data_types
23+
from clusterfuzz._internal.google_cloud_utils import storage
24+
from clusterfuzz._internal.metrics import logs
2125
from clusterfuzz._internal.system import environment
2226
from handlers import base_handler
2327
from libs import access
2428
from libs import handler
2529
from libs import helpers
2630

31+
INTROSPECTOR_INDEX_JSON_URL = 'gs://oss-fuzz-introspector/build_status.json'
32+
2733
MEMCACHE_TTL_IN_SECONDS = 30 * 60
2834

2935

@@ -60,9 +66,21 @@ def get_single_fuzz_target_or_none(project, engine_name):
6066
return fuzz_target_name
6167

6268

69+
def get_introspector_index():
70+
"""Return introspector projects status"""
71+
if storage.exists(INTROSPECTOR_INDEX_JSON_URL):
72+
introspector_index = json.loads(
73+
storage.read_data(INTROSPECTOR_INDEX_JSON_URL))
74+
else:
75+
introspector_index = {}
76+
logs.log('Loaded introspector status: %d' % len(introspector_index))
77+
return introspector_index
78+
79+
6380
def _get_project_results_for_jobs(jobs):
6481
"""Return projects for jobs."""
6582
projects = {}
83+
introspector_index = get_introspector_index()
6684
for job in sorted(jobs, key=lambda j: j.name):
6785
project_name = job.get_environment().get('PROJECT_NAME', job.name)
6886
if project_name not in projects:
@@ -71,6 +89,12 @@ def _get_project_results_for_jobs(jobs):
7189
if utils.string_is_true(job.get_environment().get('CORPUS_PRUNE')):
7290
projects[project_name]['coverage_job'] = job.name
7391

92+
projects[project_name]['has_introspector'] = False
93+
if project_name in introspector_index:
94+
projects[project_name]['has_introspector'] = True
95+
projects[project_name]['introspector_report'] = introspector_index[
96+
project_name]
97+
7498
engine_display_name, engine_name = _get_engine_names(job.name)
7599
projects[project_name]['jobs'].append({
76100
'engine_display_name':

src/appengine/private/components/oss-fuzz-home/oss-fuzz-home.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ <h2>[[project.name]]</h2>
6868
<a href="/testcases?project=[[project.name]]&open=yes"><paper-button raised>Open crashes</paper-button></a>
6969
<a href="/crash-stats?project=[[project.name]]"><paper-button raised>Crash stats</paper-button></a>
7070
<a href="/coverage-report/job/[[project.coverage_job]]/latest"><paper-button raised>Total coverage</paper-button></a>
71+
<template is="dom-if" if="{{project.has_introspector}}">
72+
<a href="[[project.introspector_report]]"><paper-button raised>Fuzz Introspector Report</paper-button></a>
73+
</template>
7174
</div>
7275
<div class="layout horizontal wrap">
7376
<template is="dom-repeat" items="[[project.jobs]]" as ="job">

src/clusterfuzz/_internal/tests/appengine/handlers/home_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ def setUp(self):
3333
'libs.access.get_access',
3434
'clusterfuzz._internal.base.external_users.allowed_jobs_for_user',
3535
'libs.helpers.get_user_email',
36+
'clusterfuzz._internal.google_cloud_utils.storage.read_data',
37+
'clusterfuzz._internal.google_cloud_utils.storage.exists'
3638
])
3739

40+
self.mock.read_data.return_value = ''
41+
self.mock.exists.return_value = False
3842
data_types.Job(
3943
name='libfuzzer_asan_lib',
4044
environment_string=('PROJECT_NAME = lib\n'
@@ -90,6 +94,8 @@ def test_results_external(self):
9094
'libfuzzer_asan_lib', 'libfuzzer_msan_lib'
9195
]
9296
self.mock.get_access.return_value = access.UserAccess.Denied
97+
self.mock.read_data.return_value = '{"lib": "lib_url"}'
98+
self.mock.exists.return_value = True
9399

94100
results = home.get_results()
95101
self.assertEqual(
@@ -115,6 +121,10 @@ def test_results_external(self):
115121
u'lib',
116122
'coverage_job':
117123
'libfuzzer_asan_lib',
124+
'has_introspector':
125+
True,
126+
'introspector_report':
127+
'lib_url'
118128
}],
119129
'is_internal_user':
120130
False,
@@ -157,6 +167,10 @@ def test_results_external(self):
157167
u'lib',
158168
'coverage_job':
159169
'libfuzzer_asan_lib',
170+
'has_introspector':
171+
True,
172+
'introspector_report':
173+
'lib_url'
160174
}, {
161175
'jobs': [{
162176
'sanitizer_string': 'Sanitizer: address (ASAN)',
@@ -184,6 +198,8 @@ def test_results_external(self):
184198
u'lib2',
185199
'coverage_job':
186200
'libfuzzer_asan_lib2',
201+
'has_introspector':
202+
False,
187203
}],
188204
'is_internal_user':
189205
False,
@@ -227,6 +243,8 @@ def test_results_internal(self):
227243
u'lib',
228244
'coverage_job':
229245
'libfuzzer_asan_lib',
246+
'has_introspector':
247+
False,
230248
}, {
231249
'jobs': [{
232250
'sanitizer_string': 'Sanitizer: address (ASAN)',
@@ -254,6 +272,8 @@ def test_results_internal(self):
254272
u'lib2',
255273
'coverage_job':
256274
'libfuzzer_asan_lib2',
275+
'has_introspector':
276+
False,
257277
}],
258278
'is_internal_user':
259279
True,

0 commit comments

Comments
 (0)