blob: cfe0e55fad9291c19eef1c32b837846b6e69146c [file] [log] [blame]
#!/bin/bash
# Copyright 2022 The Centipede Authors.
#
# 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
#
# https://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.
# Run a short fuzzing session for one puzzle and check the outcome.
# This script is executed under the name run_S_PUZZLE_NAME, where S is a single
# digit representing the seed, so we get the seed and puzzle name from $0.
# Every puzzle must have one or more lines containing "RUN:<program-text>"
# This script will execute <program-text> directly in the current context.
# <program-text> can use the functions defined in this file, see USER_FUNCTIONS.
set -eu -o pipefail
ls -la "$(dirname "$0")"
source "$(dirname "$0")/../test_util.sh"
readonly centipede_dir="$(centipede::get_centipede_test_srcdir)"
centipede::maybe_set_var_to_executable_path centipede "${centipede_dir}/centipede"
readonly centipede
readonly target_name="$(basename "$0")"
readonly seed_and_puzzle_name="${target_name#run_}"
readonly seed="${seed_and_puzzle_name:0:1}"
readonly puzzle_name="${seed_and_puzzle_name:2}"
readonly puzzle_source_name="${puzzle_name}.cc"
readonly puzzle_path="${centipede_dir}/puzzles/${puzzle_name}"
readonly puzzle_source_path="${centipede_dir}/puzzles/${puzzle_source_name}"
readonly workdir="${TEST_TMPDIR}/workdir"
readonly log="${TEST_TMPDIR}/log"
readonly script="${TEST_TMPDIR}/script"
# Read the configuration from the puzzle source.
grep 'RUN:' "${puzzle_source_path}" | sed 's/^.*RUN://' > "${script}"
echo "======== SCRIPT"
cat "${script}"
echo "======== END SCRIPT"
##################################### USER_FUNCTIONS
# Runs Centipede with additional parameters in $@, saves the result in log, cats
# the log. Expects Centipede to exit with failure.
function Run() {
echo "======== Run $*"
rm -rf "${workdir}"
mkdir "${workdir}"
"${centipede}" \
--workdir "${workdir}" \
--binary "${puzzle_path}" \
--seed="${seed}" \
--num_runs=2000000 \
--timeout_per_input=10 \
--exit_on_crash \
"$@" \
> "${log}" 2>&1 && exit 1 # Centipede must exit with failure.
cat "${log}"
}
# Checks that $1 is the solution for the puzzle.
function SolutionIs() {
echo "====== ${FUNCNAME[0]}: $1"
centipede::assert_regex_in_file "Input bytes.*: $1" "${log}"
}
# Expects that Centipede found a per-input timeout.
function ExpectPerInputTimeout() {
echo "======= ${FUNCNAME[0]}"
centipede::assert_regex_in_file "Per-input timeout exceeded" "${log}"
centipede::assert_regex_in_file "Failure.*: per-input-timeout-exceeded" "${log}"
}
# Expects that Centipede found a per-batch timeout.
function ExpectPerBatchTimeout() {
echo "======= ${FUNCNAME[0]}"
centipede::assert_regex_in_file "Per-batch timeout exceeded" "${log}"
centipede::assert_regex_in_file "Failure.*: per-batch-timeout-exceeded" "${log}"
centipede::assert_regex_in_file \
"Failure applies to entire batch: not executing inputs one-by-one" "${log}"
centipede::assert_regex_not_in_file \
"Executing inputs one-by-one, trying to find the reproducer" "${log}"
}
# Expects that Centipede found a OOM.
function ExpectOOM() {
echo "======= ${FUNCNAME[0]}"
centipede::assert_regex_in_file "RSS limit exceeded" "${log}"
centipede::assert_regex_in_file "Failure.*: rss-limit-exceeded" "${log}"
}
# Expects that $1 is found in the log.
function ExpectInLog() {
echo "======= ${FUNCNAME[0]}: $1"
centipede::assert_regex_in_file "$1" "${log}"
}
##################################### end USER_FUNCTIONS
# shellcheck disable=SC1090
source "${script}"
echo PASS