aboutsummaryrefslogtreecommitdiffhomepage
path: root/infra
diff options
context:
space:
mode:
authorGravatar jonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com>2020-08-26 11:59:56 -0700
committerGravatar GitHub <noreply@github.com>2020-08-26 11:59:56 -0700
commitdb8467bf302b0398feaf8317cbba0a2801775da5 (patch)
tree7d8436451ae03a59064024eae835e92a38fe6ffd /infra
parenta6abdaa5ac13d8c92654d2ce871de699d583e7da (diff)
[CI] Don't do coverage builds for engineless fuzzers. (#4374)
Coverage builds need to be special cased since they aren't specified in sanitizers. Instead they are done for all C/C++ projects that use libFuzzer. Move all of this special casing to `should_build_coverage` and call that from `should_build` so we have one place where we decide this. Add tests as well. Fixes: https://github.com/google/oss-fuzz/issues/4371
Diffstat (limited to 'infra')
-rwxr-xr-xinfra/ci/build.py40
-rw-r--r--infra/ci/build_test.py93
2 files changed, 122 insertions, 11 deletions
diff --git a/infra/ci/build.py b/infra/ci/build.py
index 15dd4fb6..9bdbb969 100755
--- a/infra/ci/build.py
+++ b/infra/ci/build.py
@@ -87,8 +87,34 @@ def check_build(project, engine, sanitizer, architecture):
])
+def should_build_coverage(project_yaml):
+ """Returns True if a coverage build should be done based on project.yaml
+ contents."""
+ # Enable coverage builds on projects that use engines. Those that don't use
+ # engines shouldn't get coverage builds.
+ engines = project_yaml.get('fuzzing_engines', DEFAULT_ENGINES)
+ engineless = 'none' in engines
+ if engineless:
+ assert_message = ('Forbidden to specify multiple engines for '
+ '"fuzzing_engines" if "none" is specified.')
+ assert len(engines) == 1, assert_message
+ return False
+
+ language = project_yaml.get('language')
+ if language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
+ print(('Project is written in "{language}", '
+ 'coverage is not supported yet.').format(language=language))
+ return False
+
+ return True
+
+
def should_build(project_yaml):
- """Return bool on if the build specified is enabled in the project.yaml."""
+ """Returns True on if the build specified is enabled in the project.yaml."""
+
+ if os.getenv('SANITIZER') == 'coverage':
+ # This assumes we only do coverage builds with libFuzzer on x86_64.
+ return should_build_coverage(project_yaml)
def is_enabled(env_var, yaml_name, defaults):
"""Is the value of |env_var| enabled in |project_yaml| (in the |yaml_name|
@@ -115,18 +141,10 @@ def build_project(project):
engine = os.getenv('ENGINE')
sanitizer = os.getenv('SANITIZER')
architecture = os.getenv('ARCHITECTURE')
- language = project_yaml.get('language')
-
- if (sanitizer == 'coverage' and
- language not in LANGUAGES_WITH_COVERAGE_SUPPORT):
- print(('Project "{project}" is written in "{language}", '
- 'coverage is not supported yet.').format(project=project,
- language=language))
- return
- if sanitizer != 'coverage' and not should_build(project_yaml):
+ if not should_build(project_yaml):
print(('Specified build: engine: {0}, sanitizer: {1}, architecture: {2} '
- 'not enabled for this project: {3}. skipping build.').format(
+ 'not enabled for this project: {3}. Skipping build.').format(
engine, sanitizer, architecture, project))
return
diff --git a/infra/ci/build_test.py b/infra/ci/build_test.py
new file mode 100644
index 00000000..ef2d3a80
--- /dev/null
+++ b/infra/ci/build_test.py
@@ -0,0 +1,93 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Tests for build.py"""
+
+import os
+import unittest
+from unittest import mock
+
+from ci import build
+
+
+def patch_environ(testcase_obj):
+ """Patch environment."""
+ env = {}
+ patcher = mock.patch.dict(os.environ, env)
+ testcase_obj.addCleanup(patcher.stop)
+ patcher.start()
+
+
+def _set_coverage_build():
+ """Set the right environment variables for a coverage build."""
+ os.environ['SANITIZER'] = 'coverage'
+ os.environ['ENGINE'] = 'libfuzzer'
+ os.environ['ARCHITECTURE'] = 'x86_64'
+
+
+class TestShouldBuild(unittest.TestCase):
+ """Tests that should_build() works as intended."""
+
+ def setUp(self):
+ patch_environ(self)
+
+ def test_none_engine_coverage_build(self):
+ """Tests that should_build returns False for a coverage build of a
+ project that specifies 'none' for fuzzing_engines."""
+ _set_coverage_build()
+ project_yaml = {
+ 'language': 'c++',
+ 'fuzzing_engines': ['none'],
+ 'sanitizers': ['address']
+ }
+ self.assertFalse(build.should_build(project_yaml))
+
+ def test_unspecified_engines_coverage_build(self):
+ """Tests that should_build returns True for a coverage build of a
+ project that doesn't specify fuzzing_engines."""
+ _set_coverage_build()
+ project_yaml = {'language': 'c++'}
+ self.assertTrue(build.should_build(project_yaml))
+
+ def test_libfuzzer_coverage_build(self):
+ """Tests that should_build returns True for coverage build of a project
+ specifying 'libfuzzer' and for fuzzing_engines."""
+ _set_coverage_build()
+ project_yaml = {
+ 'language': 'c++',
+ 'fuzzing_engines': ['libfuzzer'],
+ 'sanitizers': ['address']
+ }
+ self.assertTrue(build.should_build(project_yaml))
+
+ def test_go_coverage_build(self):
+ """Tests that should_build returns False for coverage build of a project
+ specifying 'libfuzzer' and for fuzzing_engines."""
+ _set_coverage_build()
+ project_yaml = {'language': 'go'}
+ self.assertFalse(build.should_build(project_yaml))
+
+ def test_engine_project_none_build(self):
+ """Tests that should_build returns False for an engine: 'none' build when
+ the project doesn't specify engines."""
+ os.environ['SANITIZER'] = 'address'
+ os.environ['ENGINE'] = 'none'
+ os.environ['ARCHITECTURE'] = 'x86_64'
+ project_yaml = {
+ 'language': 'c++',
+ 'fuzzing_engines': ['libfuzzer'],
+ 'sanitizers': ['address']
+ }
+ self.assertFalse(build.should_build(project_yaml))