Add some tests about config

Create a test infrastructure, create few tests about the config file reading and validation. Add couple of checks in config.c to avoid null pointers exceptions when running tests.
This commit is contained in:
Michele Pagot 2025-04-10 01:55:30 +02:00
parent a25645a5a6
commit 884338cff4
7 changed files with 287 additions and 24 deletions

1
.gitignore vendored
View file

@ -3,7 +3,6 @@ install_manifest.txt
*.o
*.a
bin/
test/
build/
build-*/
.cache/

View file

@ -186,6 +186,19 @@ else
)
endif
# subdir('sway') needs reference_config_file
# as input for its tests
config = configuration_data()
config.set('datadir', join_paths(prefix, datadir))
config.set('prefix', prefix)
config.set('sysconfdir', join_paths(prefix, sysconfdir))
reference_config_file = configure_file(
configuration: config,
input: 'config.in',
output: '@BASENAME@',
install_dir: join_paths(sysconfdir, 'sway')
)
sway_inc = include_directories('include')
@ -205,18 +218,6 @@ if get_option('swaynag')
subdir('swaynag')
endif
config = configuration_data()
config.set('datadir', join_paths(prefix, datadir))
config.set('prefix', prefix)
config.set('sysconfdir', join_paths(prefix, sysconfdir))
configure_file(
configuration: config,
input: 'config.in',
output: '@BASENAME@',
install_dir: join_paths(sysconfdir, 'sway')
)
install_data(
'sway.desktop',
install_dir: join_paths(datadir, 'wayland-sessions')

View file

@ -40,6 +40,10 @@ struct sway_config *config = NULL;
static struct xkb_state *keysym_translation_state_create(
struct xkb_rule_names rules, uint32_t context_flags) {
struct xkb_context *context = xkb_context_new(context_flags | XKB_CONTEXT_NO_SECURE_GETENV);
if (!context) {
sway_log(SWAY_ERROR, "Failed to create XKB context");
return NULL;
}
struct xkb_keymap *xkb_keymap = xkb_keymap_new_from_names(
context,
&rules,
@ -477,22 +481,24 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
config->active = true;
// xwayland can only be enabled/disabled at launch
sway_log(SWAY_DEBUG, "xwayland will remain %s",
if(old_config != NULL) {
sway_log(SWAY_DEBUG, "xwayland will remain %s",
old_config->xwayland ? "enabled" : "disabled");
config->xwayland = old_config->xwayland;
config->xwayland = old_config->xwayland;
// primary_selection can only be enabled/disabled at launch
sway_log(SWAY_DEBUG, "primary_selection will remain %s",
// primary_selection can only be enabled/disabled at launch
sway_log(SWAY_DEBUG, "primary_selection will remain %s",
old_config->primary_selection ? "enabled" : "disabled");
config->primary_selection = old_config->primary_selection;
config->primary_selection = old_config->primary_selection;
if (!config->validating) {
if (old_config->swaybg_client != NULL) {
if (!config->validating) {
if (old_config->swaybg_client != NULL) {
wl_client_destroy(old_config->swaybg_client);
}
}
if (old_config->swaynag_config_errors.client != NULL) {
wl_client_destroy(old_config->swaynag_config_errors.client);
if (old_config->swaynag_config_errors.client != NULL) {
wl_client_destroy(old_config->swaynag_config_errors.client);
}
}
input_manager_reset_all_inputs();

View file

@ -169,7 +169,7 @@ sway_sources = files(
'commands/input/middle_emulation.c',
'commands/input/natural_scroll.c',
'commands/input/pointer_accel.c',
'commands/input/rotation_angle.c',
'commands/input/rotation_angle.c',
'commands/input/repeat_delay.c',
'commands/input/repeat_rate.c',
'commands/input/scroll_button.c',
@ -252,3 +252,20 @@ executable(
link_with: [lib_sway_common],
install: true
)
test_config = executable('sway_test_config',
[
'config.c',
'test/test_config.c',
'test/log_stub.c',
'../common/stringop.c',
'../common/util.c',
'../common/list.c'] + wl_protos_src,
include_directories: [sway_inc, include_directories('test')],
dependencies: sway_deps)
empty_config = meson.current_source_dir() + '/test/empty_config.txt'
test('sway_test_empty_config', test_config, args: ['-c', empty_config])
test('sway_test_empty_config_validate', test_config, args: ['-c', empty_config, '-C'])
test('sway_test_empty_config_validate_activate', test_config, args: ['-c', empty_config, '-C', '-A'])
test('sway_test_reference_config_validate_activate', test_config, args: ['-c', reference_config_file, '-C', '-A'])

View file

26
sway/test/log_stub.c Normal file
View file

@ -0,0 +1,26 @@
#include <stdio.h>
#include "log.h"
void sway_log_init(sway_log_importance_t verbosity, terminate_callback_t callback) {
return;
}
void _sway_log(sway_log_importance_t verbosity, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
void _sway_vlog(sway_log_importance_t verbosity, const char *fmt, va_list args) {
vfprintf(stderr, fmt, args);
}
bool _sway_assert(bool condition, const char *format, ...) {
return true;
}
void _sway_abort(const char *format, ...) {
return;
}

214
sway/test/test_config.c Normal file
View file

@ -0,0 +1,214 @@
#include "sway/config.h"
#include "sway/output.h"
#include "sway/commands.h"
#include "sway/server.h"
#include "sway/criteria.h"
#include "pango.h"
void free_gesture_binding(struct sway_gesture_binding *binding) {
return;
}
void free_bar_config(struct bar_config *bar) {
return;
}
void free_sway_binding(struct sway_binding *binding) {
return;
}
void free_switch_binding(struct sway_switch_binding *binding) {
return;
}
void free_sway_variable(struct sway_variable *var) {
return;
}
bool translate_binding(struct sway_binding *binding) {
return true;
}
void input_config_fill_rule_names(struct input_config *ic,
struct xkb_rule_names *rules) {
return;
}
void binding_add_translated(struct sway_binding *binding,
list_t *mode_bindings) {
return;
}
int seat_name_cmp(const void *item, const void *data) {
return 0;
}
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
return;
}
void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
const char *fmt, ...) {
return;
}
void swaynag_show(struct swaynag_instance *swaynag) {
return;
}
struct cmd_results *config_commands_command(char *exec) {
struct cmd_results *results = NULL;
results = cmd_results_new(CMD_SUCCESS, NULL);
return results;
}
list_t *execute_command(char *_exec, struct sway_seat *seat,
struct sway_container *con) {
list_t *res_list = create_list();
if (!res_list) {
return NULL;
}
return res_list;
}
struct cmd_results *config_command(char *exec, char **new_block) {
struct cmd_results *results = NULL;
results = cmd_results_new(CMD_SUCCESS, NULL);
return results;
}
struct cmd_results *cmd_results_new(enum cmd_status status,
const char *format, ...) {
struct cmd_results *results = malloc(sizeof(struct cmd_results));
return results;
}
void free_cmd_results(struct cmd_results *results) {
free(results);
}
void get_text_metrics(const PangoFontDescription *description, int *height, int *baseline) {
return;
}
void request_modeset(void) {
return;
}
void sway_switch_retrigger_bindings_for_all(void) {
return;
}
void input_manager_reset_all_inputs(void) {
return;
}
struct sway_seat *input_manager_get_seat(const char *seat_name, bool create) {
struct sway_seat *seat = NULL;
return seat;
}
void input_manager_verify_fallback_seat(void) {
return;
}
void seat_destroy(struct sway_seat *seat) {
return;
}
void free_workspace_config(struct workspace_config *wsc) {
return;
}
void free_output_config(struct output_config *oc) {
return;
}
void free_input_config(struct input_config *ic) {
return;
}
void free_seat_config(struct seat_config *seat) {
return;
}
void criteria_destroy(struct criteria *criteria) {
return;
}
void input_manager_apply_input_config(struct input_config *input_config) {
return;
}
void input_manager_apply_seat_config(struct seat_config *seat_config) {
return;
}
void arrange_root(void) {
return;
}
bool spawn_swaybg(void) {
return true;
}
struct sway_server server = {0};
#include <getopt.h>
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"config", required_argument, NULL, 'c'},
{"validate", no_argument, NULL, 'C'},
{"active", no_argument, NULL, 'A'},
{0, 0, 0, 0}
};
static const char usage[] =
"Usage: sway_test_config [options]\n"
"\n"
" -h, --help Show help message and quit.\n"
" -c, --config <config> Specify a config file.\n"
" -C, --validate Check the validity of the config file, then exit.\n"
" -A, --active Set is_active to true.\n"
"\n";
int main(int argc, char **argv) {
bool active = false, validate = false, res;
char *config_path = NULL;
int c;
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "hCAc:", long_options, &option_index);
if (c == -1) {
break;
}
switch (c) {
case 'h': // help
printf("%s", usage);
exit(EXIT_SUCCESS);
break;
case 'c':
//free(config_path);
config_path = strdup(optarg);
break;
case 'C':
validate = true;
break;
case 'A':
active = true;
break;
default:
fprintf(stderr, "%s", usage);
exit(EXIT_FAILURE);
}
}
res = load_main_config(config_path, active, validate);
return res ? 0 : 1;
}