diff --git a/INSTALL.md b/INSTALL.md index 3592d8c071..fc31a49c49 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,80 +1,81 @@ # How to Install Pacemaker ## Build Dependencies | Version | Fedora-based | Suse-based | Debian-based | |:---------------:|:------------------:|:------------------:|:--------------:| | 1.13 or later | automake | automake | automake | | 2.64 or later | autoconf | autoconf | autoconf | | | libtool | libtool | libtool | | | libtool-ltdl-devel | | libltdl-dev | | | libuuid-devel | libuuid-devel | uuid-dev | | 0.27 or later | pkgconfig | pkgconfig | pkg-config | | 2.42.0 or later | glib2-devel | glib2-devel | libglib2.0-dev | | | libxml2-devel | libxml2-devel | libxml2-dev | | | libxslt-devel | libxslt-devel | libxslt-dev | | | bzip2-devel | libbz2-devel | libbz2-dev | | 0.17.0 or later | libqb-devel | libqb-devel | libqb-dev | | 3.4 or later | python3 | python3 | python3 | Also: GNU make ### Cluster Stack Dependencies *Only corosync is currently supported* | Version | Fedora-based | Suse-based | Debian-based | |:---------------:|:------------------:|:------------------:|:--------------:| | 2.0.0 or later | corosynclib | libcorosync | corosync | | 2.0.0 or later | corosynclib-devel | libcorosync-devel | | | | | | libcfg-dev | | | | | libcpg-dev | | | | | libcmap-dev | | | | | libquorum-dev | ### Optional Build Dependencies | Feature Enabled | Version | Fedora-based | Suse-based | Debian-based | |:-----------------------------------------------:|:--------------:|:-----------------------:|:-----------------------:|:-----------------------:| | Pacemaker Remote and encrypted remote CIB admin | 2.12.0 or later| gnutls-devel | libgnutls-devel | libgnutls-dev | | encrypted remote CIB admin | | pam-devel | pam-devel | libpam0g-dev | | interactive crm_mon | | ncurses-devel | ncurses-devel | ncurses-dev | | systemd support | | systemd-devel | systemd-devel | libsystemd-dev | | systemd/upstart resource support | | dbus-devel | dbus-devel | libdbus-1-dev | | Linux-HA style fencing agents | | cluster-glue-libs-devel | libglue-devel | cluster-glue-dev | | documentation | | asciidoc or asciidoctor | asciidoc or asciidoctor | asciidoc or asciidoctor | | documentation | | help2man | help2man | help2man | | documentation | | inkscape | inkscape | inkscape | | documentation | | docbook-style-xsl | docbook-xsl-stylesheets | docbook-xsl | | documentation | | python3-sphinx | python3-sphinx | python3-sphinx | | documentation (PDF) | | latexmk texlive texlive-capt-of texlive-collection-xetex texlive-fncychap texlive-framed texlive-multirow texlive-needspace texlive-tabulary texlive-titlesec texlive-threeparttable texlive-upquote texlive-wrapfig texlive-xetex | texlive texlive-latex | texlive texlive-latex-extra | | RPM packages via "make rpm" | 4.11 or later | rpm | rpm | (n/a) | +| unit tests | | libcmocka-devel | libcmocka-devel | libcmocka-dev | ## Optional testing dependencies * procps and psmisc (if running cts-exec, cts-fencing, or CTS) * valgrind (if running CTS valgrind tests) * python3-systemd (if using CTS on cluster nodes running systemd) * rsync (if running CTS container tests) * libvirt-daemon-driver-lxc (if running CTS container tests) * libvirt-daemon-lxc (if running CTS container tests) * libvirt-login-shell (if running CTS container tests) * nmap (if not specifying an IP address base) * oprofile (if running CTS profiling tests) * dlm (to log DLM debugging info after CTS tests) * xmllint (to validate tool output in cts-cli) ## Simple install $ make && sudo make install If GNU make is not your default make, use "gmake" instead. ## Detailed install First, browse the build options that are available: $ ./autogen.sh $ ./configure --help Re-run ./configure with any options you want, then proceed with the simple method. diff --git a/Makefile.am b/Makefile.am index f6ad23e19e..7e676816c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,133 +1,131 @@ # # Copyright 2003-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # # This directory must be same as in configure.ac's AC_CONFIG_MACRO_DIR ACLOCAL_AMFLAGS = -I m4 -# m4/glibtests.m4 is copied from https://gitlab.gnome.org/GNOME/glib/blob/master/m4macros/glibtests.m4. EXTRA_DIST = CONTRIBUTING.md \ GNUmakefile \ INSTALL.md \ README.markdown \ autogen.sh \ m4/CC_CHECK_LDFLAGS.m4 \ m4/CHECK_ENUM_VALUE.m4 \ - m4/glibtests.m4 \ m4/gnulib-cache.m4 \ m4/gnulib-tool.m4 \ m4/PKG_CHECK_VAR.m4 \ m4/REQUIRE_HEADER.m4 \ m4/version.m4 \ rpm/rpmlintrc \ rpm/pacemaker.spec.in DISTCLEANFILES = config.status MAINTAINERCLEANFILES = Makefile.in \ aclocal.m4 \ config.guess \ config.sub \ configure \ depcomp \ install-sh \ ltmain.sh \ missing \ py-compile \ test-driver # Don't try to install files outside build directory for "make distcheck". AM_DISTCHECK_CONFIGURE_FLAGS = --prefix="$$dc_install_base/usr" \ --sysconfdir="$$dc_install_base/etc" \ --with-initdir="$$dc_install_base/etc/init.d" \ --with-ocfdir="$$dc_install_base/usr/lib/ocf" \ --with-systemdsystemunitdir="$$dc_install_base$(systemdsystemunitdir)" # Only these will get installed with a plain "make install" CORE_INSTALL = replace include lib daemons tools xml # Only these will get built with a plain "make" or "make clean" CORE = $(CORE_INSTALL) cts SUBDIRS = $(CORE) devel doc etc extra maint tests AM_CPPFLAGS = -I$(top_srcdir)/include doc_DATA = README.markdown COPYING licensedir = $(docdir)/licenses/ dist_license_DATA = $(wildcard licenses/*) # Directories that should be created on install and removed on uninstall ## owned by root:haclient, mode 0750 ROOT_DIRS = $(PACEMAKER_CONFIG_DIR) ## owned by hacluster:haclient, mode 0750 DAEMON_R_DIRS = $(CRM_CONFIG_DIR) \ $(CRM_CORE_DIR) \ $(CRM_BLACKBOX_DIR) ## owned by hacluster:haclient, mode 0770 DAEMON_RW_DIRS = $(CRM_BUNDLE_DIR) \ $(CRM_LOG_DIR) core: @echo "Building only core components and tests: $(CORE)" @for subdir in $(CORE); do \ echo "Building $$subdir"; \ $(MAKE) $(AM_MAKEFLAGS) -C $$subdir all || exit 1; \ done core-install: @echo "Installing only core components: $(CORE_INSTALL)" @for subdir in $(CORE_INSTALL); do \ echo "Installing $$subdir"; \ $(MAKE) $(AM_MAKEFLAGS) -C $$subdir install || exit 1; \ done core-clean: @echo "Cleaning only core components and tests: $(CORE)" @for subdir in $(CORE); do \ echo "Cleaning $$subdir"; \ $(MAKE) $(AM_MAKEFLAGS) -C $$subdir clean || exit 1; \ done install-exec-local: for DIR in $(ROOT_DIRS) $(DAEMON_R_DIRS); do \ $(INSTALL) -d -m 750 "$(DESTDIR)/$$DIR"; \ done for DIR in $(DAEMON_RW_DIRS); do \ $(INSTALL) -d -m 770 "$(DESTDIR)/$$DIR"; \ done -for DIR in $(ROOT_DIRS); do \ chgrp $(CRM_DAEMON_GROUP) "$(DESTDIR)/$$DIR"; \ done -for DIR in $(DAEMON_R_DIRS) $(DAEMON_RW_DIRS); do \ chown $(CRM_DAEMON_USER):$(CRM_DAEMON_GROUP) "$(DESTDIR)/$$DIR"; \ done # Remove created directories only if they're empty uninstall-hook: -for DIR in $(ROOT_DIRS) $(DAEMON_R_DIRS) $(DAEMON_RW_DIRS); do \ rmdir "$(DESTDIR)/$$DIR"; \ done clean-generic: -rm -f *.tar.bz2 *.sed PACKAGE ?= pacemaker # In a normal build, this file is included by GNUmakefile, which serves as the # "real" makefile. But in a VPATH build, GNUmakefile won't exist in the build # tree, and this file will be the "real" makefile. EXTRA_CLEAN_TARGETS handles # both cases: GNUmakefile defines it before including this file, so the # clean-local target can clean up files created by GNUmakefile targets. # If this file is used alone, the variable will be undefined. clean-local: $(EXTRA_CLEAN_TARGETS) -rm -f $(builddir)/$(PACKAGE)-*.tar.gz distclean-local: -rm -rf libltdl autom4te.cache diff --git a/configure.ac b/configure.ac index 9165720d1d..5500c99253 100644 --- a/configure.ac +++ b/configure.ac @@ -1,2113 +1,2143 @@ dnl dnl autoconf for Pacemaker dnl dnl Copyright 2009-2021 the Pacemaker project contributors dnl dnl The version control history for this file may have further details. dnl dnl This source code is licensed under the GNU General Public License version 2 dnl or later (GPLv2+) WITHOUT ANY WARRANTY. dnl =============================================== dnl Bootstrap dnl =============================================== AC_PREREQ(2.64) dnl AC_CONFIG_MACRO_DIR is deprecated as of autoconf 2.70 (2020-12-08). dnl Once we can require that version, we can simplify this, and no longer dnl need ACLOCAL_AMFLAGS in Makefile.am. m4_ifdef([AC_CONFIG_MACRO_DIRS], [AC_CONFIG_MACRO_DIRS([m4])], [AC_CONFIG_MACRO_DIR([m4])]) AC_DEFUN([AC_DATAROOTDIR_CHECKED]) dnl Suggested structure: dnl information on the package dnl checks for programs dnl checks for libraries dnl checks for header files dnl checks for types dnl checks for structures dnl checks for compiler characteristics dnl checks for library functions dnl checks for system services m4_include([m4/version.m4]) AC_INIT([pacemaker], VERSION_NUMBER, [users@clusterlabs.org], [pacemaker], PCMK_URL) PCMK_FEATURES="" LT_CONFIG_LTDL_DIR([libltdl]) AC_CONFIG_AUX_DIR([libltdl/config]) AC_CANONICAL_HOST dnl Where #defines that autoconf makes (e.g. HAVE_whatever) go dnl dnl Internal header: include/config.h dnl - Contains ALL defines dnl - include/config.h.in is generated automatically by autoheader dnl - NOT to be included in any header files except crm_internal.h dnl (which is also not to be included in any other header files) dnl dnl External header: include/crm_config.h dnl - Contains a subset of defines checked here dnl - Manually edit include/crm_config.h.in to have configure include dnl new defines dnl - Should not include HAVE_* defines dnl - Safe to include anywhere AC_CONFIG_HEADERS([include/config.h include/crm_config.h]) dnl 1.13: minimum automake version required dnl foreign: don't require GNU-standard top-level files dnl tar-ustar: use (older) POSIX variant of generated tar rather than v7 dnl subdir-objects: keep .o's with their .c's (no-op in 2.0+) AM_INIT_AUTOMAKE([1.13 foreign tar-ustar subdir-objects]) dnl Require minimum version of pkg-config PKG_PROG_PKG_CONFIG(0.27) AS_IF([test "x${PKG_CONFIG}" != x], [], [AC_MSG_FAILURE([Could not find required build tool pkg-config (0.27 or later)])]) PKG_INSTALLDIR PKG_NOARCH_INSTALLDIR dnl Example 2.4. Silent Custom Rule to Generate a File dnl %-bar.pc: %.pc dnl $(AM_V_GEN)$(LN_S) $(notdir $^) $@ dnl Versioned attributes implementation is not yet production-ready AC_DEFINE_UNQUOTED(ENABLE_VERSIONED_ATTRS, 0, [Enable versioned attributes]) CC_IN_CONFIGURE=yes export CC_IN_CONFIGURE LDD=ldd -GLIB_TESTS - dnl ======================================================================== dnl Compiler characteristics dnl ======================================================================== dnl A particular compiler can be forced by setting the CC environment variable AC_PROG_CC dnl Use at least C99 if possible. This will generate an "obsolete" warning dnl since autoconf 2.70, but is needed for older versions. AC_PROG_CC_STDC dnl C++ is not needed for build, just maintainer utilities AC_PROG_CXX dnl We use md5.c from gnulib, which has its own m4 macros. Per its docs: dnl "The macro gl_EARLY must be called as soon as possible after verifying that dnl the C compiler is working. ... The core part of the gnulib checks are done dnl by the macro gl_INIT." In addition, prevent gnulib from introducing OpenSSL dnl as a dependency. gl_EARLY gl_SET_CRYPTO_CHECK_DEFAULT([no]) gl_INIT # --enable-new-dtags: Use RUNPATH instead of RPATH. # It is necessary to have this done before libtool does linker detection. # See also: https://github.com/kronosnet/kronosnet/issues/107 AX_CHECK_LINK_FLAG([-Wl,--enable-new-dtags], [AM_LDFLAGS=-Wl,--enable-new-dtags], [AC_MSG_ERROR(["Linker support for --enable-new-dtags is required"])]) AC_SUBST([AM_LDFLAGS]) saved_LDFLAGS="$LDFLAGS" LDFLAGS="$AM_LDFLAGS $LDFLAGS" LT_INIT([dlopen]) LDFLAGS="$saved_LDFLAGS" LTDL_INIT([convenience]) AC_TYPE_SIZE_T AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) dnl =============================================== dnl Helpers dnl =============================================== cc_supports_flag() { local CFLAGS="-Werror $@" AC_MSG_CHECKING([whether $CC supports $@]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[ ]])], [RC=0; AC_MSG_RESULT([yes])], [RC=1; AC_MSG_RESULT([no])]) return $RC } # Some tests need to use their own CFLAGS cc_temp_flags() { ac_save_CFLAGS="$CFLAGS" CFLAGS="$*" } cc_restore_flags() { CFLAGS=$ac_save_CFLAGS } # yes_no_try $user_response $default DISABLED=0 REQUIRED=1 OPTIONAL=2 yes_no_try() { local value AS_IF([test x"$1" = x""], [value="$2"], [value="$1"]) AS_CASE(["`echo "$value" | tr '[A-Z]' '[a-z]'`"], [0|no|false|disable], [return $DISABLED], [1|yes|true|enable], [return $REQUIRED], [try|check], [return $OPTIONAL] ) AC_MSG_ERROR([Invalid option value "$value"]) } check_systemdsystemunitdir() { AC_MSG_CHECKING([which system unit file directory to use]) PKG_CHECK_VAR([systemdsystemunitdir], [systemd], [systemdsystemunitdir]) AC_MSG_RESULT([${systemdsystemunitdir}]) test x"$systemdsystemunitdir" != x"" return $? } dnl =============================================== dnl Configure Options dnl =============================================== dnl Actual library checks come later, but pkg-config can be used here to grab dnl external values to use as defaults for configure options dnl --enable-* options: build process AC_ARG_ENABLE([quiet], [AS_HELP_STRING([--enable-quiet], [suppress make output unless there is an error @<:@no@:>@])] ) yes_no_try "$enable_quiet" "no" enable_quiet=$? AC_ARG_ENABLE([fatal-warnings], [AS_HELP_STRING([--enable-fatal-warnings], [enable pedantic and fatal warnings for gcc @<:@try@:>@])], ) yes_no_try "$enable_fatal_warnings" "try" enable_fatal_warnings=$? AC_ARG_ENABLE([hardening], [AS_HELP_STRING([--enable-hardening], [harden the resulting executables/libraries @<:@try@:>@])] ) yes_no_try "$enable_hardening" "try" enable_hardening=$? dnl --enable-* options: features AC_ARG_ENABLE([systemd], [AS_HELP_STRING([--enable-systemd], [enable support for managing resources via systemd @<:@try@:>@])] ) yes_no_try "$enable_systemd" "try" enable_systemd=$? AC_ARG_ENABLE([upstart], [AS_HELP_STRING([--enable-upstart], [enable support for managing resources via Upstart (deprecated) @<:@try@:>@])] ) yes_no_try "$enable_upstart" "try" enable_upstart=$? dnl --enable-* options: compatibility AC_ARG_ENABLE([compat-2.0], [AS_HELP_STRING([--enable-compat-2.0], m4_normalize([ preserve certain output as it was in 2.0; this option will be available only for the lifetime of the 2.1 series @<:@no@:>@]))] ) yes_no_try "$enable_compat_2_0" "no" enable_compat_2_0=$? AS_IF([test $enable_compat_2_0 -ne $DISABLED], [ AC_DEFINE_UNQUOTED([PCMK__COMPAT_2_0], [1], [Keep certain output compatible with 2.0 release series]) PCMK_FEATURES="$PCMK_FEATURES compat-2.0" ] ) # Add an option to create symlinks at the pre-2.0.0 daemon name locations, so # that users and tools can continue to invoke those names directly (e.g., for # meta-data). This option will be removed in a future release. AC_ARG_ENABLE([legacy-links], [AS_HELP_STRING([--enable-legacy-links], [add symlinks for old daemon names (deprecated) @<:@no@:>@])] ) yes_no_try "$enable_legacy_links" "no" enable_legacy_links=$? AM_CONDITIONAL([BUILD_LEGACY_LINKS], [test $enable_legacy_links -ne $DISABLED]) dnl --with-* options: basic parameters dnl This argument is defined via an M4 macro so default can be a variable AC_DEFUN([VERSION_ARG], [AC_ARG_WITH([version], [AS_HELP_STRING([--with-version=VERSION], [override package version @<:@$1@:>@])], [ PACEMAKER_VERSION="$withval" ], [ PACEMAKER_VERSION="$PACKAGE_VERSION" ])] ) VERSION_ARG(VERSION_NUMBER) # Redefine PACKAGE_VERSION and VERSION according to PACEMAKER_VERSION in case # the user used --with-version. Unfortunately, this can only affect the # substitution variables and later uses in this file, not the config.h # constants, so we have to be careful to use only PACEMAKER_VERSION in C code. PACKAGE_VERSION=$PACEMAKER_VERSION VERSION=$PACEMAKER_VERSION CRM_DAEMON_USER="" AC_ARG_WITH([daemon-user], [AS_HELP_STRING([--with-daemon-user=USER], [user to run unprivileged Pacemaker daemons as (advanced option: changing this may break other cluster components unless similarly configured) @<:@hacluster@:>@])], [ CRM_DAEMON_USER="$withval" ] ) CRM_DAEMON_GROUP="" AC_ARG_WITH([daemon-group], [AS_HELP_STRING([--with-daemon-group=GROUP], [group to run unprivileged Pacemaker daemons as (advanced option: changing this may break other cluster components unless similarly configured) @<:@haclient@:>@])], [ CRM_DAEMON_GROUP="$withval" ] ) BUG_URL="" AC_ARG_WITH([bug-url], [AS_HELP_STRING([--with-bug-url=DIR], m4_normalize([ address where users should submit bug reports @<:@https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker@:>@]))], [ BUG_URL="$withval" ] ) dnl --with-* options: features AC_ARG_WITH([cibsecrets], [AS_HELP_STRING([--with-cibsecrets], [support separate file for CIB secrets @<:@no@:>@])] ) yes_no_try "$with_cibsecrets" "no" with_cibsecrets=$? AC_ARG_WITH([gnutls], [AS_HELP_STRING([--with-gnutls], [support Pacemaker Remote and remote-tls-port using GnuTLS @<:@try@:>@])] ) yes_no_try "$with_gnutls" "try" with_gnutls=$? PCMK_GNUTLS_PRIORITIES="NORMAL" AC_ARG_WITH([gnutls-priorities], [AS_HELP_STRING([--with-gnutls-priorities], [default GnuTLS cipher priorities @<:@NORMAL@:>@])], [ test x"$withval" = x"no" || PCMK_GNUTLS_PRIORITIES="$withval" ] ) AC_ARG_WITH([concurrent-fencing-default], [AS_HELP_STRING([--with-concurrent-fencing-default], [default value for concurrent-fencing cluster option @<:@false@:>@])], ) AS_CASE([$with_concurrent_fencing_default], [""], [with_concurrent_fencing_default="false"], [false], [], [true], [PCMK_FEATURES="$PCMK_FEATURES default-concurrent-fencing"], [AC_MSG_ERROR([Invalid value "$with_concurrent_fencing_default" for --with-concurrent-fencing-default])] ) AC_DEFINE_UNQUOTED([PCMK__CONCURRENT_FENCING_DEFAULT], ["$with_concurrent_fencing_default"], [Default value for concurrent-fencing cluster option]) AC_ARG_WITH([sbd-sync-default], [AS_HELP_STRING([--with-sbd-sync-default], m4_normalize([ default value used by sbd if SBD_SYNC_RESOURCE_STARTUP environment variable is not set @<:@false@:>@]))], ) AS_CASE([$with_sbd_sync_default], [""], [with_sbd_sync_default=false], [false], [], [true], [PCMK_FEATURES="$PCMK_FEATURES default-sbd-sync"], [AC_MSG_ERROR([Invalid value "$with_sbd_sync_default" for --with-sbd-sync-default])] ) AC_DEFINE_UNQUOTED([PCMK__SBD_SYNC_DEFAULT], [$with_sbd_sync_default], [Default value for SBD_SYNC_RESOURCE_STARTUP environment variable]) AC_ARG_WITH([resource-stickiness-default], [AS_HELP_STRING([--with-resource-stickiness-default], [If positive, value to add to new CIBs as explicit resource default for resource-stickiness @<:@0@:>@])], ) errmsg="Invalid value \"$with_resource_stickiness_default\" for --with-resource-stickiness-default" AS_CASE([$with_resource_stickiness_default], [0|""], [with_resource_stickiness_default="0"], [*[[!0-9]]*], [AC_MSG_ERROR([$errmsg])], [PCMK_FEATURES="$PCMK_FEATURES default-resource-stickiness"] ) AC_DEFINE_UNQUOTED([PCMK__RESOURCE_STICKINESS_DEFAULT], [$with_resource_stickiness_default], [Default value for resource-stickiness resource meta-attribute]) AC_ARG_WITH([corosync], [AS_HELP_STRING([--with-corosync], [support the Corosync messaging and membership layer @<:@try@:>@])] ) yes_no_try "$with_corosync" "try" with_corosync=$? AC_ARG_WITH([nagios], [AS_HELP_STRING([--with-nagios], [support nagios resources])] ) yes_no_try "$with_nagios" "try" with_nagios=$? dnl --with-* options: directory locations AC_ARG_WITH([nagios-plugin-dir], [AS_HELP_STRING([--with-nagios-plugin-dir=DIR], [directory for nagios plugins @<:@LIBEXECDIR/nagios/plugins@:>@])], [ NAGIOS_PLUGIN_DIR="$withval" ] ) AC_ARG_WITH([nagios-metadata-dir], [AS_HELP_STRING([--with-nagios-metadata-dir=DIR], [directory for nagios plugins metadata @<:@DATADIR/nagios/plugins-metadata@:>@])], [ NAGIOS_METADATA_DIR="$withval" ] ) INITDIR="" AC_ARG_WITH([initdir], [AS_HELP_STRING([--with-initdir=DIR], [directory for init (rc) scripts])], [ INITDIR="$withval" ] ) systemdsystemunitdir="${systemdsystemunitdir-}" AC_ARG_WITH([systemdsystemunitdir], [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [directory for systemd unit files (advanced option: must match what systemd uses)])], [ systemdsystemunitdir="$withval" ] ) CONFIGDIR="" AC_ARG_WITH([configdir], [AS_HELP_STRING([--with-configdir=DIR], [directory for Pacemaker configuration file @<:@SYSCONFDIR/sysconfig@:>@])], [ CONFIGDIR="$withval" ] ) dnl --runstatedir is available as of autoconf 2.70 (2020-12-08). When users dnl have an older version, they can use our --with-runstatedir. pcmk_runstatedir="" AC_ARG_WITH([runstatedir], [AS_HELP_STRING([--with-runstatedir=DIR], [modifiable per-process data @<:@LOCALSTATEDIR/run@:>@ (ignored if --runstatedir is available)])], [ pcmk_runstatedir="$withval" ] ) CRM_LOG_DIR="" AC_ARG_WITH([logdir], [AS_HELP_STRING([--with-logdir=DIR], [directory for Pacemaker log file @<:@LOCALSTATEDIR/log/pacemaker@:>@])], [ CRM_LOG_DIR="$withval" ] ) CRM_BUNDLE_DIR="" AC_ARG_WITH([bundledir], [AS_HELP_STRING([--with-bundledir=DIR], [directory for Pacemaker bundle logs @<:@LOCALSTATEDIR/log/pacemaker/bundles@:>@])], [ CRM_BUNDLE_DIR="$withval" ] ) dnl Get default from resource-agents if possible. Otherwise, the default uses dnl /usr/lib rather than libdir because it's determined by the OCF project and dnl not Pacemaker. Even if a user wants to install Pacemaker to /usr/local or dnl such, the OCF agents will be expected in their usual location. However, we dnl do give the user the option to override it. PKG_CHECK_VAR([OCF_ROOT_DIR], [resource-agents], [ocfrootdir], [], [OCF_ROOT_DIR="/usr/lib/ocf"]) AC_ARG_WITH([ocfdir], [AS_HELP_STRING([--with-ocfdir=DIR], m4_normalize([ OCF resource agent root directory (advanced option: changing this may break other cluster components unless similarly configured) @<:@value from resource-agents package if available otherwise /usr/lib/ocf@:>@]))], [ OCF_ROOT_DIR="$withval" ] ) AC_SUBST(OCF_ROOT_DIR) AC_DEFINE_UNQUOTED([OCF_ROOT_DIR], ["$OCF_ROOT_DIR"], [OCF root directory for resource agents and libraries]) PKG_CHECK_VAR([OCF_RA_PATH], [resource-agents], [ocfrapath], [], [OCF_RA_PATH="$OCF_ROOT_DIR/resource.d"]) AC_ARG_WITH([ocfrapath], [AS_HELP_STRING([--with-ocfrapath=DIR], m4_normalize([ OCF resource agent directories (colon-separated) to search @<:@value from resource-agents package if available otherwise OCFDIR/resource.d@:>@]))], [ OCF_RA_PATH="$withval" ] ) AC_SUBST(OCF_RA_PATH) AC_DEFINE_UNQUOTED([OCF_RA_PATH], ["$OCF_RA_PATH"], [OCF directories to search for resource agents ]) OCF_RA_INSTALL_DIR="$OCF_ROOT_DIR/resource.d" AC_ARG_WITH([ocfrainstalldir], [AS_HELP_STRING([--with-ocfrainstalldir=DIR], m4_normalize([ OCF installation directory for Pacemakers resource agents @<:@OCFDIR/resource.d@:>@]))], [ OCF_RA_INSTALL_DIR="$withval" ] ) AC_SUBST(OCF_RA_INSTALL_DIR) dnl Get default from fence-agents if available PKG_CHECK_VAR([FA_PREFIX], [fence-agents], [prefix], [PCMK__FENCE_BINDIR="${FA_PREFIX}/sbin"], [PCMK__FENCE_BINDIR="$sbindir"]) AC_ARG_WITH([fence-bindir], [AS_HELP_STRING([--with-fence-bindir=DIR], m4_normalize([ directory for executable fence agents @<:@value from fence-agents package if available otherwise SBINDIR@:>@]))], [ PCMK__FENCE_BINDIR="$withval" ] ) AC_SUBST(PCMK__FENCE_BINDIR) dnl --with-* options: non-production testing AC_ARG_WITH([profiling], [AS_HELP_STRING([--with-profiling], [disable optimizations, for effective profiling @<:@no@:>@])] ) yes_no_try "$with_profiling" "no" with_profiling=$? AC_ARG_WITH([coverage], [AS_HELP_STRING([--with-coverage], [disable optimizations, for effective profiling and coverage testing @<:@no@:>@])] ) yes_no_try "$with_coverage" "no" with_coverage=$? AC_ARG_WITH([sanitizers], [AS_HELP_STRING([--with-sanitizers=...,...], [enable SANitizer build, do *NOT* use for production. Only ASAN/UBSAN/TSAN are currently supported])], [ SANITIZERS="$withval" ], [ SANITIZERS="" ]) dnl =============================================== dnl General Processing dnl =============================================== AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$VERSION", [Version number of this Pacemaker build]) PACKAGE_SERIES=`echo $VERSION | awk -F. '{ print $1"."$2 }'` AC_SUBST(PACKAGE_SERIES) AC_PROG_LN_S AC_PROG_MKDIR_P # Check for fatal warning support AS_IF([test $enable_fatal_warnings -ne $DISABLED && test "$GCC" = "yes" && cc_supports_flag -Werror], [WERROR="-Werror"], [ WERROR="" AS_CASE([$enable_fatal_warnings], [$REQUIRED], [AC_MSG_ERROR([Compiler does not support fatal warnings])], [$OPTIONAL], [ AC_MSG_NOTICE([Compiler does not support fatal warnings]) enable_fatal_warnings=$DISABLED ]) ]) AC_MSG_NOTICE([Sanitizing prefix: ${prefix}]) AS_IF([test "$prefix" = "NONE"], [ prefix=/usr dnl Fix default variables - "prefix" variable if not specified AS_IF([test "$localstatedir" = "\${prefix}/var"], [localstatedir="/var"]) AS_IF([test "$sysconfdir" = "\${prefix}/etc"], [sysconfdir="/etc"]) ]) AC_MSG_NOTICE([Sanitizing exec_prefix: ${exec_prefix}]) case $exec_prefix in prefix|NONE) exec_prefix=$prefix ;; esac AC_MSG_NOTICE([Sanitizing INITDIR: ${INITDIR}]) case $INITDIR in prefix) INITDIR=$prefix;; "") AC_MSG_CHECKING([which init (rc) directory to use]) for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d \ /usr/local/etc/rc.d /etc/rc.d do if test -d $initdir then INITDIR=$initdir break fi done AC_MSG_RESULT([$INITDIR]) ;; esac AC_SUBST(INITDIR) AC_MSG_NOTICE([Sanitizing libdir: ${libdir}]) case $libdir in prefix|NONE) AC_MSG_CHECKING([which lib directory to use]) for aDir in lib64 lib do trydir="${exec_prefix}/${aDir}" if test -d ${trydir} then libdir=${trydir} break fi done AC_MSG_RESULT([$libdir]); ;; esac dnl Expand autoconf variables so that we don't end up with '${prefix}' dnl in #defines and python scripts dnl NOTE: Autoconf deliberately leaves them unexpanded to allow dnl make exec_prefix=/foo install dnl No longer being able to do this seems like no great loss to me... eval prefix="`eval echo ${prefix}`" eval exec_prefix="`eval echo ${exec_prefix}`" eval bindir="`eval echo ${bindir}`" eval sbindir="`eval echo ${sbindir}`" eval libexecdir="`eval echo ${libexecdir}`" eval datadir="`eval echo ${datadir}`" eval sysconfdir="`eval echo ${sysconfdir}`" eval sharedstatedir="`eval echo ${sharedstatedir}`" eval localstatedir="`eval echo ${localstatedir}`" eval libdir="`eval echo ${libdir}`" eval includedir="`eval echo ${includedir}`" eval oldincludedir="`eval echo ${oldincludedir}`" eval infodir="`eval echo ${infodir}`" eval mandir="`eval echo ${mandir}`" dnl Home-grown variables if [ test "x${runstatedir}" = "x" ]; then if [ test "x${pcmk_runstatedir}" = "x" ]; then runstatedir="${localstatedir}/run" else runstatedir="${pcmk_runstatedir}" fi fi eval runstatedir="$(eval echo ${runstatedir})" AC_DEFINE_UNQUOTED([PCMK_RUN_DIR], ["$runstatedir"], [Location for modifiable per-process data]) AC_SUBST(runstatedir) eval INITDIR="${INITDIR}" eval docdir="`eval echo ${docdir}`" if test x"${docdir}" = x""; then docdir=${datadir}/doc/${PACKAGE}-${VERSION} fi AC_SUBST(docdir) if test x"${CONFIGDIR}" = x""; then CONFIGDIR="${sysconfdir}/sysconfig" fi AC_SUBST(CONFIGDIR) if test x"${CRM_LOG_DIR}" = x""; then CRM_LOG_DIR="${localstatedir}/log/pacemaker" fi AC_DEFINE_UNQUOTED(CRM_LOG_DIR,"$CRM_LOG_DIR", Location for Pacemaker log file) AC_SUBST(CRM_LOG_DIR) if test x"${CRM_BUNDLE_DIR}" = x""; then CRM_BUNDLE_DIR="${localstatedir}/log/pacemaker/bundles" fi AC_DEFINE_UNQUOTED(CRM_BUNDLE_DIR,"$CRM_BUNDLE_DIR", Location for Pacemaker bundle logs) AC_SUBST(CRM_BUNDLE_DIR) eval PCMK__FENCE_BINDIR="`eval echo ${PCMK__FENCE_BINDIR}`" AC_DEFINE_UNQUOTED(PCMK__FENCE_BINDIR,"$PCMK__FENCE_BINDIR", [Location for executable fence agents]) AS_IF([test x"${PCMK_GNUTLS_PRIORITIES}" != x""], [], [AC_MSG_ERROR([--with-gnutls-priorities value must not be empty])]) AC_DEFINE_UNQUOTED([PCMK_GNUTLS_PRIORITIES], ["$PCMK_GNUTLS_PRIORITIES"], [GnuTLS cipher priorities]) if test x"${BUG_URL}" = x""; then BUG_URL="https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker" fi AC_SUBST(BUG_URL) for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \ sharedstatedir localstatedir libdir includedir oldincludedir infodir \ mandir INITDIR docdir CONFIGDIR do dirname=`eval echo '${'${j}'}'` if test ! -d "$dirname" then AC_MSG_WARN([$j directory ($dirname) does not exist (yet)]) fi done us_auth= AC_CHECK_HEADER([sys/socket.h], [ AC_CHECK_DECL([SO_PEERCRED], [ # Linux AC_CHECK_TYPE([struct ucred], [ us_auth=peercred_ucred; AC_DEFINE([US_AUTH_PEERCRED_UCRED], [1], [Define if Unix socket auth method is getsockopt(s, SO_PEERCRED, &ucred, ...)]) ], [ # OpenBSD AC_CHECK_TYPE([struct sockpeercred], [ us_auth=localpeercred_sockepeercred; AC_DEFINE([US_AUTH_PEERCRED_SOCKPEERCRED], [1], [Define if Unix socket auth method is getsockopt(s, SO_PEERCRED, &sockpeercred, ...)]) ], [], [[#include ]]) ], [[#define _GNU_SOURCE #include ]]) ], [], [[#include ]]) ]) AS_IF([test -z "${us_auth}"], [ # FreeBSD AC_CHECK_DECL([getpeereid], [ us_auth=getpeereid; AC_DEFINE([US_AUTH_GETPEEREID], [1], [Define if Unix socket auth method is getpeereid(s, &uid, &gid)]) ], [ # Solaris/OpenIndiana AC_CHECK_DECL([getpeerucred], [ us_auth=getpeerucred; AC_DEFINE([US_AUTH_GETPEERUCRED], [1], [Define if Unix socket auth method is getpeercred(s, &ucred)]) ], [ AC_MSG_FAILURE([No way to authenticate a Unix socket peer]) ], [[#include ]]) ]) ]) dnl OS-based decision-making is poor autotools practice; feature-based dnl mechanisms are strongly preferred. Keep this section to a bare minimum; dnl regard as a "necessary evil". INIT_EXT="" PROCFS=0 case "$host_os" in dnl Solaris and some *BSD versions support procfs but not files we need *bsd*) INIT_EXT=".sh" ;; *linux*) PROCFS=1 ;; darwin*) LIBS="$LIBS -L${prefix}/lib" CFLAGS="$CFLAGS -I${prefix}/include" ;; esac AC_SUBST(INIT_EXT) AC_DEFINE_UNQUOTED([SUPPORT_PROCFS], [$PROCFS], [Define to 1 if procfs is supported]) case "$host_cpu" in ppc64|powerpc64) case $CFLAGS in *powerpc64*) ;; *) if test "$GCC" = yes; then CFLAGS="$CFLAGS -m64" fi ;; esac ;; esac # C99 doesn't guarantee uint64_t type and related format specifiers, but # prerequisites, corosync + libqb, use that widely, so the target platforms # are already pre-constrained to those "64bit-clean" (doesn't imply native # bit width) and hence we deliberately refrain from artificial surrogates # (sans manipulation through cached values). AC_CACHE_VAL( [pcmk_cv_decl_inttypes], [ AC_CHECK_DECLS( [PRIu64, PRIu32, PRIx32, SCNu64], [pcmk_cv_decl_inttypes="PRIu64 PRIu32 PRIx32 SCNu64"], [ # test shall only react on "no" cached result & error out respectively if test "x$ac_cv_have_decl_PRIu64" = xno; then AC_MSG_ERROR([lack of inttypes.h based specifier serving uint64_t (PRIu64)]) elif test "x$ac_cv_have_decl_PRIu32" = xno; then AC_MSG_ERROR([lack of inttypes.h based specifier serving uint32_t (PRIu32)]) elif test "x$ac_cv_have_decl_PRIx32" = xno; then AC_MSG_ERROR([lack of inttypes.h based hexa specifier serving uint32_t (PRIx32)]) elif test "x$ac_cv_have_decl_SCNu64" = xno; then AC_MSG_ERROR([lack of inttypes.h based specifier gathering uint64_t (SCNu64)]) fi ], [[#include ]] ) ] ) ( set $pcmk_cv_decl_inttypes AC_DEFINE_UNQUOTED([U64T], [$1], [Correct format specifier for U64T]) AC_DEFINE_UNQUOTED([U32T], [$2], [Correct format specifier for U32T]) AC_DEFINE_UNQUOTED([X32T], [$3], [Correct format specifier for X32T]) AC_DEFINE_UNQUOTED([U64TS], [$4], [Correct format specifier for U64TS]) ) dnl =============================================== dnl Program Paths dnl =============================================== PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin" export PATH dnl Replacing AC_PROG_LIBTOOL with AC_CHECK_PROG because LIBTOOL dnl was NOT being expanded all the time thus causing things to fail. AC_CHECK_PROGS(LIBTOOL, glibtool libtool libtool15 libtool13) AS_IF([test "x${LIBTOOL}" != "x"], [], [AC_MSG_FAILURE([Could not find required build tool libtool (or equivalent)])]) dnl Pacemaker's executable python scripts will invoke the python specified by dnl configure's PYTHON variable. If not specified, AM_PATH_PYTHON will check a dnl built-in list with (unversioned) "python" having precedence. To configure dnl Pacemaker to use a specific python interpreter version, define PYTHON dnl when calling configure, for example: ./configure PYTHON=/usr/bin/python3.6 dnl Ensure PYTHON is an absolute path AS_IF([test x"${PYTHON}" != x""], [AC_PATH_PROG([PYTHON], [$PYTHON])]) dnl Require a minimum Python version AM_PATH_PYTHON([3.4]) AC_PATH_PROGS([ASCIIDOC_CONV], [asciidoc asciidoctor]) AC_PATH_PROG([HELP2MAN], [help2man]) AC_PATH_PROG([SPHINX], [sphinx-build]) AC_PATH_PROG([INKSCAPE], [inkscape]) AC_PATH_PROG([XSLTPROC], [xsltproc]) AC_PATH_PROG([XMLCATALOG], [xmlcatalog]) dnl Bash is needed for building man pages and running regression tests. dnl BASH is already an environment variable, so use something else. AC_PATH_PROG([BASH_PATH], [bash]) AS_IF([test "x${BASH_PATH}" != "x"], [], [AC_MSG_FAILURE([Could not find required build tool bash])]) AC_PATH_PROGS(VALGRIND_BIN, valgrind, /usr/bin/valgrind) AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command) AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"") if test x"${HELP2MAN}" != x""; then PCMK_FEATURES="$PCMK_FEATURES generated-manpages" fi MANPAGE_XSLT="" if test x"${XSLTPROC}" != x""; then AC_MSG_CHECKING([for DocBook-to-manpage transform]) # first try to figure out correct template using xmlcatalog query, # resort to extensive (semi-deterministic) file search if that fails DOCBOOK_XSL_URI='http://docbook.sourceforge.net/release/xsl/current' DOCBOOK_XSL_PATH='manpages/docbook.xsl' MANPAGE_XSLT=$(${XMLCATALOG} "" ${DOCBOOK_XSL_URI}/${DOCBOOK_XSL_PATH} \ | sed -n 's|^file://||p;q') if test x"${MANPAGE_XSLT}" = x""; then DIRS=$(find "${datadir}" -name $(basename $(dirname ${DOCBOOK_XSL_PATH})) \ -type d 2>/dev/null | LC_ALL=C sort) XSLT=$(basename ${DOCBOOK_XSL_PATH}) for d in ${DIRS} do if test -f "${d}/${XSLT}"; then MANPAGE_XSLT="${d}/${XSLT}" break fi done fi fi AC_MSG_RESULT([$MANPAGE_XSLT]) AC_SUBST(MANPAGE_XSLT) AM_CONDITIONAL(BUILD_XML_HELP, test x"${MANPAGE_XSLT}" != x"") if test x"${MANPAGE_XSLT}" != x""; then PCMK_FEATURES="$PCMK_FEATURES agent-manpages" fi AM_CONDITIONAL([IS_ASCIIDOC], [echo "${ASCIIDOC_CONV}" | grep -Eq 'asciidoc$']) AM_CONDITIONAL([BUILD_ASCIIDOC], [test "x${ASCIIDOC_CONV}" != x]) if test "x${ASCIIDOC_CONV}" != x; then PCMK_FEATURES="$PCMK_FEATURES ascii-docs" fi AM_CONDITIONAL([BUILD_SPHINX_DOCS], [test x"${SPHINX}" != x"" && test x"${INKSCAPE}" != x""]) AM_COND_IF([BUILD_SPHINX_DOCS], [PCMK_FEATURES="$PCMK_FEATURES books"]) dnl Pacemaker's shell scripts (and thus man page builders) rely on GNU getopt AC_MSG_CHECKING([for GNU-compatible getopt]) IFS_orig=$IFS IFS=: for PATH_DIR in $PATH do IFS=$IFS_orig GETOPT_PATH="${PATH_DIR}/getopt" if test -f "$GETOPT_PATH" && test -x "$GETOPT_PATH" ; then $GETOPT_PATH -T >/dev/null 2>/dev/null if test $? -eq 4; then break fi fi GETOPT_PATH="" done IFS=$IFS_orig AS_IF([test -n "$GETOPT_PATH"], [AC_MSG_RESULT([$GETOPT_PATH])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([Could not find required build tool GNU-compatible getopt]) ]) AC_SUBST([GETOPT_PATH]) dnl ======================================================================== dnl checks for library functions to replace them dnl dnl NoSuchFunctionName: dnl is a dummy function which no system supplies. It is here to make dnl the system compile semi-correctly on OpenBSD which doesn't know dnl how to create an empty archive dnl dnl scandir: Only on BSD. dnl System-V systems may have it, but hidden and/or deprecated. dnl A replacement function is supplied for it. dnl dnl strerror: returns a string that corresponds to an errno. dnl A replacement function is supplied for it. dnl dnl strnlen: is a gnu function similar to strlen, but safer. dnl We wrote a tolerably-fast replacement function for it. dnl dnl strndup: is a gnu function similar to strdup, but safer. dnl We wrote a tolerably-fast replacement function for it. AC_REPLACE_FUNCS(alphasort NoSuchFunctionName scandir strerror strchrnul strnlen strndup) dnl =============================================== dnl Libraries dnl =============================================== AC_CHECK_LIB(socket, socket) dnl -lsocket AC_CHECK_LIB(c, dlopen) dnl if dlopen is in libc... AC_CHECK_LIB(dl, dlopen) dnl -ldl (for Linux) AC_CHECK_LIB(rt, sched_getscheduler) dnl -lrt (for Tru64) AC_CHECK_LIB(gnugetopt, getopt_long) dnl -lgnugetopt ( if available ) AC_CHECK_LIB(pam, pam_start) dnl -lpam (if available) PKG_CHECK_MODULES([UUID], [uuid], [CPPFLAGS="${CPPFLAGS} ${UUID_CFLAGS}" LIBS="${LIBS} ${UUID_LIBS}"]) AC_CHECK_FUNCS([sched_setscheduler]) if test "$ac_cv_func_sched_setscheduler" != yes; then PC_LIBS_RT="" else PC_LIBS_RT="-lrt" fi AC_SUBST(PC_LIBS_RT) # Require minimum glib version PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.42.0], [CPPFLAGS="${CPPFLAGS} ${GLIB_CFLAGS}" LIBS="${LIBS} ${GLIB_LIBS}"]) # Check whether high-resolution sleep function is available AC_CHECK_FUNCS([nanosleep usleep]) # # Where is dlopen? # if test "$ac_cv_lib_c_dlopen" = yes; then LIBADD_DL="" elif test "$ac_cv_lib_dl_dlopen" = yes; then LIBADD_DL=-ldl else LIBADD_DL=${lt_cv_dlopen_libs} fi PKG_CHECK_MODULES(LIBXML2, [libxml-2.0], [CPPFLAGS="${CPPFLAGS} ${LIBXML2_CFLAGS}" LIBS="${LIBS} ${LIBXML2_LIBS}"]) REQUIRE_LIB([xslt], [xsltApplyStylesheet]) dnl ======================================================================== dnl Headers dnl ======================================================================== # Some distributions insert #warnings into deprecated headers. If we will # enable fatal warnings for the build, then enable them for the header checks # as well, otherwise the build could fail even though the header check # succeeds. (We should probably be doing this in more places.) cc_temp_flags "$CFLAGS $WERROR" # Optional headers (inclusion of these should be conditional in C code) AC_CHECK_HEADERS([getopt.h]) AC_CHECK_HEADERS([linux/swab.h]) AC_CHECK_HEADERS([stddef.h]) AC_CHECK_HEADERS([sys/signalfd.h]) AC_CHECK_HEADERS([uuid/uuid.h]) AC_CHECK_HEADERS([security/pam_appl.h pam/pam_appl.h]) # Required headers REQUIRE_HEADER([arpa/inet.h]) REQUIRE_HEADER([ctype.h]) REQUIRE_HEADER([dirent.h]) REQUIRE_HEADER([errno.h]) REQUIRE_HEADER([glib.h]) REQUIRE_HEADER([grp.h]) REQUIRE_HEADER([limits.h]) REQUIRE_HEADER([netdb.h]) REQUIRE_HEADER([netinet/in.h]) REQUIRE_HEADER([netinet/ip.h], [ #include #include ]) REQUIRE_HEADER([pwd.h]) REQUIRE_HEADER([signal.h]) REQUIRE_HEADER([stdio.h]) REQUIRE_HEADER([stdlib.h]) REQUIRE_HEADER([string.h]) REQUIRE_HEADER([strings.h]) REQUIRE_HEADER([sys/ioctl.h]) REQUIRE_HEADER([sys/param.h]) REQUIRE_HEADER([sys/reboot.h]) REQUIRE_HEADER([sys/resource.h]) REQUIRE_HEADER([sys/socket.h]) REQUIRE_HEADER([sys/stat.h]) REQUIRE_HEADER([sys/time.h]) REQUIRE_HEADER([sys/types.h]) REQUIRE_HEADER([sys/utsname.h]) REQUIRE_HEADER([sys/wait.h]) REQUIRE_HEADER([time.h]) REQUIRE_HEADER([unistd.h]) REQUIRE_HEADER([libxml/xpath.h]) REQUIRE_HEADER([libxslt/xslt.h]) cc_restore_flags AC_CHECK_FUNCS([uuid_unparse], [], [AC_MSG_FAILURE([Could not find required C function uuid_unparse()])]) AC_CACHE_CHECK([whether __progname and __progname_full are available], [pf_cv_var_progname], AC_LINK_IFELSE([ AC_LANG_PROGRAM([[extern char *__progname, *__progname_full;]], [[__progname = "foo"; __progname_full = "foo bar";]], [pf_cv_var_progname="yes"], [pf_cv_var_progname="no"]) ])) AS_IF([test "$pf_cv_var_progname" = "yes"], [AC_DEFINE(HAVE___PROGNAME,1,[ ])]) dnl ======================================================================== dnl Generic declarations dnl ======================================================================== AC_CHECK_DECLS([CLOCK_MONOTONIC], [PCMK_FEATURES="$PCMK_FEATURES monotonic"], [], [[ #include ]]) +dnl ======================================================================== +dnl Unit test declarations +dnl ======================================================================== + +AC_CHECK_DECLS([assert_float_equal], [], [], [[ + #include + #include + #include + #include +]]) + +cc_temp_flags "$CFLAGS -Wl,--wrap=uname" + +WRAPPABLE_UNAME="no" + +AC_MSG_CHECKING([if uname() can be wrapped]) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +int __wrap_uname(struct utsname *buf) { +return 100; +} +int main(int argc, char **argv) { +struct utsname x; +return uname(&x) == 100 ? 0 : 1; +} +]])], + [ WRAPPABLE_UNAME="yes" ], [ WRAPPABLE_UNAME="no"]) +AC_MSG_RESULT([$WRAPPABLE_UNAME]) +AM_CONDITIONAL([WRAPPABLE_UNAME], [test "$WRAPPABLE_UNAME" = "yes"]) + +cc_restore_flags + dnl ======================================================================== dnl Structures dnl ======================================================================== AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include ]]) AC_CHECK_MEMBER([struct dirent.d_type], AC_DEFINE(HAVE_STRUCT_DIRENT_D_TYPE,1,[Define this if struct dirent has d_type]),, [#include ]) dnl ======================================================================== dnl Functions dnl ======================================================================== REQUIRE_FUNC([getopt]) REQUIRE_FUNC([setenv]) REQUIRE_FUNC([unsetenv]) AC_CACHE_CHECK(whether sscanf supports %m, pf_cv_var_sscanf, AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include const char *s = "some-command-line-arg"; int main(int argc, char **argv) { char *name = NULL; int n = sscanf(s, "%ms", &name); return n == 1 ? 0 : 1; } ]])], pf_cv_var_sscanf="yes", pf_cv_var_sscanf="no", pf_cv_var_sscanf="no")) AS_IF([test "$pf_cv_var_sscanf" = "yes"], [AC_DEFINE(SSCANF_HAS_M, 1, [ ])]) dnl ======================================================================== dnl bzip2 dnl ======================================================================== REQUIRE_HEADER([bzlib.h]) REQUIRE_LIB([bz2], [BZ2_bzBuffToBuffCompress]) dnl ======================================================================== dnl sighandler_t is missing from Illumos, Solaris11 systems dnl ======================================================================== AC_MSG_CHECKING([for sighandler_t]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[sighandler_t *f;]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_SIGHANDLER_T], [1], [Define to 1 if sighandler_t is available]) ], [AC_MSG_RESULT([no])]) dnl ======================================================================== dnl ncurses dnl ======================================================================== dnl dnl A few OSes (e.g. Linux) deliver a default "ncurses" alongside "curses". dnl Many non-Linux deliver "curses"; sites may add "ncurses". dnl dnl However, the source-code recommendation for both is to #include "curses.h" dnl (i.e. "ncurses" still wants the include to be simple, no-'n', "curses.h"). dnl dnl ncurses takes precedence. dnl AC_CHECK_HEADERS([curses.h curses/curses.h ncurses.h ncurses/ncurses.h]) dnl Although n-library is preferred, only look for it if the n-header was found. CURSESLIBS='' PC_NAME_CURSES="" PC_LIBS_CURSES="" AS_IF([test "$ac_cv_header_ncurses_h" = "yes"], [ AC_CHECK_LIB(ncurses, printw, [AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)]) CURSESLIBS=`$PKG_CONFIG --libs ncurses` || CURSESLIBS='-lncurses' PC_NAME_CURSES="ncurses" ]) AS_IF([test "$ac_cv_header_ncurses_ncurses_h" = "yes"], [ AC_CHECK_LIB(ncurses, printw, [AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)]) CURSESLIBS=`$PKG_CONFIG --libs ncurses` || CURSESLIBS='-lncurses' PC_NAME_CURSES="ncurses" ]) dnl Only look for non-n-library if there was no n-library. AS_IF([test X"$CURSESLIBS" = X"" && test "$ac_cv_header_curses_h" = "yes"], [ AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)]) PC_LIBS_CURSES="$CURSESLIBS" ]) dnl Only look for non-n-library if there was no n-library. AS_IF([test X"$CURSESLIBS" = X"" && test "$ac_cv_header_curses_curses_h" = "yes"], [ AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)]) PC_LIBS_CURSES="$CURSESLIBS" ]) if test "x$CURSESLIBS" != "x"; then PCMK_FEATURES="$PCMK_FEATURES ncurses" fi dnl Check for printw() prototype compatibility AS_IF([test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual], [ ac_save_LIBS=$LIBS LIBS="$CURSESLIBS" cc_temp_flags "-Wcast-qual $WERROR" # avoid broken test because of hardened build environment in Fedora 23+ # - https://fedoraproject.org/wiki/Changes/Harden_All_Packages # - https://bugzilla.redhat.com/1297985 AS_IF([cc_supports_flag -fPIC], [CFLAGS="$CFLAGS -fPIC"]) AC_MSG_CHECKING([whether curses library is compatible]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([ #if defined(HAVE_NCURSES_H) # include #elif defined(HAVE_NCURSES_NCURSES_H) # include #elif defined(HAVE_CURSES_H) # include #endif ], [printw((const char *)"Test");] )], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_WARN(m4_normalize([Disabling curses because the printw() function of your (n)curses library is old. If you wish to enable curses, update to a newer version (ncurses 5.4 or later is recommended, available from https://invisible-island.net/ncurses/) ])) AC_DEFINE([HAVE_INCOMPATIBLE_PRINTW], [1], [Define to 1 if curses library has incompatible printw()]) ] ) LIBS=$ac_save_LIBS cc_restore_flags ]) AC_SUBST(CURSESLIBS) AC_SUBST(PC_NAME_CURSES) AC_SUBST(PC_LIBS_CURSES) dnl ======================================================================== dnl Profiling and GProf dnl ======================================================================== CFLAGS_ORIG="$CFLAGS" AS_IF([test $with_coverage -ne $DISABLED], [ with_profiling=$REQUIRED PCMK_FEATURES="$PCMK_FEATURES coverage" CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" dnl During linking, make sure to specify -lgcov or -coverage ] ) AS_IF([test $with_profiling -ne $DISABLED], [ with_profiling=$REQUIRED PCMK_FEATURES="$PCMK_FEATURES profile" dnl Disable various compiler optimizations CFLAGS="$CFLAGS -fno-omit-frame-pointer -fno-inline -fno-builtin" dnl CFLAGS="$CFLAGS -fno-inline-functions" dnl CFLAGS="$CFLAGS -fno-default-inline" dnl CFLAGS="$CFLAGS -fno-inline-functions-called-once" dnl CFLAGS="$CFLAGS -fno-optimize-sibling-calls" dnl Turn off optimization so tools can get accurate line numbers CFLAGS=`echo $CFLAGS | sed \ -e 's/-O.\ //g' \ -e 's/-Wp,-D_FORTIFY_SOURCE=.\ //g' \ -e 's/-D_FORTIFY_SOURCE=.\ //g'` CFLAGS="$CFLAGS -O0 -g3 -gdwarf-2" AC_MSG_NOTICE([CFLAGS before adding profiling options: $CFLAGS_ORIG]) AC_MSG_NOTICE([CFLAGS after: $CFLAGS]) ] ) AC_DEFINE_UNQUOTED([SUPPORT_PROFILING], [$with_profiling], [Support profiling]) AM_CONDITIONAL([BUILD_PROFILING], [test "$with_profiling" = "$REQUIRED"]) dnl ======================================================================== dnl Cluster infrastructure - LibQB dnl ======================================================================== PKG_CHECK_MODULES(libqb, libqb >= 0.17) CPPFLAGS="$libqb_CFLAGS $CPPFLAGS" LIBS="$libqb_LIBS $LIBS" dnl libqb 2.0.2+ (2020-10) AC_CHECK_FUNCS(qb_ipcc_auth_get, AC_DEFINE(HAVE_IPCC_AUTH_GET, 1, [Have qb_ipcc_auth_get function])) dnl libqb 2.0.0+ (2020-05) CHECK_ENUM_VALUE([qb/qblog.h],[qb_log_conf],[QB_LOG_CONF_MAX_LINE_LEN]) CHECK_ENUM_VALUE([qb/qblog.h],[qb_log_conf],[QB_LOG_CONF_ELLIPSIS]) dnl Support Linux-HA fence agents if available if test "$cross_compiling" != "yes"; then CPPFLAGS="$CPPFLAGS -I${prefix}/include/heartbeat" fi AC_CHECK_HEADERS([stonith/stonith.h], [ AC_CHECK_LIB([pils], [PILLoadPlugin]) AC_CHECK_LIB([plumb], [G_main_add_IPC_Channel]) PCMK_FEATURES="$PCMK_FEATURES lha" ]) AM_CONDITIONAL([BUILD_LHA_SUPPORT], [test "$ac_cv_header_stonith_stonith_h" = "yes"]) dnl =============================================== dnl Variables needed for substitution dnl =============================================== CRM_SCHEMA_DIRECTORY="${datadir}/pacemaker" AC_DEFINE_UNQUOTED(CRM_SCHEMA_DIRECTORY,"$CRM_SCHEMA_DIRECTORY", Location for the Pacemaker Relax-NG Schema) AC_SUBST(CRM_SCHEMA_DIRECTORY) CRM_CORE_DIR="${localstatedir}/lib/pacemaker/cores" AC_DEFINE_UNQUOTED(CRM_CORE_DIR,"$CRM_CORE_DIR", Location to store core files produced by Pacemaker daemons) AC_SUBST(CRM_CORE_DIR) if test x"${CRM_DAEMON_USER}" = x""; then CRM_DAEMON_USER="hacluster" fi AC_DEFINE_UNQUOTED(CRM_DAEMON_USER,"$CRM_DAEMON_USER", User to run Pacemaker daemons as) AC_SUBST(CRM_DAEMON_USER) if test x"${CRM_DAEMON_GROUP}" = x""; then CRM_DAEMON_GROUP="haclient" fi AC_DEFINE_UNQUOTED(CRM_DAEMON_GROUP,"$CRM_DAEMON_GROUP", Group to run Pacemaker daemons as) AC_SUBST(CRM_DAEMON_GROUP) CRM_PACEMAKER_DIR=${localstatedir}/lib/pacemaker AC_DEFINE_UNQUOTED(CRM_PACEMAKER_DIR,"$CRM_PACEMAKER_DIR", Location to store directory produced by Pacemaker daemons) AC_SUBST(CRM_PACEMAKER_DIR) CRM_BLACKBOX_DIR=${localstatedir}/lib/pacemaker/blackbox AC_DEFINE_UNQUOTED(CRM_BLACKBOX_DIR,"$CRM_BLACKBOX_DIR", Where to keep blackbox dumps) AC_SUBST(CRM_BLACKBOX_DIR) PE_STATE_DIR="${localstatedir}/lib/pacemaker/pengine" AC_DEFINE_UNQUOTED(PE_STATE_DIR,"$PE_STATE_DIR", Where to keep scheduler outputs) AC_SUBST(PE_STATE_DIR) CRM_CONFIG_DIR="${localstatedir}/lib/pacemaker/cib" AC_DEFINE_UNQUOTED(CRM_CONFIG_DIR,"$CRM_CONFIG_DIR", Where to keep configuration files) AC_SUBST(CRM_CONFIG_DIR) CRM_CONFIG_CTS="${localstatedir}/lib/pacemaker/cts" AC_DEFINE_UNQUOTED(CRM_CONFIG_CTS,"$CRM_CONFIG_CTS", Where to keep cts stateful data) AC_SUBST(CRM_CONFIG_CTS) CRM_DAEMON_DIR="${libexecdir}/pacemaker" AC_DEFINE_UNQUOTED(CRM_DAEMON_DIR,"$CRM_DAEMON_DIR", Location for Pacemaker daemons) AC_SUBST(CRM_DAEMON_DIR) CRM_STATE_DIR="${runstatedir}/crm" AC_DEFINE_UNQUOTED([CRM_STATE_DIR], ["$CRM_STATE_DIR"], [Where to keep state files and sockets]) AC_SUBST(CRM_STATE_DIR) CRM_RSCTMP_DIR="${runstatedir}/resource-agents" AC_DEFINE_UNQUOTED(CRM_RSCTMP_DIR,"$CRM_RSCTMP_DIR", Where resource agents should keep state files) AC_SUBST(CRM_RSCTMP_DIR) PACEMAKER_CONFIG_DIR="${sysconfdir}/pacemaker" AC_DEFINE_UNQUOTED(PACEMAKER_CONFIG_DIR,"$PACEMAKER_CONFIG_DIR", Where to keep configuration files like authkey) AC_SUBST(PACEMAKER_CONFIG_DIR) AC_DEFINE_UNQUOTED(SBIN_DIR,"$sbindir",[Location for system binaries]) AC_PATH_PROGS(GIT, git false) AC_MSG_CHECKING([build version]) BUILD_VERSION=$Format:%h$ if test $BUILD_VERSION != ":%h$"; then AC_MSG_RESULT([$BUILD_VERSION (archive hash)]) elif test -x $GIT && test -d .git; then BUILD_VERSION=`$GIT log --pretty="format:%h" -n 1` AC_MSG_RESULT([$BUILD_VERSION (git hash)]) else # The current directory name make a reasonable default # Most generated archives will include the hash or tag BASE=`basename $PWD` BUILD_VERSION=`echo $BASE | sed s:.*[[Pp]]acemaker-::` AC_MSG_RESULT([$BUILD_VERSION (directory name)]) fi AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version) AC_SUBST(BUILD_VERSION) HAVE_dbus=1 PKG_CHECK_MODULES([DBUS], [dbus-1], [CPPFLAGS="${CPPFLAGS} ${DBUS_CFLAGS}"], [HAVE_dbus=0]) AC_DEFINE_UNQUOTED(SUPPORT_DBUS, $HAVE_dbus, Support dbus) AM_CONDITIONAL(BUILD_DBUS, test $HAVE_dbus = 1) AC_CHECK_TYPES([DBusBasicValue],,,[[#include ]]) if test $HAVE_dbus = 0; then PC_NAME_DBUS="" else PC_NAME_DBUS="dbus-1" fi AC_SUBST(PC_NAME_DBUS) AS_CASE([$enable_systemd], [$REQUIRED], [ AS_IF([test $HAVE_dbus = 0], [AC_MSG_FAILURE([Cannot support systemd resources without DBus])]) AS_IF([test "$ac_cv_have_decl_CLOCK_MONOTONIC" = "no"], [AC_MSG_FAILURE([Cannot support systemd resources without monotonic clock])]) AS_IF([check_systemdsystemunitdir], [], [AC_MSG_FAILURE([Cannot support systemd resources without systemdsystemunitdir])]) ], [$OPTIONAL], [ AS_IF([test $HAVE_dbus = 0 \ || test "$ac_cv_have_decl_CLOCK_MONOTONIC" = "no"], [enable_systemd=$DISABLED], [ AC_MSG_CHECKING([for systemd version (using dbus-send)]) ret=$({ dbus-send --system --print-reply \ --dest=org.freedesktop.systemd1 \ /org/freedesktop/systemd1 \ org.freedesktop.DBus.Properties.Get \ string:org.freedesktop.systemd1.Manager \ string:Version 2>/dev/null \ || echo "version unavailable"; } | tail -n1) # sanitize output a bit (interested just in value, not type), # ret is intentionally unenquoted so as to normalize whitespace ret=$(echo ${ret} | cut -d' ' -f2-) AC_MSG_RESULT([${ret}]) AS_IF([test "$ret" != "unavailable" \ || systemctl --version 2>/dev/null | grep -q systemd], [ AS_IF([check_systemdsystemunitdir], [enable_systemd=$REQUIRED], [enable_systemd=$DISABLED]) ], [enable_systemd=$DISABLED] ) ]) ], ) AC_MSG_CHECKING([whether to enable support for managing resources via systemd]) AS_IF([test $enable_systemd -eq $DISABLED], [AC_MSG_RESULT([no])], [ AC_MSG_RESULT([yes]) PCMK_FEATURES="$PCMK_FEATURES systemd" ] ) AC_SUBST([systemdsystemunitdir]) AC_DEFINE_UNQUOTED([SUPPORT_SYSTEMD], [$enable_systemd], [Support systemd resources]) AM_CONDITIONAL([BUILD_SYSTEMD], [test $enable_systemd = $REQUIRED]) AC_SUBST(SUPPORT_SYSTEMD) AS_CASE([$enable_upstart], [$REQUIRED], [ AS_IF([test $HAVE_dbus = 0], [AC_MSG_FAILURE([Cannot support Upstart resources without DBus])]) ], [$OPTIONAL], [ AS_IF([test $HAVE_dbus = 0], [enable_upstart=$DISABLED], [ AC_MSG_CHECKING([for Upstart version (using dbus-send)]) ret=$({ dbus-send --system --print-reply \ --dest=com.ubuntu.Upstart \ /com/ubuntu/Upstart org.freedesktop.DBus.Properties.Get \ string:com.ubuntu.Upstart0_6 string:version 2>/dev/null \ || echo "version unavailable"; } | tail -n1) # sanitize output a bit (interested just in value, not type), # ret is intentionally unenquoted so as to normalize whitespace ret=$(echo ${ret} | cut -d' ' -f2-) AC_MSG_RESULT([${ret}]) AS_IF([test "$ret" != "unavailable" \ || initctl --version 2>/dev/null | grep -q upstart], [enable_upstart=$REQUIRED], [enable_upstart=$DISABLED] ) ]) ], ) AC_MSG_CHECKING([whether to enable support for managing resources via Upstart]) AS_IF([test $enable_upstart -eq $DISABLED], [AC_MSG_RESULT([no])], [ AC_MSG_RESULT([yes]) PCMK_FEATURES="$PCMK_FEATURES upstart" ] ) AC_DEFINE_UNQUOTED([SUPPORT_UPSTART], [$enable_upstart], [Support Upstart resources]) AM_CONDITIONAL([BUILD_UPSTART], [test $enable_upstart -eq $REQUIRED]) AC_SUBST(SUPPORT_UPSTART) AS_CASE([$with_nagios], [$REQUIRED], [ AS_IF([test "$ac_cv_have_decl_CLOCK_MONOTONIC" = "no"], [AC_MSG_FAILURE([Cannot support nagios resources without monotonic clock])]) ], [$OPTIONAL], [ AS_IF([test "$ac_cv_have_decl_CLOCK_MONOTONIC" = "no"], [with_nagios=$DISABLED], [with_nagios=$REQUIRED]) ] ) AS_IF([test $with_nagios -eq $REQUIRED], [PCMK_FEATURES="$PCMK_FEATURES nagios"]) AC_DEFINE_UNQUOTED([SUPPORT_NAGIOS], [$with_nagios], [Support nagios plugins]) AM_CONDITIONAL([BUILD_NAGIOS], [test $with_nagios -eq $REQUIRED]) if test x"$NAGIOS_PLUGIN_DIR" = x""; then NAGIOS_PLUGIN_DIR="${libexecdir}/nagios/plugins" fi AC_DEFINE_UNQUOTED(NAGIOS_PLUGIN_DIR, "$NAGIOS_PLUGIN_DIR", Directory for nagios plugins) AC_SUBST(NAGIOS_PLUGIN_DIR) if test x"$NAGIOS_METADATA_DIR" = x""; then NAGIOS_METADATA_DIR="${datadir}/nagios/plugins-metadata" fi AC_DEFINE_UNQUOTED(NAGIOS_METADATA_DIR, "$NAGIOS_METADATA_DIR", Directory for nagios plugins metadata) AC_SUBST(NAGIOS_METADATA_DIR) STACKS="" CLUSTERLIBS="" PC_NAME_CLUSTER="" dnl ======================================================================== dnl Cluster stack - Corosync dnl ======================================================================== COROSYNC_LIBS="" AS_CASE([$with_corosync], [$REQUIRED], [ # These will be fatal if unavailable PKG_CHECK_MODULES([cpg], [libcpg]) PKG_CHECK_MODULES([cfg], [libcfg]) PKG_CHECK_MODULES([cmap], [libcmap]) PKG_CHECK_MODULES([quorum], [libquorum]) PKG_CHECK_MODULES([libcorosync_common], [libcorosync_common]) ] [$OPTIONAL], [ PKG_CHECK_MODULES([cpg], [libcpg], [], [with_corosync=$DISABLED]) PKG_CHECK_MODULES([cfg], [libcfg], [], [with_corosync=$DISABLED]) PKG_CHECK_MODULES([cmap], [libcmap], [], [with_corosync=$DISABLED]) PKG_CHECK_MODULES([quorum], [libquorum], [], [with_corosync=$DISABLED]) PKG_CHECK_MODULES([libcorosync_common], [libcorosync_common], [], [with_corosync=$DISABLED]) AS_IF([test $with_corosync -ne $DISABLED], [with_corosync=$REQUIRED]) ] ) AS_IF([test $with_corosync -ne $DISABLED], [ AC_MSG_CHECKING([for Corosync 2 or later]) AC_MSG_RESULT([yes]) CFLAGS="$CFLAGS $libqb_CFLAGS $cpg_CFLAGS $cfg_CFLAGS $cmap_CFLAGS $quorum_CFLAGS $libcorosync_common_CFLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $cpg_LIBS $cfg_LIBS $cmap_LIBS $quorum_LIBS $libcorosync_common_LIBS" CLUSTERLIBS="$CLUSTERLIBS $COROSYNC_LIBS" PC_NAME_CLUSTER="$PC_CLUSTER_NAME libcfg libcmap libcorosync_common libcpg libquorum" STACKS="$STACKS corosync-ge-2" dnl Shutdown tracking added (back) to corosync Jan 2021 saved_LIBS="$LIBS" LIBS="$LIBS $COROSYNC_LIBS" AC_CHECK_FUNCS(corosync_cfg_trackstart, AC_DEFINE(HAVE_COROSYNC_CFG_TRACKSTART, 1, [Have corosync_cfg_trackstart function])) LIBS="$saved_LIBS" ] ) AC_DEFINE_UNQUOTED([SUPPORT_COROSYNC], [$with_corosync], [Support the Corosync messaging and membership layer]) AM_CONDITIONAL([BUILD_CS_SUPPORT], [test $with_corosync -eq $REQUIRED]) AC_SUBST([SUPPORT_COROSYNC]) dnl dnl Cluster stack - Sanity dnl AS_IF([test "x$STACKS" != "x"], [AC_MSG_NOTICE([Supported stacks:${STACKS}])], [AC_MSG_FAILURE([At least one cluster stack must be supported])]) PCMK_FEATURES="${PCMK_FEATURES}${STACKS}" AC_SUBST(CLUSTERLIBS) AC_SUBST(PC_NAME_CLUSTER) dnl ======================================================================== dnl CIB secrets dnl ======================================================================== AS_IF([test $with_cibsecrets -ne $DISABLED], [ with_cibsecrets=$REQUIRED PCMK_FEATURES="$PCMK_FEATURES cibsecrets" LRM_CIBSECRETS_DIR="${localstatedir}/lib/pacemaker/lrm/secrets" AC_DEFINE_UNQUOTED([LRM_CIBSECRETS_DIR], ["$LRM_CIBSECRETS_DIR"], [Location for CIB secrets]) AC_SUBST([LRM_CIBSECRETS_DIR]) ] ) AC_DEFINE_UNQUOTED([SUPPORT_CIBSECRETS], [$with_cibsecrets], [Support CIB secrets]) AM_CONDITIONAL([BUILD_CIBSECRETS], [test $with_cibsecrets -eq $REQUIRED]) dnl ======================================================================== dnl GnuTLS dnl ======================================================================== dnl Require GnuTLS >=2.12.0 (2011-03) for Pacemaker Remote support PC_NAME_GNUTLS="" AS_CASE([$with_gnutls], [$REQUIRED], [ REQUIRE_LIB([gnutls], [gnutls_sec_param_to_pk_bits]) REQUIRE_HEADER([gnutls/gnutls.h]) ], [$OPTIONAL], [ AC_CHECK_LIB([gnutls], [gnutls_sec_param_to_pk_bits], [], [with_gnutls=$DISABLED]) AC_CHECK_HEADERS([gnutls/gnutls.h], [], [with_gnutls=$DISABLED]) ] ) AS_IF([test $with_gnutls -ne $DISABLED], [ PC_NAME_GNUTLS="gnutls" PCMK_FEATURES="$PCMK_FEATURES remote" ] ) AC_SUBST([PC_NAME_GNUTLS]) AM_CONDITIONAL([BUILD_REMOTE], [test $with_gnutls -ne $DISABLED]) dnl ======================================================================== dnl System Health dnl ======================================================================== dnl Check if servicelog development package is installed SERVICELOG=servicelog-1 SERVICELOG_EXISTS="no" AC_MSG_CHECKING([for $SERVICELOG packages]) if $PKG_CONFIG --exists $SERVICELOG then PKG_CHECK_MODULES([SERVICELOG], [servicelog-1]) SERVICELOG_EXISTS="yes" PCMK_FEATURES="$PCMK_FEATURES servicelog" fi AC_MSG_RESULT([$SERVICELOG_EXISTS]) AM_CONDITIONAL(BUILD_SERVICELOG, test "$SERVICELOG_EXISTS" = "yes") dnl Check if OpenIMPI packages and servicelog are installed OPENIPMI="OpenIPMI OpenIPMIposix" OPENIPMI_SERVICELOG_EXISTS="no" AC_MSG_CHECKING([for $SERVICELOG $OPENIPMI packages]) if $PKG_CONFIG --exists $OPENIPMI $SERVICELOG then PKG_CHECK_MODULES([OPENIPMI_SERVICELOG],[OpenIPMI OpenIPMIposix]) REQUIRE_HEADER([malloc.h]) OPENIPMI_SERVICELOG_EXISTS="yes" PCMK_FEATURES="$PCMK_FEATURES ipmiservicelogd" fi AC_MSG_RESULT([$OPENIPMI_SERVICELOG_EXISTS]) AM_CONDITIONAL(BUILD_OPENIPMI_SERVICELOG, test "$OPENIPMI_SERVICELOG_EXISTS" = "yes") # --- ASAN/UBSAN/TSAN (see man gcc) --- # when using SANitizers, we need to pass the -fsanitize.. # to both CFLAGS and LDFLAGS. The CFLAGS/LDFLAGS must be # specified as first in the list or there will be runtime # issues (for example user has to LD_PRELOAD asan for it to work # properly). AS_IF([test -n "${SANITIZERS}"], [ SANITIZERS=$(echo $SANITIZERS | sed -e 's/,/ /g') for SANITIZER in $SANITIZERS do AS_CASE([$SANITIZER], [asan|ASAN], [ SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=address" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=address -lasan" PCMK_FEATURES="$PCMK_FEATURES asan" REQUIRE_LIB([asan],[main]) ], [ubsan|UBSAN], [ SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=undefined" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=undefined -lubsan" PCMK_FEATURES="$PCMK_FEATURES ubsan" REQUIRE_LIB([ubsan],[main]) ], [tsan|TSAN], [ SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=thread" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=thread -ltsan" PCMK_FEATURES="$PCMK_FEATURES tsan" REQUIRE_LIB([tsan],[main]) ]) done ]) dnl ======================================================================== dnl Compiler flags dnl ======================================================================== dnl Make sure that CFLAGS is not exported. If the user did dnl not have CFLAGS in their environment then this should have dnl no effect. However if CFLAGS was exported from the user's dnl environment, then the new CFLAGS will also be exported dnl to sub processes. if export | fgrep " CFLAGS=" > /dev/null; then SAVED_CFLAGS="$CFLAGS" unset CFLAGS CFLAGS="$SAVED_CFLAGS" unset SAVED_CFLAGS fi AC_ARG_VAR([CFLAGS_HARDENED_LIB], [extra C compiler flags for hardened libraries]) AC_ARG_VAR([LDFLAGS_HARDENED_LIB], [extra linker flags for hardened libraries]) AC_ARG_VAR([CFLAGS_HARDENED_EXE], [extra C compiler flags for hardened executables]) AC_ARG_VAR([LDFLAGS_HARDENED_EXE], [extra linker flags for hardened executables]) CC_EXTRAS="" AS_IF([test "$GCC" != yes], [CFLAGS="$CFLAGS -g"], [ CFLAGS="$CFLAGS -ggdb" dnl When we don't have diagnostic push / pull, we can't explicitly disable dnl checking for nonliteral formats in the places where they occur on purpose dnl thus we disable nonliteral format checking globally as we are aborting dnl on warnings. dnl what makes the things really ugly is that nonliteral format checking is dnl obviously available as an extra switch in very modern gcc but for older dnl gcc this is part of -Wformat=2 dnl so if we have push/pull we can enable -Wformat=2 -Wformat-nonliteral dnl if we don't have push/pull but -Wformat-nonliteral we can enable -Wformat=2 dnl otherwise none of both gcc_diagnostic_push_pull=no cc_temp_flags "$CFLAGS $WERROR" AC_MSG_CHECKING([for gcc diagnostic push / pull]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #pragma GCC diagnostic push #pragma GCC diagnostic pop ]])], [ AC_MSG_RESULT([yes]) gcc_diagnostic_push_pull=yes ], AC_MSG_RESULT([no])) cc_restore_flags AS_IF([cc_supports_flag "-Wformat-nonliteral"], [gcc_format_nonliteral=yes], [gcc_format_nonliteral=no]) # We had to eliminate -Wnested-externs because of libtool changes # Make sure to order options so that the former stand for prerequisites # of the latter (e.g., -Wformat-nonliteral requires -Wformat). EXTRA_FLAGS="-fgnu89-inline" EXTRA_FLAGS="$EXTRA_FLAGS -Wall" EXTRA_FLAGS="$EXTRA_FLAGS -Waggregate-return" EXTRA_FLAGS="$EXTRA_FLAGS -Wbad-function-cast" EXTRA_FLAGS="$EXTRA_FLAGS -Wcast-align" EXTRA_FLAGS="$EXTRA_FLAGS -Wdeclaration-after-statement" EXTRA_FLAGS="$EXTRA_FLAGS -Wendif-labels" EXTRA_FLAGS="$EXTRA_FLAGS -Wfloat-equal" EXTRA_FLAGS="$EXTRA_FLAGS -Wformat-security" EXTRA_FLAGS="$EXTRA_FLAGS -Wmissing-prototypes" EXTRA_FLAGS="$EXTRA_FLAGS -Wmissing-declarations" EXTRA_FLAGS="$EXTRA_FLAGS -Wnested-externs" EXTRA_FLAGS="$EXTRA_FLAGS -Wno-long-long" EXTRA_FLAGS="$EXTRA_FLAGS -Wno-strict-aliasing" EXTRA_FLAGS="$EXTRA_FLAGS -Wpointer-arith" EXTRA_FLAGS="$EXTRA_FLAGS -Wstrict-prototypes" EXTRA_FLAGS="$EXTRA_FLAGS -Wwrite-strings" EXTRA_FLAGS="$EXTRA_FLAGS -Wunused-but-set-variable" EXTRA_FLAGS="$EXTRA_FLAGS -Wunsigned-char" AS_IF([test "x$gcc_diagnostic_push_pull" = "xyes"], [ AC_DEFINE([GCC_FORMAT_NONLITERAL_CHECKING_ENABLED], [], [gcc can complain about nonliterals in format]) EXTRA_FLAGS="$EXTRA_FLAGS -Wformat=2 -Wformat-nonliteral" ], [test "x$gcc_format_nonliteral" = "xyes"], [EXTRA_FLAGS="$EXTRA_FLAGS -Wformat=2"]) # Additional warnings it might be nice to enable one day # -Wshadow # -Wunreachable-code for j in $EXTRA_FLAGS do AS_IF([cc_supports_flag $CC_EXTRAS $j], [CC_EXTRAS="$CC_EXTRAS $j"]) done AC_MSG_NOTICE([Using additional gcc flags: ${CC_EXTRAS}]) ]) dnl dnl Hardening flags dnl dnl The prime control of whether to apply (targeted) hardening build flags and dnl which ones is --{enable,disable}-hardening option passed to ./configure: dnl dnl --enable-hardening=try (default): dnl depending on whether any of CFLAGS_HARDENED_EXE, LDFLAGS_HARDENED_EXE, dnl CFLAGS_HARDENED_LIB or LDFLAGS_HARDENED_LIB environment variables dnl (see below) is set and non-null, all these custom flags (even if not dnl set) are used as are, otherwise the best effort is made to offer dnl reasonably strong hardening in several categories (RELRO, PIE, dnl "bind now", stack protector) according to what the selected toolchain dnl can offer dnl dnl --enable-hardening: dnl same effect as --enable-hardening=try when the environment variables dnl in question are suppressed dnl dnl --disable-hardening: dnl do not apply any targeted hardening measures at all dnl dnl The user-injected environment variables that regulate the hardening in dnl default case are as follows: dnl dnl * CFLAGS_HARDENED_EXE, LDFLAGS_HARDENED_EXE dnl compiler and linker flags (respectively) for daemon programs dnl (pacemakerd, pacemaker-attrd, pacemaker-controld, pacemaker-execd, dnl pacemaker-based, pacemaker-fenced, pacemaker-remoted, dnl pacemaker-schedulerd) dnl dnl * CFLAGS_HARDENED_LIB, LDFLAGS_HARDENED_LIB dnl compiler and linker flags (respectively) for libraries linked dnl with the daemon programs dnl dnl Note that these are purposedly targeted variables (addressing particular dnl targets all over the scattered Makefiles) and have no effect outside of dnl the predestined scope (e.g., CLI utilities). For a global reach, dnl use CFLAGS, LDFLAGS, etc. as usual. dnl dnl For guidance on the suitable flags consult, for instance: dnl https://fedoraproject.org/wiki/Changes/Harden_All_Packages#Detailed_Harden_Flags_Description dnl https://owasp.org/index.php/C-Based_Toolchain_Hardening#GCC.2FBinutils dnl AS_IF([test $enable_hardening -eq $OPTIONAL], [ AS_IF([test "$(env | grep -Ec '^(C|LD)FLAGS_HARDENED_(EXE|LIB)=.')" = 0], [enable_hardening=$REQUIRED], [AC_MSG_NOTICE([Hardening: using custom flags from environment])] ) ], [ unset CFLAGS_HARDENED_EXE unset CFLAGS_HARDENED_LIB unset LDFLAGS_HARDENED_EXE unset LDFLAGS_HARDENED_LIB ] ) AS_CASE([$enable_hardening], [$DISABLED], [AC_MSG_NOTICE([Hardening: explicitly disabled])], [$REQUIRED], [ CFLAGS_HARDENED_EXE= CFLAGS_HARDENED_LIB= LDFLAGS_HARDENED_EXE= LDFLAGS_HARDENED_LIB= relro=0 pie=0 bindnow=0 stackprot="none" # daemons incl. libs: partial RELRO flag="-Wl,-z,relro" CC_CHECK_LDFLAGS(["${flag}"], [ LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}" LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}" relro=1 ]) # daemons: PIE for both CFLAGS and LDFLAGS AS_IF([cc_supports_flag -fPIE], [ flag="-pie" CC_CHECK_LDFLAGS(["${flag}"], [ CFLAGS_HARDENED_EXE="${CFLAGS_HARDENED_EXE} -fPIE" LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}" pie=1 ]) ] ) # daemons incl. libs: full RELRO if sensible + as-needed linking # so as to possibly mitigate startup performance # hit caused by excessive linking with unneeded # libraries AS_IF([test "${relro}" = 1 && test "${pie}" = 1], [ flag="-Wl,-z,now" CC_CHECK_LDFLAGS(["${flag}"], [ LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}" LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}" bindnow=1 ]) ] ) AS_IF([test "${bindnow}" = 1], [ flag="-Wl,--as-needed" CC_CHECK_LDFLAGS(["${flag}"], [ LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}" LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}" ]) ]) # universal: prefer strong > all > default stack protector if possible flag= AS_IF([cc_supports_flag -fstack-protector-strong], [ flag="-fstack-protector-strong" stackprot="strong" ], [cc_supports_flag -fstack-protector-all], [ flag="-fstack-protector-all" stackprot="all" ], [cc_supports_flag -fstack-protector], [ flag="-fstack-protector" stackprot="default" ] ) AS_IF([test -n "${flag}"], [CC_EXTRAS="${CC_EXTRAS} ${flag}"]) # universal: enable stack clash protection if possible AS_IF([cc_supports_flag -fstack-clash-protection], [ CC_EXTRAS="${CC_EXTRAS} -fstack-clash-protection" AS_IF([test "${stackprot}" = "none"], [stackprot="clash-only"], [stackprot="${stackprot}+clash"] ) ] ) # Log a summary AS_IF([test "${relro}" = 1 || test "${pie}" = 1 || test "${stackprot}" != "none"], [AC_MSG_NOTICE(m4_normalize([Hardening: relro=${relro} pie=${pie} bindnow=${bindnow} stackprot=${stackprot}])) ], [AC_MSG_WARN([Hardening: no suitable features in the toolchain detected])] ) ], ) CFLAGS="$SANITIZERS_CFLAGS $CFLAGS $CC_EXTRAS" LDFLAGS="$SANITIZERS_LDFLAGS $LDFLAGS" CFLAGS_HARDENED_EXE="$SANITIZERS_CFLAGS $CFLAGS_HARDENED_EXE" LDFLAGS_HARDENED_EXE="$SANITIZERS_LDFLAGS $LDFLAGS_HARDENED_EXE" NON_FATAL_CFLAGS="$CFLAGS" AC_SUBST(NON_FATAL_CFLAGS) dnl dnl We reset CFLAGS to include our warnings *after* all function dnl checking goes on, so that our warning flags don't keep the dnl AC_*FUNCS() calls above from working. In particular, -Werror will dnl *always* cause us troubles if we set it before here. dnl dnl AS_IF([test $enable_fatal_warnings -ne $DISABLED], [ AC_MSG_NOTICE([Enabling fatal compiler warnings]) CFLAGS="$CFLAGS $WERROR" ]) AC_SUBST(CFLAGS) dnl This is useful for use in Makefiles that need to remove one specific flag CFLAGS_COPY="$CFLAGS" AC_SUBST(CFLAGS_COPY) AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries AC_SUBST(LOCALE) dnl Options for cleaning up the compiler output AS_IF([test $enable_quiet -ne $DISABLED], [ AC_MSG_NOTICE([Suppressing make details]) QUIET_LIBTOOL_OPTS="--silent" QUIET_MAKE_OPTS="-s" # POSIX compliant ], [ QUIET_LIBTOOL_OPTS="" QUIET_MAKE_OPTS="" ] ) dnl Put the above variables to use LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)" MAKEFLAGS="${MAKEFLAGS} ${QUIET_MAKE_OPTS}" # Make features list available (sorted alphabetically, without leading space) PCMK_FEATURES=`echo "$PCMK_FEATURES" | sed -e 's/^ //' -e 's/ /\n/g' | sort | xargs` AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PCMK_FEATURES", Set of enabled features) AC_SUBST(PCMK_FEATURES) AC_SUBST(CC) AC_SUBST(MAKEFLAGS) AC_SUBST(LIBTOOL) AC_SUBST(QUIET_LIBTOOL_OPTS) dnl Files we output that need to be executable CONFIG_FILES_EXEC([cts/cts-cli], [cts/cts-coverage], [cts/cts-exec], [cts/cts-fencing], [cts/cts-regression], [cts/cts-scheduler], [cts/lxc_autogen.sh], [cts/benchmark/clubench], [cts/lab/CTSlab.py], [cts/lab/OCFIPraTest.py], [cts/lab/cluster_test], [cts/lab/cts], [cts/lab/cts-log-watcher], [cts/support/LSBDummy], [cts/support/cts-support], [cts/support/fence_dummy], [cts/support/pacemaker-cts-dummyd], [daemons/fenced/fence_legacy], [daemons/fenced/fence_watchdog], [doc/abi-check], [extra/resources/ClusterMon], [extra/resources/HealthSMART], [extra/resources/SysInfo], [extra/resources/ifspeed], [extra/resources/o2cb], [maint/bumplibs], [tools/crm_failcount], [tools/crm_master], [tools/crm_report], [tools/crm_standby], [tools/cibsecret], [tools/pcmk_simtimes]) dnl Other files we output AC_CONFIG_FILES(Makefile \ cts/Makefile \ cts/benchmark/Makefile \ cts/lab/Makefile \ cts/lab/CTSvars.py \ cts/scheduler/Makefile \ cts/scheduler/dot/Makefile \ cts/scheduler/exp/Makefile \ cts/scheduler/scores/Makefile \ cts/scheduler/stderr/Makefile \ cts/scheduler/summary/Makefile \ cts/scheduler/xml/Makefile \ cts/support/Makefile \ cts/support/pacemaker-cts-dummyd@.service \ daemons/Makefile \ daemons/attrd/Makefile \ daemons/based/Makefile \ daemons/controld/Makefile \ daemons/execd/Makefile \ daemons/execd/pacemaker_remote \ daemons/execd/pacemaker_remote.service \ daemons/fenced/Makefile \ daemons/pacemakerd/Makefile \ daemons/pacemakerd/pacemaker.service \ daemons/pacemakerd/pacemaker.upstart \ daemons/pacemakerd/pacemaker.combined.upstart \ daemons/schedulerd/Makefile \ devel/Makefile \ doc/Doxyfile \ doc/Makefile \ doc/sphinx/Makefile \ etc/Makefile \ etc/init.d/pacemaker \ etc/logrotate.d/pacemaker \ extra/Makefile \ extra/alerts/Makefile \ extra/resources/Makefile \ include/Makefile \ include/crm/Makefile \ include/crm/cib/Makefile \ include/crm/common/Makefile \ include/crm/cluster/Makefile \ include/crm/fencing/Makefile \ include/crm/pengine/Makefile \ include/pcmki/Makefile \ replace/Makefile \ lib/Makefile \ lib/libpacemaker.pc \ lib/pacemaker.pc \ lib/pacemaker-cib.pc \ lib/pacemaker-lrmd.pc \ lib/pacemaker-service.pc \ lib/pacemaker-pe_rules.pc \ lib/pacemaker-pe_status.pc \ lib/pacemaker-fencing.pc \ lib/pacemaker-cluster.pc \ lib/common/Makefile \ lib/common/tests/Makefile \ lib/common/tests/agents/Makefile \ lib/common/tests/cmdline/Makefile \ lib/common/tests/flags/Makefile \ lib/common/tests/io/Makefile \ lib/common/tests/iso8601/Makefile \ lib/common/tests/operations/Makefile \ lib/common/tests/results/Makefile \ lib/common/tests/strings/Makefile \ lib/common/tests/utils/Makefile \ lib/common/tests/xpath/Makefile \ lib/cluster/Makefile \ lib/cib/Makefile \ lib/gnu/Makefile \ lib/pacemaker/Makefile \ lib/pengine/Makefile \ lib/pengine/tests/Makefile \ lib/pengine/tests/rules/Makefile \ lib/fencing/Makefile \ lib/lrmd/Makefile \ lib/services/Makefile \ maint/Makefile \ tests/Makefile \ tools/Makefile \ tools/report.collector \ tools/report.common \ tools/crm_mon.service \ tools/crm_mon.upstart \ xml/Makefile \ xml/pacemaker-schemas.pc \ ) dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() dnl ***************** dnl Configure summary dnl ***************** AC_MSG_NOTICE([]) AC_MSG_NOTICE([$PACKAGE configuration:]) AC_MSG_NOTICE([ Version = ${VERSION} (Build: $BUILD_VERSION)]) AC_MSG_NOTICE([ Features = ${PCMK_FEATURES}]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ Prefix = ${prefix}]) AC_MSG_NOTICE([ Executables = ${sbindir}]) AC_MSG_NOTICE([ Man pages = ${mandir}]) AC_MSG_NOTICE([ Libraries = ${libdir}]) AC_MSG_NOTICE([ Header files = ${includedir}]) AC_MSG_NOTICE([ Arch-independent files = ${datadir}]) AC_MSG_NOTICE([ State information = ${localstatedir}]) AC_MSG_NOTICE([ System configuration = ${sysconfdir}]) AC_MSG_NOTICE([ OCF agents = ${OCF_ROOT_DIR}]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ HA group name = ${CRM_DAEMON_GROUP}]) AC_MSG_NOTICE([ HA user name = ${CRM_DAEMON_USER}]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ CFLAGS = ${CFLAGS}]) AC_MSG_NOTICE([ CFLAGS_HARDENED_EXE = ${CFLAGS_HARDENED_EXE}]) AC_MSG_NOTICE([ CFLAGS_HARDENED_LIB = ${CFLAGS_HARDENED_LIB}]) AC_MSG_NOTICE([ LDFLAGS_HARDENED_EXE = ${LDFLAGS_HARDENED_EXE}]) AC_MSG_NOTICE([ LDFLAGS_HARDENED_LIB = ${LDFLAGS_HARDENED_LIB}]) AC_MSG_NOTICE([ Libraries = ${LIBS}]) AC_MSG_NOTICE([ Stack Libraries = ${CLUSTERLIBS}]) AC_MSG_NOTICE([ Unix socket auth method = ${us_auth}]) diff --git a/doc/sphinx/Pacemaker_Development/helpers.rst b/doc/sphinx/Pacemaker_Development/helpers.rst index d7e2c22022..5b3dd8aed4 100644 --- a/doc/sphinx/Pacemaker_Development/helpers.rst +++ b/doc/sphinx/Pacemaker_Development/helpers.rst @@ -1,398 +1,397 @@ C Development Helpers --------------------- .. index:: single: unit testing Refactoring ########### Pacemaker uses an optional tool called `coccinelle `_ to do automatic refactoring. coccinelle is a very complicated tool that can be difficult to understand, and the existing documentation makes it pretty tough to get started. Much of the documentation is either aimed at kernel developers or takes the form of grammars. However, it can apply very complex transformations across an entire source tree. This is useful for tasks like code refactoring, changing APIs (number or type of arguments, etc.), catching functions that should not be called, and changing existing patterns. coccinelle is driven by input scripts called `semantic patches `_ written in its own language. These scripts bear a passing resemblance to source code patches and tell coccinelle how to match and modify a piece of source code. They are stored in ``devel/coccinelle`` and each script either contains a single source transformation or several related transformations. In general, we try to keep these as simple as possible. In Pacemaker development, we use a couple targets in ``devel/Makefile.am`` to control coccinelle. The ``cocci`` target tries to apply each script to every Pacemaker source file, printing out any changes it would make to the console. The ``cocci-inplace`` target does the same but also makes those changes to the source files. A variety of warnings might also be printed. If you aren't working on a new script, these can usually be ignored. If you are working on a new coccinelle script, it can be useful (and faster) to skip everything else and only run the new script. The ``COCCI_FILES`` variable can be used for this: .. code-block:: none $ make -C devel COCCI_FILES=coccinelle/new-file.cocci cocci This variable is also used for preventing some coccinelle scripts in the Pacemaker source tree from running. Some scripts are disabled because they are not currently fully working or because they are there as templates. When adding a new script, remember to add it to this variable if it should always be run. One complication when writing coccinelle scripts is that certain Pacemaker source files may not use private functions (those whose name starts with ``pcmk__``). Handling this requires work in both the Makefile and in the coccinelle scripts. The Makefile deals with this by maintaining two lists of source files: those that may use private functions and those that may not. For those that may, a special argument (``-D internal``) is added to the coccinelle command line. This creates a virtual dependency named ``internal``. In the coccinelle scripts, those transformations that modify source code to use a private function also have a dependency on ``internal``. If that dependency was given on the command line, the transformation will be run. Otherwise, it will be skipped. This means that not all instances of an older style of code will be changed after running a given transformation. Some developer intervention is still necessary to know whether a source code block should have been changed or not. Probably the easiest way to learn how to use coccinelle is by following other people's scripts. In addition to the ones in the Pacemaker source directory, there's several others on the `coccinelle website `_. Unit Testing ############ Where possible, changes to the C side of Pacemaker should be accompanied by unit tests. Much of Pacemaker cannot effectively be unit tested (and there are other testing systems used for those parts), but the ``lib`` subdirectory is pretty easy to write tests for. -Pacemaker uses the `GLib unit testing framework -`_ which looks a lot -like other unit testing frameworks for C and should be fairly familiar. +Pacemaker uses the `cmocka unit testing framework `_ which looks +a lot like other unit testing frameworks for C and should be fairly familiar. In +addition to regular unit tests, cmocka also gives us the ability to use +`mock functions `_ for unit testing +functions that would otherwise be difficult to test. Organization ____________ Pay close attention to the organization and naming of test cases to ensure the unit tests continue to work as they should. Tests are spread throughout the source tree, alongside the source code they test. For instance, all the tests for the source code in ``lib/common/`` are in the ``lib/common/tests`` directory. If there is no ``tests`` subdirectory, there are no tests for that library yet. Under that directory, there is a ``Makefile.am`` and additional subdirectories. Each subdirectory contains the tests for a single library source file. For instance, all the tests for ``lib/common/strings.c`` are in the ``lib/common/tests/strings`` directory. Note that the test subdirectory does not have a ``.c`` suffix. If there is no test subdirectory, there are no tests for that file yet. Finally, under that directory, there is a ``Makefile.am`` and then various source files. Each of these source files tests the single function that it is named after. For instance, ``lib/common/tests/strings/pcmk__btoa_test.c`` tests the ``pcmk__btoa_test()`` function in ``lib/common/strings.c``. If there is no test source file, there are no tests for that function yet. The ``_test`` suffix on the test source file is important. All tests have this suffix, which means all the compiled test cases will also end with this suffix. That lets us ignore all the compiled tests with a single line in ``.gitignore``: .. code-block:: none /lib/*/tests/*/*_test Adding a test _____________ Testing a new function in an already testable source file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Follow these steps if you want to test a function in a source file where there are already other tested functions. For the purposes of this example, we will add a test for the ``pcmk__scan_port()`` function in ``lib/common/strings.c``. As you can see, there are already tests for other functions in this same file in the ``lib/common/tests/strings`` directory. * cd into ``lib/common/tests/strings`` -* Add the new file to the the ``test_programs`` variable in ``Makefile.am``, making - it something like this: +* Add the new file to the the ``check_PROGRAMS`` variable in ``Makefile.am``, + making it something like this: .. code-block:: none - test_programs = pcmk__add_word_test \ - pcmk__btoa_test \ - pcmk__scan_port_test + check_PROGRAMS = \ + pcmk__add_word_test \ + pcmk__btoa_test \ + pcmk__scan_port_test * Create a new ``pcmk__scan_port_test.c`` file, copying the copyright and include boilerplate from another file in the same directory. * Continue with the steps in `Writing the test`_. Testing a function in a source file without tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Follow these steps if you want to test a function in a source file where there are not already other tested functions, but there are tests for other files in the same library. For the purposes of this example, we will add a test for the ``pcmk_acl_required()`` function in ``lib/common/acls.c``. At the time of this documentation being written, no tests existed for that source file, so there is no ``lib/common/tests/acls`` directory. * Add to ``AC_CONFIG_FILES`` in the top-level ``configure.ac`` file so the build process knows to use directory we're about to create. That variable would now look something like: .. code-block:: none dnl Other files we output AC_CONFIG_FILES(Makefile \ ... lib/common/tests/Makefile \ lib/common/tests/acls/Makefile \ lib/common/tests/agents/Makefile \ ... ) * cd into ``lib/common/tests`` * Add to the ``SUBDIRS`` variable in ``Makefile.am``, making it something like: .. code-block:: none SUBDIRS = agents acls cmdline flags operations strings utils xpath results * Create a new ``acls`` directory, copying the ``Makefile.am`` from some other directory. * cd into ``acls`` -* Get rid of any existing values for ``test_programs``, ``dist_test_data``, and - ``test_data`` in ``Makefile.am``. Set ``test_programs`` to ``pcmk_acl_required_test``, - like so: +* Get rid of any existing values for ``check_PROGRAMS`` and set it to + ``pcmk_acl_required_test`` like so: .. code-block:: none - test_programs = pcmk_acl_required_test + check_PROGRAMS = pcmk_acl_required_test * Follow the steps in `Testing a new function in an already testable source file`_ to create the new ``pcmk_acl_required_test.c`` file. Testing a function in a library without tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Adding a test case for a function in a library that doesn't have any test cases to begin with is only slightly more complicated. In general, the steps are the same as for the previous section, except with an additional layer of directory creation. For the purposes of this example, we will add a test case for the ``lrmd_send_resource_alert()`` function in ``lib/lrmd/lrmd_alerts.c``. Note that this may not be a very good function or even library to write actual unit tests for. * Add to ``AC_CONFIG_FILES`` in the top-level ``configure.ac`` file so the build process knows to use directory we're about to create. That variable would now look something like: .. code-block:: none dnl Other files we output AC_CONFIG_FILES(Makefile \ ... lib/lrmd/Makefile \ lib/lrmd/tests/Makefile \ lib/services/Makefile \ ... ) * cd into ``lib/lrmd`` * Create a ``SUBDIRS`` variable in ``Makefile.am`` if it doesn't already exist. Most libraries should not have this variable already. .. code-block:: none SUBDIRS = tests * Create a new ``tests`` directory and add a ``Makefile.am`` with the following contents: .. code-block:: none SUBDIRS = lrmd_alerts -* Follow the steps in `Testing a function in a library without tests` to create +* Follow the steps in `Testing a function in a source file without tests`_ to create the rest of the new directory structure. * Follow the steps in `Testing a new function in an already testable source file`_ to create the new ``lrmd_send_resource_alert_test.c`` file. Adding to an existing test case ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If all you need to do is add additional test cases to an existing file, none of the above work is necessary. All you need to do is find the test source file with the name matching your function and add to it and then follow the instructions in `Writing the test`_. Writing the test ________________ A test case file contains a fair amount of boilerplate. For this reason, it's usually easiest to just copy an existing file and adapt it to your needs. However, here's the basic structure: .. code-block:: c /* - * Copyright 2020-2021 the Pacemaker project contributors + * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include - #include + #include + #include + #include + #include + #include /* Put your test-specific includes here */ /* Put your test functions here */ int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - /* Register your test functions here */ - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } Each test-specific function should test one aspect of the library function, though it can include many assertions if there are many ways of testing that one aspect. For instance, there might be multiple ways of testing regular expression matching: .. code-block:: c static void - regex(void) { + regex(void **state) { const char *s1 = "abcd"; const char *s2 = "ABCD"; - g_assert_cmpint(pcmk__strcmp(NULL, "a..d", pcmk__str_regex), ==, 1); - g_assert_cmpint(pcmk__strcmp(s1, NULL, pcmk__str_regex), ==, 1); - g_assert_cmpint(pcmk__strcmp(s1, "a..d", pcmk__str_regex), ==, 0); + assert_int_equal(pcmk__strcmp(NULL, "a..d", pcmk__str_regex), 1); + assert_int_equal(pcmk__strcmp(s1, NULL, pcmk__str_regex), 1); + assert_int_equal(pcmk__strcmp(s1, "a..d", pcmk__str_regex), 0); } Each test-specific function must also be registered or it will not be called. -This is done with ``g_test_add_func()``. The first argument is a namespace for -tests. It's best to look at what is being used elsewhere and try to fit your -new functions in. +This is done with ``cmocka_unit_test()`` in the ``main`` function: .. code-block:: c - g_test_add_func("/common/strings/strcmp/same_pointer", same_pointer); - g_test_add_func("/common/strings/strcmp/one_is_null", one_is_null); - g_test_add_func("/common/strings/strcmp/case_matters", case_matters); - g_test_add_func("/common/strings/strcmp/case_insensitive", case_insensitive); - g_test_add_func("/common/strings/strcmp/regex", regex); - -Finally, be careful when calling the ``g_assert_`` functions. They are adding -new functions all the time, but we can't use functions newer than the minimum -version of glib supported by Pacemaker. Luckily, they do a good job of marking -when each function was introduced. The minimum glib version can be found in -``configure.ac``: - -.. code-block:: none - - $ grep -A 1 "Require minimum glib" configure.ac - # Require minimum glib version - PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.42.0], + const struct CMUnitTest tests[] = { + cmocka_unit_test(regex), + }; Running _______ If you had to create any new files or directories, you will first need to run ``./configure`` from the top level of the source directory. This will regenerate the Makefiles throughout the tree. If you skip this step, your changes will be skipped and you'll be left wondering why the output doesn't match what you expected. To run the tests, simply run ``make check`` after previously building the source with ``make``. The test cases in each directory will be built and then run. This should not take long. If all the tests succeed, you will be back at the prompt. Scrolling back through the history, you should see lines like the following: .. code-block:: none - PASS: pcmk__strcmp_test 1 /common/strings/strcmp/same_pointer - PASS: pcmk__strcmp_test 2 /common/strings/strcmp/one_is_null - PASS: pcmk__strcmp_test 3 /common/strings/strcmp/case_matters - PASS: pcmk__strcmp_test 4 /common/strings/strcmp/case_insensitive - PASS: pcmk__strcmp_test 5 /common/strings/strcmp/regex + PASS: pcmk__strcmp_test 1 - same_pointer + PASS: pcmk__strcmp_test 2 - one_is_null + PASS: pcmk__strcmp_test 3 - case_matters + PASS: pcmk__strcmp_test 4 - case_insensitive + PASS: pcmk__strcmp_test 5 - regex ============================================================================ Testsuite summary for pacemaker 2.1.0 ============================================================================ # TOTAL: 33 # PASS: 33 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ============================================================================ make[7]: Leaving directory '/home/clumens/src/pacemaker/lib/common/tests/strings' The testing process will quit on the first failed test, and you will see lines like these: .. code-block:: none - ERROR: pcmk__scan_double_test - Bail out! ERROR:pcmk__scan_double_test.c:77:trailing_chars: assertion failed (fabs(result - 3.0) < DBL_EPSILON): (1 < 2.22044605e-16) - PASS: pcmk__str_any_of_test 1 /common/strings/any_of/empty_list - PASS: pcmk__str_any_of_test 2 /common/strings/any_of/empty_string - PASS: pcmk__str_any_of_test 3 /common/strings/any_of/in - PASS: pcmk__str_any_of_test 4 /common/strings/any_of/not_in - PASS: pcmk__strcmp_test 1 /common/strings/strcmp/same_pointer - PASS: pcmk__strcmp_test 2 /common/strings/strcmp/one_is_null - PASS: pcmk__strcmp_test 3 /common/strings/strcmp/case_matters - PASS: pcmk__strcmp_test 4 /common/strings/strcmp/case_insensitive - PASS: pcmk__strcmp_test 5 /common/strings/strcmp/regex + PASS: pcmk__scan_double_test 3 - trailing_chars + FAIL: pcmk__scan_double_test 4 - typical_case + PASS: pcmk__scan_double_test 5 - double_overflow + PASS: pcmk__scan_double_test 6 - double_underflow + ERROR: pcmk__scan_double_test - exited with status 1 + PASS: pcmk__starts_with_test 1 - bad_input ============================================================================ Testsuite summary for pacemaker 2.1.0 ============================================================================ - # TOTAL: 30 - # PASS: 29 + # TOTAL: 56 + # PASS: 54 # SKIP: 0 # XFAIL: 0 - # FAIL: 0 + # FAIL: 1 # XPASS: 0 # ERROR: 1 ============================================================================ See lib/common/tests/strings/test-suite.log Please report to users@clusterlabs.org ============================================================================ make[7]: *** [Makefile:1218: test-suite.log] Error 1 make[7]: Leaving directory '/home/clumens/src/pacemaker/lib/common/tests/strings' -The ``ERROR`` line indicates which test failed, the line the failure occurred on, -and the test result that caused a failure. For this test case, the result is a -little hard to understand because floating point numbers are involved. It is -basically saying that it expected ``result`` to be ``3.0``, but this was not the case. - -At this point, you need to determine whether your test case is incorrect or -whether the code being tested is incorrect. Fix whichever is wrong and continue. - -Test case failures are usually much easier to understand, for instance: +The failure is in ``lib/common/tests/strings/test-suite.log``: .. code-block:: none - ERROR: pcmk__strcmp_test - Bail out! ERROR:pcmk__strcmp_test.c:64:regex: assertion failed (pcmk__strcmp(NULL, "a..d", pcmk__str_regex) == 2): (1 == 2) + ERROR: pcmk__scan_double_test + ============================= + + 1..6 + ok 1 - empty_input_string + PASS: pcmk__scan_double_test 1 - empty_input_string + ok 2 - bad_input_string + PASS: pcmk__scan_double_test 2 - bad_input_string + ok 3 - trailing_chars + PASS: pcmk__scan_double_test 3 - trailing_chars + not ok 4 - typical_case + FAIL: pcmk__scan_double_test 4 - typical_case + # 0.000000 != 3.000000 + # pcmk__scan_double_test.c:80: error: Failure! + ok 5 - double_overflow + PASS: pcmk__scan_double_test 5 - double_overflow + ok 6 - double_underflow + PASS: pcmk__scan_double_test 6 - double_underflow + # not ok - tests + ERROR: pcmk__scan_double_test - exited with status 1 + +At this point, you need to determine whether your test case is incorrect or +whether the code being tested is incorrect. Fix whichever is wrong and continue. diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am index 2fa1c1db8c..242ccb4e2a 100644 --- a/lib/common/Makefile.am +++ b/lib/common/Makefile.am @@ -1,99 +1,112 @@ # # Copyright 2004-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # include $(top_srcdir)/mk/common.mk +include $(top_srcdir)/lib/common/mock.mk AM_CPPFLAGS += -I$(top_builddir)/lib/gnu -I$(top_srcdir)/lib/gnu MOSTLYCLEANFILES = md5.c ## libraries lib_LTLIBRARIES = libcrmcommon.la +check_LTLIBRARIES = libcrmcommon_test.la # Disable -Wcast-qual if used, because we do some hacky casting, # and because libxml2 has some signatures that should be const but aren't # for backward compatibility reasons. # s390 needs -fPIC # s390-suse-linux/bin/ld: .libs/ipc.o: relocation R_390_PC32DBL against `__stack_chk_fail@@GLIBC_2.4' can not be used when making a shared object; recompile with -fPIC CFLAGS = $(CFLAGS_COPY:-Wcast-qual=) -fPIC -SUBDIRS = tests +# Without "." here, check-recursive will run through the subdirectories first +# and then run "make check" here. This will fail, because there's things in +# the subdirectories that need check_LTLIBRARIES built first. Adding "." here +# changes the order so the subdirectories are processed afterwards. +SUBDIRS = . tests -noinst_HEADERS = crmcommon_private.h +noinst_HEADERS = crmcommon_private.h mock_private.h libcrmcommon_la_LDFLAGS = -version-info 41:0:7 libcrmcommon_la_CFLAGS = $(CFLAGS_HARDENED_LIB) libcrmcommon_la_LDFLAGS += $(LDFLAGS_HARDENED_LIB) libcrmcommon_la_LIBADD = @LIBADD_DL@ # If configured with --with-profiling or --with-coverage, BUILD_PROFILING will # be set and -fno-builtin will be added to the CFLAGS. However, libcrmcommon # uses the fabs() function which is normally supplied by gcc as one of its # builtins. Therefore we need to explicitly link against libm here or the # tests won't link. if BUILD_PROFILING libcrmcommon_la_LIBADD += -lm endif # Use += rather than backlashed continuation lines for parsing by bumplibs libcrmcommon_la_SOURCES = libcrmcommon_la_SOURCES += acl.c libcrmcommon_la_SOURCES += agents.c libcrmcommon_la_SOURCES += alerts.c libcrmcommon_la_SOURCES += attrd_client.c if BUILD_CIBSECRETS libcrmcommon_la_SOURCES += cib_secrets.c endif libcrmcommon_la_SOURCES += cmdline.c libcrmcommon_la_SOURCES += digest.c libcrmcommon_la_SOURCES += io.c libcrmcommon_la_SOURCES += ipc_client.c libcrmcommon_la_SOURCES += ipc_common.c libcrmcommon_la_SOURCES += ipc_controld.c libcrmcommon_la_SOURCES += ipc_pacemakerd.c libcrmcommon_la_SOURCES += ipc_server.c libcrmcommon_la_SOURCES += iso8601.c libcrmcommon_la_SOURCES += lists.c libcrmcommon_la_SOURCES += logging.c libcrmcommon_la_SOURCES += mainloop.c libcrmcommon_la_SOURCES += messages.c libcrmcommon_la_SOURCES += nvpair.c libcrmcommon_la_SOURCES += operations.c libcrmcommon_la_SOURCES += options.c libcrmcommon_la_SOURCES += output.c libcrmcommon_la_SOURCES += output_html.c libcrmcommon_la_SOURCES += output_log.c libcrmcommon_la_SOURCES += output_none.c libcrmcommon_la_SOURCES += output_text.c libcrmcommon_la_SOURCES += output_xml.c libcrmcommon_la_SOURCES += patchset.c libcrmcommon_la_SOURCES += pid.c libcrmcommon_la_SOURCES += procfs.c libcrmcommon_la_SOURCES += remote.c libcrmcommon_la_SOURCES += results.c libcrmcommon_la_SOURCES += schemas.c libcrmcommon_la_SOURCES += strings.c libcrmcommon_la_SOURCES += utils.c libcrmcommon_la_SOURCES += watchdog.c libcrmcommon_la_SOURCES += xml.c libcrmcommon_la_SOURCES += xpath.c # It's possible to build the library adding ../gnu/md5.c directly to SOURCES, # but distclean chokes on that because it tries to include the source's .Plo # file, which may have already been cleaned. nodist_libcrmcommon_la_SOURCES = md5.c +libcrmcommon_test_la_SOURCES = $(libcrmcommon_la_SOURCES) +libcrmcommon_test_la_SOURCES += mock.c +libcrmcommon_test_la_LDFLAGS = $(LDFLAGS_HARDENED_LIB) $(WRAPPED_FLAGS) +libcrmcommon_test_la_CFLAGS = $(libcrmcommon_la_CFLAGS) +libcrmcommon_test_la_LIBADD = $(libcrmcommon_la_LIBADD) +nodist_libcrmcommon_test_la_SOURCES = $(nodist_libcrmcommon_la_SOURCES) + md5.c: ../gnu/md5.c cp "$<" "$@" clean-generic: rm -f *.log *.debug *.xml *~ diff --git a/lib/common/mock.c b/lib/common/mock.c new file mode 100644 index 0000000000..6a57fa0f7a --- /dev/null +++ b/lib/common/mock.c @@ -0,0 +1,52 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include +#include + +#include "mock_private.h" + +/* This file is only used when running "make check". It is built into + * libcrmcommon_test.a, not into libcrmcommon.so. It is used to support + * constructing mock versions of library functions for unit testing. + * + * Each unit test will only ever want to use a mocked version of one or two + * library functions. However, we need to mark all the mocked functions as + * wrapped (with -Wl,--wrap= in the LDFLAGS) in libcrmcommon_test.a so that + * all those unit tests can share the same special test library. The unit + * test then defines its own wrapped function. Because a unit test won't + * define every single wrapped function, there will be undefined references + * at link time. + * + * This file takes care of those undefined references. It defines a + * wrapped version of every function that simply calls the real libc + * version. These wrapped versions are defined with a weak attribute, + * which means the unit tests can define another wrapped version for + * unit testing that will override the version defined here. + * + * IN SUMMARY: + * + * - Define two functions for each function listed in WRAPPED in mock.mk. + * One function is a weakly defined __wrap_X function that just calls + * __real_X. + * - Add a __real_X and __wrap_X function prototype for each function to + * mock_private.h. + * - Each unit test defines its own __wrap_X for whatever function it's + * mocking that overrides the version here. + */ + +char *__attribute__((weak)) +__wrap_getenv(const char *name) { + return __real_getenv(name); +} + +int __attribute__((weak)) +__wrap_uname(struct utsname *buf) { + return __real_uname(buf); +} diff --git a/lib/common/mock.mk b/lib/common/mock.mk new file mode 100644 index 0000000000..9fcdbccf8e --- /dev/null +++ b/lib/common/mock.mk @@ -0,0 +1,2 @@ +WRAPPED = getenv uname +WRAPPED_FLAGS = $(foreach fn,$(WRAPPED),-Wl,--wrap=$(fn)) diff --git a/lib/common/mock_private.h b/lib/common/mock_private.h new file mode 100644 index 0000000000..8b455ec40b --- /dev/null +++ b/lib/common/mock_private.h @@ -0,0 +1,23 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#ifndef MOCK_PRIVATE__H +# define MOCK_PRIVATE__H + +#include + +/* This header is for the sole use of libcrmcommon_test. */ + +char *__real_getenv(const char *name); +char *__wrap_getenv(const char *name); + +int __real_uname(struct utsname *buf); +int __wrap_uname(struct utsname *buf); + +#endif // MOCK_PRIVATE__H diff --git a/lib/common/tests/agents/Makefile.am b/lib/common/tests/agents/Makefile.am index 40cb5f7776..e59585c117 100644 --- a/lib/common/tests/agents/Makefile.am +++ b/lib/common/tests/agents/Makefile.am @@ -1,29 +1,17 @@ # # Copyright 2020 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk_stonith_param_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = pcmk_stonith_param_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/agents/pcmk_stonith_param_test.c b/lib/common/tests/agents/pcmk_stonith_param_test.c index ee82b855ab..f1dce83633 100644 --- a/lib/common/tests/agents/pcmk_stonith_param_test.c +++ b/lib/common/tests/agents/pcmk_stonith_param_test.c @@ -1,59 +1,62 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include - -#include - #include +#include +#include +#include +#include +#include + static void -is_stonith_param(void) +is_stonith_param(void **state) { - g_assert_false(pcmk_stonith_param(NULL)); - g_assert_false(pcmk_stonith_param("")); - g_assert_false(pcmk_stonith_param("unrecognized")); - g_assert_false(pcmk_stonith_param("pcmk_unrecognized")); - g_assert_false(pcmk_stonith_param("x" PCMK_STONITH_ACTION_LIMIT)); - g_assert_false(pcmk_stonith_param(PCMK_STONITH_ACTION_LIMIT "x")); - - g_assert_true(pcmk_stonith_param(PCMK_STONITH_ACTION_LIMIT)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_DELAY_BASE)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_DELAY_MAX)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_ARGUMENT)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_CHECK)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_LIST)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_MAP)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_PROVIDES)); - g_assert_true(pcmk_stonith_param(PCMK_STONITH_STONITH_TIMEOUT)); + assert_false(pcmk_stonith_param(NULL)); + assert_false(pcmk_stonith_param("")); + assert_false(pcmk_stonith_param("unrecognized")); + assert_false(pcmk_stonith_param("pcmk_unrecognized")); + assert_false(pcmk_stonith_param("x" PCMK_STONITH_ACTION_LIMIT)); + assert_false(pcmk_stonith_param(PCMK_STONITH_ACTION_LIMIT "x")); + + assert_true(pcmk_stonith_param(PCMK_STONITH_ACTION_LIMIT)); + assert_true(pcmk_stonith_param(PCMK_STONITH_DELAY_BASE)); + assert_true(pcmk_stonith_param(PCMK_STONITH_DELAY_MAX)); + assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_ARGUMENT)); + assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_CHECK)); + assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_LIST)); + assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_MAP)); + assert_true(pcmk_stonith_param(PCMK_STONITH_PROVIDES)); + assert_true(pcmk_stonith_param(PCMK_STONITH_STONITH_TIMEOUT)); } static void -is_stonith_action_param(void) +is_stonith_action_param(void **state) { /* Currently, the function accepts any string not containing underbars as * the action name, so we do not need to verify particular action names. */ - g_assert_false(pcmk_stonith_param("pcmk_on_unrecognized")); - g_assert_true(pcmk_stonith_param("pcmk_on_action")); - g_assert_true(pcmk_stonith_param("pcmk_on_timeout")); - g_assert_true(pcmk_stonith_param("pcmk_on_retries")); + assert_false(pcmk_stonith_param("pcmk_on_unrecognized")); + assert_true(pcmk_stonith_param("pcmk_on_action")); + assert_true(pcmk_stonith_param("pcmk_on_timeout")); + assert_true(pcmk_stonith_param("pcmk_on_retries")); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(is_stonith_param), + cmocka_unit_test(is_stonith_action_param), + }; - g_test_add_func("/common/utils/parse_op_key/is_stonith_param", - is_stonith_param); - g_test_add_func("/common/utils/parse_op_key/is_stonith_action_param", - is_stonith_action_param); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/cmdline/Makefile.am b/lib/common/tests/cmdline/Makefile.am index e69ef2126f..bb5e2eec36 100644 --- a/lib/common/tests/cmdline/Makefile.am +++ b/lib/common/tests/cmdline/Makefile.am @@ -1,29 +1,17 @@ # -# Copyright 2020 the Pacemaker project contributors +# Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk__cmdline_preproc_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = pcmk__cmdline_preproc_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c index edc564008c..d2608511e5 100644 --- a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c +++ b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c @@ -1,157 +1,166 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include +#include +#include +#include +#include +#include +#include + #define LISTS_EQ(a, b) { \ - g_assert_cmpint(g_strv_length((gchar **) (a)), ==, g_strv_length((gchar **) (b))); \ + assert_int_equal(g_strv_length((gchar **) (a)), g_strv_length((gchar **) (b))); \ for (int i = 0; i < g_strv_length((a)); i++) { \ - g_assert_cmpstr((a)[i], ==, (b)[i]); \ + assert_string_equal((a)[i], (b)[i]); \ } \ } static void -empty_input(void) { - g_assert_null(pcmk__cmdline_preproc(NULL, "")); +empty_input(void **state) { + assert_null(pcmk__cmdline_preproc(NULL, "")); } static void -no_specials(void) { +no_specials(void **state) { const char *argv[] = { "-a", "-b", "-c", "-d", NULL }; const gchar *expected[] = { "-a", "-b", "-c", "-d", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); processed = pcmk__cmdline_preproc((char **) argv, ""); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -single_dash(void) { +single_dash(void **state) { const char *argv[] = { "-", NULL }; const gchar *expected[] = { "-", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -double_dash(void) { +double_dash(void **state) { const char *argv[] = { "-a", "--", "-bc", NULL }; const gchar *expected[] = { "-a", "--", "-bc", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -special_args(void) { +special_args(void **state) { const char *argv[] = { "-aX", "-Fval", NULL }; const gchar *expected[] = { "-a", "X", "-F", "val", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "aF"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -special_arg_at_end(void) { +special_arg_at_end(void **state) { const char *argv[] = { "-a", NULL }; const gchar *expected[] = { "-a", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "a"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -long_arg(void) { +long_arg(void **state) { const char *argv[] = { "--blah=foo", NULL }; const gchar *expected[] = { "--blah=foo", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -negative_score(void) { +negative_score(void **state) { const char *argv[] = { "-v", "-1000", NULL }; const gchar *expected[] = { "-v", "-1000", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -negative_score_2(void) { +negative_score_2(void **state) { const char *argv[] = { "-1i3", NULL }; const gchar *expected[] = { "-1", "-i", "-3", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -string_arg_with_dash(void) { +string_arg_with_dash(void **state) { const char *argv[] = { "-n", "crm_mon_options", "-v", "--opt1 --opt2", NULL }; const gchar *expected[] = { "-n", "crm_mon_options", "-v", "--opt1 --opt2", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -string_arg_with_dash_2(void) { +string_arg_with_dash_2(void **state) { const char *argv[] = { "-n", "crm_mon_options", "-v", "-1i3", NULL }; const gchar *expected[] = { "-n", "crm_mon_options", "-v", "-1i3", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void -string_arg_with_dash_3(void) { +string_arg_with_dash_3(void **state) { const char *argv[] = { "-abc", "-1i3", NULL }; const gchar *expected[] = { "-a", "-b", "-c", "-1i3", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "c"); LISTS_EQ(processed, expected); g_strfreev(processed); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/cmdline/preproc/empty_input", empty_input); - g_test_add_func("/common/cmdline/preproc/no_specials", no_specials); - g_test_add_func("/common/cmdline/preproc/single_dash", single_dash); - g_test_add_func("/common/cmdline/preproc/double_dash", double_dash); - g_test_add_func("/common/cmdline/preproc/special_args", special_args); - g_test_add_func("/common/cmdline/preproc/special_arg_at_end", special_arg_at_end); - g_test_add_func("/common/cmdline/preproc/long_arg", long_arg); - g_test_add_func("/common/cmdline/preproc/negative_score", negative_score); - g_test_add_func("/common/cmdline/preproc/negative_score_2", negative_score_2); - g_test_add_func("/common/cmdline/preproc/string_arg_with_dash", string_arg_with_dash); - g_test_add_func("/common/cmdline/preproc/string_arg_with_dash_2", string_arg_with_dash_2); - g_test_add_func("/common/cmdline/preproc/string_arg_with_dash_3", string_arg_with_dash_3); - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(empty_input), + cmocka_unit_test(no_specials), + cmocka_unit_test(single_dash), + cmocka_unit_test(double_dash), + cmocka_unit_test(special_args), + cmocka_unit_test(special_arg_at_end), + cmocka_unit_test(long_arg), + cmocka_unit_test(negative_score), + cmocka_unit_test(negative_score_2), + cmocka_unit_test(string_arg_with_dash), + cmocka_unit_test(string_arg_with_dash_2), + cmocka_unit_test(string_arg_with_dash_3), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/Makefile.am b/lib/common/tests/flags/Makefile.am index 086d4e26fa..97160bd345 100644 --- a/lib/common/tests/flags/Makefile.am +++ b/lib/common/tests/flags/Makefile.am @@ -1,32 +1,21 @@ # -# Copyright 2020 the Pacemaker project contributors +# Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk__clear_flags_as_test \ - pcmk__set_flags_as_test \ - pcmk_all_flags_set_test \ - pcmk_any_flags_set_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = \ + pcmk__clear_flags_as_test \ + pcmk__set_flags_as_test \ + pcmk_all_flags_set_test \ + pcmk_any_flags_set_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/flags/pcmk__clear_flags_as_test.c b/lib/common/tests/flags/pcmk__clear_flags_as_test.c index a476adf3dd..8a1fa1358c 100644 --- a/lib/common/tests/flags/pcmk__clear_flags_as_test.c +++ b/lib/common/tests/flags/pcmk__clear_flags_as_test.c @@ -1,45 +1,53 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -clear_none(void) { - g_assert_cmphex(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0x00f, NULL), ==, 0x0f0); - g_assert_cmphex(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0xf0f, NULL), ==, 0x0f0); +clear_none(void **state) { + assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0x00f, NULL), 0x0f0); + assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0xf0f, NULL), 0x0f0); } static void -clear_some(void) { - g_assert_cmphex(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0x020, NULL), ==, 0x0d0); - g_assert_cmphex(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0x030, NULL), ==, 0x0c0); +clear_some(void **state) { + assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0x020, NULL), 0x0d0); + assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0x030, NULL), 0x0c0); } static void -clear_all(void) { - g_assert_cmphex(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0x0f0, NULL), ==, 0x000); - g_assert_cmphex(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0xfff, NULL), ==, 0x000); +clear_all(void **state) { + assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0x0f0, NULL), 0x000); + assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0xfff, NULL), 0x000); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(clear_none), + cmocka_unit_test(clear_some), + cmocka_unit_test(clear_all), + }; - g_test_add_func("/common/flags/clear/clear_none", clear_none); - g_test_add_func("/common/flags/clear/clear_some", clear_some); - g_test_add_func("/common/flags/clear/clear_all", clear_all); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/pcmk__set_flags_as_test.c b/lib/common/tests/flags/pcmk__set_flags_as_test.c index 9a8292cfe8..1a927bbf7b 100644 --- a/lib/common/tests/flags/pcmk__set_flags_as_test.c +++ b/lib/common/tests/flags/pcmk__set_flags_as_test.c @@ -1,29 +1,37 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -set_flags(void) { - g_assert_cmphex(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0x00f, NULL), ==, 0x0ff); - g_assert_cmphex(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0xf0f, NULL), ==, 0xfff); - g_assert_cmphex(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", - "test", 0x0f0, 0xfff, NULL), ==, 0xfff); +set_flags(void **state) { + assert_int_equal(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0x00f, NULL), 0x0ff); + assert_int_equal(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0xf0f, NULL), 0xfff); + assert_int_equal(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", + "test", 0x0f0, 0xfff, NULL), 0xfff); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(set_flags), + }; - g_test_add_func("/common/flags/set/set_flags", set_flags); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/pcmk_all_flags_set_test.c b/lib/common/tests/flags/pcmk_all_flags_set_test.c index ebe175d7da..4596ad9490 100644 --- a/lib/common/tests/flags/pcmk_all_flags_set_test.c +++ b/lib/common/tests/flags/pcmk_all_flags_set_test.c @@ -1,39 +1,45 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#include -#include #include +#include +#include +#include +#include +#include + static void -all_set(void) { - g_assert_false(pcmk_all_flags_set(0x000, 0x003)); - g_assert_true(pcmk_all_flags_set(0x00f, 0x003)); - g_assert_false(pcmk_all_flags_set(0x00f, 0x010)); - g_assert_false(pcmk_all_flags_set(0x00f, 0x011)); - g_assert_true(pcmk_all_flags_set(0x000, 0x000)); - g_assert_true(pcmk_all_flags_set(0x00f, 0x000)); +all_set(void **state) { + assert_false(pcmk_all_flags_set(0x000, 0x003)); + assert_true(pcmk_all_flags_set(0x00f, 0x003)); + assert_false(pcmk_all_flags_set(0x00f, 0x010)); + assert_false(pcmk_all_flags_set(0x00f, 0x011)); + assert_true(pcmk_all_flags_set(0x000, 0x000)); + assert_true(pcmk_all_flags_set(0x00f, 0x000)); } static void -one_is_set(void) { +one_is_set(void **state) { // pcmk_is_set() is a simple macro alias for pcmk_all_flags_set() - g_assert_true(pcmk_is_set(0x00f, 0x001)); - g_assert_false(pcmk_is_set(0x00f, 0x010)); + assert_true(pcmk_is_set(0x00f, 0x001)); + assert_false(pcmk_is_set(0x00f, 0x010)); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(all_set), + cmocka_unit_test(one_is_set), + }; - g_test_add_func("/common/flags/all_set/all_set", all_set); - g_test_add_func("/common/flags/all_set/is_set", one_is_set); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/pcmk_any_flags_set_test.c b/lib/common/tests/flags/pcmk_any_flags_set_test.c index d465d0d626..1d3407dc84 100644 --- a/lib/common/tests/flags/pcmk_any_flags_set_test.c +++ b/lib/common/tests/flags/pcmk_any_flags_set_test.c @@ -1,32 +1,38 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#include -#include #include +#include +#include +#include +#include +#include + static void -any_set(void) { - g_assert_false(pcmk_any_flags_set(0x000, 0x000)); - g_assert_false(pcmk_any_flags_set(0x000, 0x001)); - g_assert_true(pcmk_any_flags_set(0x00f, 0x001)); - g_assert_false(pcmk_any_flags_set(0x00f, 0x010)); - g_assert_true(pcmk_any_flags_set(0x00f, 0x011)); - g_assert_false(pcmk_any_flags_set(0x000, 0x000)); - g_assert_false(pcmk_any_flags_set(0x00f, 0x000)); +any_set(void **state) { + assert_false(pcmk_any_flags_set(0x000, 0x000)); + assert_false(pcmk_any_flags_set(0x000, 0x001)); + assert_true(pcmk_any_flags_set(0x00f, 0x001)); + assert_false(pcmk_any_flags_set(0x00f, 0x010)); + assert_true(pcmk_any_flags_set(0x00f, 0x011)); + assert_false(pcmk_any_flags_set(0x000, 0x000)); + assert_false(pcmk_any_flags_set(0x00f, 0x000)); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(any_set), + }; - g_test_add_func("/common/flags/any_set/any_set", any_set); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/io/Makefile.am b/lib/common/tests/io/Makefile.am index 6760a1d9c9..448de6eb7d 100644 --- a/lib/common/tests/io/Makefile.am +++ b/lib/common/tests/io/Makefile.am @@ -1,30 +1,26 @@ # # Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/lib/common/mock.mk + +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/lib/common +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka + +pcmk__get_tmpdir_test_LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -lcmocka +pcmk__get_tmpdir_test_LDFLAGS = -Wl,--wrap=getenv + +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = \ - pcmk__full_path_test +check_PROGRAMS = \ + pcmk__full_path_test \ + pcmk__get_tmpdir_test -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +TESTS = $(check_PROGRAMS) -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = diff --git a/lib/common/tests/io/pcmk__full_path_test.c b/lib/common/tests/io/pcmk__full_path_test.c index 03b3d13838..47333e4d85 100644 --- a/lib/common/tests/io/pcmk__full_path_test.c +++ b/lib/common/tests/io/pcmk__full_path_test.c @@ -1,41 +1,47 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include + static void -full_path(void) +full_path(void **state) { char *path = NULL; path = pcmk__full_path("file", "/dir"); - g_assert_cmpint(strcmp(path, "/dir/file"), ==, 0); + assert_int_equal(strcmp(path, "/dir/file"), 0); free(path); path = pcmk__full_path("/full/path", "/dir"); - g_assert_cmpint(strcmp(path, "/full/path"), ==, 0); + assert_int_equal(strcmp(path, "/full/path"), 0); free(path); path = pcmk__full_path("../relative/path", "/dir"); - g_assert_cmpint(strcmp(path, "/dir/../relative/path"), ==, 0); + assert_int_equal(strcmp(path, "/dir/../relative/path"), 0); free(path); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/io/full_path/full_path", full_path); + const struct CMUnitTest tests[] = { + cmocka_unit_test(full_path), + }; - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/io/pcmk__get_tmpdir_test.c b/lib/common/tests/io/pcmk__get_tmpdir_test.c new file mode 100644 index 0000000000..3843a780c4 --- /dev/null +++ b/lib/common/tests/io/pcmk__get_tmpdir_test.c @@ -0,0 +1,93 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include +#include "mock_private.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static bool use_mocked = false; + +char * +__wrap_getenv(const char *name) +{ + /* If coverage is enabled, something in "make check" will want to call + * the real getenv(), which will of course fail if the mocked version gets + * used. This bool needs to be set and unset around every unit test so + * the mocked version is only called in that time. + */ + if (use_mocked) { + return mock_type(char *); + } else { + return __real_getenv(name); + } +} + +static void +getenv_returns_invalid(void **state) +{ + const char *result; + + use_mocked = true; + + will_return(__wrap_getenv, NULL); // getenv("TMPDIR") return value + result = pcmk__get_tmpdir(); + assert_string_equal(result, "/tmp"); + + will_return(__wrap_getenv, ""); // getenv("TMPDIR") return value + result = pcmk__get_tmpdir(); + assert_string_equal(result, "/tmp"); + + will_return(__wrap_getenv, "subpath"); // getenv("TMPDIR") return value + result = pcmk__get_tmpdir(); + assert_string_equal(result, "/tmp"); + + use_mocked = false; +} + +static void +getenv_returns_valid(void **state) +{ + const char *result; + + use_mocked = true; + + will_return(__wrap_getenv, "/var/tmp"); // getenv("TMPDIR") return value + result = pcmk__get_tmpdir(); + assert_string_equal(result, "/var/tmp"); + + will_return(__wrap_getenv, "/"); // getenv("TMPDIR") return value + result = pcmk__get_tmpdir(); + assert_string_equal(result, "/"); + + will_return(__wrap_getenv, "/tmp/abcd.1234"); // getenv("TMPDIR") return value + result = pcmk__get_tmpdir(); + assert_string_equal(result, "/tmp/abcd.1234"); + + use_mocked = false; +} + +int +main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(getenv_returns_invalid), + cmocka_unit_test(getenv_returns_valid), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/common/tests/iso8601/Makefile.am b/lib/common/tests/iso8601/Makefile.am index fe1db22d06..7bbc111282 100644 --- a/lib/common/tests/iso8601/Makefile.am +++ b/lib/common/tests/iso8601/Makefile.am @@ -1,29 +1,17 @@ # # Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk__readable_interval_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = pcmk__readable_interval_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/iso8601/pcmk__readable_interval_test.c b/lib/common/tests/iso8601/pcmk__readable_interval_test.c index 45ad9f10c5..cf0ffafb7b 100644 --- a/lib/common/tests/iso8601/pcmk__readable_interval_test.c +++ b/lib/common/tests/iso8601/pcmk__readable_interval_test.c @@ -1,34 +1,40 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include +#include +#include +#include +#include +#include #include static void -readable_interval(void) +readable_interval(void **state) { - g_assert_cmpint(strcmp(pcmk__readable_interval(0), "0s"), ==, 0); - g_assert_cmpint(strcmp(pcmk__readable_interval(30000), "30s"), ==, 0); - g_assert_cmpint(strcmp(pcmk__readable_interval(150000), "2m30s"), ==, 0); - g_assert_cmpint(strcmp(pcmk__readable_interval(3333), "3.333s"), ==, 0); - g_assert_cmpint(strcmp(pcmk__readable_interval(UINT_MAX), "49d17h2m47.295s"), ==, 0); + assert_string_equal(pcmk__readable_interval(0), "0s"); + assert_string_equal(pcmk__readable_interval(30000), "30s"); + assert_string_equal(pcmk__readable_interval(150000), "2m30s"); + assert_string_equal(pcmk__readable_interval(3333), "3.333s"); + assert_string_equal(pcmk__readable_interval(UINT_MAX), "49d17h2m47.295s"); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(readable_interval), + }; - g_test_add_func("/common/utils/pcmk__readable_interval/readable_interval", - readable_interval); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/Makefile.am b/lib/common/tests/operations/Makefile.am index cd5884b2bd..c8814ff0a8 100644 --- a/lib/common/tests/operations/Makefile.am +++ b/lib/common/tests/operations/Makefile.am @@ -1,29 +1,17 @@ # # Copyright 2020 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = parse_op_key_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = parse_op_key_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/operations/parse_op_key_test.c b/lib/common/tests/operations/parse_op_key_test.c index 857431af1b..daac346e12 100644 --- a/lib/common/tests/operations/parse_op_key_test.c +++ b/lib/common/tests/operations/parse_op_key_test.c @@ -1,228 +1,234 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include #include +#include +#include +#include +#include +#include +#include static void -basic(void) +basic(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_true(parse_op_key("Fencing_monitor_60000", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "Fencing"); - g_assert_cmpstr(ty, ==, "monitor"); - g_assert_cmpint(ms, ==, 60000); + assert_true(parse_op_key("Fencing_monitor_60000", &rsc, &ty, &ms)); + assert_string_equal(rsc, "Fencing"); + assert_string_equal(ty, "monitor"); + assert_int_equal(ms, 60000); free(rsc); free(ty); } static void -colon_in_rsc(void) +colon_in_rsc(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_true(parse_op_key("ClusterIP:0_start_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "ClusterIP:0"); - g_assert_cmpstr(ty, ==, "start"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("ClusterIP:0_start_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "ClusterIP:0"); + assert_string_equal(ty, "start"); + assert_int_equal(ms, 0); free(rsc); free(ty); - g_assert_true(parse_op_key("imagestoreclone:1_post_notify_stop_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "imagestoreclone:1"); - g_assert_cmpstr(ty, ==, "post_notify_stop"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("imagestoreclone:1_post_notify_stop_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "imagestoreclone:1"); + assert_string_equal(ty, "post_notify_stop"); + assert_int_equal(ms, 0); free(rsc); free(ty); } static void -dashes_in_rsc(void) +dashes_in_rsc(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_true(parse_op_key("httpd-bundle-0_monitor_30000", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "httpd-bundle-0"); - g_assert_cmpstr(ty, ==, "monitor"); - g_assert_cmpint(ms, ==, 30000); + assert_true(parse_op_key("httpd-bundle-0_monitor_30000", &rsc, &ty, &ms)); + assert_string_equal(rsc, "httpd-bundle-0"); + assert_string_equal(ty, "monitor"); + assert_int_equal(ms, 30000); free(rsc); free(ty); - g_assert_true(parse_op_key("httpd-bundle-ip-192.168.122.132_start_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "httpd-bundle-ip-192.168.122.132"); - g_assert_cmpstr(ty, ==, "start"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("httpd-bundle-ip-192.168.122.132_start_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "httpd-bundle-ip-192.168.122.132"); + assert_string_equal(ty, "start"); + assert_int_equal(ms, 0); free(rsc); free(ty); } static void -migrate_to_from(void) +migrate_to_from(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_true(parse_op_key("vm_migrate_from_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "vm"); - g_assert_cmpstr(ty, ==, "migrate_from"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("vm_migrate_from_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "vm"); + assert_string_equal(ty, "migrate_from"); + assert_int_equal(ms, 0); free(rsc); free(ty); - g_assert_true(parse_op_key("vm_migrate_to_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "vm"); - g_assert_cmpstr(ty, ==, "migrate_to"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("vm_migrate_to_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "vm"); + assert_string_equal(ty, "migrate_to"); + assert_int_equal(ms, 0); free(rsc); free(ty); - g_assert_true(parse_op_key("vm_idcc_devel_migrate_to_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "vm_idcc_devel"); - g_assert_cmpstr(ty, ==, "migrate_to"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("vm_idcc_devel_migrate_to_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "vm_idcc_devel"); + assert_string_equal(ty, "migrate_to"); + assert_int_equal(ms, 0); free(rsc); free(ty); } static void -pre_post(void) +pre_post(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_true(parse_op_key("rsc_drbd_7788:1_post_notify_start_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "rsc_drbd_7788:1"); - g_assert_cmpstr(ty, ==, "post_notify_start"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("rsc_drbd_7788:1_post_notify_start_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "rsc_drbd_7788:1"); + assert_string_equal(ty, "post_notify_start"); + assert_int_equal(ms, 0); free(rsc); free(ty); - g_assert_true(parse_op_key("rabbitmq-bundle-clone_pre_notify_stop_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "rabbitmq-bundle-clone"); - g_assert_cmpstr(ty, ==, "pre_notify_stop"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("rabbitmq-bundle-clone_pre_notify_stop_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "rabbitmq-bundle-clone"); + assert_string_equal(ty, "pre_notify_stop"); + assert_int_equal(ms, 0); free(rsc); free(ty); - g_assert_true(parse_op_key("post_notify_start_0", &rsc, &ty, &ms)); - g_assert_cmpstr(rsc, ==, "post_notify"); - g_assert_cmpstr(ty, ==, "start"); - g_assert_cmpint(ms, ==, 0); + assert_true(parse_op_key("post_notify_start_0", &rsc, &ty, &ms)); + assert_string_equal(rsc, "post_notify"); + assert_string_equal(ty, "start"); + assert_int_equal(ms, 0); free(rsc); free(ty); } static void -skip_rsc(void) +skip_rsc(void **state) { char *ty = NULL; guint ms = 0; - g_assert_true(parse_op_key("Fencing_monitor_60000", NULL, &ty, &ms)); - g_assert_cmpstr(ty, ==, "monitor"); - g_assert_cmpint(ms, ==, 60000); + assert_true(parse_op_key("Fencing_monitor_60000", NULL, &ty, &ms)); + assert_string_equal(ty, "monitor"); + assert_int_equal(ms, 60000); free(ty); } static void -skip_ty(void) +skip_ty(void **state) { char *rsc = NULL; guint ms = 0; - g_assert_true(parse_op_key("Fencing_monitor_60000", &rsc, NULL, &ms)); - g_assert_cmpstr(rsc, ==, "Fencing"); - g_assert_cmpint(ms, ==, 60000); + assert_true(parse_op_key("Fencing_monitor_60000", &rsc, NULL, &ms)); + assert_string_equal(rsc, "Fencing"); + assert_int_equal(ms, 60000); free(rsc); } static void -skip_ms(void) +skip_ms(void **state) { char *rsc = NULL; char *ty = NULL; - g_assert_true(parse_op_key("Fencing_monitor_60000", &rsc, &ty, NULL)); - g_assert_cmpstr(rsc, ==, "Fencing"); - g_assert_cmpstr(ty, ==, "monitor"); + assert_true(parse_op_key("Fencing_monitor_60000", &rsc, &ty, NULL)); + assert_string_equal(rsc, "Fencing"); + assert_string_equal(ty, "monitor"); free(rsc); free(ty); } static void -empty_input(void) +empty_input(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_false(parse_op_key("", &rsc, &ty, &ms)); - g_assert_null(rsc); - g_assert_null(ty); - g_assert_cmpint(ms, ==, 0); + assert_false(parse_op_key("", &rsc, &ty, &ms)); + assert_null(rsc); + assert_null(ty); + assert_int_equal(ms, 0); - g_assert_false(parse_op_key(NULL, &rsc, &ty, &ms)); - g_assert_null(rsc); - g_assert_null(ty); - g_assert_cmpint(ms, ==, 0); + assert_false(parse_op_key(NULL, &rsc, &ty, &ms)); + assert_null(rsc); + assert_null(ty); + assert_int_equal(ms, 0); } static void -malformed_input(void) +malformed_input(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; - g_assert_false(parse_op_key("httpd-bundle-0", &rsc, &ty, &ms)); - g_assert_null(rsc); - g_assert_null(ty); - g_assert_cmpint(ms, ==, 0); + assert_false(parse_op_key("httpd-bundle-0", &rsc, &ty, &ms)); + assert_null(rsc); + assert_null(ty); + assert_int_equal(ms, 0); - g_assert_false(parse_op_key("httpd-bundle-0_monitor", &rsc, &ty, &ms)); - g_assert_null(rsc); - g_assert_null(ty); - g_assert_cmpint(ms, ==, 0); + assert_false(parse_op_key("httpd-bundle-0_monitor", &rsc, &ty, &ms)); + assert_null(rsc); + assert_null(ty); + assert_int_equal(ms, 0); - g_assert_false(parse_op_key("httpd-bundle-0_30000", &rsc, &ty, &ms)); - g_assert_null(rsc); - g_assert_null(ty); - g_assert_cmpint(ms, ==, 0); + assert_false(parse_op_key("httpd-bundle-0_30000", &rsc, &ty, &ms)); + assert_null(rsc); + assert_null(ty); + assert_int_equal(ms, 0); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/utils/parse_op_key/basic", basic); - g_test_add_func("/common/utils/parse_op_key/colon_in_rsc", colon_in_rsc); - g_test_add_func("/common/utils/parse_op_key/dashes_in_rsc", dashes_in_rsc); - g_test_add_func("/common/utils/parse_op_key/migrate_to_from", migrate_to_from); - g_test_add_func("/common/utils/parse_op_key/pre_post", pre_post); - - g_test_add_func("/common/utils/parse_op_key/skip_rsc", skip_rsc); - g_test_add_func("/common/utils/parse_op_key/skip_ty", skip_ty); - g_test_add_func("/common/utils/parse_op_key/skip_ms", skip_ms); - - g_test_add_func("/common/utils/parse_op_key/empty_input", empty_input); - g_test_add_func("/common/utils/parse_op_key/malformed_input", malformed_input); - - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(basic), + cmocka_unit_test(colon_in_rsc), + cmocka_unit_test(dashes_in_rsc), + cmocka_unit_test(migrate_to_from), + cmocka_unit_test(pre_post), + + cmocka_unit_test(skip_rsc), + cmocka_unit_test(skip_ty), + cmocka_unit_test(skip_ms), + + cmocka_unit_test(empty_input), + cmocka_unit_test(malformed_input), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/results/Makefile.am b/lib/common/tests/results/Makefile.am index 1ac0488c4a..d57f134d81 100644 --- a/lib/common/tests/results/Makefile.am +++ b/lib/common/tests/results/Makefile.am @@ -1,30 +1,18 @@ # # Copyright 2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk__results_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = pcmk__results_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/results/pcmk__results_test.c b/lib/common/tests/results/pcmk__results_test.c index 8e3f8053b5..57a520c501 100644 --- a/lib/common/tests/results/pcmk__results_test.c +++ b/lib/common/tests/results/pcmk__results_test.c @@ -1,65 +1,71 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include +#include +#include +#include +#include +#include + #include #include static void -test_for_pcmk_rc_name(void) { - g_assert_cmpint(pcmk__strcmp(pcmk_rc_name(pcmk_rc_error-1), "pcmk_rc_unknown_format", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(pcmk_rc_name(pcmk_rc_ok), "pcmk_rc_ok", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(pcmk_rc_name(pcmk_rc_ok), "pcmk_rc_ok", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(pcmk_rc_name(-7777777), "Unknown", pcmk__str_none), ==, 0); +test_for_pcmk_rc_name(void **state) { + assert_string_equal(pcmk_rc_name(pcmk_rc_error-1), "pcmk_rc_unknown_format"); + assert_string_equal(pcmk_rc_name(pcmk_rc_ok), "pcmk_rc_ok"); + assert_string_equal(pcmk_rc_name(pcmk_rc_ok), "pcmk_rc_ok"); + assert_string_equal(pcmk_rc_name(-7777777), "Unknown"); } static void -test_for_pcmk_rc_str(void) { - g_assert_cmpint(pcmk__strcmp(pcmk_rc_str(pcmk_rc_error-1), "Unknown output format", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(pcmk_rc_str(pcmk_rc_ok), "OK", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(pcmk_rc_str(-1), "Unknown error", pcmk__str_none), ==, 0); +test_for_pcmk_rc_str(void **state) { + assert_string_equal(pcmk_rc_str(pcmk_rc_error-1), "Unknown output format"); + assert_string_equal(pcmk_rc_str(pcmk_rc_ok), "OK"); + assert_string_equal(pcmk_rc_str(-1), "Unknown error"); } static void -test_for_crm_exit_name(void) { - g_assert_cmpint(pcmk__strcmp(crm_exit_name(CRM_EX_OK), "CRM_EX_OK", pcmk__str_none), ==, 0); +test_for_crm_exit_name(void **state) { + assert_string_equal(crm_exit_name(CRM_EX_OK), "CRM_EX_OK"); } static void -test_for_crm_exit_str(void) { - g_assert_cmpint(pcmk__strcmp(crm_exit_str(CRM_EX_OK), "OK", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(crm_exit_str(129), "Interrupted by signal", pcmk__str_none), ==, 0); - g_assert_cmpint(pcmk__strcmp(crm_exit_str(-7777777), "Unknown exit status", pcmk__str_none), ==, 0); +test_for_crm_exit_str(void **state) { + assert_string_equal(crm_exit_str(CRM_EX_OK), "OK"); + assert_string_equal(crm_exit_str(129), "Interrupted by signal"); + assert_string_equal(crm_exit_str(-7777777), "Unknown exit status"); } static void -test_for_pcmk_rc2exitc(void) { - g_assert_cmpint(pcmk_rc2exitc(pcmk_rc_ok), ==, CRM_EX_OK); - g_assert_cmpint(pcmk_rc2exitc(-7777777), ==, CRM_EX_ERROR); +test_for_pcmk_rc2exitc(void **state) { + assert_int_equal(pcmk_rc2exitc(pcmk_rc_ok), CRM_EX_OK); + assert_int_equal(pcmk_rc2exitc(-7777777), CRM_EX_ERROR); } static void -test_for_bz2_strerror(void) { - g_assert_cmpint(pcmk__strcmp(bz2_strerror(BZ_STREAM_END), "Ok", pcmk__str_none), ==, 0); +test_for_bz2_strerror(void **state) { + assert_string_equal(bz2_strerror(BZ_STREAM_END), "Ok"); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - g_test_add_func("/common/results/test_for_pcmk_rc_name", test_for_pcmk_rc_name); - g_test_add_func("/common/results/test_for_pcmk_rc_str", test_for_pcmk_rc_str); - g_test_add_func("/common/results/test_for_crm_exit_name", test_for_crm_exit_name); - g_test_add_func("/common/results/test_for_crm_exit_str", test_for_crm_exit_str); - g_test_add_func("/common/results/test_for_pcmk_rc2exitc", test_for_pcmk_rc2exitc); - g_test_add_func("/common/results/test_for_bz2_strerror", test_for_bz2_strerror); + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_for_pcmk_rc_name), + cmocka_unit_test(test_for_pcmk_rc_str), + cmocka_unit_test(test_for_crm_exit_name), + cmocka_unit_test(test_for_crm_exit_str), + cmocka_unit_test(test_for_pcmk_rc2exitc), + cmocka_unit_test(test_for_bz2_strerror), + }; - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/Makefile.am b/lib/common/tests/strings/Makefile.am index bd6cb7a076..13a81beb2d 100644 --- a/lib/common/tests/strings/Makefile.am +++ b/lib/common/tests/strings/Makefile.am @@ -1,42 +1,31 @@ # # Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = crm_get_msec_test \ +check_PROGRAMS = \ + crm_get_msec_test \ crm_is_true_test \ crm_str_to_boolean_test \ pcmk__add_word_test \ pcmk__btoa_test \ pcmk__char_in_any_str_test \ pcmk__ends_with_test \ pcmk__parse_ll_range_test \ pcmk__scan_double_test \ pcmk__starts_with_test \ pcmk__str_any_of_test \ pcmk__str_in_list_test \ pcmk__strcmp_test -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = - -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/strings/crm_get_msec_test.c b/lib/common/tests/strings/crm_get_msec_test.c index ea9fe616ea..ad6b43bb0f 100644 --- a/lib/common/tests/strings/crm_get_msec_test.c +++ b/lib/common/tests/strings/crm_get_msec_test.c @@ -1,54 +1,62 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -bad_input(void) { - g_assert_cmpint(crm_get_msec(NULL), ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(crm_get_msec(" "), ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(crm_get_msec("abcxyz"), ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(crm_get_msec("100xs"), ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(crm_get_msec(" 100 xs "), ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(crm_get_msec("-100ms"), ==, PCMK__PARSE_INT_DEFAULT); +bad_input(void **state) { + assert_int_equal(crm_get_msec(NULL), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec(" "), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec("abcxyz"), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec("100xs"), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec(" 100 xs "), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec("-100ms"), PCMK__PARSE_INT_DEFAULT); } static void -good_input(void) { - g_assert_cmpint(crm_get_msec("100"), ==, 100000); - g_assert_cmpint(crm_get_msec(" 100 "), ==, 100000); - g_assert_cmpint(crm_get_msec("\t100\n"), ==, 100000); - - g_assert_cmpint(crm_get_msec("100ms"), ==, 100); - g_assert_cmpint(crm_get_msec("100 MSEC"), ==, 100); - g_assert_cmpint(crm_get_msec("1000US"), ==, 1); - g_assert_cmpint(crm_get_msec("1000usec"), ==, 1); - g_assert_cmpint(crm_get_msec("12s"), ==, 12000); - g_assert_cmpint(crm_get_msec("12 sec"), ==, 12000); - g_assert_cmpint(crm_get_msec("1m"), ==, 60000); - g_assert_cmpint(crm_get_msec("13 min"), ==, 780000); - g_assert_cmpint(crm_get_msec("2\th"), ==, 7200000); - g_assert_cmpint(crm_get_msec("1 hr"), ==, 3600000); +good_input(void **state) { + assert_int_equal(crm_get_msec("100"), 100000); + assert_int_equal(crm_get_msec(" 100 "), 100000); + assert_int_equal(crm_get_msec("\t100\n"), 100000); + + assert_int_equal(crm_get_msec("100ms"), 100); + assert_int_equal(crm_get_msec("100 MSEC"), 100); + assert_int_equal(crm_get_msec("1000US"), 1); + assert_int_equal(crm_get_msec("1000usec"), 1); + assert_int_equal(crm_get_msec("12s"), 12000); + assert_int_equal(crm_get_msec("12 sec"), 12000); + assert_int_equal(crm_get_msec("1m"), 60000); + assert_int_equal(crm_get_msec("13 min"), 780000); + assert_int_equal(crm_get_msec("2\th"), 7200000); + assert_int_equal(crm_get_msec("1 hr"), 3600000); } static void -overflow(void) { - g_assert_cmpint(crm_get_msec("9223372036854775807s"), ==, LLONG_MAX); +overflow(void **state) { + assert_int_equal(crm_get_msec("9223372036854775807s"), LLONG_MAX); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(bad_input), + cmocka_unit_test(good_input), + cmocka_unit_test(overflow), + }; - g_test_add_func("/common/strings/get_msec/bad_input", bad_input); - g_test_add_func("/common/strings/get_msec/good_input", good_input); - g_test_add_func("/common/strings/get_msec/overflow", overflow); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/crm_is_true_test.c b/lib/common/tests/strings/crm_is_true_test.c index 20def0d9b7..b1d5c9cab7 100644 --- a/lib/common/tests/strings/crm_is_true_test.c +++ b/lib/common/tests/strings/crm_is_true_test.c @@ -1,61 +1,69 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -bad_input(void) { - g_assert_false(crm_is_true(NULL)); +bad_input(void **state) { + assert_false(crm_is_true(NULL)); } static void -is_true(void) { - g_assert_true(crm_is_true("true")); - g_assert_true(crm_is_true("TrUe")); - g_assert_true(crm_is_true("on")); - g_assert_true(crm_is_true("ON")); - g_assert_true(crm_is_true("yes")); - g_assert_true(crm_is_true("yES")); - g_assert_true(crm_is_true("y")); - g_assert_true(crm_is_true("Y")); - g_assert_true(crm_is_true("1")); +is_true(void **state) { + assert_true(crm_is_true("true")); + assert_true(crm_is_true("TrUe")); + assert_true(crm_is_true("on")); + assert_true(crm_is_true("ON")); + assert_true(crm_is_true("yes")); + assert_true(crm_is_true("yES")); + assert_true(crm_is_true("y")); + assert_true(crm_is_true("Y")); + assert_true(crm_is_true("1")); } static void -is_false(void) { - g_assert_false(crm_is_true("false")); - g_assert_false(crm_is_true("fAlSe")); - g_assert_false(crm_is_true("off")); - g_assert_false(crm_is_true("OFF")); - g_assert_false(crm_is_true("no")); - g_assert_false(crm_is_true("No")); - g_assert_false(crm_is_true("n")); - g_assert_false(crm_is_true("N")); - g_assert_false(crm_is_true("0")); - - g_assert_false(crm_is_true("")); - g_assert_false(crm_is_true("blahblah")); - - g_assert_false(crm_is_true("truedat")); - g_assert_false(crm_is_true("onnn")); - g_assert_false(crm_is_true("yep")); - g_assert_false(crm_is_true("Y!")); - g_assert_false(crm_is_true("100")); +is_false(void **state) { + assert_false(crm_is_true("false")); + assert_false(crm_is_true("fAlSe")); + assert_false(crm_is_true("off")); + assert_false(crm_is_true("OFF")); + assert_false(crm_is_true("no")); + assert_false(crm_is_true("No")); + assert_false(crm_is_true("n")); + assert_false(crm_is_true("N")); + assert_false(crm_is_true("0")); + + assert_false(crm_is_true("")); + assert_false(crm_is_true("blahblah")); + + assert_false(crm_is_true("truedat")); + assert_false(crm_is_true("onnn")); + assert_false(crm_is_true("yep")); + assert_false(crm_is_true("Y!")); + assert_false(crm_is_true("100")); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(bad_input), + cmocka_unit_test(is_true), + cmocka_unit_test(is_false), + }; - g_test_add_func("/common/strings/crm_is_true/bad_input", bad_input); - g_test_add_func("/common/strings/crm_is_true/is_true", is_true); - g_test_add_func("/common/strings/crm_is_true/is_false", is_false); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/crm_str_to_boolean_test.c b/lib/common/tests/strings/crm_str_to_boolean_test.c index 03b799f9d9..6e9748aa91 100644 --- a/lib/common/tests/strings/crm_str_to_boolean_test.c +++ b/lib/common/tests/strings/crm_str_to_boolean_test.c @@ -1,96 +1,104 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -bad_input(void) { - g_assert_cmpint(crm_str_to_boolean(NULL, NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("blahblah", NULL), ==, -1); +bad_input(void **state) { + assert_int_equal(crm_str_to_boolean(NULL, NULL), -1); + assert_int_equal(crm_str_to_boolean("", NULL), -1); + assert_int_equal(crm_str_to_boolean("blahblah", NULL), -1); } static void -is_true(void) { +is_true(void **state) { int ret; - g_assert_cmpint(crm_str_to_boolean("true", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("TrUe", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("on", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("ON", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("yes", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("yES", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("y", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("Y", &ret), ==, 1); - g_assert_true(ret); - g_assert_cmpint(crm_str_to_boolean("1", &ret), ==, 1); - g_assert_true(ret); + assert_int_equal(crm_str_to_boolean("true", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("TrUe", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("on", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("ON", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("yes", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("yES", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("y", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("Y", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("1", &ret), 1); + assert_true(ret); } static void -is_not_true(void) { - g_assert_cmpint(crm_str_to_boolean("truedat", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("onnn", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("yep", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("Y!", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("100", NULL), ==, -1); +is_not_true(void **state) { + assert_int_equal(crm_str_to_boolean("truedat", NULL), -1); + assert_int_equal(crm_str_to_boolean("onnn", NULL), -1); + assert_int_equal(crm_str_to_boolean("yep", NULL), -1); + assert_int_equal(crm_str_to_boolean("Y!", NULL), -1); + assert_int_equal(crm_str_to_boolean("100", NULL), -1); } static void -is_false(void) { +is_false(void **state) { int ret; - g_assert_cmpint(crm_str_to_boolean("false", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("fAlSe", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("off", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("OFF", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("no", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("No", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("n", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("N", &ret), ==, 1); - g_assert_false(ret); - g_assert_cmpint(crm_str_to_boolean("0", &ret), ==, 1); - g_assert_false(ret); + assert_int_equal(crm_str_to_boolean("false", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("fAlSe", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("off", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("OFF", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("no", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("No", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("n", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("N", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("0", &ret), 1); + assert_false(ret); } static void -is_not_false(void) { - g_assert_cmpint(crm_str_to_boolean("falseee", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("of", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("nope", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("N!", NULL), ==, -1); - g_assert_cmpint(crm_str_to_boolean("000", NULL), ==, -1); +is_not_false(void **state) { + assert_int_equal(crm_str_to_boolean("falseee", NULL), -1); + assert_int_equal(crm_str_to_boolean("of", NULL), -1); + assert_int_equal(crm_str_to_boolean("nope", NULL), -1); + assert_int_equal(crm_str_to_boolean("N!", NULL), -1); + assert_int_equal(crm_str_to_boolean("000", NULL), -1); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(bad_input), + cmocka_unit_test(is_true), + cmocka_unit_test(is_not_true), + cmocka_unit_test(is_false), + cmocka_unit_test(is_not_false), + }; - g_test_add_func("/common/strings/crm_str_to_boolean/bad_input", bad_input); - g_test_add_func("/common/strings/crm_str_to_boolean/is_true", is_true); - g_test_add_func("/common/strings/crm_str_to_boolean/is_not_true", is_not_true); - g_test_add_func("/common/strings/crm_str_to_boolean/is_false", is_false); - g_test_add_func("/common/strings/crm_str_to_boolean/is_not_false", is_not_false); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__add_word_test.c b/lib/common/tests/strings/pcmk__add_word_test.c index 600e8e8dd5..50f2599c5e 100644 --- a/lib/common/tests/strings/pcmk__add_word_test.c +++ b/lib/common/tests/strings/pcmk__add_word_test.c @@ -1,104 +1,108 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include + static void -add_words(void) +add_words(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_word(&list, &list_len, "hello"); pcmk__add_word(&list, &list_len, "world"); - g_assert_cmpint(strcmp(list, "hello world"), ==, 0); + assert_int_equal(strcmp(list, "hello world"), 0); free(list); } static void -add_with_no_len(void) +add_with_no_len(void **state) { char *list = NULL; pcmk__add_word(&list, NULL, "hello"); pcmk__add_word(&list, NULL, "world"); - g_assert_cmpint(strcmp(list, "hello world"), ==, 0); + assert_int_equal(strcmp(list, "hello world"), 0); free(list); } static void -add_nothing(void) +add_nothing(void **state) { char *list = NULL; pcmk__add_word(&list, NULL, "hello"); pcmk__add_word(&list, NULL, NULL); pcmk__add_word(&list, NULL, ""); - g_assert_cmpint(strcmp(list, "hello"), ==, 0); + assert_int_equal(strcmp(list, "hello"), 0); free(list); } static void -add_with_null(void) +add_with_null(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_separated_word(&list, &list_len, "hello", NULL); pcmk__add_separated_word(&list, &list_len, "world", NULL); pcmk__add_separated_word(&list, &list_len, "I am a unit test", NULL); - g_assert_cmpint(strcmp(list, "hello world I am a unit test"), ==, 0); + assert_int_equal(strcmp(list, "hello world I am a unit test"), 0); free(list); } static void -add_with_comma(void) +add_with_comma(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_separated_word(&list, &list_len, "hello", ","); pcmk__add_separated_word(&list, &list_len, "world", ","); pcmk__add_separated_word(&list, &list_len, "I am a unit test", ","); - g_assert_cmpint(strcmp(list, "hello,world,I am a unit test"), ==, 0); + assert_int_equal(strcmp(list, "hello,world,I am a unit test"), 0); free(list); } static void -add_with_comma_and_space(void) +add_with_comma_and_space(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_separated_word(&list, &list_len, "hello", ", "); pcmk__add_separated_word(&list, &list_len, "world", ", "); pcmk__add_separated_word(&list, &list_len, "I am a unit test", ", "); - g_assert_cmpint(strcmp(list, "hello, world, I am a unit test"), ==, 0); + assert_int_equal(strcmp(list, "hello, world, I am a unit test"), 0); free(list); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/strings/add_word/add_words", add_words); - g_test_add_func("/common/strings/add_word/add_with_no_len", - add_with_no_len); - g_test_add_func("/common/strings/add_word/add_nothing", add_nothing); - g_test_add_func("/common/strings/add_word/add_with_null", add_with_null); - g_test_add_func("/common/strings/add_word/add_with_comma", add_with_comma); - g_test_add_func("/common/strings/add_word/add_with_comma_and_space", - add_with_comma_and_space); - - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(add_words), + cmocka_unit_test(add_with_no_len), + cmocka_unit_test(add_nothing), + cmocka_unit_test(add_with_null), + cmocka_unit_test(add_with_comma), + cmocka_unit_test(add_with_comma_and_space), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__btoa_test.c b/lib/common/tests/strings/pcmk__btoa_test.c index 240cb3aa7e..10261f5623 100644 --- a/lib/common/tests/strings/pcmk__btoa_test.c +++ b/lib/common/tests/strings/pcmk__btoa_test.c @@ -1,26 +1,34 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -btoa(void) { - g_assert_cmpstr(pcmk__btoa(false), ==, "false"); - g_assert_cmpstr(pcmk__btoa(true), ==, "true"); - g_assert_cmpstr(pcmk__btoa(1 == 0), ==, "false"); +btoa(void **state) { + assert_string_equal(pcmk__btoa(false), "false"); + assert_string_equal(pcmk__btoa(true), "true"); + assert_string_equal(pcmk__btoa(1 == 0), "false"); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(btoa), + }; - g_test_add_func("/common/strings/btoa/btoa", btoa); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__char_in_any_str_test.c b/lib/common/tests/strings/pcmk__char_in_any_str_test.c index 11159ccad9..cd469af990 100644 --- a/lib/common/tests/strings/pcmk__char_in_any_str_test.c +++ b/lib/common/tests/strings/pcmk__char_in_any_str_test.c @@ -1,55 +1,58 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include +#include +#include +#include +#include +#include static void -empty_list(void) +empty_list(void **state) { - g_assert_false(pcmk__char_in_any_str('x', NULL)); - g_assert_false(pcmk__char_in_any_str('\0', NULL)); + assert_false(pcmk__char_in_any_str('x', NULL)); + assert_false(pcmk__char_in_any_str('\0', NULL)); } static void -null_char(void) +null_char(void **state) { - g_assert_true(pcmk__char_in_any_str('\0', "xxx", "yyy", NULL)); - g_assert_true(pcmk__char_in_any_str('\0', "", NULL)); + assert_true(pcmk__char_in_any_str('\0', "xxx", "yyy", NULL)); + assert_true(pcmk__char_in_any_str('\0', "", NULL)); } static void -in_list(void) +in_list(void **state) { - g_assert_true(pcmk__char_in_any_str('x', "aaa", "bbb", "xxx", NULL)); + assert_true(pcmk__char_in_any_str('x', "aaa", "bbb", "xxx", NULL)); } static void -not_in_list(void) +not_in_list(void **state) { - g_assert_false(pcmk__char_in_any_str('x', "aaa", "bbb", NULL)); - g_assert_false(pcmk__char_in_any_str('A', "aaa", "bbb", NULL)); - g_assert_false(pcmk__char_in_any_str('x', "", NULL)); + assert_false(pcmk__char_in_any_str('x', "aaa", "bbb", NULL)); + assert_false(pcmk__char_in_any_str('A', "aaa", "bbb", NULL)); + assert_false(pcmk__char_in_any_str('x', "", NULL)); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/strings/char_in_any_str/empty_list", empty_list); - g_test_add_func("/common/strings/char_in_any_str/null_char", null_char); - g_test_add_func("/common/strings/char_in_any_str/in", in_list); - g_test_add_func("/common/strings/char_in_any_str/not_in", not_in_list); - - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(empty_list), + cmocka_unit_test(null_char), + cmocka_unit_test(in_list), + cmocka_unit_test(not_in_list), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__ends_with_test.c b/lib/common/tests/strings/pcmk__ends_with_test.c index 09085a181a..00a08445aa 100644 --- a/lib/common/tests/strings/pcmk__ends_with_test.c +++ b/lib/common/tests/strings/pcmk__ends_with_test.c @@ -1,61 +1,69 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -bad_input(void) { - g_assert_false(pcmk__ends_with(NULL, "xyz")); - - g_assert_true(pcmk__ends_with(NULL, NULL)); - g_assert_true(pcmk__ends_with(NULL, "")); - g_assert_true(pcmk__ends_with("", NULL)); - g_assert_true(pcmk__ends_with("", "")); - g_assert_true(pcmk__ends_with("abc", NULL)); - g_assert_true(pcmk__ends_with("abc", "")); +bad_input(void **state) { + assert_false(pcmk__ends_with(NULL, "xyz")); + + assert_true(pcmk__ends_with(NULL, NULL)); + assert_true(pcmk__ends_with(NULL, "")); + assert_true(pcmk__ends_with("", NULL)); + assert_true(pcmk__ends_with("", "")); + assert_true(pcmk__ends_with("abc", NULL)); + assert_true(pcmk__ends_with("abc", "")); } static void -ends_with(void) { - g_assert_true(pcmk__ends_with("abc", "abc")); - g_assert_true(pcmk__ends_with("abc", "bc")); - g_assert_true(pcmk__ends_with("abc", "c")); - g_assert_true(pcmk__ends_with("abcbc", "bc")); - - g_assert_false(pcmk__ends_with("abc", "def")); - g_assert_false(pcmk__ends_with("abc", "defg")); - g_assert_false(pcmk__ends_with("abc", "bcd")); - g_assert_false(pcmk__ends_with("abc", "ab")); - - g_assert_false(pcmk__ends_with("abc", "BC")); +ends_with(void **state) { + assert_true(pcmk__ends_with("abc", "abc")); + assert_true(pcmk__ends_with("abc", "bc")); + assert_true(pcmk__ends_with("abc", "c")); + assert_true(pcmk__ends_with("abcbc", "bc")); + + assert_false(pcmk__ends_with("abc", "def")); + assert_false(pcmk__ends_with("abc", "defg")); + assert_false(pcmk__ends_with("abc", "bcd")); + assert_false(pcmk__ends_with("abc", "ab")); + + assert_false(pcmk__ends_with("abc", "BC")); } static void -ends_with_ext(void) { - g_assert_true(pcmk__ends_with_ext("ab.c", ".c")); - g_assert_true(pcmk__ends_with_ext("ab.cb.c", ".c")); +ends_with_ext(void **state) { + assert_true(pcmk__ends_with_ext("ab.c", ".c")); + assert_true(pcmk__ends_with_ext("ab.cb.c", ".c")); - g_assert_false(pcmk__ends_with_ext("ab.c", ".def")); - g_assert_false(pcmk__ends_with_ext("ab.c", ".defg")); - g_assert_false(pcmk__ends_with_ext("ab.c", ".cd")); - g_assert_false(pcmk__ends_with_ext("ab.c", "ab")); + assert_false(pcmk__ends_with_ext("ab.c", ".def")); + assert_false(pcmk__ends_with_ext("ab.c", ".defg")); + assert_false(pcmk__ends_with_ext("ab.c", ".cd")); + assert_false(pcmk__ends_with_ext("ab.c", "ab")); - g_assert_false(pcmk__ends_with_ext("ab.c", ".C")); + assert_false(pcmk__ends_with_ext("ab.c", ".C")); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(bad_input), + cmocka_unit_test(ends_with), + cmocka_unit_test(ends_with_ext), + }; - g_test_add_func("/common/strings/ends_with/bad_input", bad_input); - g_test_add_func("/common/strings/ends_with/ends_with", ends_with); - g_test_add_func("/common/strings/ends_with/ends_with_ext", ends_with_ext); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__parse_ll_range_test.c b/lib/common/tests/strings/pcmk__parse_ll_range_test.c index 19049fea18..a4f91aef19 100644 --- a/lib/common/tests/strings/pcmk__parse_ll_range_test.c +++ b/lib/common/tests/strings/pcmk__parse_ll_range_test.c @@ -1,109 +1,106 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include +#include +#include +#include +#include +#include static void -empty_input_string(void) +empty_input_string(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range(NULL, &start, &end), ==, - pcmk_rc_unknown_format); - g_assert_cmpint(pcmk__parse_ll_range("", &start, &end), ==, - pcmk_rc_unknown_format); + assert_int_equal(pcmk__parse_ll_range(NULL, &start, &end), pcmk_rc_unknown_format); + assert_int_equal(pcmk__parse_ll_range("", &start, &end), pcmk_rc_unknown_format); } static void -missing_separator(void) +missing_separator(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range("1234", &start, &end), ==, pcmk_rc_ok); - g_assert_cmpint(start, ==, 1234); - g_assert_cmpint(end, ==, 1234); + assert_int_equal(pcmk__parse_ll_range("1234", &start, &end), pcmk_rc_ok); + assert_int_equal(start, 1234); + assert_int_equal(end, 1234); } static void -only_separator(void) +only_separator(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range("-", &start, &end), ==, - pcmk_rc_unknown_format); - g_assert_cmpint(start, ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(end, ==, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(pcmk__parse_ll_range("-", &start, &end), pcmk_rc_unknown_format); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); } static void -no_range_end(void) +no_range_end(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range("2000-", &start, &end), ==, - pcmk_rc_ok); - g_assert_cmpint(start, ==, 2000); - g_assert_cmpint(end, ==, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(pcmk__parse_ll_range("2000-", &start, &end), pcmk_rc_ok); + assert_int_equal(start, 2000); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); } static void -no_range_start(void) +no_range_start(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range("-2020", &start, &end), ==, - pcmk_rc_ok); - g_assert_cmpint(start, ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(end, ==, 2020); + assert_int_equal(pcmk__parse_ll_range("-2020", &start, &end), pcmk_rc_ok); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, 2020); } static void -range_start_and_end(void) +range_start_and_end(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range("2000-2020", &start, &end), ==, - pcmk_rc_ok); - g_assert_cmpint(start, ==, 2000); - g_assert_cmpint(end, ==, 2020); + assert_int_equal(pcmk__parse_ll_range("2000-2020", &start, &end), pcmk_rc_ok); + assert_int_equal(start, 2000); + assert_int_equal(end, 2020); } static void -garbage(void) +garbage(void **state) { long long start, end; - g_assert_cmpint(pcmk__parse_ll_range("2000x-", &start, &end), ==, - pcmk_rc_unknown_format); - g_assert_cmpint(start, ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(end, ==, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(pcmk__parse_ll_range("2000x-", &start, &end), pcmk_rc_unknown_format); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(pcmk__parse_ll_range("-x2000", &start, &end), ==, - pcmk_rc_unknown_format); - g_assert_cmpint(start, ==, PCMK__PARSE_INT_DEFAULT); - g_assert_cmpint(end, ==, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(pcmk__parse_ll_range("-x2000", &start, &end), pcmk_rc_unknown_format); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/strings/range/empty", empty_input_string); - g_test_add_func("/common/strings/range/no_sep", missing_separator); - g_test_add_func("/common/strings/range/only_sep", only_separator); - g_test_add_func("/common/strings/range/no_end", no_range_end); - g_test_add_func("/common/strings/range/no_start", no_range_start); - g_test_add_func("/common/strings/range/start_and_end", range_start_and_end); - - g_test_add_func("/common/strings/range/garbage", garbage); - - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(empty_input_string), + cmocka_unit_test(missing_separator), + cmocka_unit_test(only_separator), + cmocka_unit_test(no_range_end), + cmocka_unit_test(no_range_start), + cmocka_unit_test(range_start_and_end), + + cmocka_unit_test(garbage), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__scan_double_test.c b/lib/common/tests/strings/pcmk__scan_double_test.c index 3d0d0f160d..d8befd86c8 100644 --- a/lib/common/tests/strings/pcmk__scan_double_test.c +++ b/lib/common/tests/strings/pcmk__scan_double_test.c @@ -1,169 +1,164 @@ /* * Copyright 2004-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + #include // DBL_MAX, etc. #include // fabs() -#include // Ensure plenty of characters for %f display #define LOCAL_BUF_SIZE 2 * DBL_MAX_10_EXP /* - * Avoids compiler warnings for floating-point equality checks. - * Use for comparing numbers (e.g., 1.0 == 1.0), not expression values. + * assert_float_equal doesn't exist for older versions of cmocka installed on some + * of our builders, so define it in terms of regular assert() here in that case. */ -#define ASSERT_DBL_EQ(d1, d2) g_assert_cmpfloat(fabs(d1 - d2), \ - <, DBL_EPSILON); +#if HAVE_DECL_ASSERT_FLOAT_EQUAL == 0 +#define assert_float_equal(a, b, epsilon) assert_true(fabs((a) - (b)) < (epsilon)) +#endif static void -empty_input_string(void) +empty_input_string(void **state) { double result; // Without default_text - g_assert_cmpint(pcmk__scan_double(NULL, &result, NULL, NULL), ==, EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double(NULL, &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); - g_assert_cmpint(pcmk__scan_double("", &result, NULL, NULL), ==, EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double("", &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); // With default_text - g_assert_cmpint(pcmk__scan_double(NULL, &result, "2.0", NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, 2.0); + assert_int_equal(pcmk__scan_double(NULL, &result, "2.0", NULL), pcmk_rc_ok); + assert_float_equal(result, 2.0, DBL_EPSILON); - g_assert_cmpint(pcmk__scan_double("", &result, "2.0", NULL), ==, EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double("", &result, "2.0", NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); } static void -bad_input_string(void) +bad_input_string(void **state) { double result; // Without default text - g_assert_cmpint(pcmk__scan_double("asdf", &result, NULL, NULL), ==, EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double("asdf", &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); - g_assert_cmpint(pcmk__scan_double("as2.0", &result, NULL, NULL), ==, - EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double("as2.0", &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); // With default text (not used) - g_assert_cmpint(pcmk__scan_double("asdf", &result, "2.0", NULL), ==, - EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double("asdf", &result, "2.0", NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); - g_assert_cmpint(pcmk__scan_double("as2.0", &result, "2.0", NULL), ==, - EINVAL); - ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT); + assert_int_equal(pcmk__scan_double("as2.0", &result, "2.0", NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); } static void -trailing_chars(void) +trailing_chars(void **state) { double result; - g_assert_cmpint(pcmk__scan_double("2.0asdf", &result, NULL, NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, 2.0); + assert_int_equal(pcmk__scan_double("2.0asdf", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, 2.0, DBL_EPSILON); } static void -typical_case(void) +typical_case(void **state) { char str[LOCAL_BUF_SIZE]; double result; - g_assert_cmpint(pcmk__scan_double("0.0", &result, NULL, NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, 0.0); + assert_int_equal(pcmk__scan_double("0.0", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, 0.0, DBL_EPSILON); - g_assert_cmpint(pcmk__scan_double("1.0", &result, NULL, NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, 1.0); + assert_int_equal(pcmk__scan_double("1.0", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, 1.0, DBL_EPSILON); - g_assert_cmpint(pcmk__scan_double("-1.0", &result, NULL, NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, -1.0); + assert_int_equal(pcmk__scan_double("-1.0", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, -1.0, DBL_EPSILON); snprintf(str, LOCAL_BUF_SIZE, "%f", DBL_MAX); - g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, DBL_MAX); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, DBL_MAX, DBL_EPSILON); snprintf(str, LOCAL_BUF_SIZE, "%f", -DBL_MAX); - g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, - pcmk_rc_ok); - ASSERT_DBL_EQ(result, -DBL_MAX); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, -DBL_MAX, DBL_EPSILON); } static void -double_overflow(void) +double_overflow(void **state) { char str[LOCAL_BUF_SIZE]; double result; /* * 1e(DBL_MAX_10_EXP + 1) produces an inf value - * Can't use ASSERT_DBL_EQ() because (inf - inf) == NaN + * Can't use assert_float_equal() because (inf - inf) == NaN */ snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MAX_10_EXP + 1); - g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, EOVERFLOW); - g_assert_cmpfloat(result, >, DBL_MAX); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), EOVERFLOW); + assert_true(result > DBL_MAX); snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MAX_10_EXP + 1); - g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, EOVERFLOW); - g_assert_cmpfloat(result, <, -DBL_MAX); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), EOVERFLOW); + assert_true(result < -DBL_MAX); } static void -double_underflow(void) +double_underflow(void **state) { char str[LOCAL_BUF_SIZE]; double result; /* * 1e(DBL_MIN_10_EXP - 1) produces a denormalized value (between 0 * and DBL_MIN) * * C99/C11: result will be **no greater than** DBL_MIN */ snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MIN_10_EXP - 1); - g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, - pcmk_rc_underflow); - g_assert_cmpfloat(result, >=, 0.0); - g_assert_cmpfloat(result, <=, DBL_MIN); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_underflow); + assert_true(result >= 0.0); + assert_true(result <= DBL_MIN); snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MIN_10_EXP - 1); - g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, - pcmk_rc_underflow); - g_assert_cmpfloat(result, <=, 0.0); - g_assert_cmpfloat(result, >=, -DBL_MIN); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_underflow); + assert_true(result <= 0.0); + assert_true(result >= -DBL_MIN); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - // Test for input string issues - g_test_add_func("/common/strings/double/empty_input", empty_input_string); - g_test_add_func("/common/strings/double/bad_input", bad_input_string); - g_test_add_func("/common/strings/double/trailing_chars", trailing_chars); - - // Test for numeric issues - g_test_add_func("/common/strings/double/typical", typical_case); - g_test_add_func("/common/strings/double/overflow", double_overflow); - g_test_add_func("/common/strings/double/underflow", double_underflow); - - return g_test_run(); + const struct CMUnitTest tests[] = { + // Test for input string issues + cmocka_unit_test(empty_input_string), + cmocka_unit_test(bad_input_string), + cmocka_unit_test(trailing_chars), + + // Test for numeric issues + cmocka_unit_test(typical_case), + cmocka_unit_test(double_overflow), + cmocka_unit_test(double_underflow), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__starts_with_test.c b/lib/common/tests/strings/pcmk__starts_with_test.c index 01b17aa3db..f6427dd8e7 100644 --- a/lib/common/tests/strings/pcmk__starts_with_test.c +++ b/lib/common/tests/strings/pcmk__starts_with_test.c @@ -1,39 +1,47 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include +#include +#include +#include +#include + static void -bad_input(void) { - g_assert_false(pcmk__starts_with(NULL, "x")); - g_assert_false(pcmk__starts_with("abc", NULL)); +bad_input(void **state) { + assert_false(pcmk__starts_with(NULL, "x")); + assert_false(pcmk__starts_with("abc", NULL)); } static void -starts_with(void) { - g_assert_true(pcmk__starts_with("abc", "a")); - g_assert_true(pcmk__starts_with("abc", "ab")); - g_assert_true(pcmk__starts_with("abc", "abc")); +starts_with(void **state) { + assert_true(pcmk__starts_with("abc", "a")); + assert_true(pcmk__starts_with("abc", "ab")); + assert_true(pcmk__starts_with("abc", "abc")); - g_assert_false(pcmk__starts_with("abc", "A")); - g_assert_false(pcmk__starts_with("abc", "bc")); + assert_false(pcmk__starts_with("abc", "A")); + assert_false(pcmk__starts_with("abc", "bc")); - g_assert_false(pcmk__starts_with("", "x")); - g_assert_true(pcmk__starts_with("xyz", "")); + assert_false(pcmk__starts_with("", "x")); + assert_true(pcmk__starts_with("xyz", "")); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(bad_input), + cmocka_unit_test(starts_with), + }; - g_test_add_func("/common/strings/starts_with/bad_input", bad_input); - g_test_add_func("/common/strings/starts_with/starts_with", starts_with); - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__str_any_of_test.c b/lib/common/tests/strings/pcmk__str_any_of_test.c index 61340d7f8c..ee5b1ab8d8 100644 --- a/lib/common/tests/strings/pcmk__str_any_of_test.c +++ b/lib/common/tests/strings/pcmk__str_any_of_test.c @@ -1,56 +1,59 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include +#include +#include +#include +#include +#include static void -empty_input_list(void) { - g_assert_false(pcmk__strcase_any_of("xxx", NULL)); - g_assert_false(pcmk__str_any_of("xxx", NULL)); - g_assert_false(pcmk__strcase_any_of("", NULL)); - g_assert_false(pcmk__str_any_of("", NULL)); +empty_input_list(void **state) { + assert_false(pcmk__strcase_any_of("xxx", NULL)); + assert_false(pcmk__str_any_of("xxx", NULL)); + assert_false(pcmk__strcase_any_of("", NULL)); + assert_false(pcmk__str_any_of("", NULL)); } static void -empty_string(void) { - g_assert_false(pcmk__strcase_any_of("", "xxx", "yyy", NULL)); - g_assert_false(pcmk__str_any_of("", "xxx", "yyy", NULL)); - g_assert_false(pcmk__strcase_any_of(NULL, "xxx", "yyy", NULL)); - g_assert_false(pcmk__str_any_of(NULL, "xxx", "yyy", NULL)); +empty_string(void **state) { + assert_false(pcmk__strcase_any_of("", "xxx", "yyy", NULL)); + assert_false(pcmk__str_any_of("", "xxx", "yyy", NULL)); + assert_false(pcmk__strcase_any_of(NULL, "xxx", "yyy", NULL)); + assert_false(pcmk__str_any_of(NULL, "xxx", "yyy", NULL)); } static void -in_list(void) { - g_assert_true(pcmk__strcase_any_of("xxx", "aaa", "bbb", "xxx", NULL)); - g_assert_true(pcmk__str_any_of("xxx", "aaa", "bbb", "xxx", NULL)); - g_assert_true(pcmk__strcase_any_of("XXX", "aaa", "bbb", "xxx", NULL)); +in_list(void **state) { + assert_true(pcmk__strcase_any_of("xxx", "aaa", "bbb", "xxx", NULL)); + assert_true(pcmk__str_any_of("xxx", "aaa", "bbb", "xxx", NULL)); + assert_true(pcmk__strcase_any_of("XXX", "aaa", "bbb", "xxx", NULL)); } static void -not_in_list(void) { - g_assert_false(pcmk__strcase_any_of("xxx", "aaa", "bbb", NULL)); - g_assert_false(pcmk__str_any_of("xxx", "aaa", "bbb", NULL)); - g_assert_false(pcmk__str_any_of("AAA", "aaa", "bbb", NULL)); +not_in_list(void **state) { + assert_false(pcmk__strcase_any_of("xxx", "aaa", "bbb", NULL)); + assert_false(pcmk__str_any_of("xxx", "aaa", "bbb", NULL)); + assert_false(pcmk__str_any_of("AAA", "aaa", "bbb", NULL)); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/strings/any_of/empty_list", empty_input_list); - g_test_add_func("/common/strings/any_of/empty_string", empty_string); - g_test_add_func("/common/strings/any_of/in", in_list); - g_test_add_func("/common/strings/any_of/not_in", not_in_list); - - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(empty_input_list), + cmocka_unit_test(empty_string), + cmocka_unit_test(in_list), + cmocka_unit_test(not_in_list), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__str_in_list_test.c b/lib/common/tests/strings/pcmk__str_in_list_test.c index f34ac1f2c0..8d3367f559 100644 --- a/lib/common/tests/strings/pcmk__str_in_list_test.c +++ b/lib/common/tests/strings/pcmk__str_in_list_test.c @@ -1,113 +1,118 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include #include +#include +#include +#include +#include +#include + static void -empty_input_list(void) { - g_assert_false(pcmk__str_in_list(NULL, NULL, pcmk__str_none)); - g_assert_false(pcmk__str_in_list(NULL, NULL, pcmk__str_null_matches)); - g_assert_false(pcmk__str_in_list("xxx", NULL, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("", NULL, pcmk__str_none)); +empty_input_list(void **state) { + assert_false(pcmk__str_in_list(NULL, NULL, pcmk__str_none)); + assert_false(pcmk__str_in_list(NULL, NULL, pcmk__str_null_matches)); + assert_false(pcmk__str_in_list("xxx", NULL, pcmk__str_none)); + assert_false(pcmk__str_in_list("", NULL, pcmk__str_none)); } static void -empty_string(void) { +empty_string(void **state) { GList *list = NULL; list = g_list_prepend(list, (gpointer) "xxx"); - g_assert_false(pcmk__str_in_list(NULL, list, pcmk__str_none)); - g_assert_true(pcmk__str_in_list(NULL, list, pcmk__str_null_matches)); - g_assert_false(pcmk__str_in_list("", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("", list, pcmk__str_null_matches)); + assert_false(pcmk__str_in_list(NULL, list, pcmk__str_none)); + assert_true(pcmk__str_in_list(NULL, list, pcmk__str_null_matches)); + assert_false(pcmk__str_in_list("", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("", list, pcmk__str_null_matches)); g_list_free(list); } static void -star_matches(void) { +star_matches(void **state) { GList *list = NULL; list = g_list_prepend(list, (gpointer) "*"); list = g_list_append(list, (gpointer) "more"); - g_assert_true(pcmk__str_in_list("xxx", list, pcmk__str_star_matches)); - g_assert_true(pcmk__str_in_list("yyy", list, pcmk__str_star_matches)); - g_assert_true(pcmk__str_in_list("XXX", list, pcmk__str_star_matches|pcmk__str_casei)); - g_assert_true(pcmk__str_in_list("", list, pcmk__str_star_matches)); + assert_true(pcmk__str_in_list("xxx", list, pcmk__str_star_matches)); + assert_true(pcmk__str_in_list("yyy", list, pcmk__str_star_matches)); + assert_true(pcmk__str_in_list("XXX", list, pcmk__str_star_matches|pcmk__str_casei)); + assert_true(pcmk__str_in_list("", list, pcmk__str_star_matches)); g_list_free(list); } static void -star_doesnt_match(void) { +star_doesnt_match(void **state) { GList *list = NULL; list = g_list_prepend(list, (gpointer) "*"); - g_assert_false(pcmk__str_in_list("xxx", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("yyy", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("XXX", list, pcmk__str_casei)); - g_assert_false(pcmk__str_in_list("", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list(NULL, list, pcmk__str_star_matches)); + assert_false(pcmk__str_in_list("xxx", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("yyy", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("XXX", list, pcmk__str_casei)); + assert_false(pcmk__str_in_list("", list, pcmk__str_none)); + assert_false(pcmk__str_in_list(NULL, list, pcmk__str_star_matches)); g_list_free(list); } static void -in_list(void) { +in_list(void **state) { GList *list = NULL; list = g_list_prepend(list, (gpointer) "xxx"); list = g_list_prepend(list, (gpointer) "yyy"); list = g_list_prepend(list, (gpointer) "zzz"); - g_assert_true(pcmk__str_in_list("xxx", list, pcmk__str_none)); - g_assert_true(pcmk__str_in_list("XXX", list, pcmk__str_casei)); - g_assert_true(pcmk__str_in_list("yyy", list, pcmk__str_none)); - g_assert_true(pcmk__str_in_list("YYY", list, pcmk__str_casei)); - g_assert_true(pcmk__str_in_list("zzz", list, pcmk__str_none)); - g_assert_true(pcmk__str_in_list("ZZZ", list, pcmk__str_casei)); + assert_true(pcmk__str_in_list("xxx", list, pcmk__str_none)); + assert_true(pcmk__str_in_list("XXX", list, pcmk__str_casei)); + assert_true(pcmk__str_in_list("yyy", list, pcmk__str_none)); + assert_true(pcmk__str_in_list("YYY", list, pcmk__str_casei)); + assert_true(pcmk__str_in_list("zzz", list, pcmk__str_none)); + assert_true(pcmk__str_in_list("ZZZ", list, pcmk__str_casei)); g_list_free(list); } static void -not_in_list(void) { +not_in_list(void **state) { GList *list = NULL; list = g_list_prepend(list, (gpointer) "xxx"); list = g_list_prepend(list, (gpointer) "yyy"); - g_assert_false(pcmk__str_in_list("xx", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("XXX", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("zzz", list, pcmk__str_none)); - g_assert_false(pcmk__str_in_list("zzz", list, pcmk__str_casei)); + assert_false(pcmk__str_in_list("xx", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("XXX", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("zzz", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("zzz", list, pcmk__str_casei)); g_list_free(list); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/strings/in_list/empty_list", empty_input_list); - g_test_add_func("/common/strings/in_list/empty_string", empty_string); - g_test_add_func("/common/strings/in_list/star_matches", star_matches); - g_test_add_func("/common/strings/in_list/star_doesnt_match", star_doesnt_match); - g_test_add_func("/common/strings/in_list/in", in_list); - g_test_add_func("/common/strings/in_list/not_in", not_in_list); - - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(empty_input_list), + cmocka_unit_test(empty_string), + cmocka_unit_test(star_matches), + cmocka_unit_test(star_doesnt_match), + cmocka_unit_test(in_list), + cmocka_unit_test(not_in_list), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__strcmp_test.c b/lib/common/tests/strings/pcmk__strcmp_test.c index 85790eced0..100e183f64 100644 --- a/lib/common/tests/strings/pcmk__strcmp_test.c +++ b/lib/common/tests/strings/pcmk__strcmp_test.c @@ -1,87 +1,90 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include +#include +#include +#include +#include +#include static void -same_pointer(void) { +same_pointer(void **state) { const char *s1 = "abcd"; const char *s2 = "wxyz"; - g_assert_cmpint(pcmk__strcmp(s1, s1, pcmk__str_none), ==, 0); - g_assert_true(pcmk__str_eq(s1, s1, pcmk__str_none)); - g_assert_cmpint(pcmk__strcmp(s1, s2, pcmk__str_none), !=, 0); - g_assert_false(pcmk__str_eq(s1, s2, pcmk__str_none)); - g_assert_cmpint(pcmk__strcmp(NULL, NULL, pcmk__str_none), ==, 0); + assert_int_equal(pcmk__strcmp(s1, s1, pcmk__str_none), 0); + assert_true(pcmk__str_eq(s1, s1, pcmk__str_none)); + assert_int_not_equal(pcmk__strcmp(s1, s2, pcmk__str_none), 0); + assert_false(pcmk__str_eq(s1, s2, pcmk__str_none)); + assert_int_equal(pcmk__strcmp(NULL, NULL, pcmk__str_none), 0); } static void -one_is_null(void) { +one_is_null(void **state) { const char *s1 = "abcd"; - g_assert_cmpint(pcmk__strcmp(s1, NULL, pcmk__str_null_matches), ==, 0); - g_assert_true(pcmk__str_eq(s1, NULL, pcmk__str_null_matches)); - g_assert_cmpint(pcmk__strcmp(NULL, s1, pcmk__str_null_matches), ==, 0); - g_assert_cmpint(pcmk__strcmp(s1, NULL, pcmk__str_none), >, 0); - g_assert_false(pcmk__str_eq(s1, NULL, pcmk__str_none)); - g_assert_cmpint(pcmk__strcmp(NULL, s1, pcmk__str_none), <, 0); + assert_int_equal(pcmk__strcmp(s1, NULL, pcmk__str_null_matches), 0); + assert_true(pcmk__str_eq(s1, NULL, pcmk__str_null_matches)); + assert_int_equal(pcmk__strcmp(NULL, s1, pcmk__str_null_matches), 0); + assert_in_range(pcmk__strcmp(s1, NULL, pcmk__str_none), 1, 255); + assert_false(pcmk__str_eq(s1, NULL, pcmk__str_none)); + assert_in_range(pcmk__strcmp(NULL, s1, pcmk__str_none), -255, -1); } static void -case_matters(void) { +case_matters(void **state) { const char *s1 = "abcd"; const char *s2 = "ABCD"; - g_assert_cmpint(pcmk__strcmp(s1, s2, pcmk__str_none), >, 0); - g_assert_false(pcmk__str_eq(s1, s2, pcmk__str_none)); - g_assert_cmpint(pcmk__strcmp(s2, s1, pcmk__str_none), <, 0); + assert_in_range(pcmk__strcmp(s1, s2, pcmk__str_none), 1, 255); + assert_false(pcmk__str_eq(s1, s2, pcmk__str_none)); + assert_in_range(pcmk__strcmp(s2, s1, pcmk__str_none), -255, -1); } static void -case_insensitive(void) { +case_insensitive(void **state) { const char *s1 = "abcd"; const char *s2 = "ABCD"; - g_assert_cmpint(pcmk__strcmp(s1, s2, pcmk__str_casei), ==, 0); - g_assert_true(pcmk__str_eq(s1, s2, pcmk__str_casei)); + assert_int_equal(pcmk__strcmp(s1, s2, pcmk__str_casei), 0); + assert_true(pcmk__str_eq(s1, s2, pcmk__str_casei)); } static void -regex(void) { +regex(void **state) { const char *s1 = "abcd"; const char *s2 = "ABCD"; - g_assert_cmpint(pcmk__strcmp(NULL, "a..d", pcmk__str_regex), ==, 1); - g_assert_cmpint(pcmk__strcmp(s1, NULL, pcmk__str_regex), ==, 1); - g_assert_cmpint(pcmk__strcmp(s1, "a..d", pcmk__str_regex), ==, 0); - g_assert_true(pcmk__str_eq(s1, "a..d", pcmk__str_regex)); - g_assert_cmpint(pcmk__strcmp(s1, "xxyy", pcmk__str_regex), !=, 0); - g_assert_false(pcmk__str_eq(s1, "xxyy", pcmk__str_regex)); - g_assert_cmpint(pcmk__strcmp(s2, "a..d", pcmk__str_regex|pcmk__str_casei), ==, 0); - g_assert_true(pcmk__str_eq(s2, "a..d", pcmk__str_regex|pcmk__str_casei)); - g_assert_cmpint(pcmk__strcmp(s2, "a..d", pcmk__str_regex), !=, 0); - g_assert_false(pcmk__str_eq(s2, "a..d", pcmk__str_regex)); - g_assert_cmpint(pcmk__strcmp(s2, "*ab", pcmk__str_regex), ==, 1); + assert_int_equal(pcmk__strcmp(NULL, "a..d", pcmk__str_regex), 1); + assert_int_equal(pcmk__strcmp(s1, NULL, pcmk__str_regex), 1); + assert_int_equal(pcmk__strcmp(s1, "a..d", pcmk__str_regex), 0); + assert_true(pcmk__str_eq(s1, "a..d", pcmk__str_regex)); + assert_int_not_equal(pcmk__strcmp(s1, "xxyy", pcmk__str_regex), 0); + assert_false(pcmk__str_eq(s1, "xxyy", pcmk__str_regex)); + assert_int_equal(pcmk__strcmp(s2, "a..d", pcmk__str_regex|pcmk__str_casei), 0); + assert_true(pcmk__str_eq(s2, "a..d", pcmk__str_regex|pcmk__str_casei)); + assert_int_not_equal(pcmk__strcmp(s2, "a..d", pcmk__str_regex), 0); + assert_false(pcmk__str_eq(s2, "a..d", pcmk__str_regex)); + assert_int_equal(pcmk__strcmp(s2, "*ab", pcmk__str_regex), 1); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(same_pointer), + cmocka_unit_test(one_is_null), + cmocka_unit_test(case_matters), + cmocka_unit_test(case_insensitive), + cmocka_unit_test(regex), + }; - g_test_add_func("/common/strings/strcmp/same_pointer", same_pointer); - g_test_add_func("/common/strings/strcmp/one_is_null", one_is_null); - g_test_add_func("/common/strings/strcmp/case_matters", case_matters); - g_test_add_func("/common/strings/strcmp/case_insensitive", case_insensitive); - g_test_add_func("/common/strings/strcmp/regex", regex); - - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/Makefile.am b/lib/common/tests/utils/Makefile.am index ae30b77303..c2a1960fb4 100644 --- a/lib/common/tests/utils/Makefile.am +++ b/lib/common/tests/utils/Makefile.am @@ -1,30 +1,29 @@ # -# Copyright 2020 the Pacemaker project contributors +# Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/lib/common/mock.mk + +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/lib/common +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka + +include $(top_srcdir)/mk/tap.mk + +pcmk_hostname_test_LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -lcmocka +pcmk_hostname_test_LDFLAGS = -Wl,--wrap=uname -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk_str_is_infinity_test \ - pcmk_str_is_minus_infinity_test +check_PROGRAMS = \ + pcmk_str_is_infinity_test \ + pcmk_str_is_minus_infinity_test -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +if WRAPPABLE_UNAME +check_PROGRAMS += pcmk_hostname_test +endif -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/utils/pcmk_hostname_test.c b/lib/common/tests/utils/pcmk_hostname_test.c new file mode 100644 index 0000000000..7eb747b1b1 --- /dev/null +++ b/lib/common/tests/utils/pcmk_hostname_test.c @@ -0,0 +1,71 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include +#include "mock_private.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +int +__wrap_uname(struct utsname *buf) +{ + int retval = mock_type(int); + + if (retval == 0) { + strcpy(buf->nodename, mock_type(char *)); + } + + return retval; +} + +static void +uname_succeeded_test(void **state) +{ + char *retval; + + will_return(__wrap_uname, 0); // uname() return value + will_return(__wrap_uname, "somename"); // uname() buf->nodename + + retval = pcmk_hostname(); + assert_non_null(retval); + assert_string_equal("somename", retval); + + free(retval); +} + +static void +uname_failed_test(void **state) +{ + char *retval; + + will_return(__wrap_uname, -1); // uname() return value + + retval = pcmk_hostname(); + assert_null(retval); +} + +int +main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(uname_succeeded_test), + cmocka_unit_test(uname_failed_test), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/common/tests/utils/pcmk_str_is_infinity_test.c b/lib/common/tests/utils/pcmk_str_is_infinity_test.c index 1e012d9671..750f36f431 100644 --- a/lib/common/tests/utils/pcmk_str_is_infinity_test.c +++ b/lib/common/tests/utils/pcmk_str_is_infinity_test.c @@ -1,65 +1,68 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include +#include +#include +#include +#include +#include static void -uppercase_str_passes(void) +uppercase_str_passes(void **state) { - g_assert_true(pcmk_str_is_infinity("INFINITY")); - g_assert_true(pcmk_str_is_infinity("+INFINITY")); + assert_true(pcmk_str_is_infinity("INFINITY")); + assert_true(pcmk_str_is_infinity("+INFINITY")); } static void -mixed_case_str_fails(void) +mixed_case_str_fails(void **state) { - g_assert_false(pcmk_str_is_infinity("infinity")); - g_assert_false(pcmk_str_is_infinity("+infinity")); - g_assert_false(pcmk_str_is_infinity("Infinity")); - g_assert_false(pcmk_str_is_infinity("+Infinity")); + assert_false(pcmk_str_is_infinity("infinity")); + assert_false(pcmk_str_is_infinity("+infinity")); + assert_false(pcmk_str_is_infinity("Infinity")); + assert_false(pcmk_str_is_infinity("+Infinity")); } static void -added_whitespace_fails(void) +added_whitespace_fails(void **state) { - g_assert_false(pcmk_str_is_infinity(" INFINITY")); - g_assert_false(pcmk_str_is_infinity("INFINITY ")); - g_assert_false(pcmk_str_is_infinity(" INFINITY ")); - g_assert_false(pcmk_str_is_infinity("+ INFINITY")); + assert_false(pcmk_str_is_infinity(" INFINITY")); + assert_false(pcmk_str_is_infinity("INFINITY ")); + assert_false(pcmk_str_is_infinity(" INFINITY ")); + assert_false(pcmk_str_is_infinity("+ INFINITY")); } static void -empty_str_fails(void) +empty_str_fails(void **state) { - g_assert_false(pcmk_str_is_infinity(NULL)); - g_assert_false(pcmk_str_is_infinity("")); + assert_false(pcmk_str_is_infinity(NULL)); + assert_false(pcmk_str_is_infinity("")); } static void -minus_infinity_fails(void) +minus_infinity_fails(void **state) { - g_assert_false(pcmk_str_is_infinity("-INFINITY")); + assert_false(pcmk_str_is_infinity("-INFINITY")); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(uppercase_str_passes), + cmocka_unit_test(mixed_case_str_fails), + cmocka_unit_test(added_whitespace_fails), + cmocka_unit_test(empty_str_fails), + cmocka_unit_test(minus_infinity_fails), + }; - g_test_add_func("/common/utils/infinity/uppercase", uppercase_str_passes); - g_test_add_func("/common/utils/infinity/mixed_case", mixed_case_str_fails); - g_test_add_func("/common/utils/infinity/whitespace", added_whitespace_fails); - g_test_add_func("/common/utils/infinity/empty", empty_str_fails); - g_test_add_func("/common/utils/infinity/minus_infinity", minus_infinity_fails); - - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c b/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c index 9daf1100e0..f321ad4b04 100644 --- a/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c +++ b/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c @@ -1,62 +1,65 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include +#include +#include +#include +#include +#include static void -uppercase_str_passes(void) +uppercase_str_passes(void **state) { - g_assert_true(pcmk_str_is_minus_infinity("-INFINITY")); + assert_true(pcmk_str_is_minus_infinity("-INFINITY")); } static void -mixed_case_str_fails(void) +mixed_case_str_fails(void **state) { - g_assert_false(pcmk_str_is_minus_infinity("-infinity")); - g_assert_false(pcmk_str_is_minus_infinity("-Infinity")); + assert_false(pcmk_str_is_minus_infinity("-infinity")); + assert_false(pcmk_str_is_minus_infinity("-Infinity")); } static void -added_whitespace_fails(void) +added_whitespace_fails(void **state) { - g_assert_false(pcmk_str_is_minus_infinity(" -INFINITY")); - g_assert_false(pcmk_str_is_minus_infinity("-INFINITY ")); - g_assert_false(pcmk_str_is_minus_infinity(" -INFINITY ")); - g_assert_false(pcmk_str_is_minus_infinity("- INFINITY")); + assert_false(pcmk_str_is_minus_infinity(" -INFINITY")); + assert_false(pcmk_str_is_minus_infinity("-INFINITY ")); + assert_false(pcmk_str_is_minus_infinity(" -INFINITY ")); + assert_false(pcmk_str_is_minus_infinity("- INFINITY")); } static void -empty_str_fails(void) +empty_str_fails(void **state) { - g_assert_false(pcmk_str_is_minus_infinity(NULL)); - g_assert_false(pcmk_str_is_minus_infinity("")); + assert_false(pcmk_str_is_minus_infinity(NULL)); + assert_false(pcmk_str_is_minus_infinity("")); } static void -infinity_fails(void) +infinity_fails(void **state) { - g_assert_false(pcmk_str_is_minus_infinity("INFINITY")); + assert_false(pcmk_str_is_minus_infinity("INFINITY")); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); + const struct CMUnitTest tests[] = { + cmocka_unit_test(uppercase_str_passes), + cmocka_unit_test(mixed_case_str_fails), + cmocka_unit_test(added_whitespace_fails), + cmocka_unit_test(empty_str_fails), + cmocka_unit_test(infinity_fails), + }; - g_test_add_func("/common/utils/minus_infinity/uppercase", uppercase_str_passes); - g_test_add_func("/common/utils/minus_infinity/mixed_case", mixed_case_str_fails); - g_test_add_func("/common/utils/minus_infinity/whitespace", added_whitespace_fails); - g_test_add_func("/common/utils/minus_infinity/empty", empty_str_fails); - g_test_add_func("/common/utils/minus_infinity/infinity", infinity_fails); - - return g_test_run(); + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/xpath/Makefile.am b/lib/common/tests/xpath/Makefile.am index 7a53683b24..a4cba33986 100644 --- a/lib/common/tests/xpath/Makefile.am +++ b/lib/common/tests/xpath/Makefile.am @@ -1,29 +1,17 @@ # # Copyright 2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -LDADD = $(top_builddir)/lib/common/libcrmcommon.la +LDADD = $(top_builddir)/lib/common/libcrmcommon.la -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pcmk__xpath_node_id_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = pcmk__xpath_node_id_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/xpath/pcmk__xpath_node_id_test.c b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c index c7176daf6c..718f92db7b 100644 --- a/lib/common/tests/xpath/pcmk__xpath_node_id_test.c +++ b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c @@ -1,50 +1,60 @@ /* * Copyright 2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include +#include +#include +#include +#include +#include +#include +#include + static void -empty_input(void) { - g_assert_null(pcmk__xpath_node_id(NULL, "lrm")); - g_assert_null(pcmk__xpath_node_id("", "lrm")); - g_assert_null(pcmk__xpath_node_id("/blah/blah", NULL)); - g_assert_null(pcmk__xpath_node_id("/blah/blah", "")); - g_assert_null(pcmk__xpath_node_id(NULL, NULL)); +empty_input(void **state) { + assert_null(pcmk__xpath_node_id(NULL, "lrm")); + assert_null(pcmk__xpath_node_id("", "lrm")); + assert_null(pcmk__xpath_node_id("/blah/blah", NULL)); + assert_null(pcmk__xpath_node_id("/blah/blah", "")); + assert_null(pcmk__xpath_node_id(NULL, NULL)); } static void -not_present(void) { - g_assert_null(pcmk__xpath_node_id("/some/xpath/string[@id='xyz']", "lrm")); - g_assert_null(pcmk__xpath_node_id("/some/xpath/containing[@id='lrm']", "lrm")); +not_present(void **state) { + assert_null(pcmk__xpath_node_id("/some/xpath/string[@id='xyz']", "lrm")); + assert_null(pcmk__xpath_node_id("/some/xpath/containing[@id='lrm']", "lrm")); } static void -present(void) { +present(void **state) { char *s = NULL; s = pcmk__xpath_node_id("/some/xpath/containing/lrm[@id='xyz']", "lrm"); - g_assert_cmpint(strcmp(s, "xyz"), ==, 0); + assert_int_equal(strcmp(s, "xyz"), 0); free(s); s = pcmk__xpath_node_id("/some/other/lrm[@id='xyz']/xpath", "lrm"); - g_assert_cmpint(strcmp(s, "xyz"), ==, 0); + assert_int_equal(strcmp(s, "xyz"), 0); free(s); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/common/xpath/node_id/empty_input", empty_input); - g_test_add_func("/common/xpath/node_id/not_present", not_present); - g_test_add_func("/common/xpath/node_id/present", present); - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(empty_input), + cmocka_unit_test(not_present), + cmocka_unit_test(present), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/rules/Makefile.am b/lib/pengine/tests/rules/Makefile.am index 9195f8dad1..fdf2b3ae09 100644 --- a/lib/pengine/tests/rules/Makefile.am +++ b/lib/pengine/tests/rules/Makefile.am @@ -1,30 +1,19 @@ # -# Copyright 2020 the Pacemaker project contributors +# Copyright 2020-2021 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include LDADD = $(top_builddir)/lib/common/libcrmcommon.la \ - $(top_builddir)/lib/pengine/libpe_rules.la + $(top_builddir)/lib/pengine/libpe_rules.la \ + -lcmocka -include $(top_srcdir)/mk/glib-tap.mk +include $(top_srcdir)/mk/tap.mk -# Add each test program here. Each test should be written as a little standalone -# program using the glib unit testing functions. See the documentation for more -# information. -# -# https://developer.gnome.org/glib/unstable/glib-Testing.html -# # Add "_test" to the end of all test program names to simplify .gitignore. -test_programs = pe_cron_range_satisfied_test - -# If any extra data needs to be added to the source distribution, add it to the -# following list. -dist_test_data = +check_PROGRAMS = pe_cron_range_satisfied_test -# If any extra data needs to be used by tests but should not be added to the -# source distribution, add it to the following list. -test_data = +TESTS = $(check_PROGRAMS) diff --git a/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c b/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c index 9c56c0e777..4494d09639 100644 --- a/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c +++ b/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c @@ -1,133 +1,141 @@ /* * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include #include +#include +#include +#include +#include +#include + static void run_one_test(const char *t, const char *x, int expected) { crm_time_t *tm = crm_time_new(t); xmlNodePtr xml = string2xml(x); - g_assert_cmpint(pe_cron_range_satisfied(tm, xml), ==, expected); + assert_int_equal(pe_cron_range_satisfied(tm, xml), expected); crm_time_free(tm); free_xml(xml); } static void -no_time_given(void) { - g_assert_cmpint(pe_cron_range_satisfied(NULL, NULL), ==, pcmk_rc_op_unsatisfied); +no_time_given(void **state) { + assert_int_equal(pe_cron_range_satisfied(NULL, NULL), pcmk_rc_op_unsatisfied); } static void -any_time_satisfies_empty_spec(void) { +any_time_satisfies_empty_spec(void **state) { crm_time_t *tm = crm_time_new(NULL); - g_assert_cmpint(pe_cron_range_satisfied(tm, NULL), ==, pcmk_rc_ok); + assert_int_equal(pe_cron_range_satisfied(tm, NULL), pcmk_rc_ok); crm_time_free(tm); } static void -time_satisfies_year_spec(void) { +time_satisfies_year_spec(void **state) { run_one_test("2020-01-01", "", pcmk_rc_ok); } static void -time_after_year_spec(void) { +time_after_year_spec(void **state) { run_one_test("2020-01-01", "", pcmk_rc_after_range); } static void -time_satisfies_year_range(void) { +time_satisfies_year_range(void **state) { run_one_test("2020-01-01", "", pcmk_rc_ok); } static void -time_before_year_range(void) { +time_before_year_range(void **state) { run_one_test("2000-01-01", "", pcmk_rc_before_range); } static void -time_after_year_range(void) { +time_after_year_range(void **state) { run_one_test("2020-01-01", "", pcmk_rc_after_range); } static void -range_without_start_year_passes(void) { +range_without_start_year_passes(void **state) { run_one_test("2010-01-01", "", pcmk_rc_ok); } static void -range_without_end_year_passes(void) { +range_without_end_year_passes(void **state) { run_one_test("2010-01-01", "", pcmk_rc_ok); run_one_test("2000-10-01", "", pcmk_rc_ok); } static void -yeardays_satisfies(void) { +yeardays_satisfies(void **state) { run_one_test("2020-01-30", "", pcmk_rc_ok); } static void -time_after_yeardays_spec(void) { +time_after_yeardays_spec(void **state) { run_one_test("2020-02-15", "", pcmk_rc_after_range); } static void -yeardays_feb_29_satisfies(void) { +yeardays_feb_29_satisfies(void **state) { run_one_test("2016-02-29", "", pcmk_rc_ok); } static void -exact_ymd_satisfies(void) { +exact_ymd_satisfies(void **state) { run_one_test("2001-12-31", "", pcmk_rc_ok); } static void -range_in_month_satisfies(void) { +range_in_month_satisfies(void **state) { run_one_test("2001-06-10", "", pcmk_rc_ok); } static void -exact_ymd_after_range(void) { +exact_ymd_after_range(void **state) { run_one_test("2001-12-31", "", pcmk_rc_after_range); } static void -time_after_monthdays_range(void) { +time_after_monthdays_range(void **state) { run_one_test("2001-06-10", "", pcmk_rc_before_range); } int main(int argc, char **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/pengine/rules/cron_range/no_time_given", no_time_given); - g_test_add_func("/pengine/rules/cron_range/empty_spec", any_time_satisfies_empty_spec); - g_test_add_func("/pengine/rules/cron_range/year/time_satisfies", time_satisfies_year_spec); - g_test_add_func("/pengine/rules/cron_range/year/time_after", time_after_year_spec); - g_test_add_func("/pengine/rules/cron_range/range/time_satisfies_year", time_satisfies_year_range); - g_test_add_func("/pengine/rules/cron_range/range/time_before_year", time_before_year_range); - g_test_add_func("/pengine/rules/cron_range/range/time_after_year", time_after_year_range); - g_test_add_func("/pengine/rules/cron_range/range/no_start_year_passes", range_without_start_year_passes); - g_test_add_func("/pengine/rules/cron_range/range/no_end_year_passes", range_without_end_year_passes); - - g_test_add_func("/pengine/rules/cron_range/yeardays/satisfies", yeardays_satisfies); - g_test_add_func("/pengine/rules/cron_range/yeardays/time_after", time_after_yeardays_spec); - g_test_add_func("/pengine/rules/cron_range/yeardays/feb_29_sasitfies", yeardays_feb_29_satisfies); - - g_test_add_func("/pengine/rules/cron_range/exact/ymd_satisfies", exact_ymd_satisfies); - g_test_add_func("/pengine/rules/cron_range/range/in_month_satisfies", range_in_month_satisfies); - g_test_add_func("/pengine/rules/cron_range/exact/ymd_after_range", exact_ymd_after_range); - g_test_add_func("/pengine/rules/cron_range/range/in_month_after", time_after_monthdays_range); - return g_test_run(); + const struct CMUnitTest tests[] = { + cmocka_unit_test(no_time_given), + cmocka_unit_test(any_time_satisfies_empty_spec), + cmocka_unit_test(time_satisfies_year_spec), + cmocka_unit_test(time_after_year_spec), + cmocka_unit_test(time_satisfies_year_range), + cmocka_unit_test(time_before_year_range), + cmocka_unit_test(time_after_year_range), + cmocka_unit_test(range_without_start_year_passes), + cmocka_unit_test(range_without_end_year_passes), + + cmocka_unit_test(yeardays_satisfies), + cmocka_unit_test(time_after_yeardays_spec), + cmocka_unit_test(yeardays_feb_29_satisfies), + + cmocka_unit_test(exact_ymd_satisfies), + cmocka_unit_test(range_in_month_satisfies), + cmocka_unit_test(exact_ymd_after_range), + cmocka_unit_test(time_after_monthdays_range), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/m4/glibtests.m4 b/m4/glibtests.m4 deleted file mode 100644 index 581726a517..0000000000 --- a/m4/glibtests.m4 +++ /dev/null @@ -1,31 +0,0 @@ -# Increment this whenever this file is changed. -#serial 1 - -dnl GLIB_TESTS -dnl - -AC_DEFUN([GLIB_TESTS], -[ - AC_ARG_ENABLE(installed-tests, - AS_HELP_STRING([--enable-installed-tests], - [Enable installation of some test cases]), - [case ${enableval} in - yes) ENABLE_INSTALLED_TESTS="1" ;; - no) ENABLE_INSTALLED_TESTS="" ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;; - esac]) - AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1") - AC_ARG_ENABLE(always-build-tests, - AS_HELP_STRING([--enable-always-build-tests], - [Enable always building tests during 'make all']), - [case ${enableval} in - yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;; - no) ENABLE_ALWAYS_BUILD_TESTS="" ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;; - esac]) - AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1") - if test "$ENABLE_INSTALLED_TESTS" = "1"; then - AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME) - AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME) - fi -]) diff --git a/mk/glib-tap.mk b/mk/glib-tap.mk deleted file mode 100644 index 407f868723..0000000000 --- a/mk/glib-tap.mk +++ /dev/null @@ -1,136 +0,0 @@ -# GLIB - Library of useful C routines - -AM_TESTS_ENVIRONMENT= \ - G_TEST_SRCDIR="$(abs_srcdir)" \ - G_TEST_BUILDDIR="$(abs_builddir)" \ - G_DEBUG=gc-friendly \ - MALLOC_CHECK_=2 \ - MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) -LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tests/tap-driver.sh -LOG_COMPILER = $(top_srcdir)/tests/tap-test - -NULL = - -# initialize variables for unconditional += appending -BUILT_SOURCES = -BUILT_EXTRA_DIST = -CLEANFILES = *.log *.trs -DISTCLEANFILES = -MAINTAINERCLEANFILES = -EXTRA_DIST = -TESTS = - -installed_test_LTLIBRARIES = -installed_test_PROGRAMS = -installed_test_SCRIPTS = -nobase_installed_test_DATA = - -noinst_LTLIBRARIES = -noinst_PROGRAMS = -noinst_SCRIPTS = -noinst_DATA = - -check_LTLIBRARIES = -check_PROGRAMS = -check_SCRIPTS = -check_DATA = - -# We support a fairly large range of possible variables. It is expected that all types of files in a test suite -# will belong in exactly one of the following variables. -# -# First, we support the usual automake suffixes, but in lowercase, with the customary meaning: -# -# test_programs, test_scripts, test_data, test_ltlibraries -# -# The above are used to list files that are involved in both uninstalled and installed testing. The -# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite. -# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is -# installed in the same way as it appears in the package layout. -# -# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled', -# like so: -# -# installed_test_programs, uninstalled_test_programs -# installed_test_scripts, uninstalled_test_scripts -# installed_test_data, uninstalled_test_data -# installed_test_ltlibraries, uninstalled_test_ltlibraries -# -# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts -# that should not themselves be run as testcases (but exist to be used from other testcases): -# -# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs -# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts -# -# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data -# file automatically end up in the tarball. -# -# dist_test_scripts, dist_test_data, dist_test_extra_scripts -# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts -# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts -# -# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the -# standard automake convention of not disting programs scripts or data by default. -# -# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted -# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under -# gtester. That's a bit strange for scripts, but it's possible. - -TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \ - $(dist_test_scripts) $(dist_uninstalled_test_scripts) - -# Note: build even the installed-only targets during 'make check' to ensure that they still work. -# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to -# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were -# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'. -all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \ - $(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs) -all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \ - $(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts) -all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \ - $(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts) -all_test_scripts += $(all_dist_test_scripts) -EXTRA_DIST += $(all_dist_test_scripts) -all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data) -all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data) -all_test_data += $(all_dist_test_data) -EXTRA_DIST += $(all_dist_test_data) -all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries) - -if ENABLE_ALWAYS_BUILD_TESTS -noinst_LTLIBRARIES += $(all_test_ltlibs) -noinst_PROGRAMS += $(all_test_programs) -noinst_SCRIPTS += $(all_test_scripts) -noinst_DATA += $(all_test_data) -else -check_LTLIBRARIES += $(all_test_ltlibs) -check_PROGRAMS += $(all_test_programs) -check_SCRIPTS += $(all_test_scripts) -check_DATA += $(all_test_data) -endif - -if ENABLE_INSTALLED_TESTS -installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \ - $(test_extra_programs) $(installed_test_extra_programs) -installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \ - $(test_extra_scripts) $(installed_test_extra_scripts) -installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \ - $(dist_installed_test_scripts) $(dist_installed_test_extra_scripts) -nobase_installed_test_DATA += $(test_data) $(installed_test_data) -nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data) -installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries) -installed_testcases = $(test_programs) $(installed_test_programs) \ - $(test_scripts) $(installed_test_scripts) \ - $(dist_test_scripts) $(dist_installed_test_scripts) - -installed_test_meta_DATA = $(installed_testcases:=.test) - -%.test: %$(EXEEXT) Makefile - $(AM_V_GEN) ($(MKDIR_P) $(@D); \ - echo '[Test]' > $@.tmp; \ - echo 'Type=session' >> $@.tmp; \ - echo 'Exec=$(installed_testdir)/$(notdir $<) --tap' >> $@.tmp; \ - echo 'Output=TAP' >> $@.tmp; \ - mv $@.tmp $@) - -CLEANFILES += $(installed_test_meta_DATA) -endif diff --git a/mk/tap.mk b/mk/tap.mk new file mode 100644 index 0000000000..3c531d549e --- /dev/null +++ b/mk/tap.mk @@ -0,0 +1,16 @@ +# +# Copyright 2021 the Pacemaker project contributors +# +# The version control history for this file may have further details. +# +# This source code is licensed under the GNU General Public License version 2 +# or later (GPLv2+) WITHOUT ANY WARRANTY. +# + +AM_TESTS_ENVIRONMENT= \ + G_DEBUG=gc-friendly \ + MALLOC_CHECK_=2 \ + MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tests/tap-driver.sh +LOG_COMPILER = $(top_srcdir)/tests/tap-test +CLEANFILES = *.log *.trs diff --git a/rpm/pacemaker.spec.in b/rpm/pacemaker.spec.in index 0c569b9ca5..a2e48bf06f 100644 --- a/rpm/pacemaker.spec.in +++ b/rpm/pacemaker.spec.in @@ -1,916 +1,919 @@ # User-configurable globals and defines to control package behavior # (these should not test {with X} values, which are declared later) ## User and group to use for nonprivileged services %global uname hacluster %global gname haclient ## Where to install Pacemaker documentation %if 0%{?suse_version} > 0 %global pcmk_docdir %{_docdir}/%{name}-%{version} %else %if 0%{?rhel} > 7 %global pcmk_docdir %{_docdir}/%{name}-doc %else %global pcmk_docdir %{_docdir}/%{name} %endif %endif ## GitHub entity that distributes source (for ease of using a fork) %global github_owner ClusterLabs ## Where bug reports should be submitted ## Leave bug_url undefined to use ClusterLabs default, others define it here ## What to use as the OCF resource agent root directory %global ocf_root %{_prefix}/lib/ocf ## Upstream pacemaker version, and its package version (specversion ## can be incremented to build packages reliably considered "newer" ## than previously built packages with the same pcmkversion) %global pcmkversion X.Y.Z %global specversion 1 ## Upstream commit (full commit ID, abbreviated commit ID, or tag) to build %global commit HEAD ## Since git v2.11, the extent of abbreviation is autoscaled by default ## (used to be constant of 7), so we need to convey it for non-tags, too. %if (0%{?fedora} >= 26) || (0%{?rhel} >= 9) %global commit_abbrev 9 %else %global commit_abbrev 7 %endif # Define conditionals so that "rpmbuild --with " and # "rpmbuild --without " can enable and disable specific features ## Add option to enable support for stonith/external fencing agents %bcond_with stonithd ## Add option for whether to support storing sensitive information outside CIB %if (0%{?fedora} && 0%{?fedora} <= 33) || (0%{?rhel} && 0%{?rhel} <= 8) %bcond_with cibsecrets %else %bcond_without cibsecrets %endif ## Add option to create binaries suitable for use with profiling tools %bcond_with profiling ## Add option to create binaries with coverage analysis %bcond_with coverage ## Add option to skip (or enable, on RHEL) generating documentation ## (the build tools aren't available everywhere) %if 0%{?rhel} %bcond_with doc %else %bcond_without doc %endif ## Add option to default to start-up synchronization with SBD. ## ## If enabled, SBD *MUST* be built to default similarly, otherwise data ## corruption could occur. Building both Pacemaker and SBD to default ## to synchronization improves safety, without requiring higher-level tools ## to be aware of the setting or requiring users to modify configurations ## after upgrading to versions that support synchronization. %if 0%{?rhel} && 0%{?rhel} > 8 %bcond_without sbd_sync %else %bcond_with sbd_sync %endif ## Add option to prefix package version with "0." ## (so later "official" packages will be considered updates) %bcond_with pre_release ## Add option to ship Upstart job files %bcond_with upstart_job ## Add option to turn off hardening of libraries and daemon executables %bcond_without hardening ## Add option to enable (or disable, on RHEL 8) links for legacy daemon names %if 0%{?rhel} && 0%{?rhel} <= 8 %bcond_without legacy_links %else %bcond_with legacy_links %endif # Define globals for convenient use later ## Workaround to use parentheses in other globals %global lparen ( %global rparen ) ## Whether this is a tagged release (final or release candidate) %define tag_release %(c=%{commit}; case ${c} in Pacemaker-*%{rparen} echo 1 ;; *%{rparen} echo 0 ;; esac) ## Portion of export/dist tarball name after "pacemaker-", and release version %if 0%{tag_release} %define archive_version %(c=%{commit}; echo ${c:10}) %define archive_github_url %{commit}#/%{name}-%{archive_version}.tar.gz %define pcmk_release %(c=%{commit}; case $c in *-rc[[:digit:]]*%{rparen} echo 0.%{specversion}.${c: -3} ;; *%{rparen} echo %{specversion} ;; esac) %else %define archive_version %(c=%{commit}; echo ${c:0:%{commit_abbrev}}) %define archive_github_url %{archive_version}#/%{name}-%{archive_version}.tar.gz %if %{with pre_release} %define pcmk_release 0.%{specversion}.%{archive_version}.git %else %define pcmk_release %{specversion}.%{archive_version}.git %endif %endif ## Whether this platform defaults to using systemd as an init system ## (needs to be evaluated prior to BuildRequires being enumerated and ## installed as it's intended to conditionally select some of these, and ## for that there are only few indicators with varying reliability: ## - presence of systemd-defined macros (when building in a full-fledged ## environment, which is not the case with ordinary mock-based builds) ## - systemd-aware rpm as manifested with the presence of particular ## macro (rpm itself will trivially always be present when building) ## - existence of /usr/lib/os-release file, which is something heavily ## propagated by systemd project ## - when not good enough, there's always a possibility to check ## particular distro-specific macros (incl. version comparison) %define systemd_native (%{?_unitdir:1}%{!?_unitdir:0}%{nil \ } || %{?__transaction_systemd_inhibit:1}%{!?__transaction_systemd_inhibit:0}%{nil \ } || %(test -f /usr/lib/os-release; test $? -ne 0; echo $?)) %if 0%{?fedora} > 20 || 0%{?rhel} > 7 ## Base GnuTLS cipher priorities (presumably only the initial, required keyword) ## overridable with "rpmbuild --define 'pcmk_gnutls_priorities PRIORITY-SPEC'" %define gnutls_priorities %{?pcmk_gnutls_priorities}%{!?pcmk_gnutls_priorities:@SYSTEM} %endif %if 0%{?fedora} > 22 || 0%{?rhel} > 7 %global supports_recommends 1 %endif ## Different distros name certain packages differently ## (note: corosync libraries also differ, but all provide corosync-devel) %if 0%{?suse_version} > 0 %global pkgname_bzip2_devel libbz2-devel %global pkgname_docbook_xsl docbook-xsl-stylesheets %global pkgname_gnutls_devel libgnutls-devel %global pkgname_shadow_utils shadow %global pkgname_procps procps %global pkgname_glue_libs libglue %global pkgname_pcmk_libs lib%{name}3 %global hacluster_id 90 %else %global pkgname_libtool_devel libtool-ltdl-devel %global pkgname_libtool_devel_arch libtool-ltdl-devel%{?_isa} %global pkgname_bzip2_devel bzip2-devel %global pkgname_docbook_xsl docbook-style-xsl %global pkgname_gnutls_devel gnutls-devel %global pkgname_shadow_utils shadow-utils %global pkgname_procps procps-ng %global pkgname_glue_libs cluster-glue-libs %global pkgname_pcmk_libs %{name}-libs %global hacluster_id 189 %endif ## Distro-specific configuration choices ### Use 2.0-style output when other distro packages don't support current output %if 0%{?fedora} || ( 0%{?rhel} && 0%{?rhel} <= 8 ) %global compat20 --enable-compat-2.0 %endif ### Default concurrent-fencing to true when distro prefers that %if 0%{?rhel} >= 7 %global concurrent_fencing --with-concurrent-fencing-default=true %endif ### Default resource-stickiness to 1 when distro prefers that %if 0%{?fedora} >= 35 || 0%{?rhel} >= 9 %global resource_stickiness --with-resource-stickiness-default=1 %endif # Python-related definitions ## Turn off auto-compilation of Python files outside Python specific paths, ## so there's no risk that unexpected "__python" macro gets picked to do the ## RPM-native byte-compiling there (only "{_datadir}/pacemaker/tests" affected) ## -- distro-dependent tricks or automake's fallback to be applied there %if %{defined _python_bytecompile_extra} %global _python_bytecompile_extra 0 %else ### the statement effectively means no RPM-native byte-compiling will occur at ### all, so distro-dependent tricks for Python-specific packages to be applied %global __os_install_post %(echo '%{__os_install_post}' | { sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g'; }) %endif ## Prefer Python 3 definitions explicitly, in case 2 is also available %if %{defined __python3} %global python_name python3 %global python_path %{__python3} %define python_site %{?python3_sitelib}%{!?python3_sitelib:%( %{python_path} -c 'from distutils.sysconfig import get_python_lib as gpl; print(gpl(1))' 2>/dev/null)} %else %if %{defined python_version} %global python_name python%(echo %{python_version} | cut -d'.' -f1) %define python_path %{?__python}%{!?__python:/usr/bin/%{python_name}} %else %global python_name python %global python_path %{?__python}%{!?__python:/usr/bin/python%{?python_pkgversion}} %endif %define python_site %{?python_sitelib}%{!?python_sitelib:%( %{python_name} -c 'from distutils.sysconfig import get_python_lib as gpl; print(gpl(1))' 2>/dev/null)} %endif # Keep sane profiling data if requested %if %{with profiling} ## Disable -debuginfo package and stripping binaries/libraries %define debug_package %{nil} %endif Name: pacemaker Summary: Scalable High-Availability cluster resource manager Version: %{pcmkversion} Release: %{pcmk_release}%{?dist} %if %{defined _unitdir} License: GPLv2+ and LGPLv2+ %else # initscript is Revised BSD License: GPLv2+ and LGPLv2+ and BSD %endif Url: https://www.clusterlabs.org/ # Example: https://codeload.github.com/ClusterLabs/pacemaker/tar.gz/e91769e # will download pacemaker-e91769e.tar.gz # # The ending part starting with '#' is ignored by github but necessary for # rpmbuild to know what the tar archive name is. (The downloaded file will be # named correctly only for commit IDs, not tagged releases.) # # You can use "spectool -s 0 pacemaker.spec" (rpmdevtools) to show final URL. Source0: https://codeload.github.com/%{github_owner}/%{name}/tar.gz/%{archive_github_url} Requires: resource-agents Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release} Requires: %{name}-cluster-libs%{?_isa} = %{version}-%{release} Requires: %{name}-cli = %{version}-%{release} %if !%{defined _unitdir} Requires: %{pkgname_procps} Requires: psmisc %endif %{?systemd_requires} Requires: %{python_path} BuildRequires: %{python_name}-devel # Pacemaker requires a minimum libqb functionality Requires: libqb >= 0.17.0 BuildRequires: libqb-devel >= 0.17.0 # Required basic build tools BuildRequires: autoconf BuildRequires: automake BuildRequires: coreutils BuildRequires: findutils BuildRequires: gcc BuildRequires: grep BuildRequires: libtool %if %{defined pkgname_libtool_devel} BuildRequires: %{?pkgname_libtool_devel} %endif BuildRequires: make BuildRequires: pkgconfig BuildRequires: sed # Required for core functionality BuildRequires: pkgconfig(glib-2.0) >= 2.42 BuildRequires: libxml2-devel BuildRequires: libxslt-devel BuildRequires: libuuid-devel BuildRequires: %{pkgname_bzip2_devel} # Enables optional functionality BuildRequires: pkgconfig(dbus-1) BuildRequires: %{pkgname_docbook_xsl} BuildRequires: %{pkgname_gnutls_devel} BuildRequires: help2man BuildRequires: ncurses-devel BuildRequires: pam-devel +# Required for "make check" +BuildRequires: libcmocka-devel + %if %{systemd_native} BuildRequires: pkgconfig(systemd) %endif Requires: corosync >= 2.0.0 BuildRequires: corosync-devel >= 2.0.0 %if %{with stonithd} BuildRequires: %{pkgname_glue_libs}-devel %endif %if %{with doc} BuildRequires: asciidoc BuildRequires: inkscape BuildRequires: %{python_name}-sphinx %endif Provides: pcmk-cluster-manager = %{version}-%{release} Provides: pcmk-cluster-manager%{?_isa} = %{version}-%{release} # Bundled bits ## Pacemaker uses the crypto/md5-buffer module from gnulib %if 0%{?fedora} || 0%{?rhel} Provides: bundled(gnulib) %endif %description Pacemaker is an advanced, scalable High-Availability cluster resource manager. It supports more than 16 node clusters with significant capabilities for managing resources and dependencies. It will run scripts at initialization, when machines go up or down, when related resources fail and can be configured to periodically check resource health. Available rpmbuild rebuild options: --with(out) : cibsecrets coverage doc hardening pre_release profiling stonithd upstart_job %package cli License: GPLv2+ and LGPLv2+ Summary: Command line tools for controlling Pacemaker clusters Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release} %if 0%{?supports_recommends} Recommends: pcmk-cluster-manager = %{version}-%{release} # For crm_report Recommends: tar Recommends: bzip2 %endif Requires: perl-TimeDate Requires: %{pkgname_procps} Requires: psmisc Requires(post):coreutils %description cli Pacemaker is an advanced, scalable High-Availability cluster resource manager. The %{name}-cli package contains command line tools that can be used to query and control the cluster from machines that may, or may not, be part of the cluster. %package -n %{pkgname_pcmk_libs} License: GPLv2+ and LGPLv2+ Summary: Core Pacemaker libraries Requires(pre): %{pkgname_shadow_utils} Requires: %{name}-schemas = %{version}-%{release} # sbd 1.4.0+ supports the libpe_status API for pe_working_set_t Conflicts: sbd < 1.4.0 %description -n %{pkgname_pcmk_libs} Pacemaker is an advanced, scalable High-Availability cluster resource manager. The %{pkgname_pcmk_libs} package contains shared libraries needed for cluster nodes and those just running the CLI tools. %package cluster-libs License: GPLv2+ and LGPLv2+ Summary: Cluster Libraries used by Pacemaker Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release} %description cluster-libs Pacemaker is an advanced, scalable High-Availability cluster resource manager. The %{name}-cluster-libs package contains cluster-aware shared libraries needed for nodes that will form part of the cluster nodes. %package remote %if %{defined _unitdir} License: GPLv2+ and LGPLv2+ %else # initscript is Revised BSD License: GPLv2+ and LGPLv2+ and BSD %endif Summary: Pacemaker remote executor daemon for non-cluster nodes Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release} Requires: %{name}-cli = %{version}-%{release} Requires: resource-agents %if !%{defined _unitdir} Requires: %{pkgname_procps} %endif # -remote can be fully independent of systemd %{?systemd_ordering}%{!?systemd_ordering:%{?systemd_requires}} Provides: pcmk-cluster-manager = %{version}-%{release} Provides: pcmk-cluster-manager%{?_isa} = %{version}-%{release} %description remote Pacemaker is an advanced, scalable High-Availability cluster resource manager. The %{name}-remote package contains the Pacemaker Remote daemon which is capable of extending pacemaker functionality to remote nodes not running the full corosync/cluster stack. %package -n %{pkgname_pcmk_libs}-devel License: GPLv2+ and LGPLv2+ Summary: Pacemaker development package Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release} Requires: %{name}-cluster-libs%{?_isa} = %{version}-%{release} Requires: %{pkgname_bzip2_devel}%{?_isa} Requires: corosync-devel >= 2.0.0 Requires: glib2-devel%{?_isa} Requires: libqb-devel%{?_isa} %if %{defined pkgname_libtool_devel_arch} Requires: %{?pkgname_libtool_devel_arch} %endif Requires: libuuid-devel%{?_isa} Requires: libxml2-devel%{?_isa} Requires: libxslt-devel%{?_isa} %description -n %{pkgname_pcmk_libs}-devel Pacemaker is an advanced, scalable High-Availability cluster resource manager. The %{pkgname_pcmk_libs}-devel package contains headers and shared libraries for developing tools for Pacemaker. %package cts License: GPLv2+ and LGPLv2+ Summary: Test framework for cluster-related technologies like Pacemaker Requires: %{python_path} Requires: %{pkgname_pcmk_libs} = %{version}-%{release} Requires: %{name}-cli = %{version}-%{release} Requires: %{pkgname_procps} Requires: psmisc BuildArch: noarch # systemd Python bindings are a separate package in some distros %if %{defined systemd_requires} %if 0%{?fedora} > 22 || 0%{?rhel} > 7 Requires: %{python_name}-systemd %endif %endif %description cts Test framework for cluster-related technologies like Pacemaker %package doc License: CC-BY-SA-4.0 Summary: Documentation for Pacemaker BuildArch: noarch %description doc Documentation for Pacemaker. Pacemaker is an advanced, scalable High-Availability cluster resource manager. %package schemas License: GPLv2+ Summary: Schemas and upgrade stylesheets for Pacemaker BuildArch: noarch %description schemas Schemas and upgrade stylesheets for Pacemaker Pacemaker is an advanced, scalable High-Availability cluster resource manager. %prep %setup -q -n %{name}-%{archive_version} %build export systemdsystemunitdir=%{?_unitdir}%{!?_unitdir:no} %if %{with hardening} # prefer distro-provided hardening flags in case they are defined # through _hardening_{c,ld}flags macros, configure script will # use its own defaults otherwise; if such hardenings are completely # undesired, rpmbuild using "--without hardening" # (or "--define '_without_hardening 1'") export CFLAGS_HARDENED_EXE="%{?_hardening_cflags}" export CFLAGS_HARDENED_LIB="%{?_hardening_cflags}" export LDFLAGS_HARDENED_EXE="%{?_hardening_ldflags}" export LDFLAGS_HARDENED_LIB="%{?_hardening_ldflags}" %endif ./autogen.sh %{configure} \ PYTHON=%{python_path} \ %{!?with_hardening: --disable-hardening} \ %{?with_legacy_links: --enable-legacy-links} \ %{?with_profiling: --with-profiling} \ %{?with_coverage: --with-coverage} \ %{?with_cibsecrets: --with-cibsecrets} \ %{?with_sbd_sync: --with-sbd-sync-default="true"} \ %{?gnutls_priorities: --with-gnutls-priorities="%{gnutls_priorities}"} \ %{?bug_url: --with-bug-url=%{bug_url}} \ %{?ocf_root: --with-ocfdir=%{ocf_root}} \ %{?concurrent_fencing} \ %{?resource_stickiness} \ %{?compat20} \ --disable-static \ --with-initdir=%{_initrddir} \ --with-runstatedir=%{_rundir} \ --localstatedir=%{_var} \ --with-version=%{version}-%{release} %if 0%{?suse_version} >= 1200 # Fedora handles rpath removal automagically sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool %endif make %{_smp_mflags} V=1 %check make %{_smp_mflags} check { cts/cts-scheduler --run load-stopped-loop \ && cts/cts-cli \ && touch .CHECKED } 2>&1 | sed 's/[fF]ail/faiil/g' # prevent false positives in rpmlint [ -f .CHECKED ] && rm -f -- .CHECKED exit $? # TODO remove when rpm<4.14 compatibility irrelevant %install # skip automake-native Python byte-compilation, since RPM-native one (possibly # distro-confined to Python-specific directories, which is currently the only # relevant place, anyway) assures proper intrinsic alignment with wider system # (such as with py_byte_compile macro, which is concurrent Fedora/EL specific) make install \ DESTDIR=%{buildroot} V=1 docdir=%{pcmk_docdir} \ %{?_python_bytecompile_extra:%{?py_byte_compile:am__py_compile=true}} %if %{with upstart_job} mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/init install -m 644 pacemakerd/pacemaker.upstart ${RPM_BUILD_ROOT}%{_sysconfdir}/init/pacemaker.conf install -m 644 pacemakerd/pacemaker.combined.upstart ${RPM_BUILD_ROOT}%{_sysconfdir}/init/pacemaker.combined.conf install -m 644 tools/crm_mon.upstart ${RPM_BUILD_ROOT}%{_sysconfdir}/init/crm_mon.conf %endif %if %{defined _unitdir} mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/lib/rpm-state/%{name} %endif # Don't package libtool archives find %{buildroot} -name '*.la' -type f -print0 | xargs -0 rm -f # For now, don't package the servicelog-related binaries built only for # ppc64le when certain dependencies are installed. If they get more exercise by # advanced users, we can reconsider. rm -f %{buildroot}/%{_sbindir}/notifyServicelogEvent rm -f %{buildroot}/%{_sbindir}/ipmiservicelogd # Don't ship init scripts for systemd based platforms %if %{defined _unitdir} rm -f %{buildroot}/%{_initrddir}/pacemaker rm -f %{buildroot}/%{_initrddir}/pacemaker_remote %endif # Byte-compile Python sources where suitable and the distro procedures known %if %{defined py_byte_compile} %{py_byte_compile %{python_path} %{buildroot}%{_datadir}/pacemaker/tests} %if !%{defined _python_bytecompile_extra} %{py_byte_compile %{python_path} %{buildroot}%{python_site}/cts} %endif %endif %if %{with coverage} GCOV_BASE=%{buildroot}/%{_var}/lib/pacemaker/gcov mkdir -p $GCOV_BASE find . -name '*.gcno' -type f | while read F ; do D=`dirname $F` mkdir -p ${GCOV_BASE}/$D cp $F ${GCOV_BASE}/$D done %endif %post %if %{defined _unitdir} %systemd_post pacemaker.service %else /sbin/chkconfig --add pacemaker || : %endif %preun %if %{defined _unitdir} %systemd_preun pacemaker.service %else /sbin/service pacemaker stop >/dev/null 2>&1 || : if [ "$1" -eq 0 ]; then # Package removal, not upgrade /sbin/chkconfig --del pacemaker || : fi %endif %postun %if %{defined _unitdir} %systemd_postun_with_restart pacemaker.service %endif %pre remote %if %{defined _unitdir} # Stop the service before anything is touched, and remember to restart # it as one of the last actions (compared to using systemd_postun_with_restart, # this avoids suicide when sbd is in use) systemctl --quiet is-active pacemaker_remote if [ $? -eq 0 ] ; then mkdir -p %{_localstatedir}/lib/rpm-state/%{name} touch %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote systemctl stop pacemaker_remote >/dev/null 2>&1 else rm -f %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote fi %endif %post remote %if %{defined _unitdir} %systemd_post pacemaker_remote.service %else /sbin/chkconfig --add pacemaker_remote || : %endif %preun remote %if %{defined _unitdir} %systemd_preun pacemaker_remote.service %else /sbin/service pacemaker_remote stop >/dev/null 2>&1 || : if [ "$1" -eq 0 ]; then # Package removal, not upgrade /sbin/chkconfig --del pacemaker_remote || : fi %endif %postun remote %if %{defined _unitdir} # This next line is a no-op, because we stopped the service earlier, but # we leave it here because it allows us to revert to the standard behavior # in the future if desired %systemd_postun_with_restart pacemaker_remote.service # Explicitly take care of removing the flag-file(s) upon final removal if [ "$1" -eq 0 ] ; then rm -f %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote fi %endif %posttrans remote %if %{defined _unitdir} if [ -e %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote ] ; then systemctl start pacemaker_remote >/dev/null 2>&1 rm -f %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote fi %endif %post cli %if %{defined _unitdir} %systemd_post crm_mon.service %endif if [ "$1" -eq 2 ]; then # Package upgrade, not initial install: # Move any pre-2.0 logs to new location to ensure they get rotated { mv -fbS.rpmsave %{_var}/log/pacemaker.log* %{_var}/log/pacemaker \ || mv -f %{_var}/log/pacemaker.log* %{_var}/log/pacemaker } >/dev/null 2>/dev/null || : fi %preun cli %if %{defined _unitdir} %systemd_preun crm_mon.service %endif %postun cli %if %{defined _unitdir} %systemd_postun_with_restart crm_mon.service %endif %pre -n %{pkgname_pcmk_libs} getent group %{gname} >/dev/null || groupadd -r %{gname} -g %{hacluster_id} getent passwd %{uname} >/dev/null || useradd -r -g %{gname} -u %{hacluster_id} -s /sbin/nologin -c "cluster user" %{uname} exit 0 %if %{defined ldconfig_scriptlets} %ldconfig_scriptlets -n %{pkgname_pcmk_libs} %ldconfig_scriptlets cluster-libs %else %post -n %{pkgname_pcmk_libs} -p /sbin/ldconfig %postun -n %{pkgname_pcmk_libs} -p /sbin/ldconfig %post cluster-libs -p /sbin/ldconfig %postun cluster-libs -p /sbin/ldconfig %endif %files ########################################################### %config(noreplace) %{_sysconfdir}/sysconfig/pacemaker %{_sbindir}/pacemakerd %if %{defined _unitdir} %{_unitdir}/pacemaker.service %else %{_initrddir}/pacemaker %endif %exclude %{_libexecdir}/pacemaker/cts-log-watcher %exclude %{_libexecdir}/pacemaker/cts-support %exclude %{_sbindir}/pacemaker-remoted %exclude %{_sbindir}/pacemaker_remoted %{_libexecdir}/pacemaker/* %{_sbindir}/crm_attribute %{_sbindir}/crm_master %{_sbindir}/fence_legacy %{_sbindir}/fence_watchdog %doc %{_mandir}/man7/pacemaker-controld.* %doc %{_mandir}/man7/pacemaker-schedulerd.* %doc %{_mandir}/man7/pacemaker-fenced.* %doc %{_mandir}/man7/ocf_pacemaker_controld.* %doc %{_mandir}/man7/ocf_pacemaker_o2cb.* %doc %{_mandir}/man7/ocf_pacemaker_remote.* %doc %{_mandir}/man8/crm_attribute.* %doc %{_mandir}/man8/crm_master.* %doc %{_mandir}/man8/fence_legacy.* %doc %{_mandir}/man8/fence_watchdog.* %doc %{_mandir}/man8/pacemakerd.* %doc %{_datadir}/pacemaker/alerts %license licenses/GPLv2 %doc COPYING %doc ChangeLog %dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/cib %dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/pengine %{ocf_root}/resource.d/pacemaker/controld %{ocf_root}/resource.d/pacemaker/o2cb %{ocf_root}/resource.d/pacemaker/remote %if %{with upstart_job} %config(noreplace) %{_sysconfdir}/init/pacemaker.conf %config(noreplace) %{_sysconfdir}/init/pacemaker.combined.conf %endif %files cli %dir %attr (750, root, %{gname}) %{_sysconfdir}/pacemaker %config(noreplace) %{_sysconfdir}/logrotate.d/pacemaker %config(noreplace) %{_sysconfdir}/sysconfig/crm_mon %if %{defined _unitdir} %{_unitdir}/crm_mon.service %endif %if %{with upstart_job} %config(noreplace) %{_sysconfdir}/init/crm_mon.conf %endif %{_sbindir}/attrd_updater %{_sbindir}/cibadmin %if %{with cibsecrets} %{_sbindir}/cibsecret %endif %{_sbindir}/crm_diff %{_sbindir}/crm_error %{_sbindir}/crm_failcount %{_sbindir}/crm_mon %{_sbindir}/crm_node %{_sbindir}/crm_resource %{_sbindir}/crm_rule %{_sbindir}/crm_standby %{_sbindir}/crm_verify %{_sbindir}/crmadmin %{_sbindir}/iso8601 %{_sbindir}/crm_shadow %{_sbindir}/crm_simulate %{_sbindir}/crm_report %{_sbindir}/crm_ticket %{_sbindir}/stonith_admin # "dirname" is owned by -schemas, which is a prerequisite %{_datadir}/pacemaker/report.collector %{_datadir}/pacemaker/report.common # XXX "dirname" is not owned by any prerequisite %{_datadir}/snmp/mibs/PCMK-MIB.txt %exclude %{ocf_root}/resource.d/pacemaker/controld %exclude %{ocf_root}/resource.d/pacemaker/o2cb %exclude %{ocf_root}/resource.d/pacemaker/remote %dir %{ocf_root} %dir %{ocf_root}/resource.d %{ocf_root}/resource.d/pacemaker %doc %{_mandir}/man7/* %exclude %{_mandir}/man7/pacemaker-controld.* %exclude %{_mandir}/man7/pacemaker-schedulerd.* %exclude %{_mandir}/man7/pacemaker-fenced.* %exclude %{_mandir}/man7/ocf_pacemaker_controld.* %exclude %{_mandir}/man7/ocf_pacemaker_o2cb.* %exclude %{_mandir}/man7/ocf_pacemaker_remote.* %doc %{_mandir}/man8/* %exclude %{_mandir}/man8/crm_attribute.* %exclude %{_mandir}/man8/crm_master.* %exclude %{_mandir}/man8/fence_legacy.* %exclude %{_mandir}/man8/fence_watchdog.* %exclude %{_mandir}/man8/pacemakerd.* %exclude %{_mandir}/man8/pacemaker-remoted.* %license licenses/GPLv2 %doc COPYING %doc ChangeLog %dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker %dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/blackbox %dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/cores %dir %attr (770, %{uname}, %{gname}) %{_var}/log/pacemaker %dir %attr (770, %{uname}, %{gname}) %{_var}/log/pacemaker/bundles %files -n %{pkgname_pcmk_libs} %{_libdir}/libcib.so.* %{_libdir}/liblrmd.so.* %{_libdir}/libcrmservice.so.* %{_libdir}/libcrmcommon.so.* %{_libdir}/libpe_status.so.* %{_libdir}/libpe_rules.so.* %{_libdir}/libpacemaker.so.* %{_libdir}/libstonithd.so.* %license licenses/LGPLv2.1 %doc COPYING %doc ChangeLog %files cluster-libs %{_libdir}/libcrmcluster.so.* %license licenses/LGPLv2.1 %doc COPYING %doc ChangeLog %files remote %config(noreplace) %{_sysconfdir}/sysconfig/pacemaker %if %{defined _unitdir} # state directory is shared between the subpackets # let rpm take care of removing it once it isn't # referenced anymore and empty %ghost %dir %{_localstatedir}/lib/rpm-state/%{name} %{_unitdir}/pacemaker_remote.service %else %{_initrddir}/pacemaker_remote %endif %{_sbindir}/pacemaker-remoted %{_sbindir}/pacemaker_remoted %{_mandir}/man8/pacemaker-remoted.* %license licenses/GPLv2 %doc COPYING %doc ChangeLog %files doc %doc %{pcmk_docdir} %license licenses/CC-BY-SA-4.0 %files cts %{python_site}/cts %{_datadir}/pacemaker/tests %{_libexecdir}/pacemaker/cts-log-watcher %{_libexecdir}/pacemaker/cts-support %license licenses/GPLv2 %doc COPYING %doc ChangeLog %files -n %{pkgname_pcmk_libs}-devel %{_includedir}/pacemaker %{_libdir}/*.so %if %{with coverage} %{_var}/lib/pacemaker/gcov %endif %{_libdir}/pkgconfig/*.pc %license licenses/LGPLv2.1 %doc COPYING %doc ChangeLog %files schemas %license licenses/GPLv2 %dir %{_datadir}/pacemaker %{_datadir}/pacemaker/*.rng %{_datadir}/pacemaker/*.xsl %{_datadir}/pacemaker/api %{_datadir}/pkgconfig/pacemaker-schemas.pc %changelog * PACKAGE_DATE ClusterLabs PACKAGE_VERSION-1 - See included ChangeLog file for details