summaryrefslogtreecommitdiffstats
path: root/bindings/rust/tests
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/rust/tests')
-rw-r--r--bindings/rust/tests/Cargo.toml.in36
-rw-r--r--bindings/rust/tests/Makefile.am26
-rw-r--r--bindings/rust/tests/Makefile.in625
-rw-r--r--bindings/rust/tests/build.rs.in22
-rw-r--r--bindings/rust/tests/src/bin/cfg-test.rs135
-rw-r--r--bindings/rust/tests/src/bin/cmap-test.rs195
-rw-r--r--bindings/rust/tests/src/bin/cpg-test.rs142
-rw-r--r--bindings/rust/tests/src/bin/quorum-test.rs83
-rw-r--r--bindings/rust/tests/src/bin/votequorum-test.rs117
9 files changed, 1381 insertions, 0 deletions
diff --git a/bindings/rust/tests/Cargo.toml.in b/bindings/rust/tests/Cargo.toml.in
new file mode 100644
index 0000000..1d8fabf
--- /dev/null
+++ b/bindings/rust/tests/Cargo.toml.in
@@ -0,0 +1,36 @@
+[package]
+name = "rust-corosync-tests"
+version = "@corosyncrustver@"
+authors = ["Christine Caulfield <ccaulfie@redhat.com>"]
+edition = "2021"
+
+[dependencies]
+rust-corosync = { path = ".." }
+
+[build-dependencies]
+pkg-config = "0.3"
+
+[[bin]]
+name = "cpg-test"
+test = false
+bench = false
+
+[[bin]]
+name = "quorum-test"
+test = false
+bench = false
+
+[[bin]]
+name = "votequorum-test"
+test = false
+bench = false
+
+[[bin]]
+name = "cfg-test"
+test = false
+bench = false
+
+[[bin]]
+name = "cmap-test"
+test = false
+bench = false
diff --git a/bindings/rust/tests/Makefile.am b/bindings/rust/tests/Makefile.am
new file mode 100644
index 0000000..a8ac087
--- /dev/null
+++ b/bindings/rust/tests/Makefile.am
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+#
+# Author: Christine Caulfield <ccaulfie@redhat.com>
+#
+# This software licensed under GPL-2.0+
+#
+
+MAINTAINERCLEANFILES = Makefile.in
+
+include $(top_srcdir)/build-aux/rust.mk
+
+EXTRA_DIST = \
+ $(RUST_COMMON) \
+ $(RUST_SHIP_SRCS)
+
+RUST_SHIP_SRCS = src/bin/cpg-test.rs \
+ src/bin/cfg-test.rs \
+ src/bin/cmap-test.rs \
+ src/bin/quorum-test.rs \
+ src/bin/votequorum-test.rs
+
+# This will build all of the tests
+noinst_SCRIPTS = target/$(RUST_TARGET_DIR)/cpg-test
+
+clean-local: cargo-clean
diff --git a/bindings/rust/tests/Makefile.in b/bindings/rust/tests/Makefile.in
new file mode 100644
index 0000000..36cc52a
--- /dev/null
+++ b/bindings/rust/tests/Makefile.in
@@ -0,0 +1,625 @@
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+#
+# Author: Christine Caulfield <ccaulfie@redhat.com>
+#
+# This software licensed under GPL-2.0+
+#
+
+#
+# Copyright (C) 2021-2022 Red Hat, Inc. All rights reserved.
+#
+# Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
+#
+# This software licensed under GPL-2.0+
+#
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(top_srcdir)/build-aux/rust.mk $(srcdir)/Makefile.in \
+ $(srcdir)/Makefile.am $(srcdir)/Cargo.toml.in
+subdir = bindings/rust/tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/lib/libcfg.verso $(top_srcdir)/lib/libcpg.verso \
+ $(top_srcdir)/lib/libquorum.verso \
+ $(top_srcdir)/lib/libsam.verso \
+ $(top_srcdir)/lib/libvotequorum.verso \
+ $(top_srcdir)/lib/libcmap.verso $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/corosync/config.h
+CONFIG_CLEAN_FILES = Cargo.toml
+CONFIG_CLEAN_VPATH_FILES =
+SCRIPTS = $(noinst_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUGTOOL = @AUGTOOL@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASHPATH = @BASHPATH@
+BINDGEN = @BINDGEN@
+CARGO = @CARGO@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFG_SONAME = @CFG_SONAME@
+CFLAGS = @CFLAGS@
+CLIPPY = @CLIPPY@
+CMAP_SONAME = @CMAP_SONAME@
+COROSYSCONFDIR = @COROSYSCONFDIR@
+CPG_SONAME = @CPG_SONAME@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOT = @DOT@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+GROFF = @GROFF@
+INITCONFIGDIR = @INITCONFIGDIR@
+INITDDIR = @INITDDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBQB_CFLAGS = @LIBQB_CFLAGS@
+LIBQB_LIBS = @LIBQB_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LINT_FLAGS = @LINT_FLAGS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOGDIR = @LOGDIR@
+LOGROTATEDIR = @LOGROTATEDIR@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+QUORUM_SONAME = @QUORUM_SONAME@
+RANLIB = @RANLIB@
+RUSTC = @RUSTC@
+RUSTDOC = @RUSTDOC@
+RUSTFMT = @RUSTFMT@
+RUST_FLAGS = @RUST_FLAGS@
+RUST_TARGET_DIR = @RUST_TARGET_DIR@
+SAM_SONAME = @SAM_SONAME@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMPCONFIG = @SNMPCONFIG@
+SNMP_LIBS = @SNMP_LIBS@
+SOMAJOR = @SOMAJOR@
+SOMICRO = @SOMICRO@
+SOMINOR = @SOMINOR@
+SONAME = @SONAME@
+STRIP = @STRIP@
+SYSTEMDDIR = @SYSTEMDDIR@
+VERSCRIPT_LDFLAGS = @VERSCRIPT_LDFLAGS@
+VERSION = @VERSION@
+VOTEQUORUM_SONAME = @VOTEQUORUM_SONAME@
+WITH_LIST = @WITH_LIST@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+corosyncrustver = @corosyncrustver@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+knet_CFLAGS = @knet_CFLAGS@
+knet_LIBS = @knet_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libsystemd_CFLAGS = @libsystemd_CFLAGS@
+libsystemd_LIBS = @libsystemd_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nozzle_CFLAGS = @nozzle_CFLAGS@
+nozzle_LIBS = @nozzle_LIBS@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+statgrab_CFLAGS = @statgrab_CFLAGS@
+statgrab_LIBS = @statgrab_LIBS@
+statgrabge090_CFLAGS = @statgrabge090_CFLAGS@
+statgrabge090_LIBS = @statgrabge090_LIBS@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MAINTAINERCLEANFILES = Makefile.in
+RUST_COMMON = \
+ build.rs.in
+
+RUST_SRCS = $(RUST_SHIP_SRCS) $(RUST_BUILT_SRCS)
+EXTRA_DIST = \
+ $(RUST_COMMON) \
+ $(RUST_SHIP_SRCS)
+
+RUST_SHIP_SRCS = src/bin/cpg-test.rs \
+ src/bin/cfg-test.rs \
+ src/bin/cmap-test.rs \
+ src/bin/quorum-test.rs \
+ src/bin/votequorum-test.rs
+
+
+# This will build all of the tests
+noinst_SCRIPTS = target/$(RUST_TARGET_DIR)/cpg-test
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build-aux/rust.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bindings/rust/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign bindings/rust/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+$(top_srcdir)/build-aux/rust.mk:
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+Cargo.toml: $(top_builddir)/config.status $(srcdir)/Cargo.toml.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(SCRIPTS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am check check-am check-local clean clean-generic \
+ clean-libtool clean-local cscopelist-am ctags-am distclean \
+ distclean-generic distclean-libtool distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
+ uninstall-am
+
+
+%.rlib: $(RUST_SRCS) Cargo.toml build.rs
+ PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(CARGO) build $(RUST_FLAGS)
+
+%-test: $(RUST_SRCS) Cargo.toml build.rs
+ PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(CARGO) build $(RUST_FLAGS)
+
+build.rs: build.rs.in
+ rm -f $@ $@-t
+ cat $^ | sed \
+ -e 's#@ABSTOPLEVELSRC@#$(abs_top_srcdir)#g' \
+ -e 's#@ABSTOPLEVELBUILD@#$(abs_top_builddir)#g' \
+ -e 's#@LIBQBLIBS@#$(LIBQB_LIBS)#g' \
+ > $@-t
+ chmod a-w $@-t
+ mv $@-t $@
+ rm -f $@-t
+
+cargo-tree-prep:
+ if [ "${abs_builddir}" != "${abs_srcdir}" ]; then \
+ echo "Generating builddir out-of-tree rust symlinks"; \
+ src_realpath=$(shell realpath ${abs_srcdir}); \
+ for i in `find "$$src_realpath/" -type d | \
+ grep -v "${abs_builddir}" | \
+ sed -e 's#^'$$src_realpath'/##g'`; do \
+ $(MKDIR_P) ${abs_builddir}/$${i}; \
+ done; \
+ find "$$src_realpath/" -type f | { while read src; do \
+ process=no; \
+ copy=no; \
+ case $$src in \
+ ${abs_builddir}*) \
+ ;; \
+ *Makefile.*|*.in) \
+ ;; \
+ *) \
+ process=yes; \
+ ;; \
+ esac ; \
+ dst=`echo $$src | sed -e 's#^'$$src_realpath'/##g'`; \
+ if [ $${process} == yes ]; then \
+ rm -f ${abs_builddir}/$$dst; \
+ $(LN_S) $$src ${abs_builddir}/$$dst; \
+ fi; \
+ if [ $${copy} == yes ]; then \
+ rm -f ${abs_builddir}/$$dst; \
+ cp $$src ${abs_builddir}/$$dst; \
+ chmod u+w ${abs_builddir}/$$dst; \
+ fi; \
+ done; }; \
+ fi
+
+cargo-clean:
+ -$(CARGO) clean
+ rm -rf Cargo.lock $(RUST_BUILT_SRCS) build.rs target/
+ if [ "${abs_builddir}" != "${abs_srcdir}" ]; then \
+ echo "Cleaning out-of-tree rust symlinks" ; \
+ find "${abs_builddir}/" -type l -delete; \
+ find "${abs_builddir}/" -type d -empty -delete; \
+ fi
+
+clippy-check:
+ $(CARGO) clippy --verbose --all-features -- -D warnings
+
+format-check:
+ if [ "${abs_builddir}" = "${abs_srcdir}" ]; then \
+ $(CARGO) fmt --all --check; \
+ else \
+ echo "!!!!! WARNING: skipping format check !!!!!"; \
+ fi
+
+doc-check:
+ $(CARGO) doc --verbose --all-features
+
+publish-check:
+ if [ -f "${abs_srcdir}/README.md" ]; then \
+ $(CARGO) publish --dry-run; \
+ fi
+
+crates-publish:
+ if [ -f "${abs_srcdir}/README.md" ]; then \
+ bindingname=`cat Cargo.toml | grep ^name | sed -e 's#.*= ##g' -e 's#"##g'` && \
+ cratesver=`cargo search $$bindingname | grep "^$$bindingname " | sed -e 's#.*= ##g' -e 's#"##g' -e 's/\+.*//g'` && \
+ testver=`echo $(localver) | sed -e 's/\+.*//g'` && \
+ if [ "$$cratesver" != "$$testver" ]; then \
+ $(CARGO) publish; \
+ fi; \
+ fi
+
+crates-check:
+ if [ -f "${abs_srcdir}/README.md" ]; then \
+ bindingname=`cat Cargo.toml | grep ^name | sed -e 's#.*= ##g' -e 's#"##g'` && \
+ cratesver=`cargo search $$bindingname | grep "^$$bindingname " | sed -e 's#.*= ##g' -e 's#"##g' -e 's/\+.*//g'` && \
+ testver=`echo $(localver) | sed -e 's/\+.*//g'` && \
+ if [ "$$cratesver" != "$$testver" ]; then \
+ echo "!!!!! WARNING !!!!!"; \
+ echo "!!!!! WARNING: $$bindingname local version ($$testver) is higher than the current published one on crates.io ($$cratesver)"; \
+ echo "!!!!! WARNING !!!!!"; \
+ fi; \
+ fi
+
+check-local: clippy-check format-check doc-check crates-check publish-check
+
+clean-local: cargo-clean
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bindings/rust/tests/build.rs.in b/bindings/rust/tests/build.rs.in
new file mode 100644
index 0000000..39a97ba
--- /dev/null
+++ b/bindings/rust/tests/build.rs.in
@@ -0,0 +1,22 @@
+// Copyright (C) 2021-2023 Red Hat, Inc.
+//
+// All rights reserved.
+//
+// Author: Christine Caulfield (ccaulfi@redhat.com)
+//
+
+extern crate pkg_config;
+
+fn main() {
+ // Tell the compiler to use the build-tree libs & headers for compiling
+ println!("cargo:rustc-link-search=native=../../../lib/.libs/");
+ println!("cargo:rustc-link-search=native=../../../common_lib/.libs/");
+ println!("cargo:rustc-flags=@LIBQBLIBS@");
+ println!("cargo:rustc-link-lib=cpg");
+ println!("cargo:rustc-link-lib=cfg");
+ println!("cargo:rustc-link-lib=cmap");
+ println!("cargo:rustc-link-lib=quorum");
+ println!("cargo:rustc-link-lib=votequorum");
+ println!("cargo:rustc-link-lib=corosync_common");
+ println!("cargo:rustc-link-lib=qb");
+}
diff --git a/bindings/rust/tests/src/bin/cfg-test.rs b/bindings/rust/tests/src/bin/cfg-test.rs
new file mode 100644
index 0000000..cd70d38
--- /dev/null
+++ b/bindings/rust/tests/src/bin/cfg-test.rs
@@ -0,0 +1,135 @@
+// Test the CFG library. Requires that corosync is running and that we are root.
+
+extern crate rust_corosync as corosync;
+use corosync::{cfg, NodeId};
+
+use std::thread::spawn;
+
+fn dispatch_thread(handle: cfg::Handle) {
+ loop {
+ if cfg::dispatch(handle, corosync::DispatchFlags::One).is_err() {
+ return;
+ }
+ }
+}
+
+// Test the shutdown callback
+fn shutdown_check_fn(handle: &cfg::Handle, _flags: u32) {
+ println!("in shutdown callback");
+
+ // DON'T shutdown corosync - we're just testing
+ if let Err(e) = cfg::reply_to_shutdown(*handle, cfg::ShutdownReply::No) {
+ println!("Error in CFG replyto_shutdown: {e}");
+ }
+}
+
+fn main() {
+ // Initialise the callbacks data
+ let cb = cfg::Callbacks {
+ corosync_cfg_shutdown_callback_fn: Some(shutdown_check_fn),
+ };
+
+ let handle = match cfg::initialize(&cb) {
+ Ok(h) => {
+ println!("cfg initialized.");
+ h
+ }
+ Err(e) => {
+ println!("Error in CFG init: {e}");
+ return;
+ }
+ };
+
+ // Open two handles to CFG so that the second one can refuse shutdown
+ let handle2 = match cfg::initialize(&cb) {
+ Ok(h) => {
+ println!("cfg2 initialized.");
+ h
+ }
+ Err(e) => {
+ println!("Error in CFG init: {e}");
+ return;
+ }
+ };
+
+ match cfg::track_start(handle2, cfg::TrackFlags::None) {
+ Ok(_) => {
+ // Run handle2 dispatch in its own thread
+ spawn(move || dispatch_thread(handle2));
+ }
+ Err(e) => {
+ println!("Error in CFG track_start: {e}");
+ }
+ };
+
+ let local_nodeid = {
+ match cfg::local_get(handle) {
+ Ok(n) => {
+ println!("Local nodeid is {n}");
+ Some(n)
+ }
+ Err(e) => {
+ println!("Error in CFG local_get: {e}");
+ None
+ }
+ }
+ };
+
+ // Test node_status_get.
+ // node status for the local node looks odd (cos it's the loopback connection), so
+ // we try for a node ID one less or more than us just to get output that looks
+ // sensible to the user.
+ if let Some(our_nodeid) = local_nodeid {
+ let us_plus1 = NodeId::from(u32::from(our_nodeid) + 1);
+ let us_less1 = NodeId::from(u32::from(our_nodeid) - 1);
+ let mut res = cfg::node_status_get(handle, us_plus1, cfg::NodeStatusVersion::V1);
+ if let Err(e) = res {
+ println!("Error from node_status_get on nodeid {us_plus1}: {e}");
+ res = cfg::node_status_get(handle, us_less1, cfg::NodeStatusVersion::V1);
+ };
+ match res {
+ Ok(ns) => {
+ println!("Node Status for nodeid {}", ns.nodeid);
+ println!(" reachable: {}", ns.reachable);
+ println!(" remote: {}", ns.remote);
+ println!(" onwire_min: {}", ns.onwire_min);
+ println!(" onwire_max: {}", ns.onwire_max);
+ println!(" onwire_ver: {}", ns.onwire_ver);
+ for (ls_num, ls) in ns.link_status.iter().enumerate() {
+ if ls.enabled {
+ println!(" Link {ls_num}");
+ println!(" connected: {}", ls.connected);
+ println!(" mtu: {}", ls.mtu);
+ println!(" src: {}", ls.src_ipaddr);
+ println!(" dst: {}", ls.dst_ipaddr);
+ }
+ }
+ }
+ Err(e) => {
+ println!(
+ "Error in CFG node_status get: {e} (tried nodeids {us_plus1} & {us_less1})"
+ );
+ }
+ }
+ }
+
+ // This should not shutdown corosync because the callback on handle2 will refuse it.
+ match cfg::try_shutdown(handle, cfg::ShutdownFlags::Request) {
+ Ok(_) => {
+ println!("CFG try_shutdown suceeded, should return busy");
+ }
+ Err(e) => {
+ if e != corosync::CsError::CsErrBusy {
+ println!("Error in CFG try_shutdown: {e}");
+ }
+ }
+ }
+
+ // Wait for events
+ loop {
+ if cfg::dispatch(handle, corosync::DispatchFlags::One).is_err() {
+ break;
+ }
+ }
+ println!("ERROR: Corosync quit");
+}
diff --git a/bindings/rust/tests/src/bin/cmap-test.rs b/bindings/rust/tests/src/bin/cmap-test.rs
new file mode 100644
index 0000000..f435653
--- /dev/null
+++ b/bindings/rust/tests/src/bin/cmap-test.rs
@@ -0,0 +1,195 @@
+// Test the CMAP library. Requires that corosync is running and that we are root.
+
+extern crate rust_corosync as corosync;
+use corosync::cmap;
+
+fn track_notify_fn(
+ _handle: &cmap::Handle,
+ _track_handle: &cmap::TrackHandle,
+ event: cmap::TrackType,
+ key_name: &str,
+ old_value: &cmap::Data,
+ new_value: &cmap::Data,
+ user_data: u64,
+) {
+ println!("Track notify callback");
+ println!("Key: {key_name}, event: {event}, user_data: {user_data}");
+ println!(" Old value: {old_value}");
+ println!(" New value: {new_value}");
+}
+
+fn main() {
+ let handle = match cmap::initialize(cmap::Map::Icmap) {
+ Ok(h) => {
+ println!("cmap initialized.");
+ h
+ }
+ Err(e) => {
+ println!("Error in CMAP (Icmap) init: {e}");
+ return;
+ }
+ };
+
+ // Test some SETs
+ if let Err(e) = cmap::set_u32(handle, "test.test_uint32", 456) {
+ println!("Error in CMAP set_u32: {e}");
+ return;
+ };
+
+ if let Err(e) = cmap::set_i16(handle, "test.test_int16", -789) {
+ println!("Error in CMAP set_i16: {e}");
+ return;
+ };
+
+ if let Err(e) = cmap::set_number(handle, "test.test_num_1", 6809u32) {
+ println!("Error in CMAP set_number(u32): {e}");
+ return;
+ };
+
+ // NOT PI (just to avoid clippy whingeing)
+ if let Err(e) = cmap::set_number(handle, "test.test_num_2", 3.24159265) {
+ println!("Error in CMAP set_number(f32): {e}");
+ return;
+ };
+
+ if let Err(e) = cmap::set_string(handle, "test.test_string", "Hello from Rust") {
+ println!("Error in CMAP set_string: {e}");
+ return;
+ };
+
+ let test_d = cmap::Data::UInt64(0xdeadbeefbacecafe);
+ if let Err(e) = cmap::set(handle, "test.test_data", &test_d) {
+ println!("Error in CMAP set_data: {e}");
+ return;
+ };
+
+ // let test_d2 = cmap::Data::UInt32(6809);
+ let test_d2 = cmap::Data::String("Test string in data 12345".to_string());
+ if let Err(e) = cmap::set(handle, "test.test_again", &test_d2) {
+ println!("Error in CMAP set_data2: {e}");
+ return;
+ };
+
+ // get them back again
+ match cmap::get(handle, "test.test_uint32") {
+ Ok(v) => {
+ println!("GOT uint32 {v}");
+ }
+
+ Err(e) => {
+ println!("Error in CMAP get: {e}");
+ return;
+ }
+ };
+ match cmap::get(handle, "test.test_int16") {
+ Ok(v) => {
+ println!("GOT uint16 {v}");
+ }
+
+ Err(e) => {
+ println!("Error in CMAP get: {e}");
+ return;
+ }
+ };
+
+ match cmap::get(handle, "test.test_num_1") {
+ Ok(v) => {
+ println!("GOT num {v}");
+ }
+
+ Err(e) => {
+ println!("Error in CMAP get: {e}");
+ return;
+ }
+ };
+ match cmap::get(handle, "test.test_num_2") {
+ Ok(v) => {
+ println!("GOT num {v}");
+ }
+
+ Err(e) => {
+ println!("Error in CMAP get: {e}");
+ return;
+ }
+ };
+ match cmap::get(handle, "test.test_string") {
+ Ok(v) => {
+ println!("GOT string {v}");
+ }
+
+ Err(e) => {
+ println!("Error in CMAP get: {e}");
+ return;
+ }
+ };
+
+ match cmap::get(handle, "test.test_data") {
+ Ok(v) => match v {
+ cmap::Data::UInt64(u) => println!("GOT data value {u:x}"),
+ _ => println!("ERROR type was not UInt64, got {v}"),
+ },
+
+ Err(e) => {
+ println!("Error in CMAP get: {e}");
+ return;
+ }
+ };
+
+ // Test an iterator
+ match cmap::CmapIterStart::new(handle, "totem.") {
+ Ok(cmap_iter) => {
+ for i in cmap_iter {
+ println!("ITER: {i:?}");
+ }
+ println!();
+ }
+ Err(e) => {
+ println!("Error in CMAP iter start: {e}");
+ }
+ }
+
+ // Close this handle
+ if let Err(e) = cmap::finalize(handle) {
+ println!("Error in CMAP get: {e}");
+ return;
+ };
+
+ // Test notifications on the stats map
+ let handle = match cmap::initialize(cmap::Map::Stats) {
+ Ok(h) => h,
+ Err(e) => {
+ println!("Error in CMAP (Stats) init: {e}");
+ return;
+ }
+ };
+
+ let cb = cmap::NotifyCallback {
+ notify_fn: Some(track_notify_fn),
+ };
+ let _track_handle = match cmap::track_add(
+ handle,
+ "stats.srp.memb_merge_detect_tx",
+ cmap::TrackType::MODIFY | cmap::TrackType::ADD | cmap::TrackType::DELETE,
+ &cb,
+ 997u64,
+ ) {
+ Ok(th) => th,
+ Err(e) => {
+ println!("Error in CMAP track_add {e}");
+ return;
+ }
+ };
+
+ // Wait for events
+ let mut event_num = 0;
+ loop {
+ if let Err(e) = cmap::dispatch(handle, corosync::DispatchFlags::One) {
+ println!("Error from CMAP dispatch: {e}");
+ }
+ // Just do 5
+ event_num += 1;
+ if event_num > 5 {
+ break;
+ }
+ }
+}
diff --git a/bindings/rust/tests/src/bin/cpg-test.rs b/bindings/rust/tests/src/bin/cpg-test.rs
new file mode 100644
index 0000000..df83c2d
--- /dev/null
+++ b/bindings/rust/tests/src/bin/cpg-test.rs
@@ -0,0 +1,142 @@
+// Test the CPG library. Requires that corosync is running and that we are root.
+
+extern crate rust_corosync as corosync;
+use corosync::{cpg, NodeId};
+use std::str;
+
+fn deliver_fn(
+ _handle: &cpg::Handle,
+ group_name: String,
+ nodeid: NodeId,
+ pid: u32,
+ msg: &[u8],
+ msg_len: usize,
+) {
+ println!(
+ "TEST deliver_fn called for {group_name}, from nodeid/pid {nodeid}/{pid}. len={msg_len}"
+ );
+
+ // Print as text if it's valid UTF8
+ match str::from_utf8(msg) {
+ Ok(s) => println!(" {s}"),
+ Err(_) => {
+ for i in msg {
+ print!("{i:02x} ");
+ }
+ println!();
+ }
+ }
+}
+
+fn confchg_fn(
+ _handle: &cpg::Handle,
+ group_name: &str,
+ member_list: Vec<cpg::Address>,
+ left_list: Vec<cpg::Address>,
+ joined_list: Vec<cpg::Address>,
+) {
+ println!("TEST confchg_fn called for {group_name}");
+ println!(" members: {member_list:?}");
+ println!(" left: {left_list:?}");
+ println!(" joined: {joined_list:?}");
+}
+
+fn totem_confchg_fn(_handle: &cpg::Handle, ring_id: cpg::RingId, member_list: Vec<NodeId>) {
+ println!(
+ "TEST totem_confchg_fn called for {}/{}",
+ ring_id.nodeid, ring_id.seq
+ );
+ println!(" members: {member_list:?}");
+}
+
+fn main() {
+ // Initialise the model data
+ let md = cpg::ModelData::ModelV1(cpg::Model1Data {
+ flags: cpg::Model1Flags::None,
+ deliver_fn: Some(deliver_fn),
+ confchg_fn: Some(confchg_fn),
+ totem_confchg_fn: Some(totem_confchg_fn),
+ });
+
+ let handle = match cpg::initialize(&md, 99_u64) {
+ Ok(h) => h,
+ Err(e) => {
+ println!("Error in CPG init: {e}");
+ return;
+ }
+ };
+
+ if let Err(e) = cpg::join(handle, "TEST") {
+ println!("Error in CPG join: {e}");
+ return;
+ }
+
+ match cpg::local_get(handle) {
+ Ok(n) => {
+ println!("Local nodeid is {n}");
+ }
+ Err(e) => {
+ println!("Error in CPG local_get: {e}");
+ }
+ }
+
+ // Test membership_get()
+ match cpg::membership_get(handle, "TEST") {
+ Ok(m) => {
+ println!(" members: {m:?}");
+ println!();
+ }
+ Err(e) => {
+ println!("Error in CPG membership_get: {e}");
+ }
+ }
+
+ // Test context APIs
+ let set_context: u64 = 0xabcdbeefcafe;
+ if let Err(e) = cpg::context_set(handle, set_context) {
+ println!("Error in CPG context_set: {e}");
+ return;
+ }
+
+ // NOTE This will fail on 32 bit systems because void* is not u64
+ match cpg::context_get(handle) {
+ Ok(c) => {
+ if c != set_context {
+ println!("Error: context_get() returned {c:x}, context should be {set_context:x}");
+ }
+ }
+ Err(e) => {
+ println!("Error in CPG context_get: {e}");
+ }
+ }
+
+ // Test iterator
+ match cpg::CpgIterStart::new(handle, "", cpg::CpgIterType::All) {
+ Ok(cpg_iter) => {
+ for i in cpg_iter {
+ println!("ITER: {i:?}");
+ }
+ println!();
+ }
+ Err(e) => {
+ println!("Error in CPG iter start: {e}");
+ }
+ }
+
+ // We should receive our own message (at least) in the event loop
+ if let Err(e) = cpg::mcast_joined(
+ handle,
+ cpg::Guarantee::TypeAgreed,
+ &"This is a test".to_string().into_bytes(),
+ ) {
+ println!("Error in CPG mcast_joined: {e}");
+ }
+
+ // Wait for events
+ loop {
+ if cpg::dispatch(handle, corosync::DispatchFlags::One).is_err() {
+ break;
+ }
+ }
+ println!("ERROR: Corosync quit");
+}
diff --git a/bindings/rust/tests/src/bin/quorum-test.rs b/bindings/rust/tests/src/bin/quorum-test.rs
new file mode 100644
index 0000000..5797b7d
--- /dev/null
+++ b/bindings/rust/tests/src/bin/quorum-test.rs
@@ -0,0 +1,83 @@
+// Test the QUORUM library. Requires that corosync is running and that we are root.
+
+extern crate rust_corosync as corosync;
+use corosync::{quorum, NodeId};
+
+fn quorum_fn(
+ _handle: &quorum::Handle,
+ quorate: bool,
+ ring_id: quorum::RingId,
+ member_list: Vec<NodeId>,
+) {
+ println!("TEST quorum_fn called. quorate = {quorate}");
+ println!(" ring_id: {}/{}", ring_id.nodeid, ring_id.seq);
+ println!(" members: {member_list:?}");
+}
+
+fn nodelist_fn(
+ _handle: &quorum::Handle,
+ ring_id: quorum::RingId,
+ member_list: Vec<NodeId>,
+ joined_list: Vec<NodeId>,
+ left_list: Vec<NodeId>,
+) {
+ println!(
+ "TEST nodelist_fn called for {}/{}",
+ ring_id.nodeid, ring_id.seq
+ );
+ println!(" members: {member_list:?}");
+ println!(" joined: {joined_list:?}");
+ println!(" left: {left_list:?}");
+}
+
+fn main() {
+ // Initialise the model data
+ let md = quorum::ModelData::ModelV1(quorum::Model1Data {
+ flags: quorum::Model1Flags::None,
+ quorum_notification_fn: Some(quorum_fn),
+ nodelist_notification_fn: Some(nodelist_fn),
+ });
+
+ let handle = match quorum::initialize(&md, 99_u64) {
+ Ok((h, t)) => {
+ println!("Quorum initialized; type = {}", t as u32);
+ h
+ }
+ Err(e) => {
+ println!("Error in QUORUM init: {e}");
+ return;
+ }
+ };
+
+ // Test context APIs
+ let set_context: u64 = 0xabcdbeefcafe;
+ if let Err(e) = quorum::context_set(handle, set_context) {
+ println!("Error in QUORUM context_set: {e}");
+ return;
+ }
+
+ // NOTE This will fail on 32 bit systems because void* is not u64
+ match quorum::context_get(handle) {
+ Ok(c) => {
+ if c != set_context {
+ println!("Error: context_get() returned {c:x}, context should be {set_context:x}");
+ }
+ }
+ Err(e) => {
+ println!("Error in QUORUM context_get: {e}");
+ }
+ }
+
+ if let Err(e) = quorum::trackstart(handle, corosync::TrackFlags::Changes) {
+ println!("Error in QUORUM trackstart: {e}");
+ return;
+ }
+
+ // Wait for events
+ loop {
+ if quorum::dispatch(handle, corosync::DispatchFlags::One).is_err() {
+ break;
+ }
+ }
+ println!("ERROR: Corosync quit");
+}
diff --git a/bindings/rust/tests/src/bin/votequorum-test.rs b/bindings/rust/tests/src/bin/votequorum-test.rs
new file mode 100644
index 0000000..cf9746b
--- /dev/null
+++ b/bindings/rust/tests/src/bin/votequorum-test.rs
@@ -0,0 +1,117 @@
+// Test the VOTEQUORUM library. Requires that corosync is running and that we are root.
+
+extern crate rust_corosync as corosync;
+use corosync::votequorum;
+
+fn quorum_fn(
+ _handle: &votequorum::Handle,
+ _context: u64,
+ quorate: bool,
+ member_list: Vec<votequorum::Node>,
+) {
+ println!("TEST votequorum_quorum_fn called. quorate = {quorate}");
+ println!(" members: {member_list:?}");
+}
+
+fn nodelist_fn(
+ _handle: &votequorum::Handle,
+ _context: u64,
+ ring_id: votequorum::RingId,
+ member_list: Vec<corosync::NodeId>,
+) {
+ println!(
+ "TEST nodelist_fn called for {}/{}",
+ ring_id.nodeid, ring_id.seq
+ );
+ println!(" members: {member_list:?}");
+}
+
+fn expectedvotes_fn(_handle: &votequorum::Handle, _context: u64, expected_votes: u32) {
+ println!("TEST expected_votes_fn called: value is {expected_votes}");
+}
+
+fn main() {
+ // Initialise the model data
+ let cb = votequorum::Callbacks {
+ quorum_notification_fn: Some(quorum_fn),
+ nodelist_notification_fn: Some(nodelist_fn),
+ expectedvotes_notification_fn: Some(expectedvotes_fn),
+ };
+
+ let handle = match votequorum::initialize(&cb) {
+ Ok(h) => {
+ println!("Votequorum initialized.");
+ h
+ }
+ Err(e) => {
+ println!("Error in VOTEQUORUM init: {e}");
+ return;
+ }
+ };
+
+ // Test context APIs
+ let set_context: u64 = 0xabcdbeefcafe;
+ if let Err(e) = votequorum::context_set(handle, set_context) {
+ println!("Error in VOTEQUORUM context_set: {e}");
+ }
+
+ // NOTE This will fail on 32 bit systems because void* is not u64
+ match votequorum::context_get(handle) {
+ Ok(c) => {
+ if c != set_context {
+ println!("Error: context_get() returned {c:x}, context should be {set_context:x}");
+ }
+ }
+ Err(e) => {
+ println!("Error in VOTEQUORUM context_get: {e}");
+ }
+ }
+
+ const QDEVICE_NAME: &str = "RustQdevice";
+
+ if let Err(e) = votequorum::qdevice_register(handle, QDEVICE_NAME) {
+ println!("Error in VOTEQUORUM qdevice_register: {e}");
+ }
+
+ match votequorum::get_info(handle, corosync::NodeId::from(1u32)) {
+ Ok(i) => {
+ println!("Node info for nodeid 1");
+ println!(" nodeid: {}", i.node_id);
+ println!(" node_state: {:?}", i.node_state);
+ println!(" node_votes: {}", i.node_votes);
+ println!(" node_expected: {}", i.node_expected_votes);
+ println!(" highest_expected: {}", i.highest_expected);
+ println!(" quorum: {}", i.quorum);
+ println!(" flags: {:x}", i.flags);
+ println!(" qdevice_votes: {}", i.qdevice_votes);
+ println!(" qdevice_name: {}", i.qdevice_name);
+
+ if i.qdevice_name != QDEVICE_NAME {
+ println!(
+ "qdevice names do not match: s/b: \"{}\" is: \"{}\"",
+ QDEVICE_NAME, i.qdevice_name
+ );
+ }
+ }
+ Err(e) => {
+ println!("Error in VOTEQUORUM get_info: {e} (check nodeid 1 has been online)");
+ }
+ }
+
+ if let Err(e) = votequorum::qdevice_unregister(handle, QDEVICE_NAME) {
+ println!("Error in VOTEQUORUM qdevice_unregister: {e}");
+ }
+
+ if let Err(e) = votequorum::trackstart(handle, 99_u64, corosync::TrackFlags::Changes) {
+ println!("Error in VOTEQUORUM trackstart: {e}");
+ return;
+ }
+
+ // Wait for events
+ loop {
+ if votequorum::dispatch(handle, corosync::DispatchFlags::One).is_err() {
+ break;
+ }
+ }
+ println!("ERROR: Corosync quit");
+}