1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
/*
* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
*/
#include <unordered_set>
#include <glib.h>
#include <string.h>
#include <babeltrace2/babeltrace.h>
#include "common/assert.h"
#include "cpp-common/vendor/fmt/core.h"
#include "cpp-common/vendor/nlohmann/json.hpp"
#include "utils.hpp"
#ifdef HAVE_SETRLIMIT
# include <sys/resource.h>
#endif /* HAVE_SETRLIMIT */
CondTrigger::CondTrigger(const Type type, const std::string& condId,
const bt2c::CStringView nameSuffix) noexcept :
_mType {type},
_mCondId {fmt::format("{}:{}", type == Type::Pre ? "pre" : "post", condId)},
_mName {fmt::format("{}{}{}", condId, nameSuffix ? ":" : "", nameSuffix ? nameSuffix : "")}
{
}
SimpleCondTrigger::SimpleCondTrigger(std::function<void()> func, const Type type,
const std::string& condId,
const bt2c::CStringView nameSuffix) :
CondTrigger {type, condId, nameSuffix},
_mFunc {std::move(func)}
{
}
namespace {
void disableCoreDumps() noexcept
{
#ifdef HAVE_SETRLIMIT
const rlimit limits {0, 0};
const auto ret = setrlimit(RLIMIT_CORE, &limits);
if (ret != 0) {
std::perror("setrlimit");
std::exit(1);
}
#endif /* HAVE_SETRLIMIT */
}
void listCondTriggers(const CondTriggers& condTriggers) noexcept
{
auto condTriggerArray = nlohmann::json::array();
for (const auto& condTrigger : condTriggers) {
condTriggerArray.push_back(nlohmann::json {
{"cond-id", condTrigger->condId()},
{"name", condTrigger->name()},
});
}
fmt::println("{}", condTriggerArray.dump());
}
void checkNamesUnique(const CondTriggers& condTriggers)
{
std::unordered_set<std::string> names;
for (const auto& trigger : condTriggers) {
const auto res = names.insert(trigger->name());
if (!res.second) {
fmt::println(stderr, "Duplicate test name `{}`", trigger->name());
std::exit(1);
}
}
}
} /* namespace */
void condMain(const bt2s::span<const char * const> argv, const CondTriggers& condTriggers) noexcept
{
BT_ASSERT(argv.size() >= 2);
checkNamesUnique(condTriggers);
if (strcmp(argv[1], "list") == 0) {
listCondTriggers(condTriggers);
} else if (strcmp(argv[1], "run") == 0) {
/*
* It's expected that calling the trigger below aborts (calls
* bt_common_abort()). In this testing context, we don't want
* any custom abortion command to run.
*/
g_unsetenv("BABELTRACE_EXEC_ON_ABORT");
/*
* Since this program's purpose is to crash, it might generate
* a core dump every time it's started, which is not really
* useful (and has been known to overwhelm some CI workers).
* Disable them.
*/
disableCoreDumps();
/* Find the trigger */
BT_ASSERT(argv.size() == 3);
const auto name = argv[2];
const auto it = std::find_if(condTriggers.begin(), condTriggers.end(),
[&](const CondTrigger::UP& trigger) {
return trigger->name() == name;
});
if (it == condTriggers.end()) {
fmt::println(stderr, "No trigger named `{}` found.", name);
std::exit(1);
}
/* Call the trigger */
(**it)();
}
}
|