# Copy internal libraries.
# SC2156 (warning): Injecting filenames is fragile and insecure. Use parameters.
# shellcheck disable=SC2156
- find "/opt/kea/lib" -mindepth 1 -maxdepth 1 -exec sh -c "cp {} ${KEA_BUILD_DIR}" ';'
+ find "/opt/kea/lib" -mindepth 1 -maxdepth 1 -not -type d -exec sh -c "cp {} ${KEA_BUILD_DIR}" ';'
# Copy the binaries.
- for fuzzer in fuzz-config-kea-dhcp4 fuzz-packets-kea-dhcp4 fuzz-unix-socket-kea-dhcp4 \
- fuzz-config-kea-dhcp6 fuzz-packets-kea-dhcp6 fuzz-unix-socket-kea-dhcp6 \
- fuzz-http-endpoint \
+ for fuzzer in fuzz_config_kea_dhcp4 fuzz_http_endpoint_kea_dhcp4 fuzz_packets_kea_dhcp4 fuzz_unix_socket_kea_dhcp4 \
+ fuzz_config_kea_dhcp6 fuzz_http_endpoint_kea_dhcp6 fuzz_packets_kea_dhcp6 fuzz_unix_socket_kea_dhcp6 \
; do
cp "/opt/kea/sbin/${fuzzer}" "${OUT}/${fuzzer}"
# copy all required libraries
- `kea-dhcp4`
- `kea-dhcp6`
-Combining the binaries and the fuzzer types results in seven fuzzing binaries:
-- `fuzz/fuzz-config-kea-dhcp4`
-- `fuzz/fuzz-config-kea-dhcp6`
-- `fuzz/fuzz-http-endpoint`
-- `fuzz/fuzz-packets-kea-dhcp4`
-- `fuzz/fuzz-packets-kea-dhcp6`
-- `fuzz/fuzz-unix-socket-kea-dhcp4`
-- `fuzz/fuzz-unix-socket-kea-dhcp6`
+Combining the binaries and the fuzzer types results in eight fuzzing binaries:
+- `fuzz/fuzz_config_kea_dhcp4`
+- `fuzz/fuzz_config_kea_dhcp6`
+- `fuzz/fuzz_http_endpoint_kea_dhcp4`
+- `fuzz/fuzz_http_endpoint_kea_dhcp6`
+- `fuzz/fuzz_packets_kea_dhcp4`
+- `fuzz/fuzz_packets_kea_dhcp6`
+- `fuzz/fuzz_unix_socket_kea_dhcp4`
+- `fuzz/fuzz_unix_socket_kea_dhcp6`
@subsection HowToBuild How to Build the LLVM Fuzzer
/fuzz_config_kea_dhcp4
/fuzz_config_kea_dhcp6
-/fuzz_http_endpoint
+/fuzz_http_endpoint_kea_dhcp4
+/fuzz_http_endpoint_kea_dhcp6
/fuzz_packets_kea_dhcp4
/fuzz_packets_kea_dhcp6
/fuzz_unix_socket_kea_dhcp4
sbin_PROGRAMS =
sbin_PROGRAMS += fuzz_config_kea_dhcp4
sbin_PROGRAMS += fuzz_config_kea_dhcp6
-sbin_PROGRAMS += fuzz_http_endpoint
+sbin_PROGRAMS += fuzz_http_endpoint_kea_dhcp4
+sbin_PROGRAMS += fuzz_http_endpoint_kea_dhcp6
sbin_PROGRAMS += fuzz_packets_kea_dhcp4
sbin_PROGRAMS += fuzz_packets_kea_dhcp6
sbin_PROGRAMS += fuzz_unix_socket_kea_dhcp4
fuzz_config_kea_dhcp6_SOURCES += fuzz_config_kea_dhcp6.cc
fuzz_config_kea_dhcp6_LDADD = $(V6_LDADD) $(LDADD)
-fuzz_http_endpoint_SOURCES = $(common_sources)
-fuzz_http_endpoint_SOURCES += fuzz_http_endpoint.cc
-fuzz_http_endpoint_LDADD = $(LDADD)
+fuzz_http_endpoint_kea_dhcp4_SOURCES = $(common_sources)
+fuzz_http_endpoint_kea_dhcp4_SOURCES += fuzz_http_endpoint_kea_dhcp4.cc
+fuzz_http_endpoint_kea_dhcp4_LDADD = $(V4_LDADD) $(LDADD)
+
+fuzz_http_endpoint_kea_dhcp6_SOURCES = $(common_sources)
+fuzz_http_endpoint_kea_dhcp6_SOURCES += fuzz_http_endpoint_kea_dhcp6.cc
+fuzz_http_endpoint_kea_dhcp6_LDADD = $(V6_LDADD) $(LDADD)
fuzz_packets_kea_dhcp4_SOURCES = $(common_sources)
fuzz_packets_kea_dhcp4_SOURCES += fuzz_packets_kea_dhcp4.cc
#include <asiolink/interval_timer.h>
#include <cc/data.h>
#include <config/cmd_http_listener.h>
+#include <dhcp4/ctrl_dhcp4_srv.h>
+#include <dhcpsrv/cfgmgr.h>
#include <http/listener.h>
#include <http/post_request_json.h>
#include <http/response.h>
using namespace isc::asiolink;
using namespace isc::config;
using namespace isc::data;
+using namespace isc::dhcp;
using namespace isc::process;
using namespace isc::http;
using namespace isc::http::test;
namespace {
+static pid_t const PID(getpid());
+static int const PORT(getpid() % 1000 + 2000);
+static string const PID_STR(to_string(PID));
+static string const PORT_STR(to_string(PORT));
+static string const KEA_DHCP4_CONF(KEA_FUZZ_DIR + "/kea-dhcp4-" + PID_STR + ".conf");
+static string const KEA_DHCP4_CSV(KEA_FUZZ_DIR + "/kea-dhcp4-" + PID_STR + ".csv");
+
void timeoutHandler() {
cerr << "Timeout occurred while fuzzing!" << endl;
abort();
ThreadPool<function<void()>> THREAD_POOL;
-static pid_t const PID(getpid());
-static string const PID_STR(to_string(PID));
-
} // namespace
extern "C" {
static bool initialized(DoInitialization());
assert(initialized);
+ writeToFile(KEA_DHCP4_CONF, R"(
+ {
+ "Dhcp4": {
+ "control-sockets": [
+ {
+ "socket-address": "0.0.0.0",
+ "socket-port": )" + PORT_STR + R"(,
+ "socket-type": "http"
+ }
+ ],
+ "lease-database": {
+ "name": ")" + KEA_DHCP4_CSV + R"(",
+ "type": "memfile"
+ }
+ }
+ }
+ )");
+
return 0;
}
int
LLVMFuzzerTearDown() {
+ try {
+ remove(KEA_DHCP4_CONF.c_str());
+ } catch (...) {
+ }
+ try {
+ remove(KEA_DHCP4_CSV.c_str());
+ } catch (...) {
+ }
return 0;
}
int
LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) {
+ CfgMgr::instance().clear();
+ ControlledDhcpv4Srv server;
+ server.init(KEA_DHCP4_CONF);
+
string const address("127.0.0.1");
int const port(18000);
int const timeout(100000);
--- /dev/null
+// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <list>
+
+#include <fuzz.h>
+
+#include <asiolink/io_service.h>
+#include <asiolink/interval_timer.h>
+#include <cc/data.h>
+#include <config/cmd_http_listener.h>
+#include <dhcp6/ctrl_dhcp6_srv.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <http/listener.h>
+#include <http/post_request_json.h>
+#include <http/response.h>
+#include <http/response_json.h>
+#include <http/tests/response_test.h>
+#include <http/testutils/test_http_client.h>
+#include <process/d_controller.h>
+#include <util/filesystem.h>
+#include <util/multi_threading_mgr.h>
+
+using namespace isc::asiolink;
+using namespace isc::config;
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::process;
+using namespace isc::http;
+using namespace isc::http::test;
+using namespace isc::util;
+using namespace std;
+
+namespace {
+
+static pid_t const PID(getpid());
+static int const PORT(getpid() % 1000 + 2000);
+static string const PID_STR(to_string(PID));
+static string const PORT_STR(to_string(PORT));
+static string const KEA_DHCP6_CONF(KEA_FUZZ_DIR + "/kea-dhcp6-" + PID_STR + ".conf");
+static string const KEA_DHCP6_CSV(KEA_FUZZ_DIR + "/kea-dhcp6-" + PID_STR + ".csv");
+
+void timeoutHandler() {
+ cerr << "Timeout occurred while fuzzing!" << endl;
+ abort();
+}
+
+/// @brief Represents HTTP POST request with JSON body.
+///
+/// In addition to the requirements specified by the @ref PostHttpRequest
+/// this class requires that the "Content-Type" is "application/json".
+///
+/// This class provides methods to parse and retrieve JSON data structures.
+struct PostHttpRequestBytes : PostHttpRequest {
+ /// @brief Constructor for inbound HTTP request.
+ explicit PostHttpRequestBytes() : PostHttpRequest() {
+ requireHeaderValue("Content-Type", "application/json");
+ }
+
+ /// @brief Constructor for outbound HTTP request.
+ ///
+ /// This constructor adds "Content-Type" header with the value of
+ /// "application/json" to the context.
+ ///
+ /// @param method HTTP method, e.g. POST.
+ /// @param uri URI.
+ /// @param version HTTP version.
+ /// @param host_header Host header to be included in the request. The default
+ /// is the empty Host header.
+ /// @param basic_auth Basic HTTP authentication credential. The default
+ /// is no authentication.
+ explicit PostHttpRequestBytes(const Method& method,
+ const string& uri,
+ const HttpVersion& version,
+ const HostHttpHeader& host_header = HostHttpHeader(),
+ const BasicHttpAuthPtr& basic_auth = BasicHttpAuthPtr())
+ : PostHttpRequest(method, uri, version, host_header, basic_auth) {
+ requireHeaderValue("Content-Type", "application/json");
+ context()->headers_.push_back(HttpHeaderContext("Content-Type", "application/json"));
+ }
+
+ /// @brief Sets JSON body for an outbound message.
+ ///
+ /// @param body JSON structure to be used as a body.
+ void setBodyAsBytes(vector<uint8_t> const& input) {
+ context_->body_ = string(input.begin(), input.end());
+ }
+};
+
+using PostHttpRequestBytesPtr = boost::shared_ptr<PostHttpRequestBytes>;
+
+ThreadPool<function<void()>> THREAD_POOL;
+
+} // namespace
+
+extern "C" {
+
+int
+LLVMFuzzerInitialize() {
+ static bool initialized(DoInitialization());
+ assert(initialized);
+
+ writeToFile(KEA_DHCP6_CONF, R"(
+ {
+ "Dhcp6": {
+ "control-sockets": [
+ {
+ "socket-address": "0.0.0.0",
+ "socket-port": )" + PORT_STR + R"(,
+ "socket-type": "http"
+ }
+ ],
+ "lease-database": {
+ "name": ")" + KEA_DHCP6_CSV + R"(",
+ "type": "memfile"
+ },
+ "server-id": {
+ "type": "EN",
+ "enterprise-id": 2495,
+ "identifier": "0123456789",
+ "persist": false
+ }
+ }
+ }
+ )");
+
+ return 0;
+}
+
+int
+LLVMFuzzerTearDown() {
+ try {
+ remove(KEA_DHCP6_CONF.c_str());
+ } catch (...) {
+ }
+ try {
+ remove(KEA_DHCP6_CSV.c_str());
+ } catch (...) {
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) {
+ CfgMgr::instance().clear();
+ ControlledDhcpv6Srv server;
+ server.init(KEA_DHCP6_CONF);
+
+ string const address("127.0.0.1");
+ int const port(18000);
+ int const timeout(100000);
+
+ CmdHttpListener listener(IOAddress(address), port);
+ MultiThreadingMgr::instance().setMode(true);
+
+ // Start the server.
+ listener.start();
+
+ // Create a client and specify the URL on which the server can be reached.
+ IOServicePtr io_service(new IOService());
+ IntervalTimer run_io_service_timer(io_service);
+ HttpClient client(io_service, false);
+ stringstream ss;
+ ss << "http://" << address << ":" << port;
+ Url url(ss.str());
+
+ // Initiate request to the server.
+ PostHttpRequestBytesPtr request(new PostHttpRequestBytes(
+ HttpRequest::Method::HTTP_POST, "/", HttpVersion(1, 1)));
+
+ // Body is a map with a specified parameter included.
+ vector<uint8_t> const body(data, data + size);
+ request->setBodyAsBytes(body);
+ request->finalize();
+ HttpResponseJsonPtr response(new HttpResponseJson());
+ client.asyncSendRequest(
+ url, TlsContextPtr(), request, response,
+ [](boost::system::error_code const&,
+ HttpResponsePtr const&,
+ string const&) {
+ });
+
+ // Actually trigger the requests. The requests should be handlded by the
+ // server one after another. While the first request is being processed
+ // the server should queue another one.
+ io_service->getInternalIOService().reset();
+ run_io_service_timer.setup(&timeoutHandler, timeout, IntervalTimer::ONE_SHOT);
+ io_service->runOne();
+ io_service->getInternalIOService().reset();
+ io_service->poll();
+
+ // Make sure that the received responses are different. We check that by
+ // comparing value of the sequence parameters.
+ if (getenv("DEBUG")) {
+ if (response) {
+ cout << response->getBody() << endl;
+ } else {
+ cout << "no response" << endl;
+ }
+ }
+ listener.stop();
+ client.stop();
+ run_io_service_timer.cancel();
+ io_service->poll();
+ MultiThreadingMgr::instance().setMode(false);
+
+ return 0;
+}
+
+} // extern "C"
fuzzdir = "${datarootdir}/${PACKAGE_NAME}/fuzz"
nobase_dist_fuzz_DATA =
-nobase_dist_fuzz_DATA += fuzz-config-kea-dhcp4/empty
-nobase_dist_fuzz_DATA += fuzz-config-kea-dhcp4/one-byte
-nobase_dist_fuzz_DATA += fuzz-config-kea-dhcp6/empty
-nobase_dist_fuzz_DATA += fuzz-config-kea-dhcp6/one-byte
-nobase_dist_fuzz_DATA += fuzz-http-endpoint/config-get
-nobase_dist_fuzz_DATA += fuzz-http-endpoint/config-get-with-service
-nobase_dist_fuzz_DATA += fuzz-http-endpoint/empty
-nobase_dist_fuzz_DATA += fuzz-http-endpoint/empty-json-map
-nobase_dist_fuzz_DATA += fuzz-http-endpoint/one-byte
-nobase_dist_fuzz_DATA += fuzz-http-endpoint/one-entry-json-map
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp4/dhcp-payload-only
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp4/empty
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp4/full-dhcp-packet
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp4/one-byte
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp4/udp-header
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp6/dhcp-payload-only
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp6/empty
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp6/full-dhcp-packet
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp6/one-byte
-nobase_dist_fuzz_DATA += fuzz-packets-kea-dhcp6/udp-header
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp4/config-get
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp4/config-get-with-service
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp4/empty
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp4/empty-json-map
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp4/one-byte
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp4/one-entry-json-map
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp6/config-get
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp6/config-get-with-service
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp6/empty
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp6/empty-json-map
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp6/one-byte
-nobase_dist_fuzz_DATA += fuzz-unix-socket-kea-dhcp6/one-entry-json-map
+nobase_dist_fuzz_DATA += fuzz_config_kea_dhcp4/empty
+nobase_dist_fuzz_DATA += fuzz_config_kea_dhcp4/one-byte
+nobase_dist_fuzz_DATA += fuzz_config_kea_dhcp6/empty
+nobase_dist_fuzz_DATA += fuzz_config_kea_dhcp6/one-byte
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp4/config-get
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp4/config-get-with-service
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp4/empty
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp4/empty-json-map
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp4/one-byte
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp4/one-entry-json-map
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp6/config-get
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp6/config-get-with-service
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp6/empty
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp6/empty-json-map
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp6/one-byte
+nobase_dist_fuzz_DATA += fuzz_http_endpoint_kea_dhcp6/one-entry-json-map
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp4/dhcp-payload-only
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp4/empty
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp4/full-dhcp-packet
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp4/one-byte
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp4/udp-header
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp6/dhcp-payload-only
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp6/empty
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp6/full-dhcp-packet
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp6/one-byte
+nobase_dist_fuzz_DATA += fuzz_packets_kea_dhcp6/udp-header
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp4/config-get
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp4/config-get-with-service
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp4/empty
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp4/empty-json-map
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp4/one-byte
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp4/one-entry-json-map
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp6/config-get
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp6/config-get-with-service
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp6/empty
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp6/empty-json-map
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp6/one-byte
+nobase_dist_fuzz_DATA += fuzz_unix_socket_kea_dhcp6/one-entry-json-map
nobase_dist_fuzz_DATA += kea-dhcp4.conf
nobase_dist_fuzz_DATA += kea-dhcp6.conf
--- /dev/null
+{
+ "command": "config-get",
+ "service": [ "dhcp4" ]
+}
--- /dev/null
+{
+ "command": "config-get"
+}
--- /dev/null
+0a
\ No newline at end of file
--- /dev/null
+{
+ "a": 1
+}
if FUZZING
check_SCRIPTS =
-check_SCRIPTS += test-fuzz-config-kea-dhcp4.sh
-check_SCRIPTS += test-fuzz-config-kea-dhcp6.sh
-check_SCRIPTS += test-fuzz-http-endpoint.sh
-check_SCRIPTS += test-fuzz-packets-kea-dhcp4.sh
-check_SCRIPTS += test-fuzz-packets-kea-dhcp6.sh
-check_SCRIPTS += test-fuzz-unix-socket-kea-dhcp4.sh
-check_SCRIPTS += test-fuzz-unix-socket-kea-dhcp6.sh
+check_SCRIPTS += test_fuzz_config_kea_dhcp4.sh
+check_SCRIPTS += test_fuzz_config_kea_dhcp6.sh
+check_SCRIPTS += test_fuzz_http_endpoint_kea_dhcp4.sh
+check_SCRIPTS += test_fuzz_http_endpoint_kea_dhcp6.sh
+check_SCRIPTS += test_fuzz_packets_kea_dhcp4.sh
+check_SCRIPTS += test_fuzz_packets_kea_dhcp6.sh
+check_SCRIPTS += test_fuzz_unix_socket_kea_dhcp4.sh
+check_SCRIPTS += test_fuzz_unix_socket_kea_dhcp6.sh
TESTS = $(check_SCRIPTS)
+++ /dev/null
-../setup.sh
\ No newline at end of file
+++ /dev/null
-#!/bin/sh
-
-if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
-
-script_path=$(cd "$(dirname "${0}")" && pwd)
-
-script_basename=$(basename "${0}")
-
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
-
-"${script_path}/../${tested_binary}"
+++ /dev/null
-#!/bin/sh
-
-if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
-
-script_path=$(cd "$(dirname "${0}")" && pwd)
-
-script_basename=$(basename "${0}")
-
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
-
-"${script_path}/../${tested_binary}"
+++ /dev/null
-#!/bin/sh
-
-if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
-
-script_path=$(cd "$(dirname "${0}")" && pwd)
-
-script_basename=$(basename "${0}")
-
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
-
-"${script_path}/../${tested_binary}"
script_basename=$(basename "${0}")
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
"${script_path}/../${tested_binary}"
script_basename=$(basename "${0}")
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
"${script_path}/../${tested_binary}"
script_basename=$(basename "${0}")
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
"${script_path}/../${tested_binary}"
script_basename=$(basename "${0}")
-tested_binary=$(printf '%s' "${script_basename}" | sed 's/test-//g;s/.sh//g')
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
"${script_path}/../${tested_binary}"
--- /dev/null
+#!/bin/sh
+
+if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
+
+script_path=$(cd "$(dirname "${0}")" && pwd)
+
+script_basename=$(basename "${0}")
+
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
+
+"${script_path}/../${tested_binary}"
--- /dev/null
+#!/bin/sh
+
+if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
+
+script_path=$(cd "$(dirname "${0}")" && pwd)
+
+script_basename=$(basename "${0}")
+
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
+
+"${script_path}/../${tested_binary}"
--- /dev/null
+#!/bin/sh
+
+if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
+
+script_path=$(cd "$(dirname "${0}")" && pwd)
+
+script_basename=$(basename "${0}")
+
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
+
+"${script_path}/../${tested_binary}"
--- /dev/null
+#!/bin/sh
+
+if ! sudo -n true; then exec sudo -E -- "${0}" "${@}"; fi
+
+script_path=$(cd "$(dirname "${0}")" && pwd)
+
+script_basename=$(basename "${0}")
+
+tested_binary=$(printf '%s' "${script_basename}" | sed 's/test_//g;s/.sh//g')
+
+"${script_path}/../${tested_binary}"