Internal change

PiperOrigin-RevId: 469047334
diff --git a/BUILD b/BUILD
index 2b38cb2..c7ac4c4 100644
--- a/BUILD
+++ b/BUILD
@@ -28,7 +28,7 @@
 ################################################################################
 
 cc_binary(
-    name = "centipede",
+    name = "centipede_main",
     srcs = ["centipede_main.cc"],
     deps = [
         ":centipede_default_callbacks",
@@ -38,6 +38,11 @@
     ],
 )
 
+alias(
+    name = "centipede",
+    actual = ":centipede_main",
+)
+
 ################################################################################
 #                             C++ libraries
 ################################################################################
@@ -399,3 +404,21 @@
         "shared_memory_blob_sequence.h",
     ],
 )
+
+################################################################################
+#                        General-purpose testing utilities
+################################################################################
+
+cc_library(
+    name = "test_util",
+    srcs = ["test_util.cc"],
+    hdrs = ["test_util.h"],
+    deps = [
+        ":logging",
+    ],
+)
+
+sh_library(
+    name = "test_util_sh",
+    srcs = ["test_util.sh"],
+)
diff --git a/README.md b/README.md
index 9896297..6c1f7e0 100644
--- a/README.md
+++ b/README.md
@@ -223,7 +223,12 @@
 [`llvm-symbolizer`](https://llvm.org/docs/CommandGuide/llvm-symbolizer.html)
 to your `$PATH` for some of the Centipede functionality to work. The
 symbolizer can be installed as part of the [LLVM](https://releases.llvm.org)
-distribution.
+distribution:
+
+```shell
+sudo apt install llvm
+which llvm-symbolizer  # normally /usr/bin/llvm-symbolizer
+```
 
 ### Run one fuzzing job
 
diff --git a/install_dependencies_debian.sh b/install_dependencies_debian.sh
index 07861ec..34e1f08 100755
--- a/install_dependencies_debian.sh
+++ b/install_dependencies_debian.sh
@@ -27,24 +27,28 @@
 #     * -fsanitize-coverage=trace-loads
 #     (https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow)
 
+set -eux -o pipefail
+
+apt update
+
 # Add Bazel distribution URI as a package source following:
 # https://docs.bazel.build/versions/main/install-ubuntu.html
 apt install -y curl gnupg apt-transport-https
 curl -fsSL https://bazel.build/bazel-release.pub.gpg \
   | gpg --dearmor > /etc/apt/trusted.gpg.d/bazel.gpg
 echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" \
-  | tee /etc/apt/sources.list.d/bazel.list
-apt update
+  > /etc/apt/sources.list.d/bazel.list
 
-# Install dependencies.
+# Install LLVM, which provides llvm-symbolizer required for running Centipede in
+# some modes.
+apt install -y llvm
+
+# Install other dependencies.
 apt install -y git bazel binutils libssl-dev
 
-# Get Clang-14, the earlist version that supports dataflow tracing:
+# Get Clang-14, the earliest version that supports dataflow tracing:
 #   * Download Clang from Chromium to support old OS (e.g. Ubuntu 16).
 #   * Alternatively, download the fresh Clang from https://releases.llvm.org/
 mkdir /clang
 curl https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-llvmorg-14-init-9436-g65120988-1.tgz -o /clang-14.tgz
 tar zxvf /clang-14.tgz -C /clang
-
-# * TODO(kcc): llvm-symbolizer is required for running Centipede.
-#   it comes with clang, but may be called e.g. llvm-symbolizer-11
diff --git a/puzzles/puzzle.bzl b/puzzles/puzzle.bzl
index 1c85b2e..b868677 100644
--- a/puzzles/puzzle.bzl
+++ b/puzzles/puzzle.bzl
@@ -47,6 +47,6 @@
             data = [
                 ":" + name + "_centipede",
                 name + ".cc",
-                "@centipede//:centipede",
+                "@centipede//:centipede_main",
             ],
         )
diff --git a/puzzles/run_puzzle.sh b/puzzles/run_puzzle.sh
index 3b39281..39817a1 100755
--- a/puzzles/run_puzzle.sh
+++ b/puzzles/run_puzzle.sh
@@ -32,7 +32,7 @@
 readonly puzzle_path="${centipede_dir}/puzzles/${puzzle_name}_centipede"
 readonly puzzle_source_path="${centipede_dir}/puzzles/${puzzle_source_name}"
 
-readonly centipede="${centipede_dir}/centipede"
+readonly centipede="${centipede_dir}/centipede_main"
 readonly workdir="${TEST_TMPDIR}/workdir"
 readonly log="${TEST_TMPDIR}/log"
 readonly script="${TEST_TMPDIR}/script"
diff --git a/test_util.cc b/test_util.cc
new file mode 100644
index 0000000..4da16b1
--- /dev/null
+++ b/test_util.cc
@@ -0,0 +1,49 @@
+// Copyright 2022 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
+//
+//      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.
+
+#include <cstdlib>
+#include <filesystem>
+#include <string_view>
+
+#include "./logging.h"
+
+namespace centipede {
+
+std::string GetTestTempDir() {
+  if (auto* path = std::getenv("TEST_TMPDIR"); path != nullptr) return path;
+  if (auto* path = std::getenv("TMPDIR"); path != nullptr) return path;
+  return "/tmp";
+}
+
+std::filesystem::path GetTestRunfilesDir() {
+  const char* test_srcdir = std::getenv("TEST_SRCDIR");
+  CHECK(test_srcdir != nullptr) << "$TEST_SRCDIR must be set";
+  const char* test_workspace = std::getenv("TEST_WORKSPACE");
+  CHECK(test_workspace != nullptr) << "$TEST_WORKSPACE must be set";
+  auto path = std::filesystem::path{test_srcdir}.append(test_workspace);
+  CHECK(std::filesystem::exists(path))  //
+      << "No such dir: " << VV(path) << VV(test_srcdir) << VV(test_workspace);
+  return path;
+}
+
+std::filesystem::path GetDataDependencyFilepath(std::string_view rel_path) {
+  const auto runfiles_dir = GetTestRunfilesDir();
+  auto path = runfiles_dir;
+  path.append(rel_path);
+  CHECK(std::filesystem::exists(path))  //
+      << "No such path: " << VV(path) << VV(runfiles_dir) << VV(rel_path);
+  return path;
+}
+
+}  // namespace centipede
diff --git a/test_util.h b/test_util.h
new file mode 100644
index 0000000..55a9e25
--- /dev/null
+++ b/test_util.h
@@ -0,0 +1,43 @@
+// Copyright 2022 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
+//
+//      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.
+
+#ifndef THIRD_PARTY_CENTIPEDE_INTERNAL_TEST_UTIL_H_
+#define THIRD_PARTY_CENTIPEDE_INTERNAL_TEST_UTIL_H_
+
+#include <filesystem>
+#include <string>
+
+#include "./logging.h"
+
+#define EXPECT_OK(status) EXPECT_TRUE((status).ok()) << VV(status)
+#define ASSERT_OK(status) ASSERT_TRUE((status).ok()) << VV(status)
+
+namespace centipede {
+
+// Returns a temp dir for use inside tests. The dir is chosen in the following
+// order of precedence:
+// - $TEST_TMPDIR (highest)
+// - $TMPDIR
+// - /tmp
+std::string GetTestTempDir();
+
+// Returns the root directory filepath for a test's "runfiles".
+std::filesystem::path GetTestRunfilesDir();
+
+// Returns the filepath of a test's data dependency file.
+std::filesystem::path GetDataDependencyFilepath(std::string_view rel_path);
+
+}  // namespace centipede
+
+#endif  // THIRD_PARTY_CENTIPEDE_INTERNAL_TEST_UTIL_H_
diff --git a/test_util.sh b/test_util.sh
new file mode 100644
index 0000000..15ed395
--- /dev/null
+++ b/test_util.sh
@@ -0,0 +1,54 @@
+#!/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.
+
+# Returns the path to Centipede TEST_SRCDIR subdirectory.
+function centipede::get_centipede_test_srcdir() {
+  set -u
+  echo "${TEST_SRCDIR}/${TEST_WORKSPACE}"
+}
+
+# Returns the path to llvm-symbolizer.
+function centipede::get_llvm_symbolizer_path() {
+  set -u
+  local path
+  path="$(which llvm-symbolizer)"
+  if (( $? != 0 )); then
+    echo "FAILURE: llvm-symbolizer must be installed and findable via PATH:" \
+      "use install_dependencies_debian.sh to fix" >&2
+    exit 1
+  fi
+  echo "${path}"
+}
+
+# If the var named "$1" is unset, then sets it to "$2". If the var is set,
+# doesn't change it. In either case, verifies that the final value is a path to
+# an executable file.
+function centipede::maybe_set_var_to_executable_path() {
+  local var_name="$1"
+  # NOTE: `local -n` creates a reference to the var named "$1".
+  local -n var_ref="$1"
+  local path="$2"
+  if [[ -n "${var_ref+x}" ]]; then
+    echo "Not overriding ${var_name} -- already set to '${var_ref}'" >&2
+  else
+    echo "Setting ${var_name} to '${path}'" >&2
+    var_ref="${path}"
+  fi
+  if ! [[ -x "${var_ref}" ]]; then
+    echo "FAILURE: Path '${var_ref}' doesn't exist or is not executable" >&2
+    exit 1
+  fi
+}
diff --git a/util.cc b/util.cc
index f2777eb..4312ad6 100644
--- a/util.cc
+++ b/util.cc
@@ -190,13 +190,6 @@
   dirs_to_delete_at_exit->emplace_back(path);
 }
 
-// Honor $TEST_TMPDIR first, then $TMPDIR, then fall back to /tmp.
-std::string GetTestTempDir() {
-  if (auto path = getenv("TEST_TMPDIR")) return path;
-  if (auto path = getenv("TMPDIR")) return path;
-  return "/tmp";
-}
-
 static const size_t kMagicLen = 11;
 static const uint8_t kPackBegMagic[] = "-Centipede-";
 static const uint8_t kPackEndMagic[] = "-edepitneC-";
diff --git a/util.h b/util.h
index 382afe4..978dfaa 100644
--- a/util.h
+++ b/util.h
@@ -96,9 +96,6 @@
 // the caller's process and thread.
 std::string ProcessAndThreadUniqueID(std::string_view prefix);
 
-// Test-only. Returns a temp dir for use inside tests.
-std::string GetTestTempDir();
-
 // Computes a random subset of `set` that needs to be
 // removed to reach `target_size` non-zero weights in the set.
 // `set` is an array of weights, some of which could be zero.