diff --git a/daemons/attrd/pacemaker-attrd.c b/daemons/attrd/pacemaker-attrd.c index 461cb75a66e..ee0c9e4193a 100644 --- a/daemons/attrd/pacemaker-attrd.c +++ b/daemons/attrd/pacemaker-attrd.c @@ -112,7 +112,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if ((rc != pcmk_rc_ok) || (out == NULL)) { attrd_exit_status = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, attrd_exit_status, diff --git a/daemons/based/pacemaker-based.c b/daemons/based/pacemaker-based.c index 888a1f91a77..3b13feb3545 100644 --- a/daemons/based/pacemaker-based.c +++ b/daemons/based/pacemaker-based.c @@ -184,7 +184,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/daemons/controld/pacemaker-controld.c b/daemons/controld/pacemaker-controld.c index 84442c93e2c..8948477a861 100644 --- a/daemons/controld/pacemaker-controld.c +++ b/daemons/controld/pacemaker-controld.c @@ -90,7 +90,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/daemons/execd/pacemaker-execd.c b/daemons/execd/pacemaker-execd.c index 0dcf38a43f0..030fb349968 100644 --- a/daemons/execd/pacemaker-execd.c +++ b/daemons/execd/pacemaker-execd.c @@ -355,7 +355,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, @@ -371,7 +372,9 @@ main(int argc, char **argv) // Open additional log files if (options.log_files != NULL) { - for (gchar **fname = options.log_files; *fname != NULL; fname++) { + for (const char *const *fname = (const char *const *) options.log_files; + *fname != NULL; fname++) { + rc = pcmk__add_logfile(*fname); if (rc != pcmk_rc_ok) { diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index f0d4d4dbad1..26cae2a5339 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -277,8 +277,8 @@ get_value_for_target(const char *target, const char *values) mappings = g_strsplit_set(values, "; \t", 0); - for (gchar **mapping = mappings; (*mapping != NULL) && (value == NULL); - mapping++) { + for (const char *const *mapping = (const char *const *) mappings; + (*mapping != NULL) && (value == NULL); mapping++) { value = get_value_if_matching(target, *mapping); } @@ -961,7 +961,9 @@ build_port_aliases(const char *hostmap, GList **targets) stripped = g_strstrip(g_strdup(hostmap)); mappings = g_strsplit_set(stripped, "; \t", 0); - for (gchar **mapping = mappings; *mapping != NULL; mapping++) { + for (const char *const *mapping = (const char *const *) mappings; + *mapping != NULL; mapping++) { + gchar **nvpair = NULL; if (pcmk__str_empty(*mapping)) { @@ -1881,7 +1883,9 @@ fenced_register_level(xmlNode *msg, pcmk__action_result_t *result) */ gchar **devices = g_strsplit(value, ",", 0); - for (char **dev = devices; (dev != NULL) && (*dev != NULL); dev++) { + for (const char *const *dev = (const char *const *) devices; + (dev != NULL) && (*dev != NULL); dev++) { + pcmk__trace("Adding device '%s' for %s[%d]", *dev, tp->target, id); tp->levels[id] = g_list_append(tp->levels[id], pcmk__str_copy(*dev)); @@ -2143,11 +2147,14 @@ localhost_is_eligible(const fenced_device_t *device, const char *action, { bool localhost_is_target = pcmk__str_eq(target, fenced_get_local_node(), pcmk__str_casei); + const gchar *const *on_target_actions = NULL; + + CRM_CHECK((device != NULL) && (action != NULL), return true); - CRM_CHECK(action != NULL, return true); + on_target_actions = (const gchar *const *) device->on_target_actions; - if ((device != NULL) && (device->on_target_actions != NULL) - && pcmk__g_strv_contains(device->on_target_actions, action)) { + if ((on_target_actions != NULL) + && pcmk__g_strv_contains(on_target_actions, action)) { if (!localhost_is_target) { pcmk__trace("Operation '%s' using %s can only be executed for " diff --git a/daemons/fenced/pacemaker-fenced.c b/daemons/fenced/pacemaker-fenced.c index df9ebbe9990..b169b3a8344 100644 --- a/daemons/fenced/pacemaker-fenced.c +++ b/daemons/fenced/pacemaker-fenced.c @@ -370,7 +370,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c index 85487f914de..eb5ea592497 100644 --- a/daemons/pacemakerd/pacemakerd.c +++ b/daemons/pacemakerd/pacemakerd.c @@ -75,7 +75,9 @@ pacemakerd_features_xml(pcmk__output_t *out, va_list args) { NULL); out->begin_list(out, NULL, NULL, PCMK_XE_FEATURES); - for (char **s = feature_list; *s != NULL; s++) { + for (const char *const *s = (const char *const *) feature_list; *s != NULL; + s++) { + pcmk__output_create_xml_text_node(out, PCMK_XE_FEATURE, *s); } @@ -363,7 +365,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if ((rc != pcmk_rc_ok) || (out == NULL)) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", diff --git a/daemons/schedulerd/pacemaker-schedulerd.c b/daemons/schedulerd/pacemaker-schedulerd.c index 2fa0e0c4cbe..0da6b6b7388 100644 --- a/daemons/schedulerd/pacemaker-schedulerd.c +++ b/daemons/schedulerd/pacemaker-schedulerd.c @@ -98,7 +98,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if ((rc != pcmk_rc_ok) || (out == NULL)) { exit_code = CRM_EX_FATAL; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", diff --git a/include/crm/common/cmdline_internal.h b/include/crm/common/cmdline_internal.h index 0bfcd47333e..d0b8d0d78af 100644 --- a/include/crm/common/cmdline_internal.h +++ b/include/crm/common/cmdline_internal.h @@ -106,18 +106,7 @@ void pcmk__add_arg_group(GOptionContext *context, const char *name, const char *header, const char *desc, const GOptionEntry entries[]); -/*! - * \internal - * \brief Prepare the command line for being added to a pcmk__output_t as the - * request - * - * This performs various transformations on the command line arguments, such - * as surrounding arguments containing spaces with quotes and escaping any - * single quotes in the string. - * - * \param[in,out] argv Command line (typically from pcmk__cmdline_preproc()) - */ -gchar *pcmk__quote_cmdline(gchar **argv); +gchar *pcmk__quote_cmdline(const char *const *argv); /*! * \internal diff --git a/include/crm/common/output_internal.h b/include/crm/common/output_internal.h index fde8d6ee235..d7120debf95 100644 --- a/include/crm/common/output_internal.h +++ b/include/crm/common/output_internal.h @@ -42,15 +42,15 @@ typedef struct pcmk__output_s pcmk__output_t; /*! * \internal - * \brief The type of a function that creates a ::pcmk__output_t. + * \brief Function for format-specific setup of a \c pcmk__output_t * - * Instances of this type are passed to pcmk__register_format(), stored in an - * internal data structure, and later accessed by pcmk__output_new(). For - * examples, see pcmk__mk_xml_output() and pcmk__mk_text_output(). + * Instances of this type are passed to \c pcmk__register_format(), stored in an + * internal data structure, and later accessed by \c pcmk__output_new(). For + * examples, see \c pcmk__output_setup_text() and \c pcmk__output_setup_xml(). * - * \param[in] argv The list of command line arguments. + * \param[in] out Output object to set up */ -typedef pcmk__output_t * (*pcmk__output_factory_t)(char **argv); +typedef void (*pcmk__output_setup_fn_t)(pcmk__output_t *out); /*! * \internal @@ -131,9 +131,10 @@ typedef struct pcmk__supported_format_s { const char *name; /*! - * \brief A function that creates a ::pcmk__output_t. + * \internal + * \brief Function that does format-specific setup for a \c pcmk__output_t */ - pcmk__output_factory_t create; + pcmk__output_setup_fn_t setup_fn; /*! * \brief Format-specific command line options. This can be NULL if @@ -148,17 +149,19 @@ typedef struct pcmk__supported_format_s { extern GOptionEntry pcmk__html_output_entries[]; -pcmk__output_t *pcmk__mk_html_output(char **argv); -pcmk__output_t *pcmk__mk_log_output(char **argv); -pcmk__output_t *pcmk__mk_none_output(char **argv); -pcmk__output_t *pcmk__mk_text_output(char **argv); -pcmk__output_t *pcmk__mk_xml_output(char **argv); +void pcmk__output_setup_html(pcmk__output_t *out); +void pcmk__output_setup_log(pcmk__output_t *out); +void pcmk__output_setup_none(pcmk__output_t *out); +void pcmk__output_setup_text(pcmk__output_t *out); +void pcmk__output_setup_xml(pcmk__output_t *out); -#define PCMK__SUPPORTED_FORMAT_HTML { "html", pcmk__mk_html_output, pcmk__html_output_entries } -#define PCMK__SUPPORTED_FORMAT_LOG { "log", pcmk__mk_log_output, NULL } -#define PCMK__SUPPORTED_FORMAT_NONE { PCMK_VALUE_NONE, pcmk__mk_none_output, NULL } -#define PCMK__SUPPORTED_FORMAT_TEXT { "text", pcmk__mk_text_output, NULL } -#define PCMK__SUPPORTED_FORMAT_XML { "xml", pcmk__mk_xml_output, NULL } +#define PCMK__SUPPORTED_FORMAT_HTML \ + { "html", pcmk__output_setup_html, pcmk__html_output_entries } +#define PCMK__SUPPORTED_FORMAT_LOG { "log", pcmk__output_setup_log, NULL } +#define PCMK__SUPPORTED_FORMAT_NONE \ + { PCMK_VALUE_NONE, pcmk__output_setup_none, NULL } +#define PCMK__SUPPORTED_FORMAT_TEXT { "text", pcmk__output_setup_text, NULL } +#define PCMK__SUPPORTED_FORMAT_XML { "xml", pcmk__output_setup_xml, NULL } /*! * \brief This structure contains everything that makes up a single output @@ -298,20 +301,6 @@ struct pcmk__output_s { */ void (*reset) (pcmk__output_t *out); - /*! - * \internal - * \brief Register a custom message. - * - * \param[in,out] out The output functions structure. - * \param[in] message_id The name of the message to register. This name - * will be used as the message_id parameter to the - * message function in order to call the custom - * format function. - * \param[in] fn The custom format function to call for message_id. - */ - void (*register_message) (pcmk__output_t *out, const char *message_id, - pcmk__message_fn_t fn); - /*! * \internal * \brief Call a previously registered custom message. @@ -319,7 +308,7 @@ struct pcmk__output_s { * \param[in,out] out The output functions structure. * \param[in] message_id The name of the message to call. This name must * be the same as the message_id parameter of some - * previous call to register_message. + * previous call to \c pcmk__register_message(). * \param[in] ... Arguments to be passed to the registered function. * * \return A standard Pacemaker return code. Generally: 0 if a function was @@ -532,21 +521,6 @@ struct pcmk__output_s { void (*prompt) (const char *prompt, bool echo, char **dest); }; -/*! - * \internal - * \brief Call a formatting function for a previously registered message. - * - * \note This function is for implementing custom formatters. It should not - * be called directly. Instead, call out->message. - * - * \param[in,out] out The output functions structure. - * \param[in] message_id The message to be handled. Unknown messages - * will be ignored. - * \param[in] ... Arguments to be passed to the registered function. - */ -int -pcmk__call_message(pcmk__output_t *out, const char *message_id, ...); - /*! * \internal * \brief Free a ::pcmk__output_t structure that was previously created by @@ -578,27 +552,28 @@ void pcmk__output_free(pcmk__output_t *out); * \return Standard Pacemaker return code */ int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, - const char *filename, char **argv); + const char *filename, const char *const *argv); /*! * \internal * \brief Register a new output formatter, making it available for use * the same as a base formatter. * - * \param[in,out] group A ::GOptionGroup that formatted output related command - * line arguments should be added to. This can be NULL - * for use outside of command line programs. - * \param[in] name The name of the format. This will be used to select a - * format from command line options and for displaying help. - * \param[in] create A function that creates a ::pcmk__output_t. - * \param[in] options Format-specific command line options. These will be - * added to the context. This argument can also be NULL. + * \param[in,out] group Option group that formatted output-related command + * line arguments should be added to. This can be + * \c NULL for use outside of command line programs. + * \param[in] name Format name. This will be used to select a format + * from command line options and for displaying help. + * \param[in] setup_fn Function that initializes a \c pcmk__output_t + * \param[in] options Format-specific command line options. These will be + * added to the context. This argument can also be + * \c NULL. * * \return Standard Pacemaker return code */ int pcmk__register_format(GOptionGroup *group, const char *name, - pcmk__output_factory_t create, + pcmk__output_setup_fn_t setup, const GOptionEntry *options); /*! @@ -624,21 +599,6 @@ pcmk__register_formats(GOptionGroup *group, void pcmk__unregister_formats(void); -/*! - * \internal - * \brief Register a function to handle a custom message. - * - * \note This function is for implementing custom formatters. It should not - * be called directly. Instead, call out->register_message. - * - * \param[in,out] out The output functions structure. - * \param[in] message_id The message to be handled. - * \param[in] fn The custom format function to call for message_id. - */ -void -pcmk__register_message(pcmk__output_t *out, const char *message_id, - pcmk__message_fn_t fn); - /*! * \internal * \brief Register an entire table of custom formatting functions at once. diff --git a/include/crm/common/strings_internal.h b/include/crm/common/strings_internal.h index 33586adf214..930dbf34718 100644 --- a/include/crm/common/strings_internal.h +++ b/include/crm/common/strings_internal.h @@ -164,7 +164,7 @@ pcmk__intkey_table_remove(GHashTable *hash_table, int key) } bool pcmk__str_in_list(const char *str, const GList *list, uint32_t flags); -bool pcmk__g_strv_contains(gchar **strv, const gchar *str); +bool pcmk__g_strv_contains(const gchar *const *strv, const gchar *str); bool pcmk__strcase_any_of(const char *s, ...) G_GNUC_NULL_TERMINATED; bool pcmk__str_any_of(const char *s, ...) G_GNUC_NULL_TERMINATED; diff --git a/include/crm/common/unittest_internal.h b/include/crm/common/unittest_internal.h index d65f83e1f8f..60c5efeab89 100644 --- a/include/crm/common/unittest_internal.h +++ b/include/crm/common/unittest_internal.h @@ -138,7 +138,7 @@ void pcmk__cib_test_cleanup(char *out_path); void pcmk__test_init_logging(const char *name, const char *filename); -pcmk__output_t *pcmk__mk_fake_text_output(char **argv); +void pcmk__output_setup_fake_text(pcmk__output_t *out); int pcmk__output_test_setup_group(void **state); int pcmk__output_test_teardown_group(void **state); void pcmk__set_fake_text_init_succeeds(bool value); @@ -146,8 +146,8 @@ void pcmk__set_testing_output_free(bool value); void pcmk__set_testing_output_and_clear_error(bool value); void pcmk__expect_fake_text_free_priv(void); void pcmk__expect_fake_text_err(void); -pcmk__output_t *pcmk__output_null_create1(char **argv); -pcmk__output_t *pcmk__output_null_create2(char **argv); +void pcmk__output_setup_dummy1(pcmk__output_t *out); +void pcmk__output_setup_dummy2(pcmk__output_t *out); int pcmk__output_message_dummy1(pcmk__output_t *out, va_list args); int pcmk__output_message_dummy2(pcmk__output_t *out, va_list args); diff --git a/include/pacemaker.h b/include/pacemaker.h index b2bbff4b047..98135a95bca 100644 --- a/include/pacemaker.h +++ b/include/pacemaker.h @@ -296,6 +296,7 @@ int pcmk_list_nodes(xmlNode **xml, const char *types); */ int pcmk_status(xmlNodePtr *xml); +// @COMPAT Change rule_ids to type const char *const * at a compatibility break /*! * \brief Check whether each rule in a list is in effect * diff --git a/include/pcmki/pcmki_rule.h b/include/pcmki/pcmki_rule.h index 6694c8ab21b..4867319463a 100644 --- a/include/pcmki/pcmki_rule.h +++ b/include/pcmki/pcmki_rule.h @@ -22,7 +22,7 @@ extern "C" { #endif int pcmk__check_rules(pcmk__output_t *out, xmlNodePtr input, - const crm_time_t *date_time, const char **rule_ids); + const crm_time_t *date_time, const char *const *rule_ids); /*! * \internal diff --git a/lib/cib/cib_attrs.c b/lib/cib/cib_attrs.c index 1a2de1c5c17..23f1726dbfa 100644 --- a/lib/cib/cib_attrs.c +++ b/lib/cib/cib_attrs.c @@ -39,7 +39,7 @@ new_output_object(const char *ty) }; pcmk__register_formats(NULL, formats); - rc = pcmk__output_new(&out, ty, NULL, (char**)argv); + rc = pcmk__output_new(&out, ty, NULL, argv); if ((rc != pcmk_rc_ok) || (out == NULL)) { pcmk__err("Can't out due to internal error: %s", pcmk_rc_str(rc)); return NULL; diff --git a/lib/common/cmdline.c b/lib/common/cmdline.c index 656360c55ed..f7c008e30d7 100644 --- a/lib/common/cmdline.c +++ b/lib/common/cmdline.c @@ -143,8 +143,24 @@ pcmk__add_arg_group(GOptionContext *context, const char *name, // group is now owned by context, we don't free it here } +/*! + * \internal + * \brief Prepare a command line to add to a \c pcmk__output_t as the request + * + * This performs various transformations on the command line arguments, such + * as surrounding arguments containing spaces with quotes and escaping any + * single quotes in the string. + * + * \param[in] argv Command line (typically from \c pcmk__cmdline_preproc()) + * + * \return Newly allocated command line suitable for use as the + * \c PCMK_XA_REQUEST attribute value in XML output + * + * \note The caller is responsible for freeing the return value using + * \c g_free(). + */ gchar * -pcmk__quote_cmdline(gchar **argv) +pcmk__quote_cmdline(const char *const *argv) { GString *cmdline = NULL; diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h index 00354ad0846..4810961ffc4 100644 --- a/lib/common/crmcommon_private.h +++ b/lib/common/crmcommon_private.h @@ -356,7 +356,11 @@ pcmk__ipc_methods_t *pcmk__schedulerd_api_methods(void); */ G_GNUC_INTERNAL int pcmk__bare_output_new(pcmk__output_t **out, const char *fmt_name, - const char *filename, char **argv); + const char *filename, const char *const *argv); + +G_GNUC_INTERNAL +void pcmk__register_message(pcmk__output_t *out, const char *message_id, + pcmk__message_fn_t fn); G_GNUC_INTERNAL void pcmk__register_option_messages(pcmk__output_t *out); diff --git a/lib/common/logging.c b/lib/common/logging.c index 09734ad1ee3..51bf0de44a2 100644 --- a/lib/common/logging.c +++ b/lib/common/logging.c @@ -624,7 +624,8 @@ crm_log_filter_source(int source, struct qb_log_callsite *cs) char *key = pcmk__assert_asprintf("%s:%d", cs->function, cs->lineno); - if (pcmk__g_strv_contains(trace_blackbox, key)) { + if (pcmk__g_strv_contains((const gchar *const *) trace_blackbox, + key)) { qb_bit_set(cs->targets, source); } free(key); @@ -648,21 +649,24 @@ crm_log_filter_source(int source, struct qb_log_callsite *cs) } if ((trace_files != NULL) - && pcmk__g_strv_contains(trace_files, cs->filename)) { + && pcmk__g_strv_contains((const gchar *const *) trace_files, + cs->filename)) { qb_bit_set(cs->targets, source); return; } if ((trace_functions != NULL) - && pcmk__g_strv_contains(trace_functions, cs->function)) { + && pcmk__g_strv_contains((const gchar *const *) trace_functions, + cs->function)) { qb_bit_set(cs->targets, source); return; } if ((trace_formats != NULL) - && pcmk__g_strv_contains(trace_formats, cs->format)) { + && pcmk__g_strv_contains((const gchar *const *) trace_formats, + cs->format)) { qb_bit_set(cs->targets, source); return; @@ -716,7 +720,9 @@ init_tracing(void) if (tags != NULL) { gchar **trace_tags = g_strsplit(tags, ",", 0); - for (gchar **tag = trace_tags; *tag != NULL; tag++) { + for (const char *const *tag = (const char *const *) trace_tags; + *tag != NULL; tag++) { + if (pcmk__str_empty(*tag)) { continue; } @@ -1216,7 +1222,9 @@ crm_log_output_fn(const char *file, const char *function, int line, int level, c out_lines = g_strsplit(output, "\n", 0); - for (gchar **out_line = out_lines; *out_line != NULL; out_line++) { + for (const char *const *out_line = (const char *const*) out_lines; + *out_line != NULL; out_line++) { + do_crm_log_alias(level, file, function, line, "%s [ %s ]", prefix, *out_line); } diff --git a/lib/common/options.c b/lib/common/options.c index cea73792e83..2f17bd9c9bb 100644 --- a/lib/common/options.c +++ b/lib/common/options.c @@ -1180,7 +1180,7 @@ pcmk__env_option_enabled(const char *daemon, const char *option) subsystems = g_strsplit(value, ",", 0); - enabled = pcmk__g_strv_contains(subsystems, daemon); + enabled = pcmk__g_strv_contains((const gchar *const *) subsystems, daemon); g_strfreev(subsystems); return enabled; diff --git a/lib/common/options_display.c b/lib/common/options_display.c index 40cc5de75ef..0a35d1dd348 100644 --- a/lib/common/options_display.c +++ b/lib/common/options_display.c @@ -41,7 +41,9 @@ add_possible_values_default(pcmk__output_t *out, gchar **values = g_strsplit(option->values, ", ", 0); - for (gchar **value = values; *value != NULL; value++) { + for (const char *const *value = (const char *const *) values; + *value != NULL; value++) { + if (buf->len > 0) { g_string_append(buf, ", "); } @@ -297,7 +299,9 @@ add_possible_values_xml(pcmk__output_t *out, values = g_strsplit(option->values, ", ", 0); - for (gchar **value = values; *value != NULL; value++) { + for (const char *const *value = (const char *const *) values; + *value != NULL; value++) { + pcmk__output_create_xml_node(out, PCMK_XE_OPTION, PCMK_XA_VALUE, *value, NULL); diff --git a/lib/common/output.c b/lib/common/output.c index 1d6bba9533b..259b1f84761 100644 --- a/lib/common/output.c +++ b/lib/common/output.c @@ -50,6 +50,43 @@ pcmk__output_free(pcmk__output_t *out) { free(out); } +/*! + * \internal + * \brief Call a formatting function for a previously registered message + * + * \param[in,out] out Output object + * \param[in] message_id Message to handle + * \param[in] ... Arguments to be passed to the registered function + * + * \note This function is for implementing custom formatters. It should not + * be called directly. Instead, call out->message. + * + * \return Return value of the formatting function, or \c EINVAL if no + * formatting function is found + */ +static int +call_message(pcmk__output_t *out, const char *message_id, ...) +{ + va_list args; + int rc = pcmk_rc_ok; + pcmk__message_fn_t fn; + + pcmk__assert((out != NULL) && !pcmk__str_empty(message_id)); + + fn = g_hash_table_lookup(out->messages, message_id); + if (fn == NULL) { + pcmk__debug("Called unknown output message '%s' for format '%s'", + message_id, out->fmt_name); + return EINVAL; + } + + va_start(args, message_id); + rc = fn(out, args); + va_end(args); + + return rc; +} + /*! * \internal * \brief Create a new \p pcmk__output_t structure @@ -69,9 +106,9 @@ pcmk__output_free(pcmk__output_t *out) { */ int pcmk__bare_output_new(pcmk__output_t **out, const char *fmt_name, - const char *filename, char **argv) + const char *filename, const char *const *argv) { - pcmk__output_factory_t create = NULL; + pcmk__output_setup_fn_t setup_fn = NULL; pcmk__assert((formatters != NULL) && (out != NULL)); @@ -79,20 +116,25 @@ pcmk__bare_output_new(pcmk__output_t **out, const char *fmt_name, * what it supports so this also may not be valid. */ if (fmt_name == NULL) { - create = g_hash_table_lookup(formatters, "text"); + setup_fn = g_hash_table_lookup(formatters, "text"); } else { - create = g_hash_table_lookup(formatters, fmt_name); + setup_fn = g_hash_table_lookup(formatters, fmt_name); } - if (create == NULL) { + if (setup_fn == NULL) { return pcmk_rc_unknown_format; } - *out = create(argv); + *out = calloc(1, sizeof(pcmk__output_t)); if (*out == NULL) { return ENOMEM; } + setup_fn(*out); + + (*out)->request = pcmk__quote_cmdline(argv); + (*out)->message = call_message; + if (pcmk__str_eq(filename, "-", pcmk__str_null_matches)) { (*out)->dest = stdout; } else { @@ -119,7 +161,7 @@ pcmk__bare_output_new(pcmk__output_t **out, const char *fmt_name, int pcmk__output_new(pcmk__output_t **out, const char *fmt_name, - const char *filename, char **argv) + const char *filename, const char *const *argv) { int rc = pcmk__bare_output_new(out, fmt_name, filename, argv); @@ -133,12 +175,12 @@ pcmk__output_new(pcmk__output_t **out, const char *fmt_name, int pcmk__register_format(GOptionGroup *group, const char *name, - pcmk__output_factory_t create, + pcmk__output_setup_fn_t setup_fn, const GOptionEntry *options) { char *name_copy = NULL; - pcmk__assert((create != NULL) && !pcmk__str_empty(name)); + pcmk__assert((setup_fn != NULL) && !pcmk__str_empty(name)); // cppcheck doesn't understand the above pcmk__assert line // cppcheck-suppress ctunullpointer @@ -155,7 +197,7 @@ pcmk__register_format(GOptionGroup *group, const char *name, g_option_group_add_entries(group, options); } - g_hash_table_insert(formatters, name_copy, create); + g_hash_table_insert(formatters, name_copy, setup_fn); return pcmk_rc_ok; } @@ -166,9 +208,12 @@ pcmk__register_formats(GOptionGroup *group, if (formats == NULL) { return; } + for (const pcmk__supported_format_t *entry = formats; entry->name != NULL; entry++) { - pcmk__register_format(group, entry->name, entry->create, entry->options); + + pcmk__register_format(group, entry->name, entry->setup_fn, + entry->options); } } @@ -180,28 +225,14 @@ pcmk__unregister_formats(void) { } } -int -pcmk__call_message(pcmk__output_t *out, const char *message_id, ...) { - va_list args; - int rc = pcmk_rc_ok; - pcmk__message_fn_t fn; - - pcmk__assert((out != NULL) && !pcmk__str_empty(message_id)); - - fn = g_hash_table_lookup(out->messages, message_id); - if (fn == NULL) { - pcmk__debug("Called unknown output message '%s' for format '%s'", - message_id, out->fmt_name); - return EINVAL; - } - - va_start(args, message_id); - rc = fn(out, args); - va_end(args); - - return rc; -} - +/*! + * \internal + * \brief Register a function to handle a custom message + * + * \param[in,out] out Output object + * \param[in] message_id Message to handle + * \param[in] fn Format function to call for \p message_id + */ void pcmk__register_message(pcmk__output_t *out, const char *message_id, pcmk__message_fn_t fn) @@ -301,14 +332,14 @@ int pcmk__log_output_new(pcmk__output_t **out) { int rc = pcmk_rc_ok; - const char* argv[] = { "", NULL }; + const char *argv[] = { "", NULL }; pcmk__supported_format_t formats[] = { PCMK__SUPPORTED_FORMAT_LOG, { NULL, NULL, NULL } }; pcmk__register_formats(NULL, formats); - rc = pcmk__output_new(out, "log", NULL, (char **) argv); + rc = pcmk__output_new(out, "log", NULL, argv); if ((rc != pcmk_rc_ok) || (*out == NULL)) { pcmk__err("Can't log certain messages due to internal error: %s", pcmk_rc_str(rc)); @@ -330,14 +361,14 @@ int pcmk__text_output_new(pcmk__output_t **out, const char *filename) { int rc = pcmk_rc_ok; - const char* argv[] = { "", NULL }; + const char *argv[] = { "", NULL }; pcmk__supported_format_t formats[] = { PCMK__SUPPORTED_FORMAT_TEXT, { NULL, NULL, NULL } }; pcmk__register_formats(NULL, formats); - rc = pcmk__output_new(out, "text", filename, (char **) argv); + rc = pcmk__output_new(out, "text", filename, argv); if ((rc != pcmk_rc_ok) || (*out == NULL)) { pcmk__err("Can't create text output object to internal error: %s", pcmk_rc_str(rc)); diff --git a/lib/common/output_html.c b/lib/common/output_html.c index 3215e0825b1..6ba7a79075a 100644 --- a/lib/common/output_html.c +++ b/lib/common/output_html.c @@ -413,43 +413,32 @@ html_progress(pcmk__output_t *out, bool end) { /* This function intentially left blank */ } -pcmk__output_t * -pcmk__mk_html_output(char **argv) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = "html"; - retval->request = pcmk__quote_cmdline(argv); - - retval->init = html_init; - retval->free_priv = html_free_priv; - retval->finish = html_finish; - retval->reset = html_reset; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->subprocess_output = html_subprocess_output; - retval->version = html_version; - retval->info = html_info; - retval->transient = html_info; - retval->err = html_err; - retval->output_xml = html_output_xml; - - retval->begin_list = html_begin_list; - retval->list_item = html_list_item; - retval->increment_list = html_increment_list; - retval->end_list = html_end_list; - - retval->is_quiet = html_is_quiet; - retval->spacer = html_spacer; - retval->progress = html_progress; - retval->prompt = pcmk__text_prompt; - - return retval; +void +pcmk__output_setup_html(pcmk__output_t *out) +{ + out->fmt_name = "html"; + + out->init = html_init; + out->free_priv = html_free_priv; + out->finish = html_finish; + out->reset = html_reset; + + out->subprocess_output = html_subprocess_output; + out->version = html_version; + out->info = html_info; + out->transient = html_info; + out->err = html_err; + out->output_xml = html_output_xml; + + out->begin_list = html_begin_list; + out->list_item = html_list_item; + out->increment_list = html_increment_list; + out->end_list = html_end_list; + + out->is_quiet = html_is_quiet; + out->spacer = html_spacer; + out->progress = html_progress; + out->prompt = pcmk__text_prompt; } xmlNodePtr diff --git a/lib/common/output_log.c b/lib/common/output_log.c index 608efd625ed..262c8230a4c 100644 --- a/lib/common/output_log.c +++ b/lib/common/output_log.c @@ -300,42 +300,31 @@ log_prompt(const char *prompt, bool echo, char **dest) { /* This function intentionally left blank */ } -pcmk__output_t * -pcmk__mk_log_output(char **argv) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = "log"; - retval->request = pcmk__quote_cmdline(argv); - - retval->init = log_init; - retval->free_priv = log_free_priv; - retval->finish = log_finish; - retval->reset = log_reset; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->subprocess_output = log_subprocess_output; - retval->version = log_version; - retval->info = log_info; - retval->transient = log_transient; - retval->err = log_err; - retval->output_xml = log_output_xml; - - retval->begin_list = log_begin_list; - retval->list_item = log_list_item; - retval->end_list = log_end_list; - - retval->is_quiet = log_is_quiet; - retval->spacer = log_spacer; - retval->progress = log_progress; - retval->prompt = log_prompt; - - return retval; +void +pcmk__output_setup_log(pcmk__output_t *out) +{ + out->fmt_name = "log"; + + out->init = log_init; + out->free_priv = log_free_priv; + out->finish = log_finish; + out->reset = log_reset; + + out->subprocess_output = log_subprocess_output; + out->version = log_version; + out->info = log_info; + out->transient = log_transient; + out->err = log_err; + out->output_xml = log_output_xml; + + out->begin_list = log_begin_list; + out->list_item = log_list_item; + out->end_list = log_end_list; + + out->is_quiet = log_is_quiet; + out->spacer = log_spacer; + out->progress = log_progress; + out->prompt = log_prompt; } /*! diff --git a/lib/common/output_none.c b/lib/common/output_none.c index 8a5032a2242..be49c0f2b76 100644 --- a/lib/common/output_none.c +++ b/lib/common/output_none.c @@ -110,41 +110,30 @@ none_prompt(const char *prompt, bool echo, char **dest) { /* This function intentionally left blank */ } -pcmk__output_t * -pcmk__mk_none_output(char **argv) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = PCMK_VALUE_NONE; - retval->request = pcmk__quote_cmdline(argv); - - retval->init = none_init; - retval->free_priv = none_free_priv; - retval->finish = none_finish; - retval->reset = none_reset; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->subprocess_output = none_subprocess_output; - retval->version = none_version; - retval->info = none_info; - retval->transient = none_info; - retval->err = none_err; - retval->output_xml = none_output_xml; - - retval->begin_list = none_begin_list; - retval->list_item = none_list_item; - retval->increment_list = none_increment_list; - retval->end_list = none_end_list; - - retval->is_quiet = none_is_quiet; - retval->spacer = none_spacer; - retval->progress = none_progress; - retval->prompt = none_prompt; - - return retval; +void +pcmk__output_setup_none(pcmk__output_t *out) +{ + out->fmt_name = PCMK_VALUE_NONE; + + out->init = none_init; + out->free_priv = none_free_priv; + out->finish = none_finish; + out->reset = none_reset; + + out->subprocess_output = none_subprocess_output; + out->version = none_version; + out->info = none_info; + out->transient = none_info; + out->err = none_err; + out->output_xml = none_output_xml; + + out->begin_list = none_begin_list; + out->list_item = none_list_item; + out->increment_list = none_increment_list; + out->end_list = none_end_list; + + out->is_quiet = none_is_quiet; + out->spacer = none_spacer; + out->progress = none_progress; + out->prompt = none_prompt; } diff --git a/lib/common/output_text.c b/lib/common/output_text.c index fcade4736b8..6d6b6774115 100644 --- a/lib/common/output_text.c +++ b/lib/common/output_text.c @@ -305,43 +305,32 @@ text_progress(pcmk__output_t *out, bool end) { } } -pcmk__output_t * -pcmk__mk_text_output(char **argv) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = "text"; - retval->request = pcmk__quote_cmdline(argv); - - retval->init = text_init; - retval->free_priv = text_free_priv; - retval->finish = text_finish; - retval->reset = text_reset; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->subprocess_output = text_subprocess_output; - retval->version = text_version; - retval->info = text_info; - retval->transient = text_transient; - retval->err = text_err; - retval->output_xml = text_output_xml; - - retval->begin_list = text_begin_list; - retval->list_item = text_list_item; - retval->increment_list = text_increment_list; - retval->end_list = text_end_list; - - retval->is_quiet = text_is_quiet; - retval->spacer = text_spacer; - retval->progress = text_progress; - retval->prompt = pcmk__text_prompt; - - return retval; +void +pcmk__output_setup_text(pcmk__output_t *out) +{ + out->fmt_name = "text"; + + out->init = text_init; + out->free_priv = text_free_priv; + out->finish = text_finish; + out->reset = text_reset; + + out->subprocess_output = text_subprocess_output; + out->version = text_version; + out->info = text_info; + out->transient = text_transient; + out->err = text_err; + out->output_xml = text_output_xml; + + out->begin_list = text_begin_list; + out->list_item = text_list_item; + out->increment_list = text_increment_list; + out->end_list = text_end_list; + + out->is_quiet = text_is_quiet; + out->spacer = text_spacer; + out->progress = text_progress; + out->prompt = pcmk__text_prompt; } /*! diff --git a/lib/common/output_xml.c b/lib/common/output_xml.c index 1b237db96d2..0603783dbff 100644 --- a/lib/common/output_xml.c +++ b/lib/common/output_xml.c @@ -439,43 +439,32 @@ xml_progress(pcmk__output_t *out, bool end) { /* This function intentionally left blank */ } -pcmk__output_t * -pcmk__mk_xml_output(char **argv) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = "xml"; - retval->request = pcmk__quote_cmdline(argv); - - retval->init = xml_init; - retval->free_priv = xml_free_priv; - retval->finish = xml_finish; - retval->reset = xml_reset; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->subprocess_output = xml_subprocess_output; - retval->version = xml_version; - retval->info = xml_info; - retval->transient = xml_info; - retval->err = xml_err; - retval->output_xml = xml_output_xml; - - retval->begin_list = xml_begin_list; - retval->list_item = xml_list_item; - retval->increment_list = xml_increment_list; - retval->end_list = xml_end_list; - - retval->is_quiet = xml_is_quiet; - retval->spacer = xml_spacer; - retval->progress = xml_progress; - retval->prompt = pcmk__text_prompt; - - return retval; +void +pcmk__output_setup_xml(pcmk__output_t *out) +{ + out->fmt_name = "xml"; + + out->init = xml_init; + out->free_priv = xml_free_priv; + out->finish = xml_finish; + out->reset = xml_reset; + + out->subprocess_output = xml_subprocess_output; + out->version = xml_version; + out->info = xml_info; + out->transient = xml_info; + out->err = xml_err; + out->output_xml = xml_output_xml; + + out->begin_list = xml_begin_list; + out->list_item = xml_list_item; + out->increment_list = xml_increment_list; + out->end_list = xml_end_list; + + out->is_quiet = xml_is_quiet; + out->spacer = xml_spacer; + out->progress = xml_progress; + out->prompt = pcmk__text_prompt; } xmlNodePtr diff --git a/lib/common/strings.c b/lib/common/strings.c index a920a899e3c..e73484da8fb 100644 --- a/lib/common/strings.c +++ b/lib/common/strings.c @@ -984,7 +984,7 @@ pcmk__str_in_list(const char *str, const GList *list, uint32_t flags) * \return \c true if \p str is an element of \p strv, or \c false otherwise */ bool -pcmk__g_strv_contains(gchar **strv, const gchar *str) +pcmk__g_strv_contains(const gchar *const *strv, const gchar *str) { // @COMPAT Replace with calls to g_strv_contains() when we require glib 2.44 CRM_CHECK((strv != NULL) && (str != NULL), return false); diff --git a/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c b/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c index ae09f076e4c..1f40fd7474e 100644 --- a/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c +++ b/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c @@ -17,16 +17,14 @@ * says "The quoting style used is undefined (single or double quotes may be * used)." */ -static void -assert_quote_cmdline(const char **argv, const gchar *expected_single, - const gchar *expected_double) -{ - gchar *processed = pcmk__quote_cmdline((gchar **) argv); - - assert_true(pcmk__str_any_of(processed, expected_single, expected_double, - NULL)); - g_free(processed); -} +#define assert_quote_cmdline(argv, expected_single, expected_double) \ + do { \ + gchar *processed = pcmk__quote_cmdline(argv); \ + \ + assert_true(pcmk__str_any_of(processed, expected_single, \ + expected_double, NULL)); \ + g_free(processed); \ + } while (0) static void empty_input(void **state) diff --git a/lib/common/tests/iso8601/crm_time_add_days_test.c b/lib/common/tests/iso8601/crm_time_add_days_test.c index c9ad3616d78..74b3d3cfc0b 100644 --- a/lib/common/tests/iso8601/crm_time_add_days_test.c +++ b/lib/common/tests/iso8601/crm_time_add_days_test.c @@ -16,22 +16,20 @@ #include -static void -assert_add_days(const char *orig_date_time, int days, - const char *expected_date_time) -{ - crm_time_t *orig = crm_time_new(orig_date_time); - crm_time_t *expected = crm_time_new(expected_date_time); - - assert_non_null(orig); - assert_non_null(expected); - - crm_time_add_days(orig, days); - assert_int_equal(crm_time_compare(orig, expected), 0); - - crm_time_free(orig); - crm_time_free(expected); -} +#define assert_add_days(orig_date_time, days, expected_date_time) \ + do { \ + crm_time_t *orig = crm_time_new(orig_date_time); \ + crm_time_t *expected = crm_time_new(expected_date_time); \ + \ + assert_non_null(orig); \ + assert_non_null(expected); \ + \ + crm_time_add_days(orig, days); \ + assert_int_equal(crm_time_compare(orig, expected), 0); \ + \ + crm_time_free(orig); \ + crm_time_free(expected); \ + } while (0) static void invalid_argument(void **state) diff --git a/lib/common/tests/iso8601/crm_time_add_seconds_test.c b/lib/common/tests/iso8601/crm_time_add_seconds_test.c index 4315d7dcb5d..b8990cb5286 100644 --- a/lib/common/tests/iso8601/crm_time_add_seconds_test.c +++ b/lib/common/tests/iso8601/crm_time_add_seconds_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -16,22 +16,20 @@ #include -static void -assert_add_seconds(const char *orig_date_time, int seconds, - const char *expected_date_time) -{ - crm_time_t *orig = crm_time_new(orig_date_time); - crm_time_t *expected = crm_time_new(expected_date_time); - - assert_non_null(orig); - assert_non_null(expected); - - crm_time_add_seconds(orig, seconds); - assert_int_equal(crm_time_compare(orig, expected), 0); - - crm_time_free(orig); - crm_time_free(expected); -} +#define assert_add_seconds(orig_date_time, seconds, expected_date_time) \ + do { \ + crm_time_t *orig = crm_time_new(orig_date_time); \ + crm_time_t *expected = crm_time_new(expected_date_time); \ + \ + assert_non_null(orig); \ + assert_non_null(expected); \ + \ + crm_time_add_seconds(orig, seconds); \ + assert_int_equal(crm_time_compare(orig, expected), 0); \ + \ + crm_time_free(orig); \ + crm_time_free(expected); \ + } while (0) static void invalid_argument(void **state) diff --git a/lib/common/tests/iso8601/crm_time_add_years_test.c b/lib/common/tests/iso8601/crm_time_add_years_test.c index 8ea6b4d1c46..828150411cc 100644 --- a/lib/common/tests/iso8601/crm_time_add_years_test.c +++ b/lib/common/tests/iso8601/crm_time_add_years_test.c @@ -16,22 +16,20 @@ #include -static void -assert_add_years(const char *orig_date_time, int years, - const char *expected_date_time) -{ - crm_time_t *orig = crm_time_new(orig_date_time); - crm_time_t *expected = crm_time_new(expected_date_time); - - assert_non_null(orig); - assert_non_null(expected); - - crm_time_add_years(orig, years); - assert_int_equal(crm_time_compare(orig, expected), 0); - - crm_time_free(orig); - crm_time_free(expected); -} +#define assert_add_years(orig_date_time, years, expected_date_time) \ + do { \ + crm_time_t *orig = crm_time_new(orig_date_time); \ + crm_time_t *expected = crm_time_new(expected_date_time); \ + \ + assert_non_null(orig); \ + assert_non_null(expected); \ + \ + crm_time_add_years(orig, years); \ + assert_int_equal(crm_time_compare(orig, expected), 0); \ + \ + crm_time_free(orig); \ + crm_time_free(expected); \ + } while (0) static void invalid_argument(void **state) diff --git a/lib/common/tests/iso8601/pcmk__time_format_hr_test.c b/lib/common/tests/iso8601/pcmk__time_format_hr_test.c index ead23e9c8fc..889dd74f88b 100644 --- a/lib/common/tests/iso8601/pcmk__time_format_hr_test.c +++ b/lib/common/tests/iso8601/pcmk__time_format_hr_test.c @@ -27,104 +27,149 @@ /*! * \internal - * \brief Assert that pcmk__time_format_hr() produced expected result + * \brief Check that \c pcmk__time_format_hr() produced expected result * - * \param[in] format Time format string - * \param[in] expected Assertion succeeds if result matches this - * \param[in] alternate If this is not NULL, assertion may also succeed if - * result matches this - * \param[in] usec Microseconds component of the reference time + * \param[in] format Time format string (const char *) + * \param[in] expected Succeed if result matches this (const char *) + */ +#define assert_hr_format(format, expected) \ + do { \ + crm_time_t *dt = NULL; \ + char *result = NULL; \ + \ + dt = crm_time_new(DATE_TIME_S); \ + assert_non_null(dt); \ + \ + result = pcmk__time_format_hr(format, dt, 0); \ + assert_non_null(result); \ + assert_string_equal(result, expected); \ + \ + crm_time_free(dt); \ + free(result); \ + } while (0) + +/*! + * \internal + * \brief Check that \c pcmk__time_format_hr() produced expected result (or alt) + * + * \param[in] format Time format string (const char *) + * \param[in] expected Succeed if result matches this (const char *) + * \param[in] alternate Succeed if result matches this (const char *) * - * \note This allows two possible results because different strftime() + * \note This allows two possible results because different \c strftime() * implementations handle certain format syntax differently. */ -static void -assert_hr_format(const char *format, const char *expected, - const char *alternate, int usec) -{ - crm_time_t *dt = crm_time_new(DATE_TIME_S); - char *result = NULL; - - assert_non_null(dt); - - result = pcmk__time_format_hr(format, dt, usec); - - if (expected == NULL) { - assert_null(result); - return; - } +#define assert_hr_format_alt(format, expected, alternate) \ + do { \ + crm_time_t *dt = NULL; \ + char *result = NULL; \ + \ + dt = crm_time_new(DATE_TIME_S); \ + assert_non_null(dt); \ + \ + result = pcmk__time_format_hr(format, dt, 0); \ + assert_non_null(result); \ + \ + /* CMocka has no abstraction for comparing to multiple strings */ \ + assert_true((strcmp(result, expected) == 0) \ + || (strcmp(result, alternate) == 0)); \ + \ + crm_time_free(dt); \ + free(result); \ + } while (0) - assert_non_null(result); - - if (alternate == NULL) { - assert_string_equal(result, expected); - } else { - assert_true((strcmp(result, expected) == 0) - || (strcmp(result, alternate) == 0)); - } - - free(result); -} +/*! + * \internal + * \brief Check that \c pcmk__time_format_hr() produced expected high-res result + * + * \param[in] format Time format string (const char *) + * \param[in] expected Succeed if result matches this (const char *) + * \param[in] usec Microseconds component of the reference time (\c int) + */ +#define assert_hr_format_usec(format, expected, usec) \ + do { \ + crm_time_t *dt = NULL; \ + char *result = NULL; \ + \ + dt = crm_time_new(DATE_TIME_S); \ + assert_non_null(dt); \ + \ + result = pcmk__time_format_hr(format, dt, usec); \ + assert_non_null(result); \ + assert_string_equal(result, expected); \ + \ + crm_time_free(dt); \ + free(result); \ + } while (0) static void null_format(void **state) { + crm_time_t *dt = NULL; + char *result = NULL; + + // NULL format and NULL crm_time_t assert_null(pcmk__time_format_hr(NULL, NULL, 0)); - // For pcmk__time_format_hr(NULL, dt, 0) - assert_hr_format(NULL, NULL, NULL, 0); + // NULL format and non-NULL crm_time_t + dt = crm_time_new(DATE_TIME_S); + assert_non_null(dt); + + result = pcmk__time_format_hr(NULL, dt, 0); + assert_null(result); + + free(dt); } static void no_specifiers(void **state) { - assert_hr_format("no specifiers", "no specifiers", NULL, 0); + assert_hr_format("no specifiers", "no specifiers"); /* @COMPAT The following four tests will fail when we remove the fallback * to strftime(). g_date_time_format() requires a literal '%' to be escaped * as "%%". */ - assert_hr_format("this has a literal % in it", - "this has a literal % in it", - // *BSD strftime() strips single % - "this has a literal in it", 0); - assert_hr_format("this has a literal %01 in it", - "this has a literal %01 in it", - // *BSD strftime() strips %0 - "this has a literal 1 in it", 0); - assert_hr_format("%2 this starts and ends with %", - "%2 this starts and ends with %", - // *BSD strftime() strips % in front of nonzero number - "2 this starts and ends with %", 0); + assert_hr_format_alt("this has a literal % in it", + "this has a literal % in it", + // *BSD strftime() strips single % + "this has a literal in it"); + assert_hr_format_alt("this has a literal %01 in it", + "this has a literal %01 in it", + // *BSD strftime() strips %0 + "this has a literal 1 in it"); + assert_hr_format_alt("%2 this starts and ends with %", + "%2 this starts and ends with %", + // *BSD strftime() strips % in front of nonzero number + "2 this starts and ends with %"); /* strftime() treats % with a number (and no specifier) as a literal string * to be formatted with a field width (undocumented and probably a bug ...) */ - assert_hr_format("this ends with %10", "this ends with %10", - // *BSD strftime() strips % in front of nonzero number - "this ends with 10", 0); + assert_hr_format_alt("this ends with %10", "this ends with %10", + // *BSD strftime() strips % in front of nonzero number + "this ends with 10"); } static void without_frac(void **state) { - assert_hr_format("%Y-%m-%d %H:%M:%S", DATE_S " " TIME_S, NULL, 0); + assert_hr_format("%Y-%m-%d %H:%M:%S", DATE_S " " TIME_S); - assert_hr_format("%H:%M %a %b %d", HOUR_S ":" MINUTE_S " Sun Jun 02", NULL, - 0); - assert_hr_format("%H:%M:%S", TIME_S, NULL, 0); + assert_hr_format("%H:%M %a %b %d", HOUR_S ":" MINUTE_S " Sun Jun 02"); + assert_hr_format("%H:%M:%S", TIME_S); assert_hr_format("The time is %H:%M right now", - "The time is " HOUR_S ":" MINUTE_S " right now", NULL, 0); + "The time is " HOUR_S ":" MINUTE_S " right now"); /* @COMPAT This test will fail when we remove the fallback to strftime(). * g_date_time_format() doesn't support field widths. + * + * BSD strftime() also doesn't support field widths, hence the alternate. */ - assert_hr_format("%3S seconds", "0" SECOND_S " seconds", - // *BSD strftime() doesn't support field widths - "3S seconds", 0); + assert_hr_format_alt("%3S seconds", "0" SECOND_S " seconds", "3S seconds"); // strftime() treats %% as a literal % - assert_hr_format("%%H %%N", "%H %N", NULL, 0); + assert_hr_format("%%H %%N", "%H %N"); } static void @@ -133,45 +178,44 @@ with_frac(void **state) int usec = 123456; // Display time with no fractional seconds component - assert_hr_format("%Y-%m-%d %H:%M:%S.%6N", DATE_S " " TIME_S ".000000", NULL, - 0); - assert_hr_format("%H:%M:%S.%6N", TIME_S ".000000", NULL, 0); - assert_hr_format("%H:%M:%S.%6N %H", TIME_S ".000000 " HOUR_S, NULL, 0); - assert_hr_format("%H:%M:%S.%3N", TIME_S ".000", NULL, 0); - assert_hr_format("%H:%M:%S.%0N", TIME_S ".", NULL, 0); - assert_hr_format("%H:%M:%S.%N", TIME_S ".", NULL, 0); + assert_hr_format("%Y-%m-%d %H:%M:%S.%6N", DATE_S " " TIME_S ".000000"); + assert_hr_format("%H:%M:%S.%6N", TIME_S ".000000"); + assert_hr_format("%H:%M:%S.%6N %H", TIME_S ".000000 " HOUR_S); + assert_hr_format("%H:%M:%S.%3N", TIME_S ".000"); + assert_hr_format("%H:%M:%S.%0N", TIME_S "."); + assert_hr_format("%H:%M:%S.%N", TIME_S "."); assert_hr_format("The time is %H:%M:%S.%06N right NOW", - "The time is " TIME_S ".000000 right NOW", NULL, 0); + "The time is " TIME_S ".000000 right NOW"); // Display at appropriate resolution by truncating toward zero - assert_hr_format("%Y-%m-%d %H:%M:%S.%6N", DATE_S " " TIME_S ".123456", NULL, - usec); - assert_hr_format("%H:%M:%S.%6N", TIME_S ".123456", NULL, usec); - assert_hr_format("%H:%M:%S.%6N %M", TIME_S ".123456 " MINUTE_S, NULL, usec); - assert_hr_format("%H:%M:%S.%5N", TIME_S ".12345", NULL, usec); - assert_hr_format("%H:%M:%S.%4N", TIME_S ".1234", NULL, usec); - assert_hr_format("%H:%M:%S.%3N", TIME_S ".123", NULL, usec); - assert_hr_format("%H:%M:%S.%2N", TIME_S ".12", NULL, usec); - assert_hr_format("%H:%M:%S.%1N", TIME_S ".1", NULL, usec); - assert_hr_format("%H:%M:%S.%0N", TIME_S ".", NULL, usec); - assert_hr_format("%H:%M:%S.%N", TIME_S ".", NULL, usec); + assert_hr_format_usec("%Y-%m-%d %H:%M:%S.%6N", DATE_S " " TIME_S ".123456", + usec); + assert_hr_format_usec("%H:%M:%S.%6N", TIME_S ".123456", usec); + assert_hr_format_usec("%H:%M:%S.%6N %M", TIME_S ".123456 " MINUTE_S, usec); + assert_hr_format_usec("%H:%M:%S.%5N", TIME_S ".12345", usec); + assert_hr_format_usec("%H:%M:%S.%4N", TIME_S ".1234", usec); + assert_hr_format_usec("%H:%M:%S.%3N", TIME_S ".123", usec); + assert_hr_format_usec("%H:%M:%S.%2N", TIME_S ".12", usec); + assert_hr_format_usec("%H:%M:%S.%1N", TIME_S ".1", usec); + assert_hr_format_usec("%H:%M:%S.%0N", TIME_S ".", usec); + assert_hr_format_usec("%H:%M:%S.%N", TIME_S ".", usec); // Leading zero is ignored, not treated as a request for zero-padding - assert_hr_format("%H:%M:%S.%03N", TIME_S ".123", NULL, usec); + assert_hr_format_usec("%H:%M:%S.%03N", TIME_S ".123", usec); // Same as above, but with zero-padding for smaller fractional components usec = 789; - assert_hr_format("%Y-%m-%d %H:%M:%S.%6N", DATE_S " " TIME_S ".000789", NULL, - usec); - assert_hr_format("%H:%M:%S.%6N", TIME_S ".000789", NULL, usec); - assert_hr_format("%H:%M:%S.%6N %S", TIME_S ".000789 " SECOND_S, NULL, usec); - assert_hr_format("%H:%M:%S.%5N", TIME_S ".00078", NULL, usec); - assert_hr_format("%H:%M:%S.%4N", TIME_S ".0007", NULL, usec); - assert_hr_format("%H:%M:%S.%3N", TIME_S ".000", NULL, usec); - assert_hr_format("%H:%M:%S.%2N", TIME_S ".00", NULL, usec); - assert_hr_format("%H:%M:%S.%1N", TIME_S ".0", NULL, usec); - assert_hr_format("%H:%M:%S.%0N", TIME_S ".", NULL, usec); - assert_hr_format("%H:%M:%S.%N", TIME_S ".", NULL, usec); + assert_hr_format_usec("%Y-%m-%d %H:%M:%S.%6N", DATE_S " " TIME_S ".000789", + usec); + assert_hr_format_usec("%H:%M:%S.%6N", TIME_S ".000789", usec); + assert_hr_format_usec("%H:%M:%S.%6N %S", TIME_S ".000789 " SECOND_S, usec); + assert_hr_format_usec("%H:%M:%S.%5N", TIME_S ".00078", usec); + assert_hr_format_usec("%H:%M:%S.%4N", TIME_S ".0007", usec); + assert_hr_format_usec("%H:%M:%S.%3N", TIME_S ".000", usec); + assert_hr_format_usec("%H:%M:%S.%2N", TIME_S ".00", usec); + assert_hr_format_usec("%H:%M:%S.%1N", TIME_S ".0", usec); + assert_hr_format_usec("%H:%M:%S.%0N", TIME_S ".", usec); + assert_hr_format_usec("%H:%M:%S.%N", TIME_S ".", usec); } PCMK__UNIT_TEST(NULL, NULL, diff --git a/lib/common/tests/nvpair/pcmk__scan_nvpair_test.c b/lib/common/tests/nvpair/pcmk__scan_nvpair_test.c index c8cf464369c..506383c2b03 100644 --- a/lib/common/tests/nvpair/pcmk__scan_nvpair_test.c +++ b/lib/common/tests/nvpair/pcmk__scan_nvpair_test.c @@ -13,31 +13,30 @@ #include -static void -assert_scan_nvpair(const gchar *input, int expected_rc, - const gchar *expected_name, const gchar *expected_value) -{ - gchar *name = NULL; - gchar *value = NULL; - - assert_int_equal(pcmk__scan_nvpair(input, &name, &value), - expected_rc); - - if (expected_name == NULL) { - assert_null(name); - } else { - assert_string_equal(name, expected_name); - } - - if (expected_value == NULL) { - assert_null(value); - } else { - assert_string_equal(value, expected_value); - } - - g_free(name); - g_free(value); -} +#define assert_scan_nvpair_success(input, expected_name, expected_value) \ + do { \ + gchar *name = NULL; \ + gchar *value = NULL; \ + int rc = pcmk__scan_nvpair(input, &name, &value); \ + \ + assert_int_equal(rc, pcmk_rc_ok); \ + assert_string_equal(name, expected_name); \ + assert_string_equal(value, expected_value); \ + \ + g_free(name); \ + g_free(value); \ + } while (0) + +#define assert_scan_nvpair_failure(input) \ + do { \ + gchar *name = NULL; \ + gchar *value = NULL; \ + int rc = pcmk__scan_nvpair(input, &name, &value); \ + \ + assert_int_equal(rc, pcmk_rc_bad_nvpair); \ + assert_null(name); \ + assert_null(value); \ + } while (0) static void null_asserts(void **state) @@ -67,60 +66,60 @@ already_allocated_asserts(void **state) static void empty_input(void **state) { - assert_scan_nvpair("", pcmk_rc_bad_nvpair, NULL, NULL); + assert_scan_nvpair_failure(""); } static void equal_sign_only(void **state) { - assert_scan_nvpair("=", pcmk_rc_bad_nvpair, NULL, NULL); + assert_scan_nvpair_failure("="); } static void name_only(void **state) { - assert_scan_nvpair("name", pcmk_rc_bad_nvpair, NULL, NULL); + assert_scan_nvpair_failure("name"); } static void value_only(void **state) { - assert_scan_nvpair("=value", pcmk_rc_bad_nvpair, NULL, NULL); + assert_scan_nvpair_failure("=value"); } static void valid(void **state) { - assert_scan_nvpair("name=value", pcmk_rc_ok, "name", "value"); + assert_scan_nvpair_success("name=value", "name", "value"); // Empty value - assert_scan_nvpair("name=", pcmk_rc_ok, "name", ""); + assert_scan_nvpair_success("name=", "name", ""); // Whitespace is kept (checking only space characters here) - assert_scan_nvpair(" name=value", pcmk_rc_ok, " name", "value"); - assert_scan_nvpair("name =value", pcmk_rc_ok, "name ", "value"); - assert_scan_nvpair("name= value", pcmk_rc_ok, "name", " value"); - assert_scan_nvpair("name=value ", pcmk_rc_ok, "name", "value "); - assert_scan_nvpair("name = value", pcmk_rc_ok, "name ", " value"); + assert_scan_nvpair_success(" name=value", " name", "value"); + assert_scan_nvpair_success("name =value", "name ", "value"); + assert_scan_nvpair_success("name= value", "name", " value"); + assert_scan_nvpair_success("name=value ", "name", "value "); + assert_scan_nvpair_success("name = value", "name ", " value"); // Trailing characters are kept - assert_scan_nvpair("name=value=", pcmk_rc_ok, "name", "value="); - assert_scan_nvpair("name=value=\n\n", pcmk_rc_ok, "name", "value=\n\n"); - assert_scan_nvpair("name=value=e", pcmk_rc_ok, "name", "value=e"); - assert_scan_nvpair("name=value=e\n\n", pcmk_rc_ok, "name", "value=e\n\n"); + assert_scan_nvpair_success("name=value=", "name", "value="); + assert_scan_nvpair_success("name=value=\n\n", "name", "value=\n\n"); + assert_scan_nvpair_success("name=value=e", "name", "value=e"); + assert_scan_nvpair_success("name=value=e\n\n", "name", "value=e\n\n"); // Quotes are not treated specially - assert_scan_nvpair("name=''", pcmk_rc_ok, "name", "''"); - assert_scan_nvpair("name='value'", pcmk_rc_ok, "name", "'value'"); - assert_scan_nvpair("'name'=value", pcmk_rc_ok, "'name'", "value"); - assert_scan_nvpair("'name=value'", pcmk_rc_ok, "'name", "value'"); - assert_scan_nvpair("name=\"value\"", pcmk_rc_ok, "name", "\"value\""); - assert_scan_nvpair("\"name\"=value", pcmk_rc_ok, "\"name\"", "value"); - assert_scan_nvpair("\"name=value\"", pcmk_rc_ok, "\"name", "value\""); + assert_scan_nvpair_success("name=''", "name", "''"); + assert_scan_nvpair_success("name='value'", "name", "'value'"); + assert_scan_nvpair_success("'name'=value", "'name'", "value"); + assert_scan_nvpair_success("'name=value'", "'name", "value'"); + assert_scan_nvpair_success("name=\"value\"", "name", "\"value\""); + assert_scan_nvpair_success("\"name\"=value", "\"name\"", "value"); + assert_scan_nvpair_success("\"name=value\"", "\"name", "value\""); // Other special characters are not treated specially (small sample) - assert_scan_nvpair("!@#$%=^&*()", pcmk_rc_ok, "!@#$%", "^&*()"); - assert_scan_nvpair("name=$value", pcmk_rc_ok, "name", "$value"); + assert_scan_nvpair_success("!@#$%=^&*()", "!@#$%", "^&*()"); + assert_scan_nvpair_success("name=$value", "name", "$value"); } PCMK__UNIT_TEST(NULL, NULL, diff --git a/lib/common/tests/output/pcmk__output_free_test.c b/lib/common/tests/output/pcmk__output_free_test.c index e8555cc7126..669bab8e62a 100644 --- a/lib/common/tests/output/pcmk__output_free_test.c +++ b/lib/common/tests/output/pcmk__output_free_test.c @@ -13,6 +13,8 @@ #include +#include "../../crmcommon_private.h" // pcmk__register_message + static int setup(void **state) { diff --git a/lib/common/tests/output/pcmk__register_format_test.c b/lib/common/tests/output/pcmk__register_format_test.c index 29a1ba3d173..12768dc805d 100644 --- a/lib/common/tests/output/pcmk__register_format_test.c +++ b/lib/common/tests/output/pcmk__register_format_test.c @@ -16,10 +16,10 @@ invalid_params(void **state) { pcmk__assert_asserts(pcmk__register_format(NULL, "fake", NULL, NULL)); pcmk__assert_asserts(pcmk__register_format(NULL, "", - pcmk__output_null_create1, + pcmk__output_setup_dummy1, NULL)); pcmk__assert_asserts(pcmk__register_format(NULL, NULL, - pcmk__output_null_create1, + pcmk__output_setup_dummy1, NULL)); } @@ -36,26 +36,26 @@ add_format(void **state) /* Add a fake formatter and check that it's the only item in the hash * table */ - rc = pcmk__register_format(NULL, "fake", pcmk__output_null_create1, NULL); + rc = pcmk__register_format(NULL, "fake", pcmk__output_setup_dummy1, NULL); assert_int_equal(rc, pcmk_rc_ok); formatters = pcmk__output_formatters(); assert_int_equal(g_hash_table_size(formatters), 1); value = g_hash_table_lookup(formatters, "fake"); - assert_ptr_equal(value, pcmk__output_null_create1); + assert_ptr_equal(value, pcmk__output_setup_dummy1); /* Add a second fake formatter that should overwrite the first one, leaving * only one item (with the new function) in the hash table */ - rc = pcmk__register_format(NULL, "fake", pcmk__output_null_create2, NULL); + rc = pcmk__register_format(NULL, "fake", pcmk__output_setup_dummy2, NULL); assert_int_equal(rc, pcmk_rc_ok); formatters = pcmk__output_formatters(); assert_int_equal(g_hash_table_size(formatters), 1); value = g_hash_table_lookup(formatters, "fake"); - assert_ptr_equal(value, pcmk__output_null_create2); + assert_ptr_equal(value, pcmk__output_setup_dummy2); pcmk__unregister_formats(); } diff --git a/lib/common/tests/output/pcmk__register_formats_test.c b/lib/common/tests/output/pcmk__register_formats_test.c index 7743bc12ddf..e5133e6c9ff 100644 --- a/lib/common/tests/output/pcmk__register_formats_test.c +++ b/lib/common/tests/output/pcmk__register_formats_test.c @@ -25,7 +25,7 @@ invalid_entries(void **state) * the marker for the end of the format table. */ pcmk__supported_format_t formats[] = { - { "", pcmk__output_null_create1, NULL }, + { "", pcmk__output_setup_dummy1, NULL }, { NULL }, }; @@ -38,8 +38,8 @@ valid_entries(void **state) GHashTable *formatters = NULL; pcmk__supported_format_t formats[] = { - { "fmt1", pcmk__output_null_create1, NULL }, - { "fmt2", pcmk__output_null_create2, NULL }, + { "fmt1", pcmk__output_setup_dummy1, NULL }, + { "fmt2", pcmk__output_setup_dummy2, NULL }, { NULL }, }; @@ -48,9 +48,9 @@ valid_entries(void **state) formatters = pcmk__output_formatters(); assert_int_equal(g_hash_table_size(formatters), 2); assert_ptr_equal(g_hash_table_lookup(formatters, "fmt1"), - pcmk__output_null_create1); + pcmk__output_setup_dummy1); assert_ptr_equal(g_hash_table_lookup(formatters, "fmt2"), - pcmk__output_null_create2); + pcmk__output_setup_dummy2); pcmk__unregister_formats(); } @@ -61,8 +61,8 @@ duplicate_keys(void **state) GHashTable *formatters = NULL; pcmk__supported_format_t formats[] = { - { "fmt1", pcmk__output_null_create1, NULL }, - { "fmt1", pcmk__output_null_create2, NULL }, + { "fmt1", pcmk__output_setup_dummy1, NULL }, + { "fmt1", pcmk__output_setup_dummy2, NULL }, { NULL }, }; @@ -71,7 +71,7 @@ duplicate_keys(void **state) formatters = pcmk__output_formatters(); assert_int_equal(g_hash_table_size(formatters), 1); assert_ptr_equal(g_hash_table_lookup(formatters, "fmt1"), - pcmk__output_null_create2); + pcmk__output_setup_dummy2); pcmk__unregister_formats(); } @@ -82,8 +82,8 @@ duplicate_values(void **state) GHashTable *formatters = NULL; pcmk__supported_format_t formats[] = { - { "fmt1", pcmk__output_null_create1, NULL }, - { "fmt2", pcmk__output_null_create1, NULL }, + { "fmt1", pcmk__output_setup_dummy1, NULL }, + { "fmt2", pcmk__output_setup_dummy1, NULL }, { NULL }, }; @@ -92,9 +92,9 @@ duplicate_values(void **state) formatters = pcmk__output_formatters(); assert_int_equal(g_hash_table_size(formatters), 2); assert_ptr_equal(g_hash_table_lookup(formatters, "fmt1"), - pcmk__output_null_create1); + pcmk__output_setup_dummy1); assert_ptr_equal(g_hash_table_lookup(formatters, "fmt2"), - pcmk__output_null_create1); + pcmk__output_setup_dummy1); pcmk__unregister_formats(); } diff --git a/lib/common/tests/output/pcmk__register_message_test.c b/lib/common/tests/output/pcmk__register_message_test.c index 381063ec6ab..ca0acb49789 100644 --- a/lib/common/tests/output/pcmk__register_message_test.c +++ b/lib/common/tests/output/pcmk__register_message_test.c @@ -13,7 +13,7 @@ #include -#include "../../crmcommon_private.h" +#include "../../crmcommon_private.h" // pcmk__register_message static void null_params(void **state) diff --git a/lib/common/tests/output/pcmk__unregister_formats_test.c b/lib/common/tests/output/pcmk__unregister_formats_test.c index 6c979cb1d40..91899f05f84 100644 --- a/lib/common/tests/output/pcmk__unregister_formats_test.c +++ b/lib/common/tests/output/pcmk__unregister_formats_test.c @@ -24,7 +24,7 @@ invalid_params(void **state) static void non_null_formatters(void **state) { - pcmk__register_format(NULL, "fake", pcmk__output_null_create1, NULL); + pcmk__register_format(NULL, "fake", pcmk__output_setup_dummy1, NULL); pcmk__unregister_formats(); assert_null(pcmk__output_formatters()); diff --git a/lib/common/tests/patchset/pcmk__cib_element_in_patchset_test.c b/lib/common/tests/patchset/pcmk__cib_element_in_patchset_test.c index 56cca4e99e1..930611c6311 100644 --- a/lib/common/tests/patchset/pcmk__cib_element_in_patchset_test.c +++ b/lib/common/tests/patchset/pcmk__cib_element_in_patchset_test.c @@ -30,9 +30,8 @@ "<" PCMK_XE_STATUS "/>" \ "" -static void -assert_in_patchset(const char *source_s, const char *target_s, - const char *element, bool reference) +static xmlNode * +create_patchset(const char *source_s, const char *target_s) { xmlNode *source = pcmk__xml_parse(source_s); xmlNode *target = pcmk__xml_parse(target_s); @@ -42,17 +41,27 @@ assert_in_patchset(const char *source_s, const char *target_s, pcmk__xml_mark_changes(source, target); patchset = xml_create_patchset(2, source, target, NULL, false); - if (reference) { - assert_true(pcmk__cib_element_in_patchset(patchset, element)); - } else { - assert_false(pcmk__cib_element_in_patchset(patchset, element)); - } - pcmk__xml_free(source); pcmk__xml_free(target); - pcmk__xml_free(patchset); + return patchset; } +#define assert_in_patchset(source_s, target_s, element) \ + do { \ + xmlNode *patchset = create_patchset(source_s, target_s); \ + \ + assert_true(pcmk__cib_element_in_patchset(patchset, element)); \ + pcmk__xml_free(patchset); \ + } while (0) + +#define assert_not_in_patchset(source_s, target_s, element) \ + do { \ + xmlNode *patchset = create_patchset(source_s, target_s); \ + \ + assert_false(pcmk__cib_element_in_patchset(patchset, element)); \ + pcmk__xml_free(patchset); \ + } while (0) + static void null_patchset_asserts(void **state) { @@ -82,28 +91,28 @@ static void create_op(void **state) { // Requested element was created - assert_in_patchset(ORIG_CIB, CREATE_CIB, PCMK_XE_ALERTS, true); + assert_in_patchset(ORIG_CIB, CREATE_CIB, PCMK_XE_ALERTS); // Requested element's descendant was created - assert_in_patchset(ORIG_CIB, CREATE_CIB, PCMK_XE_CONFIGURATION, true); - assert_in_patchset(ORIG_CIB, CREATE_CIB, NULL, true); + assert_in_patchset(ORIG_CIB, CREATE_CIB, PCMK_XE_CONFIGURATION); + assert_in_patchset(ORIG_CIB, CREATE_CIB, NULL); // Requested element was not changed - assert_in_patchset(ORIG_CIB, CREATE_CIB, PCMK_XE_STATUS, false); + assert_not_in_patchset(ORIG_CIB, CREATE_CIB, PCMK_XE_STATUS); } static void delete_op(void **state) { // Requested element was deleted - assert_in_patchset(CREATE_CIB, ORIG_CIB, PCMK_XE_ALERTS, true); + assert_in_patchset(CREATE_CIB, ORIG_CIB, PCMK_XE_ALERTS); // Requested element's descendant was deleted - assert_in_patchset(CREATE_CIB, ORIG_CIB, PCMK_XE_CONFIGURATION, true); - assert_in_patchset(CREATE_CIB, ORIG_CIB, NULL, true); + assert_in_patchset(CREATE_CIB, ORIG_CIB, PCMK_XE_CONFIGURATION); + assert_in_patchset(CREATE_CIB, ORIG_CIB, NULL); // Requested element was not changed - assert_in_patchset(CREATE_CIB, ORIG_CIB, PCMK_XE_STATUS, false); + assert_not_in_patchset(CREATE_CIB, ORIG_CIB, PCMK_XE_STATUS); } // PCMK_XE_CIB XML attribute was added relative to ORIG_CIB @@ -180,31 +189,31 @@ static void modify_op(void **state) { // Requested element was modified (attribute added) - assert_in_patchset(ORIG_CIB, MODIFY_ADD_CIB, PCMK_XE_CIB, true); + assert_in_patchset(ORIG_CIB, MODIFY_ADD_CIB, PCMK_XE_CIB); // Requested element was modified (attribute updated) - assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_CIB, PCMK_XE_CIB, true); + assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_CIB, PCMK_XE_CIB); // Requested element was modified (attribute deleted) - assert_in_patchset(MODIFY_ADD_CIB, ORIG_CIB, PCMK_XE_CIB, true); + assert_in_patchset(MODIFY_ADD_CIB, ORIG_CIB, PCMK_XE_CIB); // Requested element's descendant was modified (attribute added) - assert_in_patchset(ORIG_CIB, MODIFY_ADD_NODE_CIB, PCMK_XE_CIB, true); - assert_in_patchset(ORIG_CIB, MODIFY_ADD_NODE_CIB, NULL, true); + assert_in_patchset(ORIG_CIB, MODIFY_ADD_NODE_CIB, PCMK_XE_CIB); + assert_in_patchset(ORIG_CIB, MODIFY_ADD_NODE_CIB, NULL); // Requested element's descendant was modified (attribute updated) - assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_NODE_CIB, PCMK_XE_CIB, true); - assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_NODE_CIB, NULL, true); + assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_NODE_CIB, PCMK_XE_CIB); + assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_NODE_CIB, NULL); // Requested element's descenant was modified (attribute deleted) - assert_in_patchset(MODIFY_ADD_NODE_CIB, ORIG_CIB, PCMK_XE_CIB, true); - assert_in_patchset(MODIFY_ADD_NODE_CIB, ORIG_CIB, NULL, true); + assert_in_patchset(MODIFY_ADD_NODE_CIB, ORIG_CIB, PCMK_XE_CIB); + assert_in_patchset(MODIFY_ADD_NODE_CIB, ORIG_CIB, NULL); // Requested element was not changed - assert_in_patchset(ORIG_CIB, MODIFY_ADD_CIB, PCMK_XE_STATUS, false); - assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_CIB, PCMK_XE_STATUS, false); - assert_in_patchset(ORIG_CIB, MODIFY_ADD_NODE_CIB, PCMK_XE_STATUS, false); - assert_in_patchset(ORIG_CIB, MODIFY_UPDATE_NODE_CIB, PCMK_XE_STATUS, false); + assert_not_in_patchset(ORIG_CIB, MODIFY_ADD_CIB, PCMK_XE_STATUS); + assert_not_in_patchset(ORIG_CIB, MODIFY_UPDATE_CIB, PCMK_XE_STATUS); + assert_not_in_patchset(ORIG_CIB, MODIFY_ADD_NODE_CIB, PCMK_XE_STATUS); + assert_not_in_patchset(ORIG_CIB, MODIFY_UPDATE_NODE_CIB, PCMK_XE_STATUS); } // PCMK_XE_RESOURCES and PCMK_XE_CONSTRAINTS are swapped relative to ORIG_CIB @@ -225,15 +234,15 @@ static void move_op(void **state) { // Requested element was moved - assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_RESOURCES, true); - assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_CONSTRAINTS, true); + assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_RESOURCES); + assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_CONSTRAINTS); // Requested element's descendant was moved - assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_CONFIGURATION, true); - assert_in_patchset(ORIG_CIB, MOVE_CIB, NULL, true); + assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_CONFIGURATION); + assert_in_patchset(ORIG_CIB, MOVE_CIB, NULL); // Requested element was not changed - assert_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_STATUS, false); + assert_not_in_patchset(ORIG_CIB, MOVE_CIB, PCMK_XE_STATUS); } PCMK__UNIT_TEST(pcmk__xml_test_setup_group, pcmk__xml_test_teardown_group, diff --git a/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c b/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c index 4cd1bd7e871..1dbfe102811 100644 --- a/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c +++ b/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c @@ -19,43 +19,48 @@ #include #include -static void -assert_pid2path_one(int errno_to_set, const char *link_contents, char **dest, - int reference_rc) -{ - pcmk__mock_readlink = true; - - expect_string(__wrap_readlink, path, "/proc/1000/exe"); - expect_uint_value(__wrap_readlink, bufsize, PATH_MAX); - will_return(__wrap_readlink, errno_to_set); - will_return(__wrap_readlink, link_contents); - - assert_int_equal(pcmk__procfs_pid2path(1000, dest), reference_rc); - - pcmk__mock_readlink = false; -} - -static void -assert_pid2path(int errno_to_set, const char *link_contents, int reference_rc, - const char *reference_result) -{ - char *dest = NULL; - - assert_pid2path_one(errno_to_set, link_contents, NULL, reference_rc); - assert_pid2path_one(errno_to_set, link_contents, &dest, reference_rc); - - if (reference_result == NULL) { - assert_null(dest); - } else { - assert_string_equal(dest, reference_result); - free(dest); - } -} +#define assert_pid2path_one(errno_to_set, link_contents, dest, expected_rc) \ + do { \ + pcmk__mock_readlink = true; \ + \ + expect_string(__wrap_readlink, path, "/proc/1000/exe"); \ + expect_uint_value(__wrap_readlink, bufsize, PATH_MAX); \ + will_return(__wrap_readlink, errno_to_set); \ + will_return(__wrap_readlink, link_contents); \ + \ + assert_int_equal(pcmk__procfs_pid2path(1000, dest), expected_rc); \ + \ + pcmk__mock_readlink = false; \ + } while (0) + +#define assert_pid2path_null(errno_to_set, link_contents, expected_rc) \ + do { \ + char *dest = NULL; \ + \ + assert_pid2path_one(errno_to_set, link_contents, NULL, \ + expected_rc); \ + assert_pid2path_one(errno_to_set, link_contents, &dest, \ + expected_rc); \ + assert_null(dest); \ + } while (0) + +#define assert_pid2path_equals(errno_to_set, link_contents, expected_rc, \ + expected_result) \ + do { \ + char *dest = NULL; \ + \ + assert_pid2path_one(errno_to_set, link_contents, NULL, \ + expected_rc); \ + assert_pid2path_one(errno_to_set, link_contents, &dest, \ + expected_rc); \ + assert_string_equal(dest, expected_result); \ + free(dest); \ + } while (0) static void no_exe_file(void **state) { - assert_pid2path(ENOENT, NULL, ENOENT, NULL); + assert_pid2path_null(ENOENT, NULL, ENOENT); } static void @@ -64,7 +69,7 @@ contents_too_long(void **state) // String length equals PATH_MAX char *long_path = pcmk__assert_asprintf("%0*d", PATH_MAX, 0); - assert_pid2path(0, long_path, ENAMETOOLONG, NULL); + assert_pid2path_null(0, long_path, ENAMETOOLONG); free(long_path); } @@ -73,13 +78,13 @@ contents_ok(void **state) { char *real_path = pcmk__str_copy("/ok"); - assert_pid2path(0, real_path, pcmk_rc_ok, real_path); + assert_pid2path_equals(0, real_path, pcmk_rc_ok, real_path); free(real_path); // String length equals PATH_MAX - 1 real_path = pcmk__assert_asprintf("%0*d", PATH_MAX - 1, 0); - assert_pid2path(0, real_path, pcmk_rc_ok, real_path); + assert_pid2path_equals(0, real_path, pcmk_rc_ok, real_path); free(real_path); } diff --git a/lib/common/tests/rules/pcmk__evaluate_attr_expression_test.c b/lib/common/tests/rules/pcmk__evaluate_attr_expression_test.c index b229893aa59..747ef9995dd 100644 --- a/lib/common/tests/rules/pcmk__evaluate_attr_expression_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_attr_expression_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -79,18 +79,18 @@ teardown(void **state) * \internal * \brief Run one test, comparing return value * - * \param[in] xml_string Node attribute expression XML as string - * \param[in] reference_rc Assert that evaluation result equals this + * \param[in] xml_string Node attribute expression XML as string + * (const char *) + * \param[in] expected_rc Assert that evaluation result equals this (\c int) */ -static void -assert_attr_expression(const char *xml_string, int reference_rc) -{ - xmlNode *xml = pcmk__xml_parse(xml_string); - - assert_int_equal(pcmk__evaluate_attr_expression(xml, &rule_input), - reference_rc); - pcmk__xml_free(xml); -} +#define assert_attr_expression(xml_string, expected_rc) \ + do { \ + xmlNode *xml = pcmk__xml_parse(xml_string); \ + \ + assert_int_equal(pcmk__evaluate_attr_expression(xml, &rule_input), \ + expected_rc); \ + pcmk__xml_free(xml); \ + } while (0) /* diff --git a/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c b/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c index cfb6bdbf7f5..39b0cdaebd0 100644 --- a/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c @@ -19,44 +19,50 @@ /*! * \internal - * \brief Run one test, comparing return value and output argument + * \brief Run one test, checking return value * - * \param[in] xml Date expression XML - * \param[in] now_s Time to evaluate expression with (as string) - * \param[in] next_change_s If this and \p reference_s are not NULL, initialize - * next change time with this time (as string), - * and assert that its value after evaluation is the - * reference - * \param[in] reference_s If not NULL, time (as string) that next change - * should be after expression evaluation - * \param[in] reference_rc Assert that evaluation result equals this + * \param[in] xml Date expression XML (const xmlNode *) + * \param[in] now_s Time to evaluate expression with + * (const char *) + * \param[in] expected_rc Assert that evaluation result equals this (\c int) */ -static void -assert_date_expression(const xmlNode *xml, const char *now_s, - const char *next_change_s, const char *reference_s, - int reference_rc) -{ - crm_time_t *now = NULL; - crm_time_t *next_change = NULL; - bool check_next_change = (next_change_s != NULL) && (reference_s != NULL); - - if (check_next_change) { - next_change = crm_time_new(next_change_s); - } - - now = crm_time_new(now_s); - assert_int_equal(pcmk__evaluate_date_expression(xml, now, next_change), - reference_rc); - crm_time_free(now); - - if (check_next_change) { - crm_time_t *reference = crm_time_new(reference_s); - - assert_int_equal(crm_time_compare(next_change, reference), 0); - crm_time_free(reference); - crm_time_free(next_change); - } -} +#define assert_date_expr(xml, now_s, expected_rc) \ + do { \ + crm_time_t *now = crm_time_new(now_s); \ + int rc = pcmk__evaluate_date_expression(xml, now, NULL); \ + \ + assert_int_equal(rc, expected_rc); \ + crm_time_free(now); \ + } while (0) + +/*! + * \internal + * \brief Run one test, checking return value and output argument + * + * \param[in] xml Date expression XML (const xmlNode *) + * \param[in] now_s Time to evaluate expression with + * (const char *) + * \param[in] next_change_s Initialize next change time with this time + * (const char *) + * \param[in] expected_s Time that next change should be after expression + * evaluation (const char *) + * \param[in] expected_rc Assert that evaluation result equals this (\c int) + */ +#define assert_date_expr_change(xml, now_s, next_change_s, expected_s, \ + expected_rc) \ + do { \ + crm_time_t *now = crm_time_new(now_s); \ + crm_time_t *next_change = crm_time_new(next_change_s); \ + crm_time_t *expected = crm_time_new(expected_s); \ + int rc = pcmk__evaluate_date_expression(xml, now, next_change); \ + \ + assert_int_equal(rc, expected_rc); \ + assert_int_equal(crm_time_compare(next_change, expected), 0); \ + \ + crm_time_free(now); \ + crm_time_free(next_change); \ + crm_time_free(expected); \ + } while (0) #define EXPR_LT_VALID \ "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \ @@ -82,7 +88,7 @@ null_next_change_ok(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_VALID); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_within_range); + assert_date_expr(xml, "2024-01-01", pcmk_rc_within_range); pcmk__xml_free(xml); } @@ -96,7 +102,7 @@ id_missing(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_ID_MISSING); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -109,7 +115,7 @@ op_invalid(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_OP_INVALID); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -122,7 +128,7 @@ lt_missing_end(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_MISSING_END); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -136,7 +142,7 @@ lt_invalid_end(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_INVALID_END); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -146,20 +152,20 @@ lt_valid(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_VALID); // Now and next change are both before end - assert_date_expression(xml, "2023-01-01 05:00:00", "2024-02-01 10:00:00", - "2024-02-01 10:00:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2023-01-01 05:00:00", "2024-02-01 10:00:00", + "2024-02-01 10:00:00", pcmk_rc_within_range); // Now is before end, next change is after end - assert_date_expression(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00", - "2024-02-01 15:00:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00", + "2024-02-01 15:00:00", pcmk_rc_within_range); // Now is equal to end, next change is after end - assert_date_expression(xml, "2024-02-01 15:00:00", "2024-02-01 20:00:00", - "2024-02-01 20:00:00", pcmk_rc_after_range); + assert_date_expr_change(xml, "2024-02-01 15:00:00", "2024-02-01 20:00:00", + "2024-02-01 20:00:00", pcmk_rc_after_range); // Now and next change are both after end - assert_date_expression(xml, "2024-03-01 12:00:00", "2024-02-01 20:00:00", - "2024-02-01 20:00:00", pcmk_rc_after_range); + assert_date_expr_change(xml, "2024-03-01 12:00:00", "2024-02-01 20:00:00", + "2024-02-01 20:00:00", pcmk_rc_after_range); pcmk__xml_free(xml); } @@ -173,7 +179,7 @@ gt_missing_start(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_GT_MISSING_START); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -187,7 +193,7 @@ gt_invalid_start(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_GT_INVALID_START); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -202,24 +208,24 @@ gt_valid(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_GT_VALID); // Now and next change are both before start - assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", - "2024-01-01 11:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", + "2024-01-01 11:00:00", pcmk_rc_before_range); // Now is before start, next change is after start - assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00", - "2024-02-01 12:00:01", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00", + "2024-02-01 12:00:01", pcmk_rc_before_range); // Now is equal to start, next change is after start - assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00", - "2024-02-01 12:00:01", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00", + "2024-02-01 12:00:01", pcmk_rc_before_range); // Now is one second after start, next change is after start - assert_date_expression(xml, "2024-02-01 12:00:01", "2024-02-01 18:00:00", - "2024-02-01 18:00:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 12:00:01", "2024-02-01 18:00:00", + "2024-02-01 18:00:00", pcmk_rc_within_range); // t is after start, next change is after start - assert_date_expression(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04", - "2024-04-04 04:04:04", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04", + "2024-04-04 04:04:04", pcmk_rc_within_range); pcmk__xml_free(xml); } @@ -252,7 +258,7 @@ range_invalid_start_invalid_end(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_INVALID_START_INVALID_END); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -266,7 +272,7 @@ range_invalid_start_only(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_INVALID_START_ONLY); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -281,20 +287,20 @@ range_valid_start_only(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_START_ONLY); // Now and next change are before start - assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", - "2024-01-01 11:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", + "2024-01-01 11:00:00", pcmk_rc_before_range); // Now is before start, next change is after start - assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00", - "2024-02-01 12:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00", + "2024-02-01 12:00:00", pcmk_rc_before_range); // Now is equal to start, next change is after start - assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00", - "2024-02-01 18:00:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00", + "2024-02-01 18:00:00", pcmk_rc_within_range); // Now and next change are after start - assert_date_expression(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04", - "2024-04-04 04:04:04", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04", + "2024-04-04 04:04:04", pcmk_rc_within_range); pcmk__xml_free(xml); } @@ -309,7 +315,7 @@ range_invalid_end_only(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_INVALID_END_ONLY); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -324,20 +330,20 @@ range_valid_end_only(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_END_ONLY); // Now and next change are before end - assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", - "2024-01-01 11:00:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", + "2024-01-01 11:00:00", pcmk_rc_within_range); // Now is before end, next change is after end - assert_date_expression(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00", - "2024-02-01 15:00:01", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00", + "2024-02-01 15:00:01", pcmk_rc_within_range); // Now is equal to end, next change is after end - assert_date_expression(xml, "2024-02-01 15:00:00", "2024-02-01 18:00:00", - "2024-02-01 15:00:01", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 15:00:00", "2024-02-01 18:00:00", + "2024-02-01 15:00:01", pcmk_rc_within_range); // Now and next change are after end - assert_date_expression(xml, "2024-02-01 15:00:01", "2024-04-04 04:04:04", - "2024-04-04 04:04:04", pcmk_rc_after_range); + assert_date_expr_change(xml, "2024-02-01 15:00:01", "2024-04-04 04:04:04", + "2024-04-04 04:04:04", pcmk_rc_after_range); pcmk__xml_free(xml); } @@ -353,8 +359,7 @@ range_valid_start_invalid_end(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_START_INVALID_END); - assert_date_expression(xml, "2024-01-01 04:30:05", NULL, NULL, - pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01 04:30:05", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -369,8 +374,7 @@ range_invalid_start_valid_end(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_INVALID_START_VALID_END); - assert_date_expression(xml, "2024-01-01 04:30:05", NULL, NULL, - pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01 04:30:05", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -386,28 +390,28 @@ range_valid_start_valid_end(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_START_VALID_END); // Now and next change are before start - assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", - "2024-01-01 11:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", + "2024-01-01 11:00:00", pcmk_rc_before_range); // Now is before start, next change is between start and end - assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00", - "2024-02-01 12:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00", + "2024-02-01 12:00:00", pcmk_rc_before_range); // Now is equal to start, next change is between start and end - assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00", - "2024-02-01 14:30:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00", + "2024-02-01 14:30:00", pcmk_rc_within_range); // Now is between start and end, next change is after end - assert_date_expression(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04", - "2024-02-01 15:00:01", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04", + "2024-02-01 15:00:01", pcmk_rc_within_range); // Now is equal to end, next change is after end - assert_date_expression(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04", - "2024-02-01 15:00:01", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04", + "2024-02-01 15:00:01", pcmk_rc_within_range); // Now and next change are after end - assert_date_expression(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04", - "2028-04-04 04:04:04", pcmk_rc_after_range); + assert_date_expr_change(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04", + "2028-04-04 04:04:04", pcmk_rc_after_range); pcmk__xml_free(xml); } @@ -425,8 +429,7 @@ range_valid_start_invalid_duration(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_START_INVALID_DURATION); - assert_date_expression(xml, "2024-02-01 04:30:05", NULL, NULL, - pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-02-01 04:30:05", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -444,28 +447,28 @@ range_valid_start_valid_duration(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_START_VALID_DURATION); // Now and next change are before start - assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", - "2024-01-01 11:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00", + "2024-01-01 11:00:00", pcmk_rc_before_range); // Now is before start, next change is between start and end - assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00", - "2024-02-01 12:00:00", pcmk_rc_before_range); + assert_date_expr_change(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00", + "2024-02-01 12:00:00", pcmk_rc_before_range); // Now is equal to start, next change is between start and end - assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00", - "2024-02-01 14:30:00", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00", + "2024-02-01 14:30:00", pcmk_rc_within_range); // Now is between start and end, next change is after end - assert_date_expression(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04", - "2024-02-01 15:00:01", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04", + "2024-02-01 15:00:01", pcmk_rc_within_range); // Now is equal to end, next change is after end - assert_date_expression(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04", - "2024-02-01 15:00:01", pcmk_rc_within_range); + assert_date_expr_change(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04", + "2024-02-01 15:00:01", pcmk_rc_within_range); // Now and next change are after end - assert_date_expression(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04", - "2028-04-04 04:04:04", pcmk_rc_after_range); + assert_date_expr_change(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04", + "2028-04-04 04:04:04", pcmk_rc_after_range); pcmk__xml_free(xml); } @@ -484,8 +487,7 @@ range_valid_start_duration_missing_id(void **state) xml = pcmk__xml_parse(EXPR_RANGE_VALID_START_DURATION_MISSING_ID); - assert_date_expression(xml, "2024-02-01 04:30:05", NULL, NULL, - pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-02-01 04:30:05", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -498,7 +500,7 @@ spec_missing(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_MISSING); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -514,7 +516,7 @@ spec_invalid(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_INVALID); - assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01", pcmk_rc_unpack_error); pcmk__xml_free(xml); } @@ -532,21 +534,19 @@ spec_valid(void **state) xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_VALID); // Now is just before spec start - assert_date_expression(xml, "2024-01-01 23:59:59", NULL, NULL, - pcmk_rc_before_range); + assert_date_expr(xml, "2024-01-01 23:59:59", pcmk_rc_before_range); // Now matches spec start - assert_date_expression(xml, "2024-02-01 00:00:00", NULL, NULL, pcmk_rc_ok); + assert_date_expr(xml, "2024-02-01 00:00:00", pcmk_rc_ok); // Now is within spec range - assert_date_expression(xml, "2024-02-22 22:22:22", NULL, NULL, pcmk_rc_ok); + assert_date_expr(xml, "2024-02-22 22:22:22", pcmk_rc_ok); // Now matches spec end - assert_date_expression(xml, "2024-02-29 23:59:59", NULL, NULL, pcmk_rc_ok); + assert_date_expr(xml, "2024-02-29 23:59:59", pcmk_rc_ok); // Now is just past spec end - assert_date_expression(xml, "2024-03-01 00:00:00", NULL, NULL, - pcmk_rc_after_range); + assert_date_expr(xml, "2024-03-01 00:00:00", pcmk_rc_after_range); pcmk__xml_free(xml); } @@ -563,8 +563,7 @@ spec_missing_id(void **state) { xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_MISSING_ID); - assert_date_expression(xml, "2024-01-01 23:59:59", NULL, NULL, - pcmk_rc_unpack_error); + assert_date_expr(xml, "2024-01-01 23:59:59", pcmk_rc_unpack_error); pcmk__xml_free(xml); } diff --git a/lib/common/tests/rules/pcmk__evaluate_op_expression_test.c b/lib/common/tests/rules/pcmk__evaluate_op_expression_test.c index e04497f22f2..2a2047a7ac0 100644 --- a/lib/common/tests/rules/pcmk__evaluate_op_expression_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_op_expression_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -28,20 +28,19 @@ static pcmk_rule_input_t rule_input = { /*! * \internal - * \brief Run one test, comparing return value + * \brief Run one test, checking return value * - * \param[in] xml_string Operation expression XML as string - * \param[in] reference_rc Assert that evaluation result equals this + * \param[in] xml_string Operation expression XML (const char *) + * \param[in] expected_rc Assert that evaluation result equals this (\c int) */ -static void -assert_op_expression(const char *xml_string, int reference_rc) -{ - xmlNode *xml = pcmk__xml_parse(xml_string); - - assert_int_equal(pcmk__evaluate_op_expression(xml, &rule_input), - reference_rc); - pcmk__xml_free(xml); -} +#define assert_op_expression(xml_string, expected_rc) \ + do { \ + xmlNode *xml = pcmk__xml_parse(xml_string); \ + \ + assert_int_equal(pcmk__evaluate_op_expression(xml, &rule_input), \ + expected_rc); \ + pcmk__xml_free(xml); \ + } while (0) /* diff --git a/lib/common/tests/rules/pcmk__evaluate_rsc_expression_test.c b/lib/common/tests/rules/pcmk__evaluate_rsc_expression_test.c index e1d24853e5c..fb953ca6cc5 100644 --- a/lib/common/tests/rules/pcmk__evaluate_rsc_expression_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_rsc_expression_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -29,20 +29,19 @@ static pcmk_rule_input_t rule_input = { /*! * \internal - * \brief Run one test, comparing return value + * \brief Run one test, checking return value * - * \param[in] xml_string Resource expression XML as string - * \param[in] reference_rc Assert that evaluation result equals this + * \param[in] xml_string Resource expression XML (const char *) + * \param[in] expected_rc Assert that evaluation result equals this (\c int) */ -static void -assert_rsc_expression(const char *xml_string, int reference_rc) -{ - xmlNode *xml = pcmk__xml_parse(xml_string); - - assert_int_equal(pcmk__evaluate_rsc_expression(xml, &rule_input), - reference_rc); - pcmk__xml_free(xml); -} +#define assert_rsc_expression(xml_string, expected_rc) \ + do { \ + xmlNode *xml = pcmk__xml_parse(xml_string); \ + \ + assert_int_equal(pcmk__evaluate_rsc_expression(xml, &rule_input), \ + expected_rc); \ + pcmk__xml_free(xml); \ + } while (0) /* diff --git a/lib/common/tests/rules/pcmk__replace_submatches_test.c b/lib/common/tests/rules/pcmk__replace_submatches_test.c index 5f3b2fd837f..ee34815397c 100644 --- a/lib/common/tests/rules/pcmk__replace_submatches_test.c +++ b/lib/common/tests/rules/pcmk__replace_submatches_test.c @@ -22,27 +22,21 @@ static const regmatch_t submatches[] = { }; static const int nmatches = 3; -static void -assert_submatch(const char *string, const char *reference) -{ - char *expanded = NULL; - - expanded = pcmk__replace_submatches(string, match, submatches, nmatches); - if ((expanded == NULL) || (reference == NULL)) { - assert_null(expanded); - assert_null(reference); - } else { - assert_string_equal(expanded, reference); - } - free(expanded); -} +#define assert_submatch(string, expected) \ + do { \ + char *expanded = pcmk__replace_submatches(string, match, \ + submatches, nmatches); \ + \ + assert_string_equal(expanded, expected); \ + free(expanded); \ + } while (0) static void no_source(void **state) { assert_null(pcmk__replace_submatches(NULL, NULL, NULL, 0)); - assert_submatch(NULL, NULL); - assert_submatch("", NULL); + assert_null(pcmk__replace_submatches(NULL, match, submatches, nmatches)); + assert_null(pcmk__replace_submatches("", match, submatches, nmatches)); } static void diff --git a/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c b/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c index 9da185802f9..38ddacafe55 100644 --- a/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c +++ b/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -15,18 +15,17 @@ #include #include -static void -assert_recheck(time_t now_time, time_t orig_time, time_t update_time, - time_t expected_time, const char *reason) -{ - pcmk_scheduler_t *scheduler = pcmk_new_scheduler(); - - scheduler->priv->now = pcmk__copy_timet(now_time); - scheduler->priv->recheck_by = orig_time; - pcmk__update_recheck_time(update_time, scheduler, reason); - assert_int_equal(scheduler->priv->recheck_by, expected_time); - pcmk_free_scheduler(scheduler); -} +#define assert_recheck(now_time, orig_time, update_time, expected_time, \ + reason) \ + do { \ + pcmk_scheduler_t *scheduler = pcmk_new_scheduler(); \ + \ + scheduler->priv->now = pcmk__copy_timet(now_time); \ + scheduler->priv->recheck_by = orig_time; \ + pcmk__update_recheck_time(update_time, scheduler, reason); \ + assert_int_equal(scheduler->priv->recheck_by, expected_time); \ + pcmk_free_scheduler(scheduler); \ + } while (0) // A NULL scheduler argument is invalid and should assert static void diff --git a/lib/common/tests/schemas/pcmk__find_x_0_schema_test.c b/lib/common/tests/schemas/pcmk__find_x_0_schema_test.c index 0dda558071d..3fa5b5ea73c 100644 --- a/lib/common/tests/schemas/pcmk__find_x_0_schema_test.c +++ b/lib/common/tests/schemas/pcmk__find_x_0_schema_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the Pacemaker project contributors + * Copyright 2023-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -33,21 +33,20 @@ teardown(void **state) return 0; } -static void -assert_schema_0(int schema_index, const char *schema_name) -{ - GList *entry = NULL; - pcmk__schema_t *schema = NULL; - - entry = pcmk__find_x_0_schema(); - assert_non_null(entry); - - schema = entry->data; - assert_non_null(schema); - - assert_int_equal(schema->schema_index, schema_index); - assert_string_equal(schema->name, schema_name); -} +#define assert_schema_0(schema_idx, schema_name) \ + do { \ + GList *entry = NULL; \ + pcmk__schema_t *schema = NULL; \ + \ + entry = pcmk__find_x_0_schema(); \ + assert_non_null(entry); \ + \ + schema = entry->data; \ + assert_non_null(schema); \ + \ + assert_int_equal(schema->schema_index, schema_idx); \ + assert_string_equal(schema->name, schema_name); \ + } while (0) static void last_is_0(void **state) diff --git a/lib/common/tests/schemas/pcmk__get_schema_test.c b/lib/common/tests/schemas/pcmk__get_schema_test.c index d9c999fca1e..a5fd836f09f 100644 --- a/lib/common/tests/schemas/pcmk__get_schema_test.c +++ b/lib/common/tests/schemas/pcmk__get_schema_test.c @@ -29,20 +29,19 @@ teardown(void **state) return 0; } -static void -assert_schema(const char *name, int expected_index) -{ - GList *schema_entry = NULL; - pcmk__schema_t *schema = NULL; - - schema_entry = pcmk__get_schema(name); - assert_non_null(schema_entry); - - schema = schema_entry->data; - assert_non_null(schema); - - assert_int_equal(schema->schema_index, expected_index); -} +#define assert_schema(name, expected_index) \ + do { \ + GList *schema_entry = NULL; \ + pcmk__schema_t *schema = NULL; \ + \ + schema_entry = pcmk__get_schema(name); \ + assert_non_null(schema_entry); \ + \ + schema = schema_entry->data; \ + assert_non_null(schema); \ + \ + assert_int_equal(schema->schema_index, expected_index); \ + } while (0) static void unknown_schema(void **state) diff --git a/lib/common/tests/schemas/pcmk__schema_init_test.c b/lib/common/tests/schemas/pcmk__schema_init_test.c index 2b2196a69cf..0afbbc02d11 100644 --- a/lib/common/tests/schemas/pcmk__schema_init_test.c +++ b/lib/common/tests/schemas/pcmk__schema_init_test.c @@ -109,20 +109,19 @@ teardown(void **state) return rc; } -static void -assert_schema(const char *schema_name, int schema_index) -{ - GList *entry = NULL; - pcmk__schema_t *schema = NULL; - - entry = pcmk__get_schema(schema_name); - assert_non_null(entry); - - schema = entry->data; - assert_non_null(schema); - - assert_int_equal(schema_index, schema->schema_index); -} +#define assert_schema(schema_name, schema_idx) \ + do { \ + GList *entry = NULL; \ + pcmk__schema_t *schema = NULL; \ + \ + entry = pcmk__get_schema(schema_name); \ + assert_non_null(entry); \ + \ + schema = entry->data; \ + assert_non_null(schema); \ + \ + assert_int_equal(schema_idx, schema->schema_index); \ + } while (0) static void extra_schema_files(void **state) diff --git a/lib/common/tests/scores/pcmk_parse_score_test.c b/lib/common/tests/scores/pcmk_parse_score_test.c index a79a1f74450..16989420dec 100644 --- a/lib/common/tests/scores/pcmk_parse_score_test.c +++ b/lib/common/tests/scores/pcmk_parse_score_test.c @@ -20,15 +20,14 @@ extern int pcmk__score_yellow; static int default_score = 99; -static void -assert_score(const char *score_s, int expected_rc, int expected_score) -{ - int score = 0; - int rc = pcmk_parse_score(score_s, &score, default_score); - - assert_int_equal(rc, expected_rc); - assert_int_equal(score, expected_score); -} +#define assert_score(score_s, expected_rc, expected_score) \ + do { \ + int score = 0; \ + int rc = pcmk_parse_score(score_s, &score, default_score); \ + \ + assert_int_equal(rc, expected_rc); \ + assert_int_equal(score, expected_score); \ + } while (0) static void null_score_string(void **state) diff --git a/lib/common/tests/strings/pcmk__parse_bool_test.c b/lib/common/tests/strings/pcmk__parse_bool_test.c index d1d12666cb1..0c5b7799367 100644 --- a/lib/common/tests/strings/pcmk__parse_bool_test.c +++ b/lib/common/tests/strings/pcmk__parse_bool_test.c @@ -15,103 +15,131 @@ /*! * \internal - * \brief Check a call with given input against expected return value and result + * \brief Check \c pcmk__parse_bool() succeeds and parses the input to true * - * \param[in] input Input string - * \param[in] expected_rc Expected return code - * \param[in] expected_result Expected parsed value (ignored unless - * \p expected_rc is \c pcmk_rc_ok) + * \param[in] input Input string (const char *) */ -static void -assert_parse_bool(const char *input, int expected_rc, bool expected_result) -{ - bool result = false; - - // Ensure we still validate the string with a NULL result argument - assert_int_equal(pcmk__parse_bool(input, NULL), expected_rc); - - if (expected_rc != pcmk_rc_ok) { - // Make sure the value of result does not change on failure - expected_result = result; - } +#define assert_parse_bool_true(input) \ + do { \ + bool result = false; \ + \ + /* Test with NULL result argument (for validation only) */ \ + assert_int_equal(pcmk__parse_bool(input, NULL), pcmk_rc_ok); \ + \ + assert_int_equal(pcmk__parse_bool(input, &result), pcmk_rc_ok); \ + assert_true(result); \ + \ + /* Repeat with result initially set to true */ \ + result = true; \ + \ + assert_int_equal(pcmk__parse_bool(input, &result), pcmk_rc_ok); \ + assert_true(result); \ + } while (0) - assert_int_equal(pcmk__parse_bool(input, &result), expected_rc); - if (expected_result) { - assert_true(result); - } else { - assert_false(result); - } - - // Repeat with result initially set to true - result = true; - if (expected_rc != pcmk_rc_ok) { - expected_result = result; - } +/*! + * \internal + * \brief Check \c pcmk__parse_bool() succeeds and parses the input to false + * + * \param[in] input Input string (const char *) + */ +#define assert_parse_bool_false(input) \ + do { \ + bool result = false; \ + \ + /* Test with NULL result argument (for validation only) */ \ + assert_int_equal(pcmk__parse_bool(input, NULL), pcmk_rc_ok); \ + \ + assert_int_equal(pcmk__parse_bool(input, &result), pcmk_rc_ok); \ + assert_false(result); \ + \ + /* Repeat with result initially set to true */ \ + result = true; \ + \ + assert_int_equal(pcmk__parse_bool(input, &result), pcmk_rc_ok); \ + assert_false(result); \ + } while (0) - assert_int_equal(pcmk__parse_bool(input, &result), expected_rc); - if (expected_result) { - assert_true(result); - } else { - assert_false(result); - } -} +/*! + * \internal + * \brief Check that \c pcmk__parse_bool() fails and returns the expected value + * + * \param[in] input Input string (const char *) + * \param[in] expected_rc Expected return code (\c int) + */ +#define assert_parse_bool_failure(input, expected_rc) \ + do { \ + bool result = false; \ + \ + /* Test with NULL result argument (for validation only) */ \ + assert_int_equal(pcmk__parse_bool(input, NULL), expected_rc); \ + \ + /* Make sure the value of result does not change on failure */ \ + assert_int_equal(pcmk__parse_bool(input, &result), expected_rc); \ + assert_false(result); \ + \ + /* Repeat with result initially set to true */ \ + result = true; \ + \ + assert_int_equal(pcmk__parse_bool(input, &result), expected_rc); \ + assert_true(result); \ + } while (0) static void bad_input(void **state) { // Dumps core via CRM_CHECK() - assert_parse_bool(NULL, EINVAL, false); + assert_parse_bool_failure(NULL, EINVAL); - assert_parse_bool("", pcmk_rc_bad_input, false); - assert_parse_bool("blahblah", pcmk_rc_bad_input, false); + assert_parse_bool_failure("", pcmk_rc_bad_input); + assert_parse_bool_failure("blahblah", pcmk_rc_bad_input); } static void is_true(void **state) { - assert_parse_bool("true", pcmk_rc_ok, true); - assert_parse_bool("TrUe", pcmk_rc_ok, true); - assert_parse_bool("on", pcmk_rc_ok, true); - assert_parse_bool("ON", pcmk_rc_ok, true); - assert_parse_bool("yes", pcmk_rc_ok, true); - assert_parse_bool("yES", pcmk_rc_ok, true); - assert_parse_bool("y", pcmk_rc_ok, true); - assert_parse_bool("Y", pcmk_rc_ok, true); - assert_parse_bool("1", pcmk_rc_ok, true); + assert_parse_bool_true("true"); + assert_parse_bool_true("TrUe"); + assert_parse_bool_true("on"); + assert_parse_bool_true("ON"); + assert_parse_bool_true("yes"); + assert_parse_bool_true("yES"); + assert_parse_bool_true("y"); + assert_parse_bool_true("Y"); + assert_parse_bool_true("1"); } static void is_not_true(void **state) { - assert_parse_bool("truedat", pcmk_rc_bad_input, false); - assert_parse_bool("onnn", pcmk_rc_bad_input, false); - assert_parse_bool("yep", pcmk_rc_bad_input, false); - assert_parse_bool("Y!", pcmk_rc_bad_input, false); - assert_parse_bool("100", pcmk_rc_bad_input, false); + assert_parse_bool_failure("truedat", pcmk_rc_bad_input); + assert_parse_bool_failure("onnn", pcmk_rc_bad_input); + assert_parse_bool_failure("yep", pcmk_rc_bad_input); + assert_parse_bool_failure("Y!", pcmk_rc_bad_input); + assert_parse_bool_failure("100", pcmk_rc_bad_input); } static void is_false(void **state) { - assert_parse_bool("false", pcmk_rc_ok, false); - assert_parse_bool("fAlSe", pcmk_rc_ok, false); - assert_parse_bool("off", pcmk_rc_ok, false); - assert_parse_bool("OFF", pcmk_rc_ok, false); - assert_parse_bool("no", pcmk_rc_ok, false); - assert_parse_bool("No", pcmk_rc_ok, false); - assert_parse_bool("n", pcmk_rc_ok, false); - assert_parse_bool("N", pcmk_rc_ok, false); - assert_parse_bool("0", pcmk_rc_ok, false); + assert_parse_bool_false("false"); + assert_parse_bool_false("fAlSe"); + assert_parse_bool_false("off"); + assert_parse_bool_false("OFF"); + assert_parse_bool_false("no"); + assert_parse_bool_false("No"); + assert_parse_bool_false("n"); + assert_parse_bool_false("N"); + assert_parse_bool_false("0"); } static void is_not_false(void **state) { - assert_parse_bool("falseee", pcmk_rc_bad_input, false); - assert_parse_bool("of", pcmk_rc_bad_input, false); - assert_parse_bool("nope", pcmk_rc_bad_input, false); - assert_parse_bool("N!", pcmk_rc_bad_input, false); - assert_parse_bool("000", pcmk_rc_bad_input, false); + assert_parse_bool_failure("falseee", pcmk_rc_bad_input); + assert_parse_bool_failure("of", pcmk_rc_bad_input); + assert_parse_bool_failure("nope", pcmk_rc_bad_input); + assert_parse_bool_failure("N!", pcmk_rc_bad_input); + assert_parse_bool_failure("000", pcmk_rc_bad_input); } PCMK__UNIT_TEST(NULL, NULL, diff --git a/lib/common/tests/strings/pcmk__parse_ms_test.c b/lib/common/tests/strings/pcmk__parse_ms_test.c index 2a2c29fa88c..d3f0a565d04 100644 --- a/lib/common/tests/strings/pcmk__parse_ms_test.c +++ b/lib/common/tests/strings/pcmk__parse_ms_test.c @@ -14,14 +14,13 @@ //! Magic initial value to test whether a "result" output variable has changed static const long long magic = -12345678; -static void -assert_parse_ms(const char *input, int expected_rc, long long expected_result) -{ - long long result = magic; - - assert_int_equal(pcmk__parse_ms(input, &result), expected_rc); - assert_int_equal(result, expected_result); -} +#define assert_parse_ms(input, expected_rc, expected_result) \ + do { \ + long long result = magic; \ + \ + assert_int_equal(pcmk__parse_ms(input, &result), expected_rc); \ + assert_int_equal(result, expected_result); \ + } while (0) static void bad_input(void **state) diff --git a/lib/common/tests/utils/pcmk__compare_versions_test.c b/lib/common/tests/utils/pcmk__compare_versions_test.c index 22844e9d5ad..9ddeb6afd3f 100644 --- a/lib/common/tests/utils/pcmk__compare_versions_test.c +++ b/lib/common/tests/utils/pcmk__compare_versions_test.c @@ -16,288 +16,283 @@ * \brief Compare two version strings in both directions * * \param[in] v1 First argument for \c pcmk__compare_versions() + * (const char *) * \param[in] v2 Second argument for \c pcmk__compare_versions() + * (const char *) * \param[in] expected_rc Expected return code from - * pcmk__compare_versions(v1, v2) + * pcmk__compare_versions(v1, v2) (\c int) */ -static void -assert_compare_version(const char *v1, const char *v2, int expected_rc) -{ - assert_int_equal(pcmk__compare_versions(v1, v2), expected_rc); - - if (v1 != v2) { - /* Try reverse order even if expected_rc == 0, if v1 and v2 are - * different strings - */ - assert_int_equal(pcmk__compare_versions(v2, v1), -expected_rc); - } -} +#define assert_compare_versions(v1, v2, expected_rc) \ + do { \ + assert_int_equal(pcmk__compare_versions(v1, v2), expected_rc); \ + assert_int_equal(pcmk__compare_versions(v2, v1), -expected_rc); \ + } while (0) static void empty_params(void **state) { - assert_compare_version(NULL, NULL, 0); - assert_compare_version(NULL, "", 0); - assert_compare_version("", "", 0); + assert_compare_versions(NULL, NULL, 0); + assert_compare_versions(NULL, "", 0); + assert_compare_versions("", "", 0); - assert_compare_version(NULL, "1.0.1", -1); - assert_compare_version("", "1.0.1", -1); + assert_compare_versions(NULL, "1.0.1", -1); + assert_compare_versions("", "1.0.1", -1); // NULL or empty is treated as equal to an invalid version - assert_compare_version(NULL, "abc", 0); - assert_compare_version("", "abc", 0); + assert_compare_versions(NULL, "abc", 0); + assert_compare_versions("", "abc", 0); } static void equal_versions(void **state) { - assert_compare_version("0.4.7", "0.4.7", 0); - assert_compare_version("1.0", "1.0", 0); + assert_compare_versions("0.4.7", "0.4.7", 0); + assert_compare_versions("1.0", "1.0", 0); } static void unequal_versions(void **state) { - assert_compare_version("0.4.7", "0.4.8", -1); - assert_compare_version("0.2.3", "0.3", -1); - assert_compare_version("0.99", "1.0", -1); + assert_compare_versions("0.4.7", "0.4.8", -1); + assert_compare_versions("0.2.3", "0.3", -1); + assert_compare_versions("0.99", "1.0", -1); } static void shorter_versions(void **state) { - assert_compare_version("1.0", "1.0.1", -1); - assert_compare_version("1.0", "1", 0); - assert_compare_version("1", "1.2", -1); - assert_compare_version("1.0.0", "1.0", 0); - assert_compare_version("1.0.0", "1.2", -1); - assert_compare_version("0.99", "1", -1); + assert_compare_versions("1.0", "1.0.1", -1); + assert_compare_versions("1.0", "1", 0); + assert_compare_versions("1", "1.2", -1); + assert_compare_versions("1.0.0", "1.0", 0); + assert_compare_versions("1.0.0", "1.2", -1); + assert_compare_versions("0.99", "1", -1); } static void leading_zeros(void **state) { // Equal to self - assert_compare_version("00001.0", "00001.0", 0); + assert_compare_versions("00001.0", "00001.0", 0); // Leading zeros in each segment are ignored - assert_compare_version("0001.0", "1", 0); - assert_compare_version("0.0001", "0.1", 0); - assert_compare_version("0001.1", "1.0001", 0); + assert_compare_versions("0001.0", "1", 0); + assert_compare_versions("0.0001", "0.1", 0); + assert_compare_versions("0001.1", "1.0001", 0); } static void negative_sign(void **state) { // Equal to self - assert_compare_version("-1", "-1", 0); - assert_compare_version("1.-1.5", "1.-1.5", 0); + assert_compare_versions("-1", "-1", 0); + assert_compare_versions("1.-1.5", "1.-1.5", 0); // Negative version is treated as 0 (invalid) - assert_compare_version("-1", "0", 0); - assert_compare_version("-1", "0.0", 0); - assert_compare_version("-1", "0.1", -1); - assert_compare_version("-1", "1.0", -1); + assert_compare_versions("-1", "0", 0); + assert_compare_versions("-1", "0.0", 0); + assert_compare_versions("-1", "0.1", -1); + assert_compare_versions("-1", "1.0", -1); - assert_compare_version("-1", "-0", 0); - assert_compare_version("-1", "-0.0", 0); - assert_compare_version("-1", "-0.1", 0); - assert_compare_version("-1", "-1.0", 0); - assert_compare_version("-1", "-2.0", 0); + assert_compare_versions("-1", "-0", 0); + assert_compare_versions("-1", "-0.0", 0); + assert_compare_versions("-1", "-0.1", 0); + assert_compare_versions("-1", "-1.0", 0); + assert_compare_versions("-1", "-2.0", 0); // Negative sign inside version is treated as garbage - assert_compare_version("1.-1.5", "1.0", 0); - assert_compare_version("1.-1.5", "1.0.5", -1); + assert_compare_versions("1.-1.5", "1.0", 0); + assert_compare_versions("1.-1.5", "1.0.5", -1); - assert_compare_version("1.-1.5", "1.-0", 0); - assert_compare_version("1.-1.5", "1.-0.5", 0); + assert_compare_versions("1.-1.5", "1.-0", 0); + assert_compare_versions("1.-1.5", "1.-0.5", 0); - assert_compare_version("1.-1.5", "1.-1", 0); - assert_compare_version("1.-1.5", "1.-1.9", 0); + assert_compare_versions("1.-1.5", "1.-1", 0); + assert_compare_versions("1.-1.5", "1.-1.9", 0); - assert_compare_version("1.-1.5", "1.-2", 0); - assert_compare_version("1.-1.5", "1.-2.5", 0); + assert_compare_versions("1.-1.5", "1.-2", 0); + assert_compare_versions("1.-1.5", "1.-2.5", 0); - assert_compare_version("1.-1.5", "2.0.5", -1); - assert_compare_version("1.-1.5", "0.0.5", 1); + assert_compare_versions("1.-1.5", "2.0.5", -1); + assert_compare_versions("1.-1.5", "0.0.5", 1); } static void positive_sign(void **state) { // Equal to self - assert_compare_version("+1", "+1", 0); - assert_compare_version("1.+1.5", "1.+1.5", 0); + assert_compare_versions("+1", "+1", 0); + assert_compare_versions("1.+1.5", "1.+1.5", 0); // Version with explicit positive sign is treated as 0 (invalid) - assert_compare_version("+1", "0", 0); - assert_compare_version("+1", "0.0", 0); - assert_compare_version("+1", "0.1", -1); - assert_compare_version("+1", "1.0", -1); - assert_compare_version("+1", "2.0", -1); - - assert_compare_version("+1", "+0", 0); - assert_compare_version("+1", "+0.0", 0); - assert_compare_version("+1", "+0.1", 0); - assert_compare_version("+1", "+1.0", 0); - assert_compare_version("+1", "+2.0", 0); + assert_compare_versions("+1", "0", 0); + assert_compare_versions("+1", "0.0", 0); + assert_compare_versions("+1", "0.1", -1); + assert_compare_versions("+1", "1.0", -1); + assert_compare_versions("+1", "2.0", -1); + + assert_compare_versions("+1", "+0", 0); + assert_compare_versions("+1", "+0.0", 0); + assert_compare_versions("+1", "+0.1", 0); + assert_compare_versions("+1", "+1.0", 0); + assert_compare_versions("+1", "+2.0", 0); // Positive sign inside version is treated as garbage - assert_compare_version("1.+1.5", "1.0", 0); - assert_compare_version("1.+1.5", "1.0.5", -1); + assert_compare_versions("1.+1.5", "1.0", 0); + assert_compare_versions("1.+1.5", "1.0.5", -1); - assert_compare_version("1.+1.5", "1.+0", 0); - assert_compare_version("1.+1.5", "1.+0.5", 0); + assert_compare_versions("1.+1.5", "1.+0", 0); + assert_compare_versions("1.+1.5", "1.+0.5", 0); - assert_compare_version("1.+1.5", "1.+1", 0); - assert_compare_version("1.+1.5", "1.+1.9", 0); + assert_compare_versions("1.+1.5", "1.+1", 0); + assert_compare_versions("1.+1.5", "1.+1.9", 0); - assert_compare_version("1.+1.5", "1.+2", 0); - assert_compare_version("1.+1.5", "1.+2.5", 0); + assert_compare_versions("1.+1.5", "1.+2", 0); + assert_compare_versions("1.+1.5", "1.+2.5", 0); - assert_compare_version("1.+1.5", "2.0.5", -1); - assert_compare_version("1.+1.5", "0.0.5", 1); + assert_compare_versions("1.+1.5", "2.0.5", -1); + assert_compare_versions("1.+1.5", "0.0.5", 1); } static void hex_digits(void **state) { // Equal to self - assert_compare_version("a", "a", 0); + assert_compare_versions("a", "a", 0); // Hex digits > 9 are garbage - assert_compare_version("a", "0", 0); - assert_compare_version("a111", "0", 0); - assert_compare_version("a", "1", -1); - assert_compare_version("a111", "1", -1); - - assert_compare_version("1a", "1", 0); - assert_compare_version("1a111", "1", 0); - assert_compare_version("1a", "2", -1); - assert_compare_version("1a111", "2", -1); - assert_compare_version("1a", "0", 1); - assert_compare_version("1a111", "0", 1); + assert_compare_versions("a", "0", 0); + assert_compare_versions("a111", "0", 0); + assert_compare_versions("a", "1", -1); + assert_compare_versions("a111", "1", -1); + + assert_compare_versions("1a", "1", 0); + assert_compare_versions("1a111", "1", 0); + assert_compare_versions("1a", "2", -1); + assert_compare_versions("1a111", "2", -1); + assert_compare_versions("1a", "0", 1); + assert_compare_versions("1a111", "0", 1); } static void bare_dot(void **state) { // Equal to self - assert_compare_version(".", ".", 0); + assert_compare_versions(".", ".", 0); // Bare dot is treated as 0 - assert_compare_version(".", "0", 0); - assert_compare_version(".", "0.1", -1); - assert_compare_version(".", "1.0", -1); + assert_compare_versions(".", "0", 0); + assert_compare_versions(".", "0.1", -1); + assert_compare_versions(".", "1.0", -1); } static void leading_dot(void **state) { // Equal to self - assert_compare_version(".0", ".0", 0); - assert_compare_version(".1", ".1", 0); + assert_compare_versions(".0", ".0", 0); + assert_compare_versions(".1", ".1", 0); // Version with leading dot is treated as 0 (invalid) - assert_compare_version(".0", "0", 0); - assert_compare_version(".0", "0.0", 0); - assert_compare_version(".0", "0.0.0", 0); - assert_compare_version(".0", "0.1", -1); - - assert_compare_version(".1", "0", 0); - assert_compare_version(".1", "0.0", 0); - assert_compare_version(".1", "0.0.0", 0); - assert_compare_version(".1", "0.1", -1); - assert_compare_version(".1", "0.1.0", -1); + assert_compare_versions(".0", "0", 0); + assert_compare_versions(".0", "0.0", 0); + assert_compare_versions(".0", "0.0.0", 0); + assert_compare_versions(".0", "0.1", -1); + + assert_compare_versions(".1", "0", 0); + assert_compare_versions(".1", "0.0", 0); + assert_compare_versions(".1", "0.0.0", 0); + assert_compare_versions(".1", "0.1", -1); + assert_compare_versions(".1", "0.1.0", -1); } static void trailing_dot(void **state) { // Equal to self - assert_compare_version("0.", "0.", 0); - assert_compare_version("0.1.", "0.1.", 0); + assert_compare_versions("0.", "0.", 0); + assert_compare_versions("0.1.", "0.1.", 0); // Trailing dot is ignored - assert_compare_version("0.", "0", 0); - assert_compare_version("0.", "0.0", 0); - assert_compare_version("0.", "0.1", -1); - assert_compare_version("0.1.", "0.1", 0); - assert_compare_version("0.1.", "0.1.0", 0); - assert_compare_version("0.1.", "0.2", -1); - assert_compare_version("0.1.", "0", 1); + assert_compare_versions("0.", "0", 0); + assert_compare_versions("0.", "0.0", 0); + assert_compare_versions("0.", "0.1", -1); + assert_compare_versions("0.1.", "0.1", 0); + assert_compare_versions("0.1.", "0.1.0", 0); + assert_compare_versions("0.1.", "0.2", -1); + assert_compare_versions("0.1.", "0", 1); } static void leading_spaces(void **state) { // Equal to self - assert_compare_version(" ", " ", 0); - assert_compare_version(" 1", " 1", 0); + assert_compare_versions(" ", " ", 0); + assert_compare_versions(" 1", " 1", 0); // Leading spaces are ignored - assert_compare_version(" 1", "1.0", 0); - assert_compare_version("1", " 1.0", 0); - assert_compare_version(" 1", " 1.0", 0); - assert_compare_version(" 1", "1.1", -1); - assert_compare_version("1", " 1.1", -1); - assert_compare_version(" 1", " 1.1", -1); + assert_compare_versions(" 1", "1.0", 0); + assert_compare_versions("1", " 1.0", 0); + assert_compare_versions(" 1", " 1.0", 0); + assert_compare_versions(" 1", "1.1", -1); + assert_compare_versions("1", " 1.1", -1); + assert_compare_versions(" 1", " 1.1", -1); } static void trailing_spaces(void **state) { // Equal to self - assert_compare_version("1 ", "1 ", 0); + assert_compare_versions("1 ", "1 ", 0); // Trailing spaces are ignored - assert_compare_version("1 ", "1.0", 0); - assert_compare_version("1", "1.0 ", 0); - assert_compare_version("1 ", "1.0 ", 0); - assert_compare_version("1 ", "1.1", -1); - assert_compare_version("1", "1.1 ", -1); - assert_compare_version("1 ", "1.1 ", -1); + assert_compare_versions("1 ", "1.0", 0); + assert_compare_versions("1", "1.0 ", 0); + assert_compare_versions("1 ", "1.0 ", 0); + assert_compare_versions("1 ", "1.1", -1); + assert_compare_versions("1", "1.1 ", -1); + assert_compare_versions("1 ", "1.1 ", -1); } static void leading_garbage(void **state) { // Equal to self - assert_compare_version("@1", "@1", 0); + assert_compare_versions("@1", "@1", 0); // Version with leading garbage is treated as 0 - assert_compare_version("@1", "0", 0); - assert_compare_version("@1", "1", -1); + assert_compare_versions("@1", "0", 0); + assert_compare_versions("@1", "1", -1); - assert_compare_version("@0.1", "0", 0); - assert_compare_version("@0.1", "1", -1); + assert_compare_versions("@0.1", "0", 0); + assert_compare_versions("@0.1", "1", -1); } static void trailing_garbage(void **state) { // Equal to self - assert_compare_version("0.1@", "0.1@", 0); + assert_compare_versions("0.1@", "0.1@", 0); // Trailing garbage is ignored - assert_compare_version("0.1@", "0.1", 0); - assert_compare_version("0.1.@", "0.1", 0); - assert_compare_version("0.1 @", "0.1", 0); - assert_compare_version("0.1. @", "0.1", 0); - assert_compare_version("0.1 .@", "0.1", 0); + assert_compare_versions("0.1@", "0.1", 0); + assert_compare_versions("0.1.@", "0.1", 0); + assert_compare_versions("0.1 @", "0.1", 0); + assert_compare_versions("0.1. @", "0.1", 0); + assert_compare_versions("0.1 .@", "0.1", 0); // This includes more numbers after spaces - assert_compare_version("0.1 1", "0.1", 0); - assert_compare_version("0.1. 1", "0.1", 0); - assert_compare_version("0.1 .1", "0.1", 0); + assert_compare_versions("0.1 1", "0.1", 0); + assert_compare_versions("0.1. 1", "0.1", 0); + assert_compare_versions("0.1 .1", "0.1", 0); // Second consecutive dot is treated as garbage - assert_compare_version("1..", "1", 0); - assert_compare_version("1..1", "1", 0); - assert_compare_version("1..", "1.0.0", 0); - assert_compare_version("1..1", "1.0.0", 0); - assert_compare_version("1..", "1.0.1", -1); - assert_compare_version("1..1", "1.0.1", -1); + assert_compare_versions("1..", "1", 0); + assert_compare_versions("1..1", "1", 0); + assert_compare_versions("1..", "1.0.0", 0); + assert_compare_versions("1..1", "1.0.0", 0); + assert_compare_versions("1..", "1.0.1", -1); + assert_compare_versions("1..1", "1.0.1", -1); } PCMK__UNIT_TEST(NULL, NULL, diff --git a/lib/common/tests/utils/pcmk__lookup_user_test.c b/lib/common/tests/utils/pcmk__lookup_user_test.c index 962d3adfb85..9ed65ac23ee 100644 --- a/lib/common/tests/utils/pcmk__lookup_user_test.c +++ b/lib/common/tests/utils/pcmk__lookup_user_test.c @@ -19,39 +19,61 @@ #include #include +#define USER_NAME "ha_user" + +#define assert_lookup_user_one(errno_to_set, returned_ent, uid, gid, \ + expected_rc) \ + do { \ + expect_string(__wrap_getpwnam, name, USER_NAME); \ + will_return(__wrap_getpwnam, errno_to_set); \ + will_return(__wrap_getpwnam, returned_ent); \ + assert_int_equal(pcmk__lookup_user(USER_NAME, uid, gid), \ + expected_rc); \ + } while (0) + /*! * \internal - * \brief Perform one test of \c pcmk__lookup_user() + * \brief Perform one test of \c pcmk__lookup_user() with non-NULL name * - * \param[in] name \c name argument for \c pcmk__lookup_user() - * \param[in] uid \c uid argument for \c pcmk__lookup_user() - * (unchanged upon return) - * \param[in] gid \c gid argument for \c pcmk__lookup_user() - * (unchanged upon return) + * \param[in] errno_to_set Value that \c getpwnam() should set \c errno to + * (\c int) + * \param[in] returned_ent Passwd entry that \c getpwnam() should return + * (struct passwd *) * \param[in] expected_rc Expected return code of \c pcmk__lookup_user() + * (\c int) * \param[in] expected_uid Expected value at \p *uid after - * \c pcmk__lookup_user() call + * \c pcmk__lookup_user() call (\c uid_t) * \param[in] expected_gid Expected value at \p *gid after - * \c pcmk__lookup_user() call + * \c pcmk__lookup_user() call (\c gid_t) */ -static void -assert_lookup_user(const char *name, uid_t *uid, gid_t *gid, int expected_rc, - uid_t expected_uid, gid_t expected_gid) -{ - uid_t uid_orig = ((uid != NULL)? *uid : 0); - gid_t gid_orig = ((gid != NULL)? *gid : 0); - - assert_int_equal(pcmk__lookup_user(name, uid, gid), expected_rc); - - if (uid != NULL) { - assert_int_equal(*uid, expected_uid); - *uid = uid_orig; - } - if (gid != NULL) { - assert_int_equal(*gid, expected_gid); - *gid = gid_orig; - } -} +#define assert_lookup_user(errno_to_set, returned_ent, expected_rc, \ + expected_uid, expected_gid) \ + do { \ + uid_t uid = 0; \ + gid_t gid = 0; \ + \ + pcmk__mock_getpwnam = true; \ + \ + assert_lookup_user_one(errno_to_set, returned_ent, NULL, NULL, \ + expected_rc); \ + \ + assert_lookup_user_one(errno_to_set, returned_ent, &uid, NULL, \ + expected_rc); \ + assert_int_equal(uid, expected_uid); \ + uid = 0; \ + \ + assert_lookup_user_one(errno_to_set, returned_ent, NULL, &gid, \ + expected_rc); \ + assert_int_equal(gid, expected_gid); \ + gid = 0; \ + \ + assert_lookup_user_one(errno_to_set, returned_ent, &uid, &gid, \ + expected_rc); \ + assert_int_equal(uid, expected_uid); \ + assert_int_equal(gid, expected_gid); \ + \ + pcmk__mock_getpwnam = false; \ + } while (0) static void null_name(void **state) @@ -60,86 +82,44 @@ null_name(void **state) gid_t gid = 0; // These dump core via CRM_CHECK() - assert_lookup_user(NULL, NULL, NULL, EINVAL, 0, 0); - assert_lookup_user(NULL, NULL, &gid, EINVAL, 0, 0); - assert_lookup_user(NULL, &uid, NULL, EINVAL, 0, 0); - assert_lookup_user(NULL, &uid, &gid, EINVAL, 0, 0); + assert_int_equal(pcmk__lookup_user(NULL, NULL, NULL), EINVAL); + + assert_int_equal(pcmk__lookup_user(NULL, &uid, 0), EINVAL); + assert_int_equal(uid, 0); + + assert_int_equal(pcmk__lookup_user(NULL, NULL, &gid), EINVAL); + assert_int_equal(gid, 0); + + assert_int_equal(pcmk__lookup_user(NULL, &uid, &gid), EINVAL); + assert_int_equal(uid, 0); + assert_int_equal(gid, 0); } static void getpwnam_fails(void **state) { - uid_t uid = 0; - gid_t gid = 0; - - pcmk__mock_getpwnam = true; - - expect_string(__wrap_getpwnam, name, "hauser"); - will_return(__wrap_getpwnam, EIO); // errno - will_return(__wrap_getpwnam, NULL); // return value - assert_lookup_user("hauser", &uid, &gid, EIO, 0, 0); - - pcmk__mock_getpwnam = false; + assert_lookup_user(EIO, NULL, EIO, 0, 0); } static void no_matching_pwent(void **state) { - uid_t uid = 0; - gid_t gid = 0; - - pcmk__mock_getpwnam = true; - /* errno may or may not be set when no matching passwd entry is found. * However, if the return value is NULL and errno == 0, then we can be sure * no entry was found. In other words, it's sufficient but not necessary. So * this is our test case for "no matching entry," and we should return * ENOENT. */ - expect_string(__wrap_getpwnam, name, "hauser"); - will_return(__wrap_getpwnam, 0); // errno - will_return(__wrap_getpwnam, NULL); // return value - assert_lookup_user("hauser", &uid, &gid, ENOENT, 0, 0); - - pcmk__mock_getpwnam = false; + assert_lookup_user(0, NULL, ENOENT, 0, 0); } static void entry_found(void **state) { - uid_t uid = 0; - gid_t gid = 0; - // We don't care about the other fields of the passwd entry struct passwd returned_ent = { .pw_uid = 1000, .pw_gid = 1000 }; - pcmk__mock_getpwnam = true; - - // NULL uid and NULL gid - expect_string(__wrap_getpwnam, name, "hauser"); - will_return(__wrap_getpwnam, 0); - will_return(__wrap_getpwnam, &returned_ent); - assert_lookup_user("hauser", NULL, NULL, pcmk_rc_ok, 0, 0); - - // Non-NULL uid and NULL gid - expect_string(__wrap_getpwnam, name, "hauser"); - will_return(__wrap_getpwnam, 0); - will_return(__wrap_getpwnam, &returned_ent); - assert_lookup_user("hauser", &uid, NULL, pcmk_rc_ok, 1000, 0); - - // NULL uid and non-NULL gid - expect_string(__wrap_getpwnam, name, "hauser"); - will_return(__wrap_getpwnam, 0); - will_return(__wrap_getpwnam, &returned_ent); - assert_lookup_user("hauser", NULL, &gid, pcmk_rc_ok, 0, 1000); - - // Non-NULL uid and non-NULL gid - expect_string(__wrap_getpwnam, name, "hauser"); - will_return(__wrap_getpwnam, 0); - will_return(__wrap_getpwnam, &returned_ent); - assert_lookup_user("hauser", &uid, &gid, pcmk_rc_ok, 1000, 1000); - - pcmk__mock_getpwnam = false; + assert_lookup_user(0, &returned_ent, pcmk_rc_ok, 1000, 1000); } PCMK__UNIT_TEST(NULL, NULL, diff --git a/lib/common/tests/xml/pcmk__xml_escape_test.c b/lib/common/tests/xml/pcmk__xml_escape_test.c index 39972cdfa1d..cbdad568beb 100644 --- a/lib/common/tests/xml/pcmk__xml_escape_test.c +++ b/lib/common/tests/xml/pcmk__xml_escape_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -13,15 +13,13 @@ #include "crmcommon_private.h" -static void -assert_escape(const char *str, const char *reference, - enum pcmk__xml_escape_type type) -{ - gchar *buf = pcmk__xml_escape(str, type); - - assert_string_equal(buf, reference); - g_free(buf); -} +#define assert_escape(str, reference, type) \ + do { \ + gchar *buf = pcmk__xml_escape(str, type); \ + \ + assert_string_equal(buf, reference); \ + g_free(buf); \ + } while (0) static void null_empty(void **state) diff --git a/lib/common/tests/xml/pcmk__xml_is_name_char_test.c b/lib/common/tests/xml/pcmk__xml_is_name_char_test.c index 2187fb99683..f4bb9ff1480 100644 --- a/lib/common/tests/xml/pcmk__xml_is_name_char_test.c +++ b/lib/common/tests/xml/pcmk__xml_is_name_char_test.c @@ -19,42 +19,35 @@ /*! * \internal - * \brief Assert that a Unicode character is (not) a valid XML \c NameChar + * \brief Assert that a Unicode character is a valid XML \c NameChar * - * \param[in] c Unicode code point of character to check - * \param[in] reference If \c true, \p c should be considered a valid - * \c NameChar; if \c false, it should not + * \param[in] code_pt Unicode code point of character to check (\c int) */ -static void -assert_name_char(int c, bool reference) -{ - gchar utf8_buf[6] = { 0, }; - int len = 4; - int ref_len = g_unichar_to_utf8(c, utf8_buf); - bool result = pcmk__xml_is_name_char(utf8_buf, &len); +#define assert_name_char(code_pt) \ + do { \ + gchar utf8_buf[6] = { 0, }; \ + int len = 4; \ + int ref_len = g_unichar_to_utf8(code_pt, utf8_buf); \ + \ + assert_true(pcmk__xml_is_name_char(utf8_buf, &len)); \ + assert_int_equal(len, ref_len); \ + } while (0) - if (reference) { - assert_true(result); - } else { - assert_false(result); - } - - if ((c < 0xD800) || (c > 0xDFFF)) { - /* Unicode code points in the range D800 to DFFF are UTF-16 surrogate - * pair halves. They can be represented in UTF-8, but they shouldn't - * appear in valid UTF-8-encoded text. RFC 3629 (Nov 2003) says they - * should be treated as invalid: - * https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling. - * - * GLib treats these characters as valid and returns a length of 3 - * bytes. So did libxml until v2.12 (commit 845bd99). Since that commit, - * libxml treats these characters as invalid and returns a length of 0. - * To avoid version-dependent testing behavior, skip the length check - * for code points in that range. - */ - assert_int_equal(len, ref_len); - } -} +/*! + * \internal + * \brief Assert that a Unicode character is not a valid XML \c NameChar + * + * \param[in] code_pt Unicode code point of character to check (\c int) + */ +#define assert_not_name_char(code_pt) \ + do { \ + gchar utf8_buf[6] = { 0, }; \ + int len = 4; \ + int ref_len = g_unichar_to_utf8(code_pt, utf8_buf); \ + \ + assert_false(pcmk__xml_is_name_char(utf8_buf, &len)); \ + assert_int_equal(len, ref_len); \ + } while (0) static void null_len(void **state) @@ -70,9 +63,9 @@ ascii(void **state) if (g_ascii_isalnum(c) || c == ':' || c == '_' || c == '-' || c == '.') { - assert_name_char(c, true); + assert_name_char(c); } else { - assert_name_char(c, false); + assert_not_name_char(c); } } } @@ -81,21 +74,21 @@ static void unicode_0x80_to_0xB6(void **state) { for (int c = 0x80; c <= 0xB6; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } static void unicode_0xB7(void **state) { - assert_name_char(0xB7, true); + assert_name_char(0xB7); } static void unicode_0xB8_to_0xBF(void **state) { for (int c = 0xB8; c <= 0xBF; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -103,35 +96,35 @@ static void unicode_0xC0_to_0xD6(void **state) { for (int c = 0xC0; c <= 0xD6; c++) { - assert_name_char(c, true); + assert_name_char(c); } } static void unicode_0xD7(void **state) { - assert_name_char(0xD7, false); + assert_not_name_char(0xD7); } static void unicode_0xD8_to_0xF6(void **state) { for (int c = 0xD8; c <= 0xF6; c++) { - assert_name_char(c, true); + assert_name_char(c); } } static void unicode_0xF7(void **state) { - assert_name_char(0xF7, false); + assert_not_name_char(0xF7); } static void unicode_0xF8_to_0x2FF(void **state) { for (int c = 0xF8; c <= 0x2FF; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -139,7 +132,7 @@ static void unicode_0x300_to_0x36F(void **state) { for (int c = 0x300; c <= 0x36F; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -147,21 +140,21 @@ static void unicode_0x370_to_0x37D(void **state) { for (int c = 0x370; c <= 0x37D; c++) { - assert_name_char(c, true); + assert_name_char(c); } } static void unicode_0x37E(void **state) { - assert_name_char(0x37E, false); + assert_not_name_char(0x37E); } static void unicode_0x37F_to_0x1FFF(void **state) { for (int c = 0x37F; c <= 0x1FFF; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -169,7 +162,7 @@ static void unicode_0x2000_to_0x200B(void **state) { for (int c = 0x2000; c <= 0x200B; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -177,7 +170,7 @@ static void unicode_0x200C_to_0x200D(void **state) { for (int c = 0x200C; c <= 0x200D; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -185,7 +178,7 @@ static void unicode_0x200E_to_0x203E(void **state) { for (int c = 0x200E; c <= 0x203E; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -193,7 +186,7 @@ static void unicode_0x203F_to_0x2040(void **state) { for (int c = 0x203F; c <= 0x2040; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -201,7 +194,7 @@ static void unicode_0x2041_to_0x206F(void **state) { for (int c = 0x2041; c <= 0x206F; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -209,7 +202,7 @@ static void unicode_0x2070_to_0x218F(void **state) { for (int c = 0x2070; c <= 0x218F; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -217,7 +210,7 @@ static void unicode_0x2190_to_0x2BFF(void **state) { for (int c = 0x2190; c <= 0x2BFF; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -225,7 +218,7 @@ static void unicode_0x2C00_to_0x2FEF(void **state) { for (int c = 0x2C00; c <= 0x2FEF; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -233,7 +226,7 @@ static void unicode_0x2FF0_to_0x3000(void **state) { for (int c = 0x2FF0; c <= 0x3000; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -241,15 +234,39 @@ static void unicode_0x3001_to_0xD7FF(void **state) { for (int c = 0x3001; c <= 0xD7FF; c++) { - assert_name_char(c, true); + assert_name_char(c); + } +} + +static void +unicode_0xD800_to_0xDFFF(void **state) +{ + /* Unicode code points in the range D800 to DFFF are UTF-16 surrogate pair + * halves. They can be represented in UTF-8, but they shouldn't appear in + * valid UTF-8-encoded text. RFC 3629 (Nov 2003) says they should be treated + * as invalid: + * https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling. + * + * GLib treats these characters as valid and returns a length of 3 bytes. So + * did libxml until v2.12 (commit 845bd99). Since that commit, libxml treats + * these characters as invalid and returns a length of 0. To avoid version- + * dependent testing behavior, skip the length check for code points in that + * range. This means we don't use the helper. + */ + for (int c = 0xD800; c <= 0xDFFF; c++) { + gchar utf8_buf[6] = { 0, }; + + g_unichar_to_utf8(c, utf8_buf); + + assert_false(pcmk__xml_is_name_char(utf8_buf, NULL)); } } static void -unicode_0xD800_to_0xF8FF(void **state) +unicode_0xE000_to_0xF8FF(void **state) { - for (int c = 0xD800; c <= 0xF8FF; c++) { - assert_name_char(c, false); + for (int c = 0xE000; c <= 0xF8FF; c++) { + assert_not_name_char(c); } } @@ -257,7 +274,7 @@ static void unicode_0xF900_to_0xFDCF(void **state) { for (int c = 0xF900; c <= 0xFDCF; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -265,7 +282,7 @@ static void unicode_0xFDD0_to_0xFDEF(void **state) { for (int c = 0xFDD0; c <= 0xFDEF; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -273,7 +290,7 @@ static void unicode_0xFDF0_to_0xFFFD(void **state) { for (int c = 0xFDF0; c <= 0xFFFD; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -281,7 +298,7 @@ static void unicode_0xFFFE_to_0xFFFF(void **state) { for (int c = 0xFFFE; c <= 0xFFFF; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -289,7 +306,7 @@ static void unicode_0x10000_to_0xEFFFF(void **state) { for (int c = 0x10000; c <= 0xEFFFF; c++) { - assert_name_char(c, true); + assert_name_char(c); } } @@ -297,7 +314,7 @@ static void unicode_0xF0000_to_0x10FFFF(void **state) { for (int c = 0xF0000; c <= 0x10FFFF; c++) { - assert_name_char(c, false); + assert_not_name_char(c); } } @@ -326,7 +343,8 @@ PCMK__UNIT_TEST(NULL, NULL, cmocka_unit_test(unicode_0x2C00_to_0x2FEF), cmocka_unit_test(unicode_0x2FF0_to_0x3000), cmocka_unit_test(unicode_0x3001_to_0xD7FF), - cmocka_unit_test(unicode_0xD800_to_0xF8FF), + cmocka_unit_test(unicode_0xD800_to_0xDFFF), + cmocka_unit_test(unicode_0xE000_to_0xF8FF), cmocka_unit_test(unicode_0xF900_to_0xFDCF), cmocka_unit_test(unicode_0xFDD0_to_0xFDEF), cmocka_unit_test(unicode_0xFDF0_to_0xFFFD), diff --git a/lib/common/tests/xml/pcmk__xml_is_name_start_char_test.c b/lib/common/tests/xml/pcmk__xml_is_name_start_char_test.c index 5d264a6c67a..6abfd0f9f4d 100644 --- a/lib/common/tests/xml/pcmk__xml_is_name_start_char_test.c +++ b/lib/common/tests/xml/pcmk__xml_is_name_start_char_test.c @@ -12,7 +12,6 @@ #include #include // gchar, g_ascii_isalpha(), etc. -#include // xmlGetUTF8Char() #include @@ -20,42 +19,35 @@ /*! * \internal - * \brief Assert that a Unicode character is (not) a valid XML \c NameStartChar + * \brief Assert that a Unicode character is a valid XML \c NameStartChar * - * \param[in] c Unicode code point of character to check - * \param[in] reference If \c true, \p c should be considered a valid - * \c NameStartChar; if \c false, it should not + * \param[in] code_pt Unicode code point of character to check (\c int) */ -static void -assert_name_start_char(int c, bool reference) -{ - gchar utf8_buf[6] = { 0, }; - int len = 4; - int ref_len = g_unichar_to_utf8(c, utf8_buf); - bool result = pcmk__xml_is_name_start_char(utf8_buf, &len); - - if (reference) { - assert_true(result); - } else { - assert_false(result); - } +#define assert_name_start_char(code_pt) \ + do { \ + gchar utf8_buf[6] = { 0, }; \ + int len = 4; \ + int ref_len = g_unichar_to_utf8(code_pt, utf8_buf); \ + \ + assert_true(pcmk__xml_is_name_start_char(utf8_buf, &len)); \ + assert_int_equal(len, ref_len); \ + } while (0) - if ((c < 0xD800) || (c > 0xDFFF)) { - /* Unicode code points in the range D800 to DFFF are UTF-16 surrogate - * pair halves. They can be represented in UTF-8, but they shouldn't - * appear in valid UTF-8-encoded text. RFC 3629 (Nov 2003) says they - * should be treated as invalid: - * https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling. - * - * GLib treats these characters as valid and returns a length of 3 - * bytes. So did libxml until v2.12 (commit 845bd99). Since that commit, - * libxml treats these characters as invalid and returns a length of 0. - * To avoid version-dependent testing behavior, skip the length check - * for code points in that range. - */ - assert_int_equal(len, ref_len); - } -} +/*! + * \internal + * \brief Assert that a Unicode character is not a valid XML \c NameStartChar + * + * \param[in] code_pt Unicode code point of character to check (\c int) + */ +#define assert_not_name_start_char(code_pt) \ + do { \ + gchar utf8_buf[6] = { 0, }; \ + int len = 4; \ + int ref_len = g_unichar_to_utf8(code_pt, utf8_buf); \ + \ + assert_false(pcmk__xml_is_name_start_char(utf8_buf, &len)); \ + assert_int_equal(len, ref_len); \ + } while (0) static void null_len(void **state) @@ -69,9 +61,9 @@ ascii(void **state) { for (int c = 0x00; c <= 0x7F; c++) { if (g_ascii_isalpha(c) || c == ':' || c == '_') { - assert_name_start_char(c, true); + assert_name_start_char(c); } else { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } } @@ -80,7 +72,7 @@ static void unicode_0x80_to_0xBF(void **state) { for (int c = 0x80; c <= 0xBF; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -88,35 +80,35 @@ static void unicode_0xC0_to_0xD6(void **state) { for (int c = 0xC0; c <= 0xD6; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } static void unicode_0xD7(void **state) { - assert_name_start_char(0xD7, false); + assert_not_name_start_char(0xD7); } static void unicode_0xD8_to_0xF6(void **state) { for (int c = 0xD8; c <= 0xF6; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } static void unicode_0xF7(void **state) { - assert_name_start_char(0xF7, false); + assert_not_name_start_char(0xF7); } static void unicode_0xF8_to_0x2FF(void **state) { for (int c = 0xF8; c <= 0x2FF; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -124,7 +116,7 @@ static void unicode_0x300_to_0x36F(void **state) { for (int c = 0x300; c <= 0x36F; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -132,21 +124,21 @@ static void unicode_0x370_to_0x37D(void **state) { for (int c = 0x370; c <= 0x37D; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } static void unicode_0x37E(void **state) { - assert_name_start_char(0x37E, false); + assert_not_name_start_char(0x37E); } static void unicode_0x37F_to_0x1FFF(void **state) { for (int c = 0x37F; c <= 0x1FFF; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -154,7 +146,7 @@ static void unicode_0x2000_to_0x200B(void **state) { for (int c = 0x2000; c <= 0x200B; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -162,7 +154,7 @@ static void unicode_0x200C_to_0x200D(void **state) { for (int c = 0x200C; c <= 0x200D; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -170,7 +162,7 @@ static void unicode_0x200E_to_0x206F(void **state) { for (int c = 0x200E; c <= 0x206F; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -178,7 +170,7 @@ static void unicode_0x2070_to_0x218F(void **state) { for (int c = 0x2070; c <= 0x218F; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -186,7 +178,7 @@ static void unicode_0x2190_to_0x2BFF(void **state) { for (int c = 0x2190; c <= 0x2BFF; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -194,7 +186,7 @@ static void unicode_0x2C00_to_0x2FEF(void **state) { for (int c = 0x2C00; c <= 0x2FEF; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -202,7 +194,7 @@ static void unicode_0x2FF0_to_0x3000(void **state) { for (int c = 0x2FF0; c <= 0x3000; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -210,15 +202,39 @@ static void unicode_0x3001_to_0xD7FF(void **state) { for (int c = 0x3001; c <= 0xD7FF; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); + } +} + +static void +unicode_0xD800_to_0xDFFF(void **state) +{ + /* Unicode code points in the range D800 to DFFF are UTF-16 surrogate pair + * halves. They can be represented in UTF-8, but they shouldn't appear in + * valid UTF-8-encoded text. RFC 3629 (Nov 2003) says they should be treated + * as invalid: + * https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling. + * + * GLib treats these characters as valid and returns a length of 3 bytes. So + * did libxml until v2.12 (commit 845bd99). Since that commit, libxml treats + * these characters as invalid and returns a length of 0. To avoid version- + * dependent testing behavior, skip the length check for code points in that + * range. This means we don't use the helper. + */ + for (int c = 0xD800; c <= 0xDFFF; c++) { + gchar utf8_buf[6] = { 0, }; + + g_unichar_to_utf8(c, utf8_buf); + + assert_false(pcmk__xml_is_name_start_char(utf8_buf, NULL)); } } static void -unicode_0xD800_to_0xF8FF(void **state) +unicode_0xE000_to_0xF8FF(void **state) { - for (int c = 0xD800; c <= 0xF8FF; c++) { - assert_name_start_char(c, false); + for (int c = 0xE000; c <= 0xF8FF; c++) { + assert_not_name_start_char(c); } } @@ -226,7 +242,7 @@ static void unicode_0xF900_to_0xFDCF(void **state) { for (int c = 0xF900; c <= 0xFDCF; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -234,7 +250,7 @@ static void unicode_0xFDD0_to_0xFDEF(void **state) { for (int c = 0xFDD0; c <= 0xFDEF; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -242,7 +258,7 @@ static void unicode_0xFDF0_to_0xFFFD(void **state) { for (int c = 0xFDF0; c <= 0xFFFD; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -250,7 +266,7 @@ static void unicode_0xFFFE_to_0xFFFF(void **state) { for (int c = 0xFFFE; c <= 0xFFFF; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -258,7 +274,7 @@ static void unicode_0x10000_to_0xEFFFF(void **state) { for (int c = 0x10000; c <= 0xEFFFF; c++) { - assert_name_start_char(c, true); + assert_name_start_char(c); } } @@ -266,7 +282,7 @@ static void unicode_0xF0000_to_0x10FFFF(void **state) { for (int c = 0xF0000; c <= 0x10FFFF; c++) { - assert_name_start_char(c, false); + assert_not_name_start_char(c); } } @@ -291,7 +307,8 @@ PCMK__UNIT_TEST(NULL, NULL, cmocka_unit_test(unicode_0x2C00_to_0x2FEF), cmocka_unit_test(unicode_0x2FF0_to_0x3000), cmocka_unit_test(unicode_0x3001_to_0xD7FF), - cmocka_unit_test(unicode_0xD800_to_0xF8FF), + cmocka_unit_test(unicode_0xD800_to_0xDFFF), + cmocka_unit_test(unicode_0xE000_to_0xF8FF), cmocka_unit_test(unicode_0xF900_to_0xFDCF), cmocka_unit_test(unicode_0xFDD0_to_0xFDEF), cmocka_unit_test(unicode_0xFDF0_to_0xFFFD), diff --git a/lib/common/tests/xml/pcmk__xml_sanitize_id_test.c b/lib/common/tests/xml/pcmk__xml_sanitize_id_test.c index cdf2ed9ed87..95976122ed3 100644 --- a/lib/common/tests/xml/pcmk__xml_sanitize_id_test.c +++ b/lib/common/tests/xml/pcmk__xml_sanitize_id_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 the Pacemaker project contributors + * Copyright 2024-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -11,15 +11,14 @@ #include -static void -assert_sanitized(const char *str, const char *reference) -{ - char *buf = pcmk__str_copy(str); - - pcmk__xml_sanitize_id(buf); - assert_string_equal(buf, reference); - free(buf); -} +#define assert_sanitized(str, expected) \ + do { \ + char *buf = pcmk__str_copy(str); \ + \ + pcmk__xml_sanitize_id(buf); \ + assert_string_equal(buf, expected); \ + free(buf); \ + } while (0) static void null_empty(void **state) diff --git a/lib/common/tests/xml_comment/pcmk__xc_create_test.c b/lib/common/tests/xml_comment/pcmk__xc_create_test.c index 280c50ae420..c61bba845de 100644 --- a/lib/common/tests/xml_comment/pcmk__xc_create_test.c +++ b/lib/common/tests/xml_comment/pcmk__xc_create_test.c @@ -18,39 +18,30 @@ * hassle. */ -static void -assert_comment(const char *content) -{ - xmlDoc *doc = pcmk__xml_new_doc(); - xml_doc_private_t *docpriv = doc->_private; - xmlNode *node = NULL; - xml_node_private_t *nodepriv = NULL; - - pcmk__xml_doc_set_flags(doc, pcmk__xf_tracking); - - node = pcmk__xc_create(doc, content); - assert_non_null(node); - assert_int_equal(node->type, XML_COMMENT_NODE); - assert_ptr_equal(node->doc, doc); - - if (content == NULL) { - assert_null(node->content); - } else { - assert_non_null(node->content); - assert_string_equal((const char *) node->content, content); - } - - nodepriv = node->_private; - assert_non_null(nodepriv); - assert_int_equal(nodepriv->check, PCMK__XML_NODE_PRIVATE_MAGIC); - assert_true(pcmk__all_flags_set(nodepriv->flags, - pcmk__xf_dirty|pcmk__xf_created)); +#define CONTENT "some content" - assert_true(pcmk__is_set(docpriv->flags, pcmk__xf_dirty)); - - pcmk__xml_free(node); - pcmk__xml_free_doc(doc); -} +#define assert_create_comment(content, doc_ptr, node_ptr) \ + do { \ + xml_doc_private_t *docpriv = NULL; \ + xml_node_private_t *nodepriv = NULL; \ + \ + *(doc_ptr) = pcmk__xml_new_doc(); \ + pcmk__xml_doc_set_flags(*(doc_ptr), pcmk__xf_tracking); \ + \ + *(node_ptr) = pcmk__xc_create(*(doc_ptr), content); \ + assert_non_null(*(node_ptr)); \ + assert_int_equal((*(node_ptr))->type, XML_COMMENT_NODE); \ + assert_ptr_equal((*(node_ptr))->doc, *(doc_ptr)); \ + \ + docpriv = (*(doc_ptr))->_private; \ + assert_true(pcmk__is_set(docpriv->flags, pcmk__xf_dirty)); \ + \ + nodepriv = (*(node_ptr))->_private; \ + assert_non_null(nodepriv); \ + assert_int_equal(nodepriv->check, PCMK__XML_NODE_PRIVATE_MAGIC); \ + assert_true(pcmk__all_flags_set(nodepriv->flags, \ + pcmk__xf_dirty|pcmk__xf_created)); \ + } while (0) static void null_doc(void **state) @@ -62,8 +53,21 @@ null_doc(void **state) static void with_doc(void **state) { - assert_comment(NULL); - assert_comment("some content"); + xmlDoc *doc = NULL; + xmlNode *node = NULL; + + assert_create_comment(NULL, &doc, &node); + assert_null(node->content); + + g_clear_pointer(&node, pcmk__xml_free); + g_clear_pointer(&doc, pcmk__xml_free_doc); + + assert_create_comment(CONTENT, &doc, &node); + assert_non_null(node->content); + assert_string_equal((const char *) node->content, CONTENT); + + g_clear_pointer(&node, pcmk__xml_free); + g_clear_pointer(&doc, pcmk__xml_free_doc); } PCMK__UNIT_TEST(pcmk__xml_test_setup_group, pcmk__xml_test_teardown_group, diff --git a/lib/common/tests/xml_element/pcmk__xe_get_flags_test.c b/lib/common/tests/xml_element/pcmk__xe_get_flags_test.c index 7f26333496b..4fe1533330e 100644 --- a/lib/common/tests/xml_element/pcmk__xe_get_flags_test.c +++ b/lib/common/tests/xml_element/pcmk__xe_get_flags_test.c @@ -17,29 +17,28 @@ #include #include +#define ATTR_NAME "attribute" #define DEFAULT_VALUE 0xfff -static void -assert_flags(const char *value, int expected_rc, unsigned int expected_flags) -{ - int rc = pcmk_rc_ok; - uint32_t flags = 0U; - xmlNode *xml = pcmk__xe_create(NULL, "element"); - - assert_non_null(xml); - pcmk__xe_set(xml, "attribute", value); - - // Without output argument - assert_int_equal(pcmk__xe_get_flags(xml, "attribute", NULL, DEFAULT_VALUE), - expected_rc); - - // With output argument - rc = pcmk__xe_get_flags(xml, "attribute", &flags, DEFAULT_VALUE); - assert_int_equal(rc, expected_rc); - assert_true(flags == expected_flags); - - pcmk__xml_free(xml); -} +#define assert_flags(value, expected_rc, expected_flags) \ + do { \ + int rc = pcmk_rc_ok; \ + uint32_t flags = 0; \ + xmlNode *xml = pcmk__xe_create(NULL, "element"); \ + \ + pcmk__xe_set(xml, ATTR_NAME, value); \ + \ + /* Without output argument */ \ + rc = pcmk__xe_get_flags(xml, ATTR_NAME, NULL, DEFAULT_VALUE); \ + assert_int_equal(rc, expected_rc); \ + \ + /* With output argument */ \ + rc = pcmk__xe_get_flags(xml, ATTR_NAME, &flags, DEFAULT_VALUE); \ + assert_int_equal(rc, expected_rc); \ + assert_true(flags == expected_flags); \ + \ + pcmk__xml_free(xml); \ + } while (0) static void null_name_invalid(void **state) @@ -74,10 +73,10 @@ null_xml_default(void **state) int rc = pcmk_rc_ok; uint32_t flags = 0U; - assert_int_equal(pcmk__xe_get_flags(NULL, "attribute", NULL, DEFAULT_VALUE), + assert_int_equal(pcmk__xe_get_flags(NULL, ATTR_NAME, NULL, DEFAULT_VALUE), pcmk_rc_ok); - rc = pcmk__xe_get_flags(NULL, "attribute", &flags, DEFAULT_VALUE); + rc = pcmk__xe_get_flags(NULL, ATTR_NAME, &flags, DEFAULT_VALUE); assert_int_equal(rc, pcmk_rc_ok); assert_true(flags == DEFAULT_VALUE); } diff --git a/lib/common/tests/xml_element/pcmk__xe_get_score_test.c b/lib/common/tests/xml_element/pcmk__xe_get_score_test.c index ef2acce9ae5..776b7fa011f 100644 --- a/lib/common/tests/xml_element/pcmk__xe_get_score_test.c +++ b/lib/common/tests/xml_element/pcmk__xe_get_score_test.c @@ -14,25 +14,23 @@ #include #include -extern int pcmk__score_red; -extern int pcmk__score_green; -extern int pcmk__score_yellow; +#define ATTR_NAME "test_attr" static int default_score = 99; -static void -assert_score(const char *score_s, int expected_rc, int expected_score) -{ - int score = 0; - int rc = pcmk_rc_ok; - xmlNode *xml = pcmk__xe_create(NULL, __func__); - - pcmk__xe_set(xml, "test_attr", score_s); - rc = pcmk__xe_get_score(xml, "test_attr", &score, default_score); - assert_int_equal(rc, expected_rc); - assert_int_equal(score, expected_score); - pcmk__xml_free(xml); -} +#define assert_score(score_s, expected_rc, expected_score) \ + do { \ + int rc = pcmk_rc_ok; \ + int score = 0; \ + xmlNode *xml = pcmk__xe_create(NULL, __func__); \ + \ + pcmk__xe_set(xml, ATTR_NAME, score_s); \ + \ + rc = pcmk__xe_get_score(xml, ATTR_NAME, &score, default_score); \ + assert_int_equal(rc, expected_rc); \ + assert_int_equal(score, expected_score); \ + pcmk__xml_free(xml); \ + } while (0) static void invalid_args(void **state) @@ -70,15 +68,15 @@ null_score(void **state) { xmlNode *xml = pcmk__xe_create(NULL, __func__); - assert_int_equal(pcmk__xe_get_score(xml, "test_attr", NULL, default_score), + assert_int_equal(pcmk__xe_get_score(xml, ATTR_NAME, NULL, default_score), pcmk_rc_ok); - pcmk__xe_set(xml, "test_attr", "0"); - assert_int_equal(pcmk__xe_get_score(xml, "test_attr", NULL, default_score), + pcmk__xe_set(xml, ATTR_NAME, "0"); + assert_int_equal(pcmk__xe_get_score(xml, ATTR_NAME, NULL, default_score), pcmk_rc_ok); - pcmk__xe_set(xml, "test_attr", "foo"); - assert_int_equal(pcmk__xe_get_score(xml, "test_attr", NULL, default_score), + pcmk__xe_set(xml, ATTR_NAME, "foo"); + assert_int_equal(pcmk__xe_get_score(xml, ATTR_NAME, NULL, default_score), pcmk_rc_bad_input); pcmk__xml_free(xml); diff --git a/lib/common/tests/xml_element/pcmk__xe_set_score_test.c b/lib/common/tests/xml_element/pcmk__xe_set_score_test.c index 08b1a8d3c88..356368a958a 100644 --- a/lib/common/tests/xml_element/pcmk__xe_set_score_test.c +++ b/lib/common/tests/xml_element/pcmk__xe_set_score_test.c @@ -15,68 +15,74 @@ #include "crmcommon_private.h" // pcmk__xe_set_score() +#define ATTR_NAME "test_attr" + /*! * \internal - * \brief Update an XML attribute value and check it against a reference value + * \brief Update an XML attribute value and check it against the expected value * - * The attribute name is hard-coded as \c "X". + * The attribute name is hard-coded as \c ATTR_NAME. * - * \param[in] initial Initial value - * \param[in] new Value to set - * \param[in] reference_val Expected attribute value after update - * \param[in] reference_rc Expected return code from \c pcmk__xe_set_score() + * \param[in] initial Initial value (const char *) + * \param[in] new Value to set (const char *) + * \param[in] expected_value Expected attribute value after update + * (const char *) + * \param[in] expected_rc Expected return code from \c pcmk__xe_set_score() + * (\c int) */ -static void -assert_set_score(const char *initial, const char *new, - const char *reference_val, int reference_rc) -{ - const char *name = "X"; - xmlNode *test_xml = pcmk__xe_create(NULL, "test_xml"); - - pcmk__xe_set(test_xml, name, initial); - assert_int_equal(pcmk__xe_set_score(test_xml, name, new), reference_rc); - assert_string_equal(pcmk__xe_get(test_xml, name), reference_val); - - pcmk__xml_free(test_xml); -} +#define assert_set_score(initial, new, expected_value, expected_rc) \ + do { \ + xmlNode *test_xml = pcmk__xe_create(NULL, "test_xml"); \ + \ + pcmk__xe_set(test_xml, ATTR_NAME, initial); \ + \ + assert_int_equal(pcmk__xe_set_score(test_xml, ATTR_NAME, new), \ + expected_rc); \ + assert_string_equal(pcmk__xe_get(test_xml, ATTR_NAME), \ + expected_value); \ + \ + pcmk__xml_free(test_xml); \ + } while (0) static void -value_is_name_plus_plus(void **state) +new_value_name_plus_plus(void **state) { - assert_set_score("5", "X++", "6", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "++", "6", pcmk_rc_ok); } static void -value_is_name_plus_equals_integer(void **state) +new_value_name_plus_equals_integer(void **state) { - assert_set_score("5", "X+=2", "7", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "+=2", "7", pcmk_rc_ok); } // NULL input static void -target_is_NULL(void **state) +null_target(void **state) { // Dumps core via CRM_CHECK() - assert_int_equal(pcmk__xe_set_score(NULL, "X", "X++"), EINVAL); + assert_int_equal(pcmk__xe_set_score(NULL, ATTR_NAME, ATTR_NAME "++"), + EINVAL); } static void -name_is_NULL(void **state) +null_name(void **state) { xmlNode *test_xml = pcmk__xe_create(NULL, "test_xml"); - pcmk__xe_set(test_xml, "X", "5"); + pcmk__xe_set(test_xml, ATTR_NAME, "5"); // Dumps core via CRM_CHECK() - assert_int_equal(pcmk__xe_set_score(test_xml, NULL, "X++"), EINVAL); - assert_string_equal(pcmk__xe_get(test_xml, "X"), "5"); + assert_int_equal(pcmk__xe_set_score(test_xml, NULL, ATTR_NAME "++"), + EINVAL); + assert_string_equal(pcmk__xe_get(test_xml, ATTR_NAME), "5"); pcmk__xml_free(test_xml); } static void -value_is_NULL(void **state) +null_new_value(void **state) { assert_set_score("5", NULL, "5", pcmk_rc_ok); } @@ -84,13 +90,14 @@ value_is_NULL(void **state) // the value input doesn't start with the name input static void -value_is_wrong_name(void **state) +new_value_wrong_name(void **state) { - assert_set_score("5", "Y++", "Y++", pcmk_rc_ok); + assert_set_score("5", "garbage" ATTR_NAME "++", "garbage" ATTR_NAME "++", + pcmk_rc_ok); } static void -value_is_only_an_integer(void **state) +new_value_bare_integer(void **state) { assert_set_score("5", "2", "2", pcmk_rc_ok); } @@ -98,91 +105,62 @@ value_is_only_an_integer(void **state) // non-integers static void -variable_is_initialized_to_be_non_numeric(void **state) +initial_value_non_numeric(void **state) { - assert_set_score("hello", "X++", "1", pcmk_rc_ok); + assert_set_score("hello", ATTR_NAME "++", "1", pcmk_rc_ok); + assert_set_score("hello", ATTR_NAME "+=2", "2", pcmk_rc_ok); } static void -variable_is_initialized_to_be_non_numeric_2(void **state) +initial_value_decimal(void **state) { - assert_set_score("hello", "X+=2", "2", pcmk_rc_ok); + assert_set_score("5.01", ATTR_NAME "++", "6", pcmk_rc_ok); + assert_set_score("5.50", ATTR_NAME "++", "6", pcmk_rc_ok); + assert_set_score("5.99", ATTR_NAME "++", "6", pcmk_rc_ok); } static void -variable_is_initialized_to_be_numeric_and_decimal_point_containing(void **state) +new_value_non_numeric(void **state) { - assert_set_score("5.01", "X++", "6", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "+=hello", "5", pcmk_rc_ok); } static void -variable_is_initialized_to_be_numeric_and_decimal_point_containing_2(void **state) +new_value_decimal(void **state) { - assert_set_score("5.50", "X++", "6", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "+=2.01", "7", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "+=1.50", "6", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "+=1.99", "6", pcmk_rc_ok); } static void -variable_is_initialized_to_be_numeric_and_decimal_point_containing_3(void **state) -{ - assert_set_score("5.99", "X++", "6", pcmk_rc_ok); -} - -static void -value_is_non_numeric(void **state) -{ - assert_set_score("5", "X+=hello", "5", pcmk_rc_ok); -} - -static void -value_is_numeric_and_decimal_point_containing(void **state) -{ - assert_set_score("5", "X+=2.01", "7", pcmk_rc_ok); -} - -static void -value_is_numeric_and_decimal_point_containing_2(void **state) -{ - assert_set_score("5", "X+=1.50", "6", pcmk_rc_ok); -} - -static void -value_is_numeric_and_decimal_point_containing_3(void **state) -{ - assert_set_score("5", "X+=1.99", "6", pcmk_rc_ok); -} - -// undefined input - -static void -name_is_undefined(void **state) +initial_value_unset(void **state) { - assert_set_score(NULL, "X++", "X++", pcmk_rc_ok); + assert_set_score(NULL, ATTR_NAME "++", ATTR_NAME "++", pcmk_rc_ok); } -// large input +// https://gcc.gnu.org/onlinedocs/gcc-15.2.0/cpp/Stringizing.html +#define xstr(s) str(s) +#define str(s) #s static void -assignment_result_is_too_large(void **state) +new_value_overflows(void **state) { - assert_set_score("5", "X+=100000000000", "1000000", pcmk_rc_ok); + assert_set_score("5", ATTR_NAME "+=100000000000", xstr(PCMK_SCORE_INFINITY), + pcmk_rc_ok); } PCMK__UNIT_TEST(pcmk__xml_test_setup_group, pcmk__xml_test_teardown_group, - cmocka_unit_test(value_is_name_plus_plus), - cmocka_unit_test(value_is_name_plus_equals_integer), - cmocka_unit_test(target_is_NULL), - cmocka_unit_test(name_is_NULL), - cmocka_unit_test(value_is_NULL), - cmocka_unit_test(value_is_wrong_name), - cmocka_unit_test(value_is_only_an_integer), - cmocka_unit_test(variable_is_initialized_to_be_non_numeric), - cmocka_unit_test(variable_is_initialized_to_be_non_numeric_2), - cmocka_unit_test(variable_is_initialized_to_be_numeric_and_decimal_point_containing), - cmocka_unit_test(variable_is_initialized_to_be_numeric_and_decimal_point_containing_2), - cmocka_unit_test(variable_is_initialized_to_be_numeric_and_decimal_point_containing_3), - cmocka_unit_test(value_is_non_numeric), - cmocka_unit_test(value_is_numeric_and_decimal_point_containing), - cmocka_unit_test(value_is_numeric_and_decimal_point_containing_2), - cmocka_unit_test(value_is_numeric_and_decimal_point_containing_3), - cmocka_unit_test(name_is_undefined), - cmocka_unit_test(assignment_result_is_too_large)) + cmocka_unit_test(new_value_name_plus_plus), + cmocka_unit_test(new_value_name_plus_equals_integer), + cmocka_unit_test(null_target), + cmocka_unit_test(null_name), + cmocka_unit_test(null_new_value), + cmocka_unit_test(new_value_wrong_name), + cmocka_unit_test(new_value_bare_integer), + cmocka_unit_test(initial_value_non_numeric), + cmocka_unit_test(initial_value_decimal), + cmocka_unit_test(new_value_non_numeric), + cmocka_unit_test(new_value_decimal), + cmocka_unit_test(initial_value_unset), + cmocka_unit_test(new_value_overflows)) diff --git a/lib/common/tests/xml_element/pcmk__xe_sort_attrs_test.c b/lib/common/tests/xml_element/pcmk__xe_sort_attrs_test.c index e7aad245639..31d4267c0c3 100644 --- a/lib/common/tests/xml_element/pcmk__xe_sort_attrs_test.c +++ b/lib/common/tests/xml_element/pcmk__xe_sort_attrs_test.c @@ -25,63 +25,71 @@ * preserved. * * \param[in,out] test_xml XML whose attributes to sort + * (xmlNode *) * \param[in] reference_xml XML whose attribute order to compare against * (attributes must have the same values as in - * \p test_xml) + * \p test_xml) (const xmlNode *) */ -static void -assert_order(xmlNode *test_xml, const xmlNode *reference_xml) -{ - GHashTable *attr_flags = pcmk__strkey_table(free, NULL); - xmlAttr *test_attr = NULL; - xmlAttr *ref_attr = NULL; - - // Save original flags - for (xmlAttr *attr = pcmk__xe_first_attr(test_xml); attr != NULL; - attr = attr->next) { - - xml_node_private_t *nodepriv = attr->_private; - uint32_t flags = (nodepriv != NULL)? nodepriv->flags : pcmk__xf_none; - - g_hash_table_insert(attr_flags, - pcmk__str_copy((const char *) attr->name), - GUINT_TO_POINTER((guint) flags)); - } - - pcmk__xe_sort_attrs(test_xml); - - test_attr = pcmk__xe_first_attr(test_xml); - ref_attr = pcmk__xe_first_attr(reference_xml); - - for (; (test_attr != NULL) && (ref_attr != NULL); - test_attr = test_attr->next, ref_attr = ref_attr->next) { - - const char *test_name = (const char *) test_attr->name; - xml_node_private_t *nodepriv = test_attr->_private; - uint32_t flags = (nodepriv != NULL)? nodepriv->flags : pcmk__xf_none; - - gpointer old_flags_ptr = g_hash_table_lookup(attr_flags, test_name); - uint32_t old_flags = pcmk__xf_none; - - if (old_flags_ptr != NULL) { - old_flags = GPOINTER_TO_UINT(old_flags_ptr); - } - - // Flags must not change - assert_true(flags == old_flags); - - // Attributes must be in expected order with expected values - assert_string_equal(test_name, (const char *) ref_attr->name); - assert_string_equal(pcmk__xml_attr_value(test_attr), - pcmk__xml_attr_value(ref_attr)); - } - - // Attribute lists must be the same length - assert_null(test_attr); - assert_null(ref_attr); - - g_hash_table_destroy(attr_flags); -} +#define assert_order(test_xml, reference_xml) \ + do { \ + GHashTable *attr_flags = pcmk__strkey_table(free, NULL); \ + xmlAttr *test_attr = NULL; \ + xmlAttr *ref_attr = NULL; \ + \ + /* Save original flags */ \ + for (xmlAttr *attr = pcmk__xe_first_attr(test_xml); attr != NULL; \ + attr = attr->next) { \ + \ + xml_node_private_t *nodepriv = attr->_private; \ + uint32_t flags = pcmk__xf_none; \ + \ + if (nodepriv != NULL) { \ + flags = nodepriv->flags; \ + } \ + \ + g_hash_table_insert(attr_flags, \ + pcmk__str_copy((const char *) attr->name), \ + GUINT_TO_POINTER((guint) flags)); \ + } \ + \ + pcmk__xe_sort_attrs(test_xml); \ + \ + test_attr = pcmk__xe_first_attr(test_xml); \ + ref_attr = pcmk__xe_first_attr(reference_xml); \ + \ + for (; (test_attr != NULL) && (ref_attr != NULL); \ + test_attr = test_attr->next, ref_attr = ref_attr->next) { \ + \ + const char *test_name = (const char *) test_attr->name; \ + xml_node_private_t *nodepriv = test_attr->_private; \ + gpointer old_flags_ptr = NULL; \ + uint32_t flags = pcmk__xf_none; \ + uint32_t old_flags = pcmk__xf_none; \ + \ + if (nodepriv != NULL) { \ + flags = nodepriv->flags; \ + } \ + \ + old_flags_ptr = g_hash_table_lookup(attr_flags, test_name); \ + if (old_flags_ptr != NULL) { \ + old_flags = GPOINTER_TO_UINT(old_flags_ptr); \ + } \ + \ + /* Flags must not change */ \ + assert_true(flags == old_flags); \ + \ + /* Attributes must be in expected order with expected values */ \ + assert_string_equal(test_name, (const char *) ref_attr->name); \ + assert_string_equal(pcmk__xml_attr_value(test_attr), \ + pcmk__xml_attr_value(ref_attr)); \ + } \ + \ + /* Attribute lists must be the same length */ \ + assert_null(test_attr); \ + assert_null(ref_attr); \ + \ + g_hash_table_destroy(attr_flags); \ + } while (0) static void null_arg(void **state) diff --git a/lib/common/tests/xml_idref/pcmk__xe_dereference_children_test.c b/lib/common/tests/xml_idref/pcmk__xe_dereference_children_test.c index 103b0121f4b..5f4a8bec0a9 100644 --- a/lib/common/tests/xml_idref/pcmk__xe_dereference_children_test.c +++ b/lib/common/tests/xml_idref/pcmk__xe_dereference_children_test.c @@ -13,97 +13,115 @@ #include -/*! - * \internal - * \brief Test an invocation of pcmk__xe_dereference_children() - * - * \param[in] xml_string XML to parse, with "test" child to pass to tested - * function - * \param[in] element_name Element name to pass to tested function - * \param[in] ... NULL-terminated list of child "testattr" values to - * expect in tested function's returned list - */ -static void -assert_deref(const char *xml_string, const char *element_name, ...) +#define TEST_ELEMENT "test" +#define TEST_ATTR "test_attr" + +// C requires at least one named argument before a variadic argument list +static GHashTable * +create_id_table(const void *dummy, ...) { - xmlNode *xml = NULL; - GList *list = NULL; + va_list args; GHashTable *table = NULL; - va_list ap; - // Parse given XML - if (xml_string != NULL) { - xml = pcmk__xml_parse(xml_string); - assert_non_null(xml); - } + va_start(args, dummy); + + for (const char *value = va_arg(args, const char *); value != NULL; + value = va_arg(args, const char *)) { - // Create a hash table with all expected child IDs - va_start(ap, element_name); - for (const char *value = va_arg(ap, const char *); - value != NULL; value = va_arg(ap, const char *)) { if (table == NULL) { table = pcmk__strkey_table(NULL, NULL); } g_hash_table_add(table, (gpointer) value); } - va_end(ap); - - // Call tested function on "test" child - list = pcmk__xe_dereference_children(pcmk__xe_first_child(xml, "test", - NULL, NULL), - element_name); - - // Ensure returned list has exactly the expected child IDs - if (table == NULL) { - assert_null(list); - } else { - while (list != NULL) { - const char *value = pcmk__xe_get((xmlNode *) list->data, - "testattr"); - - assert_true(g_hash_table_remove(table, value)); - list = list->next; - } - assert_int_equal(g_hash_table_size(table), 0); - } - g_list_free(list); - if (table != NULL) { - g_hash_table_destroy(table); - } - pcmk__xml_free(xml); + va_end(args); + + return table; } +/*! + * \internal + * \brief Test an invocation of \c pcmk__xe_dereference_children() + * + * \param[in] xml_string XML to parse, with \c TEST_ELEMENT child to pass + * to tested function (const char *) + * \param[in] element_name Element name to pass to tested function + * (const char *) + * \param[in] expected_values NULL-terminated list of child + * \c TEST_ATTR values to expect in tested + * function's returned list (list of + * const char *) + */ +#define assert_deref(xml_string, element_name, expected_values...) \ + do { \ + xmlNode *xml = NULL; \ + const xmlNode *test_element = NULL; \ + GHashTable *table = NULL; \ + GList *list = NULL; \ + \ + xml = pcmk__xml_parse(xml_string); \ + assert_non_null(xml); \ + \ + /* Create a hash table with all expected child IDs */ \ + table = create_id_table(NULL, expected_values); \ + \ + /* Call tested function on TEST_ELEMENT child */ \ + test_element = pcmk__xe_first_child(xml, TEST_ELEMENT, NULL, NULL); \ + list = pcmk__xe_dereference_children(test_element, element_name); \ + \ + /* Ensure returned list has exactly the expected child IDs */ \ + \ + if (table == NULL) { \ + assert_null(list); \ + pcmk__xml_free(xml); \ + break; \ + } \ + \ + for (GList *iter = list; iter != NULL; iter = iter->next) { \ + const xmlNode *node = iter->data; \ + const char *value = pcmk__xe_get(node, TEST_ATTR); \ + \ + assert_true(g_hash_table_remove(table, value)); \ + } \ + \ + assert_int_equal(g_hash_table_size(table), 0); \ + \ + g_hash_table_destroy(table); \ + g_list_free(list); \ + pcmk__xml_free(xml); \ + } while (0) + static void null_for_null(void **state) { - assert_deref(NULL, NULL, NULL); - assert_deref(NULL, "test", NULL); + assert_null(pcmk__xe_dereference_children(NULL, NULL)); + assert_null(pcmk__xe_dereference_children(NULL, TEST_ELEMENT)); } -#define XML_NO_CHILDREN "" -#define XML_NO_ELEMENT_CHILDREN "text" +#define XML_NO_CHILDREN "<" TEST_ELEMENT "/>" +#define XML_NO_ELEMENT_CHILDREN \ + "<" TEST_ELEMENT ">text" static void null_for_no_children(void **state) { assert_deref(XML_NO_CHILDREN, NULL, NULL); - assert_deref(XML_NO_CHILDREN, "test", NULL); + assert_deref(XML_NO_CHILDREN, TEST_ELEMENT, NULL); assert_deref(XML_NO_ELEMENT_CHILDREN, NULL, NULL); - assert_deref(XML_NO_ELEMENT_CHILDREN, "test", NULL); + assert_deref(XML_NO_ELEMENT_CHILDREN, TEST_ELEMENT, NULL); } -#define XML_NO_IDREF \ - "\n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ +#define XML_NO_IDREF \ + "\n" \ + " <" TEST_ELEMENT ">\n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ "\n" static void @@ -122,19 +140,19 @@ without_idref(void **state) assert_deref(XML_NO_IDREF, "nonexistent", NULL); } -#define XML_WITH_IDREF \ - "\n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ +#define XML_WITH_IDREF \ + "\n" \ + " \n" \ + " \n" \ + " <" TEST_ELEMENT ">\n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ "\n" static void @@ -153,17 +171,17 @@ with_idref(void **state) assert_deref(XML_WITH_IDREF, "nonexistent", NULL); } -#define XML_WITH_BROKEN_IDREF \ - "\n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ +#define XML_WITH_BROKEN_IDREF \ + "\n" \ + " <" TEST_ELEMENT ">\n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ "\n" static void diff --git a/lib/common/unittest.c b/lib/common/unittest.c index 66fa748af0c..3da2f293919 100644 --- a/lib/common/unittest.c +++ b/lib/common/unittest.c @@ -202,32 +202,19 @@ fake_text_err(pcmk__output_t *out, const char *format, ...) } } -pcmk__output_t * -pcmk__mk_fake_text_output(char **argv) +void +pcmk__output_setup_fake_text(pcmk__output_t *out) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = "text"; - - retval->init = fake_text_init; - retval->free_priv = fake_text_free_priv; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->err = fake_text_err; - - return retval; + out->fmt_name = "text"; + out->init = fake_text_init; + out->free_priv = fake_text_free_priv; + out->err = fake_text_err; } int pcmk__output_test_setup_group(void **state) { - pcmk__register_format(NULL, "text", pcmk__mk_fake_text_output, NULL); + pcmk__register_format(NULL, "text", pcmk__output_setup_fake_text, NULL); return 0; } @@ -268,16 +255,16 @@ pcmk__expect_fake_text_err(void) expect_function_call(fake_text_err); } -pcmk__output_t * -pcmk__output_null_create1(char **argv) +void +pcmk__output_setup_dummy1(pcmk__output_t *out) { - return NULL; + return; } -pcmk__output_t * -pcmk__output_null_create2(char **argv) +void +pcmk__output_setup_dummy2(pcmk__output_t *out) { - return NULL; + return; } int diff --git a/lib/common/utils.c b/lib/common/utils.c index 9c0c115e5e8..bcb5ec8b856 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -242,7 +242,8 @@ pcmk__compare_versions(const char *version1, const char *version2) segments1 = g_strsplit(pcmk__s(match1, ""), ".", 0); segments2 = g_strsplit(pcmk__s(match2, ""), ".", 0); - for (gchar **segment1 = segments1, **segment2 = segments2; + for (const char *const *segment1 = (const char *const *) segments1, + *const *segment2 = (const char *const *) segments2; (*segment1 != NULL) || (*segment2 != NULL); ) { long long value1 = 0; diff --git a/lib/common/xml_display.c b/lib/common/xml_display.c index 26dfb7f44ca..4623817b719 100644 --- a/lib/common/xml_display.c +++ b/lib/common/xml_display.c @@ -121,7 +121,8 @@ show_xml_element(pcmk__output_t *out, GString *buffer, const char *prefix, if ((hidden != NULL) && !pcmk__str_empty(p_name)) { gchar **hidden_names = g_strsplit(hidden, ",", 0); - if (pcmk__g_strv_contains(hidden_names, p_name)) { + if (pcmk__g_strv_contains((const gchar *const *) hidden_names, + p_name)) { p_value = "*****"; } g_strfreev(hidden_names); diff --git a/lib/lrmd/lrmd_alerts.c b/lib/lrmd/lrmd_alerts.c index 3fba9d47bd1..da3e86a46fe 100644 --- a/lib/lrmd/lrmd_alerts.c +++ b/lib/lrmd/lrmd_alerts.c @@ -125,14 +125,16 @@ exec_alert_list(lrmd_t *lrmd, const GList *alert_list, } if (kind == pcmk__alert_attribute) { + const gchar *const *select_attr_name = + (const gchar *const *) entry->select_attribute_name; + if (attr_name == NULL) { CRM_LOG_ASSERT(attr_name != NULL); continue; } - if ((entry->select_attribute_name != NULL) - && !pcmk__g_strv_contains(entry->select_attribute_name, - attr_name)) { + if ((select_attr_name != NULL) + && !pcmk__g_strv_contains(select_attr_name, attr_name)) { pcmk__trace("Filtering unwanted attribute '%s' alert to %s via " "%s", attr_name, entry->recipient, entry->id); diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c index 90438ded189..63270fa6d16 100644 --- a/lib/pacemaker/pcmk_cluster_queries.c +++ b/lib/pacemaker/pcmk_cluster_queries.c @@ -865,24 +865,28 @@ pcmk__list_nodes(pcmk__output_t *out, const char *types, bool bash_export) all = pcmk__str_empty(types); if (!all) { node_types = g_strsplit(types, ",", 0); - all = pcmk__g_strv_contains(node_types, "all"); + all = pcmk__g_strv_contains((const gchar *const *) node_types, "all"); } - if (all || pcmk__g_strv_contains(node_types, "cluster")) { + if (all + || pcmk__g_strv_contains((const gchar *const *) node_types, + "cluster")) { data.field = PCMK_XA_ID; data.type = "cluster"; pcmk__xpath_foreach_result(xml_node->doc, PCMK__XP_MEMBER_NODE_CONFIG, remote_node_print_helper, &data); } - if (all || pcmk__g_strv_contains(node_types, "guest")) { + if (all + || pcmk__g_strv_contains((const gchar *const *) node_types, "guest")) { data.field = PCMK_XA_VALUE; data.type = "guest"; pcmk__xpath_foreach_result(xml_node->doc, PCMK__XP_GUEST_NODE_CONFIG, remote_node_print_helper, &data); } - if (all || pcmk__g_strv_contains(node_types, "remote")) { + if (all + || pcmk__g_strv_contains((const gchar *const *) node_types, "remote")) { data.field = PCMK_XA_ID; data.type = "remote"; pcmk__xpath_foreach_result(xml_node->doc, PCMK__XP_REMOTE_NODE_CONFIG, diff --git a/lib/pacemaker/pcmk_rule.c b/lib/pacemaker/pcmk_rule.c index 39bd2d97063..7ded5d3aa5a 100644 --- a/lib/pacemaker/pcmk_rule.c +++ b/lib/pacemaker/pcmk_rule.c @@ -161,7 +161,7 @@ eval_rule(pcmk_scheduler_t *scheduler, const char *rule_id, const char **error) */ int pcmk__check_rules(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *date, - const char **rule_ids) + const char *const *rule_ids) { pcmk_scheduler_t *scheduler = NULL; int rc = pcmk_rc_ok; @@ -178,7 +178,7 @@ pcmk__check_rules(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *date, return rc; } - for (const char **rule_id = rule_ids; *rule_id != NULL; rule_id++) { + for (const char *const *rule_id = rule_ids; *rule_id != NULL; rule_id++) { const char *error = NULL; int last_rc = eval_rule(scheduler, *rule_id, &error); @@ -208,7 +208,7 @@ pcmk_check_rules(xmlNodePtr *xml, xmlNodePtr input, const crm_time_t *date, pcmk__register_lib_messages(out); - rc = pcmk__check_rules(out, input, date, rule_ids); + rc = pcmk__check_rules(out, input, date, (const char *const *) rule_ids); pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); return rc; } diff --git a/lib/pengine/pe_digest.c b/lib/pengine/pe_digest.c index 2c809da9b40..1a7ba585193 100644 --- a/lib/pengine/pe_digest.c +++ b/lib/pengine/pe_digest.c @@ -51,7 +51,7 @@ attr_in_strv(xmlAttrPtr a, void *user_data) const char *name = (const char *) a->name; gchar **strv = user_data; - return pcmk__g_strv_contains(strv, name); + return pcmk__g_strv_contains((const gchar *const *) strv, name); } // Return true if XML attribute name is not an element of a given gchar ** array diff --git a/lib/services/services.c b/lib/services/services.c index 84e0e5afaa3..dff44d4926b 100644 --- a/lib/services/services.c +++ b/lib/services/services.c @@ -1454,7 +1454,9 @@ get_directory_list(const char *root, gboolean files, gboolean executable) dir_paths = g_strsplit(root, ":", 0); - for (gchar **dir = dir_paths; *dir != NULL; dir++) { + for (const char *const *dir = (const char *const *) dir_paths; + *dir != NULL; dir++) { + list = g_list_concat(list, gdl_helper(*dir, files, executable)); } diff --git a/lib/services/services_ocf.c b/lib/services/services_ocf.c index 85f7be9b279..8e755cc3829 100644 --- a/lib/services/services_ocf.c +++ b/lib/services/services_ocf.c @@ -43,7 +43,9 @@ services__list_ocf_providers(void) // NULL dirs should be impossible if PCMK__OCF_RA_PATH is defined correctly CRM_CHECK(dirs != NULL, return NULL); - for (gchar **dir = dirs; *dir != NULL; dir++) { + for (const char *const *dir = (const char *const *) dirs; *dir != NULL; + dir++) { + list = g_list_concat(list, services__list_dir(*dir, false)); } @@ -94,7 +96,9 @@ services__list_ocf_agents(const char *provider) // NULL dirs should be impossible if PCMK__OCF_RA_PATH is defined correctly CRM_CHECK(dirs != NULL, return NULL); - for (gchar **dir = dirs; *dir != NULL; dir++) { + for (const char *const *dir = (const char *const *) dirs; *dir != NULL; + dir++) { + char *buf = pcmk__assert_asprintf("%s/%s", *dir, provider); list = g_list_concat(list, services__list_dir(buf, true)); @@ -140,7 +144,9 @@ services__ocf_agent_exists(const char *provider, const char *agent, char **path) // NULL dirs should be impossible if PCMK__OCF_RA_PATH is defined correctly CRM_CHECK(dirs != NULL, return NULL); - for (gchar **dir = dirs; !found && (*dir != NULL); dir++) { + for (const char *const *dir = (const char *const *) dirs; + !found && (*dir != NULL); dir++) { + char *buf = pcmk__assert_asprintf("%s/%s/%s", *dir, provider, agent); struct stat sb; diff --git a/tools/attrd_updater.c b/tools/attrd_updater.c index 6dca3a51f91..1dc1fd6f779 100644 --- a/tools/attrd_updater.c +++ b/tools/attrd_updater.c @@ -304,7 +304,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("attrd_updater", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", diff --git a/tools/cibadmin.c b/tools/cibadmin.c index fc20bdea950..ab960cd4887 100644 --- a/tools/cibadmin.c +++ b/tools/cibadmin.c @@ -1099,7 +1099,8 @@ main(int argc, char **argv) } } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/cibsecret.c b/tools/cibsecret.c index 8a20ad436ed..c39bfbfa386 100644 --- a/tools/cibsecret.c +++ b/tools/cibsecret.c @@ -62,7 +62,8 @@ static GOptionEntry entries[] = { * * \note On error, \p out->err() will be called to record stderr of the process */ -typedef int (*rsh_fn_t)(pcmk__output_t *out, gchar **nodes, const char *cmdline); +typedef int (*rsh_fn_t)(pcmk__output_t *out, const char *const *nodes, + const char *cmdline); /*! * \internal @@ -82,8 +83,8 @@ typedef int (*rsh_fn_t)(pcmk__output_t *out, gchar **nodes, const char *cmdline) * * \note On error, \p out->err() will be called to record stderr of the process */ -typedef int (*rcp_fn_t)(pcmk__output_t *out, gchar **nodes, const char *to, - const char *from); +typedef int (*rcp_fn_t)(pcmk__output_t *out, const char *const *nodes, + const char *to, const char *from); struct subcommand_entry { const char *name; @@ -150,11 +151,11 @@ run_cmdline(pcmk__output_t *out, const char *cmdline, char **standard_out) } static int -pssh(pcmk__output_t *out, gchar **nodes, const char *cmdline) +pssh(pcmk__output_t *out, const char *const *nodes, const char *cmdline) { int rc = pcmk_rc_ok; char *s = NULL; - gchar *hosts = g_strjoinv(" ", nodes); + gchar *hosts = g_strjoinv(" ", (gchar **) nodes); s = pcmk__assert_asprintf("pssh -i -H \"%s\" -x \"" SSH_OPTS "\" -- \"%s\"", hosts, cmdline); @@ -166,11 +167,11 @@ pssh(pcmk__output_t *out, gchar **nodes, const char *cmdline) } static int -pdsh(pcmk__output_t *out, gchar **nodes, const char *cmdline) +pdsh(pcmk__output_t *out, const char *const *nodes, const char *cmdline) { int rc = pcmk_rc_ok; char *s = NULL; - gchar *hosts = g_strjoinv(",", nodes); + gchar *hosts = g_strjoinv(",", (gchar **) nodes); s = pcmk__assert_asprintf("pdsh -w \"%s\" -- \"%s\"", hosts, cmdline); setenv("PDSH_SSH_ARGS_APPEND", SSH_OPTS, 1); @@ -183,11 +184,11 @@ pdsh(pcmk__output_t *out, gchar **nodes, const char *cmdline) } static int -ssh(pcmk__output_t *out, gchar **nodes, const char *cmdline) +ssh(pcmk__output_t *out, const char *const *nodes, const char *cmdline) { int rc = pcmk_rc_ok; - for (gchar **node = nodes; *node != NULL; node++) { + for (const char *const *node = nodes; *node != NULL; node++) { char *s = pcmk__assert_asprintf("ssh " SSH_OPTS " \"%s\" -- \"%s\"", *node, cmdline); @@ -204,11 +205,12 @@ ssh(pcmk__output_t *out, gchar **nodes, const char *cmdline) } static int -pscp(pcmk__output_t *out, gchar **nodes, const char *to, const char *from) +pscp(pcmk__output_t *out, const char *const *nodes, const char *to, + const char *from) { int rc = pcmk_rc_ok; char *s = NULL; - gchar *hosts = g_strjoinv(" ", nodes); + gchar *hosts = g_strjoinv(" ", (gchar **) nodes); s = pcmk__assert_asprintf("pscp.pssh -H \"%s\" -x \"-pr\" " "-x \"" SSH_OPTS "\" -- \"%s\" \"%s\"", @@ -221,11 +223,12 @@ pscp(pcmk__output_t *out, gchar **nodes, const char *to, const char *from) } static int -pdcp(pcmk__output_t *out, gchar **nodes, const char *to, const char *from) +pdcp(pcmk__output_t *out, const char *const *nodes, const char *to, + const char *from) { int rc = pcmk_rc_ok; char *s = NULL; - gchar *hosts = g_strjoinv(",", nodes); + gchar *hosts = g_strjoinv(",", (gchar **) nodes); s = pcmk__assert_asprintf("pdcp -pr -w \"%s\" -- \"%s\" \"%s\"", hosts, from, to); @@ -239,11 +242,12 @@ pdcp(pcmk__output_t *out, gchar **nodes, const char *to, const char *from) } static int -scp(pcmk__output_t *out, gchar **nodes, const char *to, const char *from) +scp(pcmk__output_t *out, const char *const *nodes, const char *to, + const char *from) { int rc = pcmk_rc_ok; - for (gchar **node = nodes; *node != NULL; node++) { + for (const char *const *node = nodes; *node != NULL; node++) { char *s = pcmk__assert_asprintf("scp -pqr " SSH_OPTS " \"%s\" " "\"%s:%s\"", from, *node, to); @@ -299,7 +303,9 @@ reachable_hosts(pcmk__output_t *out, GList *all) run_cmdline(out, cmdline, &standard_out); parts = g_strsplit(standard_out, "\n", 0); - for (gchar **p = parts; *p != NULL; p++) { + for (const char *const *p = (const char *const *) parts; *p != NULL; + p++) { + if (pcmk__str_empty(*p)) { continue; } @@ -315,7 +321,7 @@ reachable_hosts(pcmk__output_t *out, GList *all) g_free(path); g_ptr_array_add(reachable, NULL); - return (char **) g_ptr_array_free(reachable, FALSE); + return (gchar **) g_ptr_array_free(reachable, FALSE); } struct node_data { @@ -395,7 +401,8 @@ get_live_peers(pcmk__output_t *out) for (const GList *iter = nd.all_nodes; iter != NULL; iter = iter->next) { const char *node_name = iter->data; - if (!pcmk__g_strv_contains(reachable, node_name)) { + if (!pcmk__g_strv_contains((const gchar *const *) reachable, + node_name)) { out->info(out, "Node %s is down - you'll need to update it " "with `cibsecret sync` later", node_name); } @@ -439,7 +446,7 @@ sync_one_file(pcmk__output_t *out, rsh_fn_t rsh_fn, rcp_fn_t rcp_fn, dirname = g_path_get_dirname(path); cmdline = pcmk__assert_asprintf("mkdir -p %s", dirname); - rc = rsh_fn(out, peers, cmdline); + rc = rsh_fn(out, (const char *const *) peers, cmdline); if (rc != pcmk_rc_ok) { goto done; } @@ -447,19 +454,19 @@ sync_one_file(pcmk__output_t *out, rsh_fn_t rsh_fn, rcp_fn_t rcp_fn, if (g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) { char *sign_path = NULL; - rc = rcp_fn(out, peers, dirname, path); + rc = rcp_fn(out, (const char *const *) peers, dirname, path); if (rc != pcmk_rc_ok) { goto done; } sign_path = pcmk__assert_asprintf("%s.sign", path); - rc = rcp_fn(out, peers, dirname, sign_path); + rc = rcp_fn(out, (const char *const *) peers, dirname, sign_path); free(sign_path); } else { free(cmdline); cmdline = pcmk__assert_asprintf("rm -f %s %s.sign", path, path); - rc = rsh_fn(out, peers, cmdline); + rc = rsh_fn(out, (const char *const *) peers, cmdline); } done: @@ -892,20 +899,22 @@ subcommand_sync(pcmk__output_t *out, rsh_fn_t rsh_fn, rcp_fn_t rcp_fn) dirname = g_path_get_dirname(PCMK__CIB_SECRETS_DIR); - rc = rsh_fn(out, peers, "rm -rf " PCMK__CIB_SECRETS_DIR); + rc = rsh_fn(out, (const char *const *) peers, + "rm -rf " PCMK__CIB_SECRETS_DIR); if (rc != pcmk_rc_ok) { goto done; } cmdline = pcmk__assert_asprintf("mkdir -p %s", dirname); - rc = rsh_fn(out, peers, cmdline); + rc = rsh_fn(out, (const char *const *) peers, cmdline); free(cmdline); if (rc != pcmk_rc_ok) { goto done; } - rc = rcp_fn(out, peers, dirname, PCMK__CIB_SECRETS_DIR); + rc = rcp_fn(out, (const char *const *) peers, dirname, + PCMK__CIB_SECRETS_DIR); done: g_strfreev(peers); @@ -1115,7 +1124,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("cibsecret", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crm_attribute.c b/tools/crm_attribute.c index c7de7b71376..bc0c5338e20 100644 --- a/tools/crm_attribute.c +++ b/tools/crm_attribute.c @@ -765,7 +765,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_attribute", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", diff --git a/tools/crm_diff.c b/tools/crm_diff.c index 8661ec6c77c..13d291fb655 100644 --- a/tools/crm_diff.c +++ b/tools/crm_diff.c @@ -262,7 +262,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_diff", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crm_error.c b/tools/crm_error.c index 8a0d2f1dde8..9f968a9c9de 100644 --- a/tools/crm_error.c +++ b/tools/crm_error.c @@ -98,7 +98,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_error", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crm_mon.c b/tools/crm_mon.c index ab42c3bac96..eab0f9bc774 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -302,11 +302,12 @@ find_section_bit(const char *name) { static gboolean apply_exclude(const gchar *excludes, GError **error) { - char **parts = NULL; + gchar **parts = NULL; gboolean result = TRUE; parts = g_strsplit(excludes, ",", 0); - for (char **s = parts; *s != NULL; s++) { + + for (const char *const *s = (const char *const *) parts; *s != NULL; s++) { uint32_t bit = find_section_bit(*s); if (pcmk__str_eq(*s, "all", pcmk__str_none)) { @@ -332,11 +333,12 @@ apply_exclude(const gchar *excludes, GError **error) { static gboolean apply_include(const gchar *includes, GError **error) { - char **parts = NULL; + gchar **parts = NULL; gboolean result = TRUE; parts = g_strsplit(includes, ",", 0); - for (char **s = parts; *s != NULL; s++) { + + for (const char *const *s = (const char *const *) parts; *s != NULL; s++) { uint32_t bit = find_section_bit(*s); if (pcmk__str_eq(*s, "all", pcmk__str_none)) { @@ -1447,7 +1449,8 @@ main(int argc, char **argv) reconcile_output_format(args); set_default_exec_mode(args); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_ERROR, "Error creating output format %s: %s", diff --git a/tools/crm_mon.h b/tools/crm_mon.h index eba01717f54..f1df66a1cd9 100644 --- a/tools/crm_mon.h +++ b/tools/crm_mon.h @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 the Pacemaker project contributors + * Copyright 2019-2025 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -55,13 +55,14 @@ enum mon_exec_mode { void crm_mon_register_messages(pcmk__output_t *out); #if PCMK__ENABLE_CURSES -pcmk__output_t *crm_mon_mk_curses_output(char **argv); +void crm_mon_output_setup_curses(pcmk__output_t *out); void curses_formatted_printf(pcmk__output_t *out, const char *format, ...) G_GNUC_PRINTF(2, 3); void curses_formatted_vprintf(pcmk__output_t *out, const char *format, va_list args) G_GNUC_PRINTF(2, 0); void curses_indented_printf(pcmk__output_t *out, const char *format, ...) G_GNUC_PRINTF(2, 3); void curses_indented_vprintf(pcmk__output_t *out, const char *format, va_list args) G_GNUC_PRINTF(2, 0); -#define CRM_MON_SUPPORTED_FORMAT_CURSES { "console", crm_mon_mk_curses_output, NULL } +#define CRM_MON_SUPPORTED_FORMAT_CURSES \ + { "console", crm_mon_output_setup_curses, NULL } #endif #endif diff --git a/tools/crm_mon_curses.c b/tools/crm_mon_curses.c index 2732ac00eb4..7f14dd87f38 100644 --- a/tools/crm_mon_curses.c +++ b/tools/crm_mon_curses.c @@ -337,43 +337,32 @@ curses_prompt(const char *prompt, bool do_echo, char **dest) } } -pcmk__output_t * -crm_mon_mk_curses_output(char **argv) { - pcmk__output_t *retval = calloc(1, sizeof(pcmk__output_t)); - - if (retval == NULL) { - return NULL; - } - - retval->fmt_name = "console"; - retval->request = pcmk__quote_cmdline(argv); - - retval->init = curses_init; - retval->free_priv = curses_free_priv; - retval->finish = curses_finish; - retval->reset = curses_reset; - - retval->register_message = pcmk__register_message; - retval->message = pcmk__call_message; - - retval->subprocess_output = curses_subprocess_output; - retval->version = curses_ver; - retval->err = curses_error; - retval->info = curses_info; - retval->transient = curses_info; - retval->output_xml = curses_output_xml; - - retval->begin_list = curses_begin_list; - retval->list_item = curses_list_item; - retval->increment_list = curses_increment_list; - retval->end_list = curses_end_list; - - retval->is_quiet = curses_is_quiet; - retval->spacer = curses_spacer; - retval->progress = curses_progress; - retval->prompt = curses_prompt; - - return retval; +void +crm_mon_output_setup_curses(pcmk__output_t *out) +{ + out->fmt_name = "console"; + + out->init = curses_init; + out->free_priv = curses_free_priv; + out->finish = curses_finish; + out->reset = curses_reset; + + out->subprocess_output = curses_subprocess_output; + out->version = curses_ver; + out->err = curses_error; + out->info = curses_info; + out->transient = curses_info; + out->output_xml = curses_output_xml; + + out->begin_list = curses_begin_list; + out->list_item = curses_list_item; + out->increment_list = curses_increment_list; + out->end_list = curses_end_list; + + out->is_quiet = curses_is_quiet; + out->spacer = curses_spacer; + out->progress = curses_progress; + out->prompt = curses_prompt; } G_GNUC_PRINTF(2, 0) diff --git a/tools/crm_node.c b/tools/crm_node.c index 0a89e7f3cb6..ca74b617c52 100644 --- a/tools/crm_node.c +++ b/tools/crm_node.c @@ -792,7 +792,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_node", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = pcmk_rc2exitc(rc); g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crm_resource.c b/tools/crm_resource.c index bbcd5f77738..9de8a612d72 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -2086,7 +2086,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_resource", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, _("Error creating output format %s: %s"), @@ -2132,7 +2133,9 @@ main(int argc, char **argv) goto done; } - for (gchar **arg = options.remainder; *arg != NULL; arg++) { + for (const char *const *arg = (const char *const *) options.remainder; + *arg != NULL; arg++) { + gchar *name = NULL; gchar *value = NULL; int rc = pcmk__scan_nvpair(*arg, &name, &value); diff --git a/tools/crm_rule.c b/tools/crm_rule.c index bf22b197c3b..629c260fc1c 100644 --- a/tools/crm_rule.c +++ b/tools/crm_rule.c @@ -120,7 +120,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_rule", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", @@ -200,7 +201,7 @@ main(int argc, char **argv) switch(options.mode) { case crm_rule_mode_check: rc = pcmk__check_rules(out, input, rule_date, - (const char **) options.rules); + (const char *const *) options.rules); exit_code = pcmk_rc2exitc(rc); break; diff --git a/tools/crm_shadow.c b/tools/crm_shadow.c index 890994815de..2df4ed0ae85 100644 --- a/tools/crm_shadow.c +++ b/tools/crm_shadow.c @@ -1196,7 +1196,8 @@ main(int argc, char **argv) goto done; } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crm_simulate.c b/tools/crm_simulate.c index 6f08a917f44..9af843c3cee 100644 --- a/tools/crm_simulate.c +++ b/tools/crm_simulate.c @@ -482,7 +482,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_simulate", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { fprintf(stderr, "Error creating output format %s: %s\n", args->output_ty, pcmk_rc_str(rc)); diff --git a/tools/crm_ticket.c b/tools/crm_ticket.c index 428a59524e9..3643d04ca14 100644 --- a/tools/crm_ticket.c +++ b/tools/crm_ticket.c @@ -369,7 +369,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_ticket", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = pcmk_rc2exitc(rc); g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crm_verify.c b/tools/crm_verify.c index 145fb1d0220..bae40385284 100644 --- a/tools/crm_verify.c +++ b/tools/crm_verify.c @@ -193,7 +193,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crm_verify", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/crmadmin.c b/tools/crmadmin.c index 62b8aadcdfc..121928c6dcd 100644 --- a/tools/crmadmin.c +++ b/tools/crmadmin.c @@ -189,7 +189,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("crmadmin", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s", diff --git a/tools/iso8601.c b/tools/iso8601.c index d8d0a1a7f8a..c3126fe89c6 100644 --- a/tools/iso8601.c +++ b/tools/iso8601.c @@ -333,7 +333,8 @@ main(int argc, char **argv) pcmk__cli_init_logging("iso8601", args->verbosity); - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = pcmk_rc2exitc(rc); g_set_error(&error, PCMK__EXITC_ERROR, exit_code, diff --git a/tools/stonith_admin.c b/tools/stonith_admin.c index 431f4705b70..7d0d96f9faa 100644 --- a/tools/stonith_admin.c +++ b/tools/stonith_admin.c @@ -422,7 +422,8 @@ main(int argc, char **argv) name = strdup(crm_system_name); } - rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv); + rc = pcmk__output_new(&out, args->output_ty, args->output_dest, + (const char *const *) argv); if (rc != pcmk_rc_ok) { exit_code = CRM_EX_ERROR; g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",