2021-11-27 17:23:33 +01:00
|
|
|
|
#if !defined(_DEBUG)
|
|
|
|
|
|
#define _DEBUG
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#undef NDEBUG
|
|
|
|
|
|
|
|
|
|
|
|
#include "../log.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "../config.c"
|
|
|
|
|
|
|
|
|
|
|
|
#define ALEN(v) (sizeof(v) / sizeof((v)[0]))
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Stubs
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
user_notification_add_fmt(user_notifications_t *notifications,
|
|
|
|
|
|
enum user_notification_kind kind,
|
|
|
|
|
|
const char *fmt, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_invalid_key(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key)
|
|
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
ctx->value = "value for invalid key";
|
|
|
|
|
|
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s: did not fail to parse as expected"
|
|
|
|
|
|
"(key should be invalid)", ctx->section, ctx->key);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
test_string(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, char *const *conf_ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
const char *value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"a string", "a string"},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
|
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (strcmp(*conf_ptr, input[i].value) != 0) {
|
|
|
|
|
|
BUG("[%s].%s=%s: set value (%s) not the expected one (%s)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
*conf_ptr, input[i].value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
test_wstring(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, wchar_t *const *conf_ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
const wchar_t *value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"a string", L"a string"},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
|
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (wcscmp(*conf_ptr, input[i].value) != 0) {
|
|
|
|
|
|
BUG("[%s].%s=%s: set value (%ls) not the expected one (%ls)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
*conf_ptr, input[i].value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-11-27 17:23:33 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_boolean(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
2021-11-27 20:40:45 +01:00
|
|
|
|
const char *key, const bool *conf_ptr)
|
2021-11-27 17:23:33 +01:00
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
bool value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"1", true}, {"0", false},
|
|
|
|
|
|
{"on", true}, {"off", false},
|
|
|
|
|
|
{"true", true}, {"false", false},
|
|
|
|
|
|
{"unittest-invalid-boolean-value", false, true},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
|
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
2021-11-27 20:40:45 +01:00
|
|
|
|
if (*conf_ptr != input[i].value) {
|
2021-11-27 17:23:33 +01:00
|
|
|
|
BUG("[%s].%s=%s: set value (%s) not the expected one (%s)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
*conf_ptr ? "true" : "false",
|
|
|
|
|
|
input[i].value ? "true" : "false");
|
2021-11-27 20:40:45 +01:00
|
|
|
|
}
|
2021-11-27 17:23:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-11-27 20:40:45 +01:00
|
|
|
|
test_uint16(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, const uint16_t *conf_ptr)
|
2021-11-27 17:23:33 +01:00
|
|
|
|
{
|
2021-11-27 20:40:45 +01:00
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
uint16_t value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"0", 0}, {"65535", 65535}, {"65536", 0, true},
|
|
|
|
|
|
{"abc", 0, true}, {"true", 0, true},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
2021-12-26 12:36:43 +01:00
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*conf_ptr != input[i].value) {
|
|
|
|
|
|
BUG("[%s].%s=%s: set value (%hu) not the expected one (%hu)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
*conf_ptr, input[i].value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
test_uint32(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, const uint32_t *conf_ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
uint32_t value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"0", 0}, {"65536", 65536}, {"4294967295", 4294967295},
|
|
|
|
|
|
{"4294967296", 0, true}, {"abc", 0, true}, {"true", 0, true},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
2021-11-27 20:40:45 +01:00
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*conf_ptr != input[i].value) {
|
|
|
|
|
|
BUG("[%s].%s=%s: set value (%hu) not the expected one (%hu)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
*conf_ptr, input[i].value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-26 12:36:55 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_double(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, const float *conf_ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
float value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"0", 0}, {"0.1", 0.1}, {"1e10", 1e10}, {"-10.7", -10.7},
|
|
|
|
|
|
{"abc", 0, true}, {"true", 0, true},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
|
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*conf_ptr != input[i].value) {
|
|
|
|
|
|
BUG("[%s].%s=%s: set value (%f) not the expected one (%f)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
*conf_ptr, input[i].value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_pt_or_px(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, const struct pt_or_px *conf_ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
ctx->key = key;
|
2021-11-27 17:23:33 +01:00
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
static const struct {
|
|
|
|
|
|
const char *option_string;
|
|
|
|
|
|
struct pt_or_px value;
|
|
|
|
|
|
bool invalid;
|
|
|
|
|
|
} input[] = {
|
|
|
|
|
|
{"12", {.pt = 12}}, {"12px", {.px = 12}},
|
|
|
|
|
|
{"unittest-invalid-pt-or-px-value", {0}, true},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(input); i++) {
|
|
|
|
|
|
ctx->value = input[i].option_string;
|
|
|
|
|
|
|
|
|
|
|
|
if (input[i].invalid) {
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (memcmp(conf_ptr, &input[i].value, sizeof(*conf_ptr)) != 0) {
|
|
|
|
|
|
BUG("[%s].%s=%s: "
|
|
|
|
|
|
"set value (pt=%f, px=%d) not the expected one (pt=%f, px=%d)",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
conf_ptr->pt, conf_ptr->px,
|
|
|
|
|
|
input[i].value.pt, input[i].value.px);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-25 23:27:10 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_spawn_template(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
const char *key, const struct config_spawn_template *ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
static const char *const args[] = {
|
|
|
|
|
|
"command", "arg1", "arg2", "arg3 has spaces"};
|
|
|
|
|
|
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
ctx->value = "command arg1 arg2 \"arg3 has spaces\"";
|
|
|
|
|
|
|
|
|
|
|
|
if (!parse_fun(ctx))
|
|
|
|
|
|
BUG("[%s].%s=%s: failed to parse", ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
|
|
|
|
|
|
if (ptr->argv.args == NULL)
|
|
|
|
|
|
BUG("[%s].%s=%s: argv is NULL", ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(args); i++) {
|
|
|
|
|
|
if (ptr->argv.args[i] == NULL ||
|
|
|
|
|
|
strcmp(ptr->argv.args[i], args[i]) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
BUG("[%s].%s=%s: set value not the expected one: "
|
|
|
|
|
|
"mismatch of arg #%zu: expected=\"%s\", got=\"%s\"",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value, i,
|
|
|
|
|
|
args[i], ptr->argv.args[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ptr->argv.args[ALEN(args)] != NULL) {
|
|
|
|
|
|
BUG("[%s].%s=%s: set value not the expected one: "
|
|
|
|
|
|
"expected NULL terminator at arg #%zu, got=\"%s\"",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
ALEN(args), ptr->argv.args[ALEN(args)]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Trigger parse failure */
|
|
|
|
|
|
ctx->value = "command with \"unterminated quote";
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_main(void)
|
|
|
|
|
|
{
|
2021-11-27 17:23:33 +01:00
|
|
|
|
struct config conf = {0};
|
2021-11-27 20:40:45 +01:00
|
|
|
|
struct context ctx = {.conf = &conf, .section = "main", .path = "unittest"};
|
2021-11-27 17:23:33 +01:00
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
test_invalid_key(&ctx, &parse_section_main, "invalid-key");
|
2021-11-27 17:23:33 +01:00
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
test_string(&ctx, &parse_section_main, "shell", &conf.shell);
|
|
|
|
|
|
test_string(&ctx, &parse_section_main, "term", &conf.term);
|
|
|
|
|
|
test_string(&ctx, &parse_section_main, "app-id", &conf.app_id);
|
|
|
|
|
|
|
|
|
|
|
|
test_wstring(&ctx, &parse_section_main, "word-delimiters", &conf.word_delimiters);
|
2021-11-27 17:23:33 +01:00
|
|
|
|
|
|
|
|
|
|
test_boolean(&ctx, &parse_section_main, "login-shell", &conf.login_shell);
|
2021-11-27 20:40:45 +01:00
|
|
|
|
test_boolean(&ctx, &parse_section_main, "box-drawings-uses-font-glyphs", &conf.box_drawings_uses_font_glyphs);
|
|
|
|
|
|
test_boolean(&ctx, &parse_section_main, "locked-title", &conf.locked_title);
|
|
|
|
|
|
test_boolean(&ctx, &parse_section_main, "notify-focus-inhibit", &conf.notify_focus_inhibit);
|
|
|
|
|
|
|
|
|
|
|
|
test_pt_or_px(&ctx, &parse_section_main, "line-height", &conf.line_height);
|
|
|
|
|
|
test_pt_or_px(&ctx, &parse_section_main, "letter-spacing", &conf.letter_spacing);
|
|
|
|
|
|
test_pt_or_px(&ctx, &parse_section_main, "horizontal-letter-offset", &conf.horizontal_letter_offset);
|
|
|
|
|
|
test_pt_or_px(&ctx, &parse_section_main, "vertical-letter-offset", &conf.vertical_letter_offset);
|
|
|
|
|
|
|
|
|
|
|
|
test_uint16(&ctx, &parse_section_main, "resize-delay-ms", &conf.resize_delay_ms);
|
|
|
|
|
|
test_uint16(&ctx, &parse_section_main, "workers", &conf.render_worker_count);
|
|
|
|
|
|
|
2021-12-25 23:27:23 +01:00
|
|
|
|
test_spawn_template(&ctx, &parse_section_main, "notify", &conf.notify);
|
|
|
|
|
|
|
2021-11-27 20:40:45 +01:00
|
|
|
|
/* TODO: font (custom) */
|
|
|
|
|
|
/* TODO: include (custom) */
|
|
|
|
|
|
/* TODO: dpi-aware (enum/boolean) */
|
|
|
|
|
|
/* TODO: bold-text-in-bright (enum/boolean) */
|
|
|
|
|
|
/* TODO: pad (geometry + optional string)*/
|
|
|
|
|
|
/* TODO: initial-window-size-pixels (geometry) */
|
|
|
|
|
|
/* TODO: initial-window-size-chars (geometry) */
|
|
|
|
|
|
/* TODO: selection-target (enum) */
|
|
|
|
|
|
/* TODO: initial-window-mode (enum) */
|
2021-11-27 17:23:33 +01:00
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-25 23:03:11 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_bell(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {.conf = &conf, .section = "bell", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_invalid_key(&ctx, &parse_section_bell, "invalid-key");
|
|
|
|
|
|
|
|
|
|
|
|
test_boolean(&ctx, &parse_section_bell, "urgent", &conf.bell.urgent);
|
|
|
|
|
|
test_boolean(&ctx, &parse_section_bell, "notify", &conf.bell.notify);
|
|
|
|
|
|
test_boolean(&ctx, &parse_section_bell, "command-focused",
|
|
|
|
|
|
&conf.bell.command_focused);
|
2021-12-25 23:27:36 +01:00
|
|
|
|
test_spawn_template(&ctx, &parse_section_bell, "command",
|
|
|
|
|
|
&conf.bell.command);
|
2021-12-25 23:03:11 +01:00
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 18:30:17 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
|
|
|
|
|
int action, int max_action, const char *const *map,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
struct config_key_binding_list *bindings,
|
|
|
|
|
|
enum config_key_binding_type type)
|
2021-12-11 18:30:17 +01:00
|
|
|
|
{
|
|
|
|
|
|
xassert(map[action] != NULL);
|
|
|
|
|
|
xassert(bindings->count == 0);
|
|
|
|
|
|
|
|
|
|
|
|
const char *key = map[action];
|
|
|
|
|
|
|
|
|
|
|
|
/* “Randomize” which modifiers to enable */
|
|
|
|
|
|
const bool ctrl = action % 2;
|
|
|
|
|
|
const bool alt = action % 3;
|
|
|
|
|
|
const bool shift = action % 4;
|
|
|
|
|
|
const bool super = action % 5;
|
2021-12-25 23:37:04 +01:00
|
|
|
|
const bool argv = action % 6;
|
|
|
|
|
|
|
|
|
|
|
|
static const char *const args[] = {
|
|
|
|
|
|
"command", "arg1", "arg2", "arg3 has spaces"};
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
|
|
|
|
|
/* Generate the modifier part of the ‘value’ */
|
|
|
|
|
|
char modifier_string[32];
|
2021-12-11 20:01:16 +01:00
|
|
|
|
sprintf(modifier_string, "%s%s%s%s",
|
|
|
|
|
|
ctrl ? XKB_MOD_NAME_CTRL "+" : "",
|
|
|
|
|
|
alt ? XKB_MOD_NAME_ALT "+" : "",
|
|
|
|
|
|
shift ? XKB_MOD_NAME_SHIFT "+" : "",
|
|
|
|
|
|
super ? XKB_MOD_NAME_LOGO "+" : "");
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
/* Use a unique symbol for this action (key bindings) */
|
|
|
|
|
|
const xkb_keysym_t sym = XKB_KEY_a + action;
|
|
|
|
|
|
|
|
|
|
|
|
/* Mouse button (mouse bindings) */
|
|
|
|
|
|
const int button_idx = action % ALEN(button_map);
|
|
|
|
|
|
const int button = button_map[button_idx].code;
|
|
|
|
|
|
const int click_count = action % 3 + 1;
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
|
|
|
|
|
/* Finally, generate the ‘value’ (e.g. “Control+shift+x”) */
|
2021-12-18 20:42:37 +01:00
|
|
|
|
char value[128] = {0};
|
|
|
|
|
|
|
|
|
|
|
|
ctx->key = key;
|
|
|
|
|
|
ctx->value = value;
|
|
|
|
|
|
|
|
|
|
|
|
/* First, try setting the empty string */
|
|
|
|
|
|
if (parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=<empty>: did not fail to parse as expected",
|
|
|
|
|
|
ctx->section, ctx->key);
|
|
|
|
|
|
}
|
2021-12-11 20:01:16 +01:00
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case KEY_BINDING: {
|
|
|
|
|
|
char sym_name[16];
|
|
|
|
|
|
xkb_keysym_get_name(sym, sym_name, sizeof(sym_name));
|
|
|
|
|
|
|
2021-12-25 23:37:04 +01:00
|
|
|
|
snprintf(value, sizeof(value), "%s%s%s",
|
|
|
|
|
|
argv ? "[command arg1 arg2 \"arg3 has spaces\"] " : "",
|
|
|
|
|
|
modifier_string, sym_name);
|
2021-12-11 20:01:16 +01:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case MOUSE_BINDING: {
|
|
|
|
|
|
const char *const button_name = button_map[button_idx].name;
|
|
|
|
|
|
int chars = snprintf(
|
2021-12-25 23:37:04 +01:00
|
|
|
|
value, sizeof(value), "%s%s%s",
|
|
|
|
|
|
argv ? "[command arg1 arg2 \"arg3 has spaces\"] " : "",
|
|
|
|
|
|
modifier_string, button_name);
|
2021-12-11 20:01:16 +01:00
|
|
|
|
|
|
|
|
|
|
xassert(click_count > 0);
|
|
|
|
|
|
if (click_count > 1)
|
|
|
|
|
|
snprintf(&value[chars], sizeof(value) - chars, "-%d", click_count);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
|
|
|
|
|
if (!parse_fun(ctx)) {
|
|
|
|
|
|
BUG("[%s].%s=%s failed to parse",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const struct config_key_binding *binding =
|
|
|
|
|
|
&bindings->arr[bindings->count - 1];
|
|
|
|
|
|
|
2021-12-25 23:37:04 +01:00
|
|
|
|
if (argv) {
|
|
|
|
|
|
if (binding->pipe.argv.args == NULL) {
|
|
|
|
|
|
BUG("[%s].%s=%s: pipe argv is NULL",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ALEN(args); i++) {
|
|
|
|
|
|
if (binding->pipe.argv.args[i] == NULL ||
|
|
|
|
|
|
strcmp(binding->pipe.argv.args[i], args[i]) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
BUG("[%s].%s=%s: pipe argv not the expected one: "
|
|
|
|
|
|
"mismatch of arg #%zu: expected=\"%s\", got=\"%s\"",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value, i,
|
|
|
|
|
|
args[i], binding->pipe.argv.args[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (binding->pipe.argv.args[ALEN(args)] != NULL) {
|
|
|
|
|
|
BUG("[%s].%s=%s: pipe argv not the expected one: "
|
|
|
|
|
|
"expected NULL terminator at arg #%zu, got=\"%s\"",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
ALEN(args), binding->pipe.argv.args[ALEN(args)]);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (binding->pipe.argv.args != NULL) {
|
|
|
|
|
|
BUG("[%s].%s=%s: pipe argv not NULL",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
|
|
|
|
|
if (binding->action != action) {
|
|
|
|
|
|
BUG("[%s].%s=%s: action mismatch: %d != %d",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value, binding->action, action);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (binding->modifiers.ctrl != ctrl ||
|
|
|
|
|
|
binding->modifiers.alt != alt ||
|
|
|
|
|
|
binding->modifiers.shift != shift ||
|
2021-12-11 20:01:16 +01:00
|
|
|
|
binding->modifiers.super != super)
|
2021-12-11 18:30:17 +01:00
|
|
|
|
{
|
|
|
|
|
|
BUG("[%s].%s=%s: modifier mismatch:\n"
|
|
|
|
|
|
" have: ctrl=%d, alt=%d, shift=%d, super=%d\n"
|
|
|
|
|
|
" expected: ctrl=%d, alt=%d, shift=%d, super=%d",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
binding->modifiers.ctrl, binding->modifiers.alt,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
binding->modifiers.shift, binding->modifiers.super,
|
2021-12-11 18:30:17 +01:00
|
|
|
|
ctrl, alt, shift, super);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
switch (type) {
|
|
|
|
|
|
case KEY_BINDING:
|
|
|
|
|
|
if (binding->k.sym != sym) {
|
|
|
|
|
|
BUG("[%s].%s=%s: key symbol mismatch: %d != %d",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value, binding->k.sym, sym);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
case MOUSE_BINDING:;
|
|
|
|
|
|
if (binding->m.button != button) {
|
|
|
|
|
|
BUG("[%s].%s=%s: mouse button mismatch: %d != %d",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value, binding->m.button, button);
|
|
|
|
|
|
}
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
if (binding->m.count != click_count) {
|
|
|
|
|
|
BUG("[%s].%s=%s: mouse button click count mismatch: %d != %d",
|
|
|
|
|
|
ctx->section, ctx->key, ctx->value,
|
|
|
|
|
|
binding->m.count, click_count);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2021-12-11 18:30:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
free_key_binding_list(bindings);
|
2021-12-11 18:30:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
enum collision_test_mode {
|
|
|
|
|
|
FAIL_DIFFERENT_ACTION,
|
|
|
|
|
|
FAIL_DIFFERENT_ARGV,
|
2021-12-11 20:44:01 +01:00
|
|
|
|
FAIL_MOUSE_OVERRIDE,
|
|
|
|
|
|
SUCCED_SAME_ACTION_AND_ARGV,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2021-12-11 18:49:59 +01:00
|
|
|
|
static void
|
2021-12-11 20:01:16 +01:00
|
|
|
|
_test_binding_collisions(struct context *ctx,
|
|
|
|
|
|
int max_action, const char *const *map,
|
|
|
|
|
|
enum config_key_binding_type type,
|
|
|
|
|
|
enum collision_test_mode test_mode)
|
2021-12-11 18:49:59 +01:00
|
|
|
|
{
|
2021-12-11 20:01:16 +01:00
|
|
|
|
struct config_key_binding *bindings_array =
|
|
|
|
|
|
xcalloc(2, sizeof(bindings_array[0]));
|
2021-12-11 18:49:59 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
struct config_key_binding_list bindings = {
|
|
|
|
|
|
.count = 2,
|
|
|
|
|
|
.arr = bindings_array,
|
|
|
|
|
|
};
|
2021-12-11 18:49:59 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
/* First, verify we get a collision when trying to assign the same
|
|
|
|
|
|
* key combo to multiple actions */
|
|
|
|
|
|
bindings.arr[0] = (struct config_key_binding){
|
|
|
|
|
|
.action = (test_mode == FAIL_DIFFERENT_ACTION
|
|
|
|
|
|
? max_action - 1 : max_action),
|
|
|
|
|
|
.modifiers = {.ctrl = true},
|
|
|
|
|
|
.path = "unittest",
|
|
|
|
|
|
};
|
|
|
|
|
|
bindings.arr[1] = (struct config_key_binding){
|
|
|
|
|
|
.action = max_action,
|
|
|
|
|
|
.modifiers = {.ctrl = true},
|
|
|
|
|
|
.path = "unittest",
|
|
|
|
|
|
};
|
2021-12-11 18:49:59 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
switch (type) {
|
|
|
|
|
|
case KEY_BINDING:
|
|
|
|
|
|
bindings.arr[0].k.sym = XKB_KEY_a;
|
|
|
|
|
|
bindings.arr[1].k.sym = XKB_KEY_a;
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case MOUSE_BINDING:
|
|
|
|
|
|
bindings.arr[0].m.button = BTN_LEFT;
|
|
|
|
|
|
bindings.arr[0].m.count = 1;
|
|
|
|
|
|
bindings.arr[1].m.button = BTN_LEFT;
|
|
|
|
|
|
bindings.arr[1].m.count = 1;
|
|
|
|
|
|
break;
|
2021-12-11 18:49:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
switch (test_mode) {
|
|
|
|
|
|
case FAIL_DIFFERENT_ACTION:
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2021-12-11 20:44:01 +01:00
|
|
|
|
case FAIL_MOUSE_OVERRIDE:
|
|
|
|
|
|
ctx->conf->mouse.selection_override_modifiers.ctrl = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
case FAIL_DIFFERENT_ARGV:
|
|
|
|
|
|
case SUCCED_SAME_ACTION_AND_ARGV:
|
|
|
|
|
|
bindings.arr[0].pipe.master_copy = true;
|
|
|
|
|
|
bindings.arr[0].pipe.argv.args = xcalloc(
|
|
|
|
|
|
4, sizeof(bindings.arr[0].pipe.argv.args[0]));
|
|
|
|
|
|
bindings.arr[0].pipe.argv.args[0] = xstrdup("/usr/bin/foobar");
|
|
|
|
|
|
bindings.arr[0].pipe.argv.args[1] = xstrdup("hello");
|
|
|
|
|
|
bindings.arr[0].pipe.argv.args[2] = xstrdup("world");
|
|
|
|
|
|
|
|
|
|
|
|
bindings.arr[1].pipe.master_copy = true;
|
|
|
|
|
|
bindings.arr[1].pipe.argv.args = xcalloc(
|
|
|
|
|
|
4, sizeof(bindings.arr[1].pipe.argv.args[0]));
|
|
|
|
|
|
bindings.arr[1].pipe.argv.args[0] = xstrdup("/usr/bin/foobar");
|
|
|
|
|
|
bindings.arr[1].pipe.argv.args[1] = xstrdup("hello");
|
|
|
|
|
|
|
|
|
|
|
|
if (test_mode == SUCCED_SAME_ACTION_AND_ARGV)
|
|
|
|
|
|
bindings.arr[1].pipe.argv.args[2] = xstrdup("world");
|
|
|
|
|
|
break;
|
2021-12-11 18:49:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
bool expected_result =
|
|
|
|
|
|
test_mode == SUCCED_SAME_ACTION_AND_ARGV ? true : false;
|
2021-12-11 18:49:59 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
if (resolve_key_binding_collisions(
|
|
|
|
|
|
ctx->conf, ctx->section, map, &bindings, type) != expected_result)
|
2021-12-11 18:49:59 +01:00
|
|
|
|
{
|
2021-12-11 20:01:16 +01:00
|
|
|
|
BUG("[%s].%s vs. %s: %s",
|
|
|
|
|
|
ctx->section, map[max_action - 1], map[max_action],
|
|
|
|
|
|
(expected_result == true
|
|
|
|
|
|
? "invalid key combo collision detected"
|
|
|
|
|
|
: "key combo collision not detected"));
|
2021-12-11 18:49:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
if (expected_result == false) {
|
|
|
|
|
|
if (bindings.count != 1)
|
|
|
|
|
|
BUG("[%s]: colliding binding not removed", ctx->section);
|
2021-12-11 18:49:59 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
if (bindings.arr[0].action !=
|
|
|
|
|
|
(test_mode == FAIL_DIFFERENT_ACTION ? max_action - 1 : max_action))
|
|
|
|
|
|
{
|
|
|
|
|
|
BUG("[%s]: wrong binding removed", ctx->section);
|
|
|
|
|
|
}
|
2021-12-11 18:49:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
free_key_binding_list(&bindings);
|
|
|
|
|
|
}
|
2021-12-11 18:49:59 +01:00
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_binding_collisions(struct context *ctx,
|
|
|
|
|
|
int max_action, const char *const *map,
|
|
|
|
|
|
enum config_key_binding_type type)
|
|
|
|
|
|
{
|
|
|
|
|
|
_test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ACTION);
|
|
|
|
|
|
_test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ARGV);
|
|
|
|
|
|
_test_binding_collisions(ctx, max_action, map, type, SUCCED_SAME_ACTION_AND_ARGV);
|
2021-12-11 20:44:01 +01:00
|
|
|
|
|
|
|
|
|
|
if (type == MOUSE_BINDING) {
|
|
|
|
|
|
_test_binding_collisions(
|
|
|
|
|
|
ctx, max_action, map, type, FAIL_MOUSE_OVERRIDE);
|
|
|
|
|
|
}
|
2021-12-11 18:49:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 18:30:17 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_key_bindings(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "key-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_invalid_key(&ctx, &parse_section_key_bindings, "invalid-key");
|
|
|
|
|
|
|
|
|
|
|
|
for (int action = 0; action < BIND_ACTION_KEY_COUNT; action++) {
|
|
|
|
|
|
if (binding_action_map[action] == NULL)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
test_key_binding(
|
|
|
|
|
|
&ctx, &parse_section_key_bindings,
|
|
|
|
|
|
action, BIND_ACTION_KEY_COUNT - 1,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
binding_action_map, &conf.bindings.key, KEY_BINDING);
|
2021-12-11 18:30:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_key_bindings_collisions(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "key-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_binding_collisions(
|
|
|
|
|
|
&ctx, BIND_ACTION_KEY_COUNT - 1, binding_action_map, KEY_BINDING);
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 18:30:17 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_search_bindings(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "search-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_invalid_key(&ctx, &parse_section_search_bindings, "invalid-key");
|
|
|
|
|
|
|
|
|
|
|
|
for (int action = 0; action < BIND_ACTION_SEARCH_COUNT; action++) {
|
|
|
|
|
|
if (search_binding_action_map[action] == NULL)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
test_key_binding(
|
|
|
|
|
|
&ctx, &parse_section_search_bindings,
|
|
|
|
|
|
action, BIND_ACTION_SEARCH_COUNT - 1,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
search_binding_action_map, &conf.bindings.search, KEY_BINDING);
|
2021-12-11 18:30:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_search_bindings_collisions(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "search-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_binding_collisions(
|
|
|
|
|
|
&ctx,
|
|
|
|
|
|
BIND_ACTION_SEARCH_COUNT - 1, search_binding_action_map, KEY_BINDING);
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 18:30:17 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_url_bindings(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "rul-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_invalid_key(&ctx, &parse_section_url_bindings, "invalid-key");
|
|
|
|
|
|
|
|
|
|
|
|
for (int action = 0; action < BIND_ACTION_URL_COUNT; action++) {
|
|
|
|
|
|
if (url_binding_action_map[action] == NULL)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
test_key_binding(
|
|
|
|
|
|
&ctx, &parse_section_url_bindings,
|
|
|
|
|
|
action, BIND_ACTION_URL_COUNT - 1,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
url_binding_action_map, &conf.bindings.url, KEY_BINDING);
|
2021-12-11 18:30:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
2021-12-11 20:01:16 +01:00
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
test_section_url_bindings_collisions(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "url-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_binding_collisions(
|
|
|
|
|
|
&ctx,
|
|
|
|
|
|
BIND_ACTION_URL_COUNT - 1, url_binding_action_map, KEY_BINDING);
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
2021-12-11 18:30:17 +01:00
|
|
|
|
|
2021-12-11 18:49:59 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_mouse_bindings(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "mouse-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_invalid_key(&ctx, &parse_section_mouse_bindings, "invalid-key");
|
|
|
|
|
|
|
|
|
|
|
|
for (int action = 0; action < BIND_ACTION_COUNT; action++) {
|
|
|
|
|
|
if (binding_action_map[action] == NULL)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
test_key_binding(
|
2021-12-11 18:49:59 +01:00
|
|
|
|
&ctx, &parse_section_mouse_bindings,
|
|
|
|
|
|
action, BIND_ACTION_COUNT - 1,
|
2021-12-11 20:01:16 +01:00
|
|
|
|
binding_action_map, &conf.bindings.mouse, MOUSE_BINDING);
|
2021-12-11 18:49:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-11 20:01:16 +01:00
|
|
|
|
static void
|
|
|
|
|
|
test_section_mouse_bindings_collisions(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct config conf = {0};
|
|
|
|
|
|
struct context ctx = {
|
|
|
|
|
|
.conf = &conf, .section = "mouse-bindings", .path = "unittest"};
|
|
|
|
|
|
|
|
|
|
|
|
test_binding_collisions(
|
|
|
|
|
|
&ctx,
|
|
|
|
|
|
BIND_ACTION_COUNT - 1, binding_action_map, MOUSE_BINDING);
|
|
|
|
|
|
|
|
|
|
|
|
config_free(conf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-11-27 17:23:33 +01:00
|
|
|
|
int
|
|
|
|
|
|
main(int argc, const char *const *argv)
|
|
|
|
|
|
{
|
|
|
|
|
|
log_init(LOG_COLORIZE_AUTO, false, 0, LOG_CLASS_ERROR);
|
|
|
|
|
|
test_section_main();
|
2021-12-25 23:03:11 +01:00
|
|
|
|
test_section_bell();
|
2021-12-11 18:30:17 +01:00
|
|
|
|
test_section_key_bindings();
|
2021-12-11 20:01:16 +01:00
|
|
|
|
test_section_key_bindings_collisions();
|
2021-12-11 18:30:17 +01:00
|
|
|
|
test_section_search_bindings();
|
2021-12-11 20:01:16 +01:00
|
|
|
|
test_section_search_bindings_collisions();
|
2021-12-11 18:30:17 +01:00
|
|
|
|
test_section_url_bindings();
|
2021-12-11 20:01:16 +01:00
|
|
|
|
test_section_url_bindings_collisions();
|
2021-12-11 18:49:59 +01:00
|
|
|
|
test_section_mouse_bindings();
|
2021-12-11 20:01:16 +01:00
|
|
|
|
test_section_mouse_bindings_collisions();
|
2021-11-27 17:23:33 +01:00
|
|
|
|
log_deinit();
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|