libzt_0.3.1/.pvs-studio.cfg 0000644 0001750 0001750 00000000234 13632013546 014305 0 ustar zyga zyga exclude-path = /usr/lib
exclude-path = /usr/lib64
preprocessor = gcc
#platform = macos
platform = linux64
#General Analysis
analysis-mode = 4
language = C
libzt_0.3.1/.version 0000664 0001750 0001750 00000000006 13675422474 013131 0 ustar zyga zyga 0.3.1
libzt_0.3.1/GNUmakefile 0000664 0001750 0001750 00000011354 13675422322 013515 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of libzt.
#
# Libzt is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Libzt is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Libzt. If not, see .
NAME = libzt
VERSION = 0.3.1
srcdir ?= .
# Include optional generated makefile from the configuration system.
-include GNUmakefile.configure.mk
# Use bundled ZMK
include $(srcdir)/z.mk
$(eval $(call ZMK.Import,Toolchain))
$(eval $(call ZMK.Import,Configure))
$(eval $(call ZMK.Import,OS))
$(eval $(call ZMK.Import,GitVersion))
# Manual pages
manpages = \
libzt-test.1 \
libzt.3 \
zt_check.3 \
zt_claim.3 \
ZT_CMP_BOOL.3 \
ZT_CMP_INT.3 \
ZT_CMP_PTR.3 \
ZT_CMP_RUNE.3 \
ZT_CMP_UINT.3 \
ZT_CURRENT_LOCATION.3 \
ZT_FALSE.3 \
zt_location.3 \
zt_location_at.3 \
zt_main.3 \
ZT_NOT_NULL.3 \
ZT_NULL.3 \
zt_pack_boolean.3 \
zt_pack_integer.3 \
zt_pack_nothing.3 \
zt_pack_pointer.3 \
zt_pack_rune.3 \
zt_pack_string.3 \
zt_pack_unsigned.3 \
zt_test.3 \
zt_test_case_func.3 \
zt_test_suite_func.3 \
ZT_TRUE.3 \
zt_value.3 \
zt_visit_test_case.3 \
zt_visitor.3
# The release tarball.
$(NAME)_$(VERSION).tar.gz.Files += zt.h zt.c zt-test.c
$(NAME)_$(VERSION).tar.gz.Files += libzt.map libzt.export_list libzt.def
$(NAME)_$(VERSION).tar.gz.Files += configure GNUmakefile build.bat Makefile.nmake.mk
$(NAME)_$(VERSION).tar.gz.Files += examples/demo.c examples/test-root-user.c examples/GNUmakefile
$(NAME)_$(VERSION).tar.gz.Files += .pvs-studio.cfg
$(NAME)_$(VERSION).tar.gz.Files += README.md LICENSE NEWS
$(NAME)_$(VERSION).tar.gz.Files += $(foreach m,$(manpages),man/$m.in)
$(eval $(call ZMK.Expand,Tarball.Src,$(NAME)_$(VERSION).tar.gz))
# The custom configuration script sets the variable Configure.Configured
# In its absence provide defaults appropriate for each compiler.
ifeq (,$(Configure.Configured))
$(info NOTE: Build tree is not configured, using curated compiler options.)
$(info NOTE: Use ./configure to disable this mechanism)
# Optimize a little by default.
CFLAGS += -O2
# -Werror is enabled when building without a configuration file created
# by the configure script. This is explicitly meant to find bugs, break the
# build and be noticed.
CFLAGS += -Werror
# Extra careful when using gcc or clang.
ifneq (,$(or $(Toolchain.CC.IsGcc),$(Toolchain.CC.IsClang)))
CFLAGS += -Wall -Wextra -Wpedantic -Wconversion -Wchar-subscripts
endif # gcc || clang
# More careful than default when using watcom
ifneq (,$(Toolchain.CC.IsWatcom))
CFLAGS += -Wall -Wextra
endif
endif # !configured
# The configure script
configure.Interpreter = sh
configure.InstallDir = noinst
$(eval $(call ZMK.Expand,Script,configure))
# Public header file
$(eval $(call ZMK.Expand,Header,zt.h))
# Libraries (.a, .so and .dylib)
libzt.a.Sources = zt.c
$(eval $(call ZMK.Expand,Library.A,libzt.a))
ifeq ($(Toolchain.CC.ImageFormat),ELF)
libzt.so.1.Sources = zt.c
libzt.so.1.VersionScript = $(srcdir)/libzt.map
$(eval $(call ZMK.Expand,Library.So,libzt.so.1))
endif
ifeq ($(Toolchain.CC.ImageFormat),Mach-O)
libzt.1.dylib.Sources = zt.c
libzt.1.dylib.ExportList = $(srcdir)/libzt.export_list
$(eval $(call ZMK.Expand,Library.DyLib,libzt.1.dylib))
endif
# Manual pages, generated from .in files
all:: $(foreach m,$(manpages),man/$m)
clean::
rm -f $(addprefix man/,$(manpages))
ifneq ($(srcdir),.)
test -d man && rmdir man || :
endif
$(CURDIR)/man: # For out-of-tree builds.
install -d $@
man/%: man/%.in | $(CURDIR)/man
sed -e 's/@VERSION@/$(VERSION)/g' $< >$@
$(foreach m,$(manpages),$(eval $(call ZMK.Expand,ManPage,man/$m)))
# The test program
libzt-test.Sources = zt-test.c
libzt-test.SourcesCoverage = zt.c
$(eval $(call ZMK.Expand,Program.Test,libzt-test))
ifneq (,$(Toolchain.CC.IsGcc))
libzt-test: CFLAGS += -Wno-overlength-strings # Old gcc complains about the assert() in zt-test.c
endif
# Support formatting using clang-format, if installed.
ifneq ($(shell command -v clang-format 2>/dev/null),)
fmt:: $(wildcard $(srcdir)/*.[ch] $(srcdir)/examples/*.[ch])
clang-format -i -style=WebKit $^
else
fmt:
echo "error: clang-format not found, cannot format" >&2
exit 1
endif
# Static analysis using PVS Studio.
PVS.Sources=zt.c zt-test.c
PLOG_CONVERTER_FLAGS += -d V1042 # libzt is FOSS, no need to tell us.
$(eval $(call ZMK.Import,PVS))
# Static analysis using Coverity
Coverity.Sources=zt.c zt.h zt-test.c
$(eval $(call ZMK.Import,Coverity))
libzt_0.3.1/LICENSE 0000644 0001750 0001750 00000016743 13640205631 012447 0 ustar zyga zyga GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
libzt_0.3.1/Makefile.nmake.mk 0000664 0001750 0001750 00000000577 13651643626 014616 0 ustar zyga zyga !if [set CL=/nologo /Wall /wd4820 /wd4100 /wd4996 /wd4710 /wd5045]
!endif
all: libzt-test.exe zt.dll
clean:
del /F zt.obj zt-test.obj libzt-test.exe zt.dll zt.lib zt.exp
check: libzt-test.exe
libzt-test.exe
libzt-test.exe: zt-test.obj
cl /Fe: $@ $?
zt.dll: zt.obj
cl /LD /DEF libzt.def /Fe: $@ $?
zt.obj: zt.c zt.h
cl /c zt.c
zt-test.obj: zt-test.c zt.c zt.h
cl /c zt-test.c
libzt_0.3.1/NEWS 0000664 0001750 0001750 00000005363 13675422336 012152 0 ustar zyga zyga Changes in 0.3.1:
* The build system has been updated to ZMK 0.3.6. This should fix
current build issues encountered in Debian.
Changes in 0.3:
* Pointers captured in zt_value by zt_pack_pointer() are now constant.
This allows testing pointers to constants with ZT_NULL and ZT_NOT_NULL.
This does not impact the ABI.
* Added ZT_CMP_PTR for comparing pointers for equality and inequality.
Other relations are explicitly left out, at least for now.
* ZT_CMP_INT and ZT_CMP_UINT now support maximum integral types of the
architecture. This allows ZT_CMP_UINT to safely work with size_t values.
This is achieved in a backwards compatible way. Existing test programs
compiled and linked with libzt 0.1 or 0.2 retain their current semantic.
The type zt_value has grown two new kinds, ZT_INTMAX and ZT_UINTMAX,
along with new union members. The static inline pack functions
zt_pack_integer and zt_pack_unsigned now take intmax_t and uintmax_t
arguments respectively. Since they are always inlined this is not an
ABI break. Test programs built with older definitions of the two pack
functions use distinct kind (ZT_INTEGER instead of ZT_INTMAX and
ZT_UNSIGNED instead of ZT_UINTMAX) which is now detected and handled
by zt_cmp_int and zt_cmp_uint. Internally the values are promoted
and comparison is always performed on the extended types.
* The function zt_main() now displays both the test case name and the outcome
of each test when invoked with "-v" command-line argument.
* Libzt can now build for DOS as either 16bit or extended mode 32bit.
Note that libzt-test.exe requires the DOS extender as it is too large to fit
into 64K code segment.
* The configuration system is more robust and can now detect the use of Gcc,
Clang and the OpenWatcom compilers. Using OpenWatcom from the open-watcom
snap allows cross-compiling libzt for DOS and other older targets.
* The build system is now decoupled from libzt and can be used for other
projects. Currently a copy resides in-tree but at some later date it may
become a new development-only dependency. Distribution tarballs will not
require any new dependencies.
* The tree now contains comprehensive integration tests that build and
exercise the library on several different Linux distributions. One of the
tests cross builds libzt for DOS and tests it with DosBox and DOS/32
extender.
Changes in 0.2:
* Argument type to all unit test functions was typedef'd
to zt_t, to abbreviate the boilerplate text and to avoid
having to type struct zt_test.
* The field zt_claim.verifier was renamed to zt_claim.make_verifier.
There is no public API breakage on this as claims are not constructed
by user code apart from the existing stable helpers.
libzt_0.3.1/README.md 0000644 0001750 0001750 00000002446 13641710542 012717 0 ustar zyga zyga 
# libzt is an unit test library for C
libzt is a simple and robust unit test library for C.
## Features
- Robust, allowing you to focus on your code.
- Simple and small, making it quick to learn and use.
- Doesn't use dynamic memory allocation, reducing error handling.
- Equipped with useful helpers for writing test cases.
- Portable and supported on Linux, MacOS, Windows and DOS.
- Documented and fully coverage and integration tested.
## Example
```
#include
#include
static const char *greeting(void) {
return "hello there";
}
static void test_smoke(zt_t t) {
zt_check(t, ZT_TRUE(2 + 2 == 4));
zt_check(t, ZT_CMP_INT(2 + 2, ==, 4));
zt_check(t, ZT_CMP_STR(greeting(), ==, "hello there"));
}
static void test_writing_to_tmpfile(zt_t t) {
FILE *f = tmpfile();
zt_assert(t, ZT_NOT_NULL(f)); // stops test on failure
zt_check(t, ZT_CMP_INT(fprintf(f, "%s", greeting()), >, 0);
zt_check(t, ZT_CMP_INT(ftell(f), ==, strlen(greeting()));
zt_check(t, ZT_CMP_INT(fclose(f), ==, 0);
}
static void test_suite(zt_visitor v) {
ZT_VISIT_TEST(v, test_smoke);
ZT_VISIT_TEST(v, test_writing_to_tmpfile);
}
int main(int argc, char **argv, char **envp) {
return zt_main(argc, argv, envp, test_suite);
}
```
libzt_0.3.1/build.bat 0000664 0001750 0001750 00000000033 13651643626 013230 0 ustar zyga zyga nmake /f Makefile.nmake.mk
libzt_0.3.1/configure 0000775 0001750 0001750 00000030611 13675422474 013357 0 ustar zyga zyga #!/bin/sh
# Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# This script was automatically generated by zmk version 0.3.6.
while [ "$#" -ge 1 ]; do
case "$1" in
-h|--help)
echo "Usage: ./configure [OPTIONS]"
echo
echo "Compilation options:"
echo " --build=GNU_TRIPLET Describe the build machine with the given GNU_TRIPLET"
echo " --host=GNU_TRIPLET Describe the host machine with the given GNU_TRIPLET"
echo " --enable-dependency-tracking"
echo " Track dependencies between files (implicit)"
echo " --disable-dependency-tracking"
echo " Do not generate or use dependency data during builds"
echo " --enable-maintainer-mode Enable maintainer mode (implicit)"
echo " --disable-maintainer-mode Disable maintainer mode"
echo
echo "Build-time directory selection:"
echo " --prefix=PREFIX Set prefix for all directories to PREFIX"
echo " --exec-prefix=PREFIX Set prefix for libraries and programs to PREFIX"
echo
echo " --bindir=DIR Install user programs to DIR"
echo " --sbindir=DIR Install super-user programs to DIR"
echo " --libdir=DIR Install runtime and development libraries to DIR"
echo " --libexecdir=DIR Install library-internal programs to DIR"
echo " --includedir=DIR Install development header files to DIR"
echo " --mandir=DIR Install manual pages to DIR"
echo " --infodir=DIR Install GNU info pages to DIR"
echo " --sysconfdir=DIR Install system configuration files to DIR"
echo " --datadir=DIR Install read-only data files to DIR"
echo
echo " --localstatedir=DIR Store persistent state specific to a machine in DIR"
echo " --runstatedir=DIR Store ephemeral state specific to a machine in DIR"
echo " --sharedstatedir=DIR Store state shared across machines in DIR"
echo
echo "Options for altering program names:"
echo " --program-prefix=PREFIX Put PREFIX before installed program names"
echo " --program-suffix=SUFFIX Put SUFFIX after installed program names"
echo " --program-transform-name=PROGRAM"
echo " Use sed PROGRAM to transform installed program names"
echo
echo "Miscellaneous options:"
echo " --enable-option-checking Report unrecognized configuration options (implicit)"
echo " --disable-option-checking Ignore unrecognized configuration options"
echo " --enable-silent-rules Do not display commands while building"
echo " --disable-silent-rules Display commands while building (implicit)"
echo
echo "Memorized environment variables:"
echo " CC Name of the C compiler"
echo " CXX Name of the C++ compiler"
echo " CFLAGS Options for the C compiler"
echo " CXXFLAGS Options for the C++ compiler"
echo " CPPFLAGS Options for the preprocessor"
echo " LDFLAGS Options for the linker"
exit 0
;;
--version)
echo "z.mk configure script version 0.3.6"
exit 0
;;
*)
break
;;
esac
done
{
# Given key=value or key="value value", print the value
rhs() {
echo "$*" | cut -d '=' -f 2- | sed -e 's/^"//' -e 's/"$//'
}
echo "# Generated by zmk configuration script version 0.3.6"
echo "# ./configure $*"
configureOptions="$*"
echo
echo "# Location of the source code."
if [ -n "${srcdir:-}" ]; then
echo "srcdir=$srcdir"
else
echo "srcdir=$(dirname "$0")"
fi
echo
echo "# Set VPATH for make (for out-of-tree builds)."
echo "VPATH=\$(srcdir)"
while [ "$#" -ge 1 ]; do
case "$1" in
--build=*) buildArchTriplet="$(rhs "$1")" && shift ;;
--host=*) hostArchTriplet="$(rhs "$1")" && shift ;;
--enable-dependency-tracking) dependencyTracking=yes && shift ;;
--disable-dependency-tracking) dependencyTracking=no && shift ;;
--enable-maintainer-mode) maintainerMode=yes && shift ;;
--disable-maintainer-mode) maintainerMode=no && shift ;;
--enable-silent-rules) silentRules=yes && shift ;;
--disable-silent-rules) silentRules=no && shift ;;
--enable-option-checking) disableOptionChecking=no && shift ;;
--disable-option-checking) disableOptionChecking=yes && shift ;;
--program-prefix=*) programPrefix="$(rhs "$1")" && shift ;;
--program-suffix=*) programSuffix="$(rhs "$1")" && shift ;;
--program-transform-name=*) programTransformName="$(rhs "$1")" && shift ;;
--exec-prefix=*) exec_prefix="$(rhs "$1")" && shift ;;
--prefix=*) prefix="$(rhs "$1")" && shift ;;
--bindir=*) bindir="$(rhs "$1")" && shift ;;
--sbindir=*) sbindir="$(rhs "$1")" && shift ;;
--libdir=*) libdir="$(rhs "$1")" && shift ;;
--libexecdir=*) libexecdir="$(rhs "$1")" && shift ;;
--datadir=*) datadir="$(rhs "$1")" && shift ;;
--includedir=*) includedir="$(rhs "$1")" && shift ;;
--infodir=*) infodir="$(rhs "$1")" && shift ;;
--mandir=*) mandir="$(rhs "$1")" && shift ;;
--sysconfdir=*) sysconfdir="$(rhs "$1")" && shift ;;
--localstatedir=*) localstatedir="$(rhs "$1")" && shift ;;
--runstatedir=*) runstatedir="$(rhs "$1")" && shift ;;
--sharedstatedir=*) sharedstatedir="$(rhs "$1")" && shift ;;
CC=*) CC="$(rhs "$1")" && shift ;;
CXX=*) CXX="$(rhs "$1")" && shift ;;
CFLAGS=*) CFLAGS="$(rhs "$1")" && shift ;;
OBJCFLAGS=*) OBJCFLAGS="$(rhs "$1")" && shift ;;
CXXFLAGS=*) CXXFLAGS="$(rhs "$1")" && shift ;;
CPPFLAGS=*) CPPFLAGS="$(rhs "$1")" && shift ;;
LDFLAGS=*) LDFLAGS="$(rhs "$1")" && shift ;;
*)
if [ "${disableOptionChecking:-}" != yes ]; then
echo "configure: unknown option $1" >&2
configureFailed=1
fi
shift
;;
esac
done
echo
echo "# Build and host architecture triplets."
echo "# Note that those impact compiler selection unless overridden."
test -n "${buildArchTriplet:-}" && echo "Configure.BuildArchTriplet=$buildArchTriplet" || echo "# Configure.BuildArchTriplet was not specified."
test -n "${hostArchTriplet:-}" && echo "Configure.HostArchTriplet=$hostArchTriplet" || echo "# Configure.HostArchTriplet was not specified."
echo
echo "# Build-time configuration of application directories."
test -n "${prefix:-}" && echo "prefix=$prefix" || echo "# prefix was not specified."
test -n "${exec_prefix:-}" && echo "exec_prefix=$exec_prefix" || echo "# exec_prefix was not specified."
test -n "${bindir:-}" && echo "bindir=$bindir" || echo "# bindir was not specified."
test -n "${sbindir:-}" && echo "sbindir=$sbindir" || echo "# sbindir was not specified."
test -n "${datadir:-}" && echo "datadir=$datadir" || echo "# datadir was not specified."
test -n "${includedir:-}" && echo "includedir=$includedir" || echo "# includedir was not specified."
test -n "${infodir:-}" && echo "infodir=$infodir" || echo "# infodir was not specified."
test -n "${libdir:-}" && echo "libdir=$libdir" || echo "# libdir was not specified."
test -n "${libexecdir:-}" && echo "libexecdir=$libexecdir" || echo "# libexecdir was not specified."
test -n "${localstatedir:-}" && echo "localstatedir=$localstatedir" || echo "# localstatedir was not specified."
test -n "${mandir:-}" && echo "mandir=$mandir" || echo "# mandir was not specified."
test -n "${runstatedir:-}" && echo "runstatedir=$runstatedir" || echo "# runstatedir was not specified."
test -n "${sharedstatedir:-}" && echo "sharedstatedir=$sharedstatedir" || echo "# sharedstatedir was not specified."
test -n "${sysconfdir:-}" && echo "sysconfdir=$sysconfdir" || echo "# sysconfdir was not specified."
echo
echo "# Inherited environment variables and overrides."
test -n "$CC" && echo "CC=$CC" || echo "# CC was not specified."
test -n "$CXX" && echo "CXX=$CXX" || echo "# CXX was not specified."
test -n "$CFLAGS" && echo "CFLAGS=$CFLAGS" || echo "# CFLAGS was not specified."
test -n "$CXXFLAGS" && echo "CXXFLAGS=$CXXFLAGS" || echo "# CXXFLAGS was not specified."
test -n "$OBJCFLAGS" && echo "OBJCFLAGS=$OBJCFLAGS" || echo "# OBJCFLAGS was not specified."
test -n "$CPPFLAGS" && echo "CPPFLAGS=$CPPFLAGS" || echo "# CPPFLAGS was not specified."
test -n "$LDFLAGS" && echo "LDFLAGS=$LDFLAGS" || echo "# LDFLAGS was not specified."
echo
echo "# Track dependencies between objects and source and header files."
case "${dependencyTracking:-implicit}" in
yes)
echo "Configure.DependencyTracking=yes"
;;
no)
echo "Configure.DependencyTracking="
;;
implicit)
echo "# Configure.DependencyTracking was not specified."
;;
esac
echo
echo "# Additional options for package maintainers."
case "${maintainerMode:-implicit}" in
yes)
echo "Configure.MaintainerMode=yes"
;;
no)
echo "Configure.MaintainerMode="
;;
implicit)
echo "# Configure.MaintainerMode was not specified."
;;
esac
echo
echo "# Silence shell commands used by make."
case "${silentRules:-implicit}" in
yes)
echo "Configure.SilentRules=yes"
;;
no)
echo "Configure.SilentRules="
;;
implicit)
echo "# Configure.SilentRules was not specified."
;;
esac
echo
echo "# Program name customization options."
test -n "${programPrefix:-}" && echo "Configure.ProgramPrefix=$programPrefix" || echo "# Configure.ProgramPrefix was not specified."
test -n "${programSuffix:-}" && echo "Configure.ProgramSuffix=$programSuffix" || echo "# Configure.ProgramSuffix was not specified."
test -n "${programTransformName:-}" && echo "Configure.ProgramTransformName=$programTransformName" || echo "# Configure.ProgramTransformName was not specified."
echo
echo "# Remember that the configuration script was executed."
echo "Configure.Configured=yes"
echo "Configure.Options=$configureOptions"
} > "${ZMK_CONFIGURE_MAKEFILE:=GNUmakefile.configure.mk}"
if [ "${configureFailed:-0}" -eq 1 ]; then
rm -f "${ZMK_CONFIGURE_MAKEFILE}"
exit 1
fi
if [ ! -e Makefile ] && [ ! -e GNUmakefile ]; then
ln -s "$(dirname "$0")"/GNUmakefile GNUmakefile
fi
libzt_0.3.1/examples/GNUmakefile 0000644 0001750 0001750 00000000176 13632013546 015326 0 ustar zyga zyga .PHONY: all clean
CFLAGS ?= -Wall -Werror -O2
LDLIBS += -lzt
all: demo test-root-user
clean:
rm -f *.o demo test-root-user
libzt_0.3.1/examples/demo.c 0000644 0001750 0001750 00000001654 13632013546 014346 0 ustar zyga zyga #include
#include
#include
#include
static void passing_test(zt_t t)
{
zt_check(t, ZT_TRUE(2 + 2 == 4));
zt_check(t, ZT_FALSE(2 + 2 == 5));
zt_check(t, ZT_CMP_INT(2 + 2, ==, 4));
zt_check(t, ZT_CMP_BOOL(false, ==, false));
}
static void failing_test(zt_t t)
{
zt_check(t, ZT_TRUE(2 + 2 != 4));
zt_check(t, ZT_FALSE(2 + 2 != 5));
zt_check(t, ZT_CMP_INT(2 + 2, ==, 5));
zt_check(t, ZT_CMP_BOOL(false, ==, true));
}
static void badly_failing_test(zt_t t)
{
zt_assert(t, ZT_CMP_INT(0, ==, -1));
abort();
}
static void passing_suite(zt_visitor v) { ZT_VISIT_TEST_CASE(v, passing_test); }
static void test_suite(zt_visitor v)
{
ZT_VISIT_TEST_SUITE(v, passing_suite);
ZT_VISIT_TEST_CASE(v, failing_test);
ZT_VISIT_TEST_CASE(v, badly_failing_test);
}
int main(int argc, char** argv, char** envp)
{
return zt_main(argc, argv, envp, test_suite);
}
libzt_0.3.1/examples/test-root-user.c 0000644 0001750 0001750 00000000765 13632013546 016340 0 ustar zyga zyga #include
#include
#include
static void test_root_user(zt_t t)
{
struct passwd* p = getpwnam("root");
zt_assert(t, ZT_NOT_NULL(p));
zt_check(t, ZT_CMP_CSTR(p->pw_name, ==, "root"));
zt_check(t, ZT_CMP_INT(p->pw_uid, ==, 0));
zt_check(t, ZT_CMP_INT(p->pw_gid, ==, 0));
}
static void test_suite(zt_visitor v) { ZT_VISIT_TEST_CASE(v, test_root_user); }
int main(int argc, char** argv, char** envp)
{
return zt_main(argc, argv, envp, test_suite);
}
libzt_0.3.1/libzt.def 0000664 0001750 0001750 00000000374 13675422322 013247 0 ustar zyga zyga LIBRARY ZT
VERSION 0.3
EXPORTS
zt_assert
zt_check
zt_cmp_bool
zt_cmp_cstr
zt_cmp_int
zt_cmp_ptr
zt_cmp_rune
zt_cmp_uint
zt_false
zt_main
zt_not_null
zt_null
zt_pack_rune
zt_true
zt_visit_test_case
zt_visit_test_suite
libzt_0.3.1/libzt.export_list 0000664 0001750 0001750 00000000312 13675422322 015055 0 ustar zyga zyga _zt_assert
_zt_check
_zt_cmp_bool
_zt_cmp_cstr
_zt_cmp_int
_zt_cmp_ptr
_zt_cmp_rune
_zt_cmp_uint
_zt_false
_zt_main
_zt_not_null
_zt_null
_zt_pack_rune
_zt_true
_zt_visit_test_case
_zt_visit_test_suite
libzt_0.3.1/libzt.map 0000664 0001750 0001750 00000000506 13675422322 013263 0 ustar zyga zyga VERS_0_1 {
global:
zt_assert;
zt_check;
zt_cmp_bool;
zt_cmp_cstr;
zt_cmp_int;
zt_cmp_rune;
zt_cmp_uint;
zt_false;
zt_main;
zt_not_null;
zt_null;
zt_pack_rune;
zt_true;
zt_visit_test_case;
zt_visit_test_suite;
local: *;
};
VERS_0_2 {
} VERS_0_1;
VERS_0_3 {
global:
zt_cmp_ptr;
} VERS_0_2;
libzt_0.3.1/man/ZT_CMP_BOOL.3.in 0000644 0001750 0001750 00000002672 13673206643 014563 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_CMP_BOOL 3 PRM
.Sh NAME
.Nm ZT_CMP_BOOL ,
.Nm zt_cmp_bool
.Nd construct a claim of a relation between two booleans
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_CMP_BOOL(left, rel, right) \\
zt_cmp_bool( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_boolean((left), (#left)), \\
zt_pack_string((#rel), (#rel)), \\
zt_pack_boolean((right), (#right)))
.Ed
.Ft zt_claim
.Fo zt_cmp_bool
.Fa "zt_location location"
.Fa "zt_value left"
.Fa "zt_value rel"
.Fa "zt_value right"
.Fc
.Sh DESCRIPTION
.Fn zt_cmp_bool
constructs a claim of a relation between two booleans. It should be used
through the macro
.Fn ZT_CMP_BOOL
which passes source code location and packs arguments.
.Pp
The relation must be either
.Em ==
or
.Em != .
.Pp
It may be more natural to use
.Fn ZT_TRUE
or
.Fn ZT_FALSE
instead.
.Sh IMPLEMENTATION NOTES
.Fn ZT_CMP_BOOL
evaluates
.Em left
and
.Em right
exactly once.
.Sh RETURN VALUES
Both the macro and the function return a claim structure with the right
attributes set. The returned claim is usually passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_INT 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr ZT_TRUE 3 ,
.Xr zt_check 3 ,
.Sh HISTORY
The
.Fn ZT_CMP_BOOL
macro and the
.Fn zt_cmp_bool
function first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_CMP_INT.3.in 0000644 0001750 0001750 00000003012 13673206643 014447 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_CMP_INT 3 PRM
.Sh NAME
.Nm ZT_CMP_INT ,
.Nm zt_cmp_int
.Nd construct a claim of a relation between two integers
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_CMP_INT(left, rel, right) \\
zt_cmp_int( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_integer((left), (#left)), \\
zt_pack_string((#rel), (#rel)), \\
zt_pack_integer((right), (#right)))
.Ed
.Ft zt_claim
.Fo zt_cmp_int
.Fa "zt_location location"
.Fa "zt_value left"
.Fa "zt_value rel"
.Fa "zt_value right"
.Fc
.Sh DESCRIPTION
.Fn zt_cmp_int
constructs a claim of a relation between two integers. It should be used
through the macro
.Fn ZT_CMP_INT
which passes source code location and packs arguments.
.Pp
The relation must be one of
.Em == ,
.Em != ,
.Em < ,
.Em <= ,
.Em >
or
.Em >= .
.Sh IMPLEMENTATION NOTES
.Fn ZT_CMP_INT
evaluates
.Em left
and
.Em right
exactly once.
.Sh RETURN VALUES
Both the macro and the function return a claim structure with the right
attributes set. The returned claim is usually passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr ZT_TRUE 3 ,
.Xr zt_check 3 ,
.Sh HISTORY
The
.Fn ZT_CMP_INT
macro and the
.Fn zt_cmp_int
function first appeared in libzt 0.1
.Pp
Since libzt 0.3
.Fn zt_cmp_int
internally promotes
.Nm left
and
.Nm right
arguments from
.Nm ZT_INTEGER
to
.Nm ZT_INTMAX .
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_CMP_PTR.3.in 0000644 0001750 0001750 00000002547 13673206643 014476 0 ustar zyga zyga .Dd March 12, 2020
.Os libzt @VERSION@
.Dt ZT_CMP_PTR 3 PRM
.Sh NAME
.Nm ZT_CMP_PTR ,
.Nm zt_cmp_int
.Nd construct a claim of a relation between two pointers
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_CMP_PTR(left, rel, right) \\
zt_cmp_ptr( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_pointer((left), (#left)), \\
zt_pack_string((#rel), (#rel)), \\
zt_pack_pointer((right), (#right)))
.Ed
.Ft zt_claim
.Fo zt_cmp_ptr
.Fa "zt_location location"
.Fa "zt_value left"
.Fa "zt_value rel"
.Fa "zt_value right"
.Fc
.Sh DESCRIPTION
.Fn zt_cmp_ptr
constructs a claim of a relation between two integers. It should be used
through the macro
.Fn ZT_CMP_PTR
which passes source code location and packs arguments.
.Pp
The relation must be either
.Em == ,
or
.Em !=
.Sh IMPLEMENTATION NOTES
.Fn ZT_CMP_PTR
evaluates
.Em left
and
.Em right
exactly once.
.Sh RETURN VALUES
Both the macro and the function return a claim structure with the right
attributes set. The returned claim is usually passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_CHAR 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr ZT_TRUE 3 ,
.Xr zt_check 3 ,
.Sh HISTORY
The
.Fn ZT_CMP_PTR
macro and the
.Fn zt_cmp_ptr
function first appeared in libzt 0.3
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_CMP_RUNE.3.in 0000644 0001750 0001750 00000002643 13673206643 014577 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_CMP_RUNE 3 PRM
.Sh NAME
.Nm ZT_CMP_RUNE ,
.Nm zt_cmp_rune
.Nd construct a claim of a relation between two characters (runes)
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_CMP_RUNE(left, rel, right) \\
zt_cmp_rune( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_rune((left), (#left)), \\
zt_pack_string((#rel), (#rel)), \\
zt_pack_rune((right), (#right)))
.Ed
.Ft zt_claim
.Fo zt_cmp_rune
.Fa "zt_location location"
.Fa "zt_value left"
.Fa "zt_value rel"
.Fa "zt_value right"
.Fc
.Sh DESCRIPTION
.Fn zt_cmp_rune
constructs a claim of a relation between two unsigned integers. It should be
used through the macro
.Fn ZT_CMP_RUNE
which passes source code location and packs arguments.
.Pp
The relation must be one of
.Em == ,
.Em != ,
.Em < ,
.Em <= ,
.Em >
or
.Em >= .
.Sh IMPLEMENTATION NOTES
.Fn ZT_CMP_RUNE
evaluates
.Em left
and
.Em right
exactly once.
.Sh RETURN VALUES
Both the macro and the function return a claim structure with the right
attributes set. The returned claim is usually passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr ZT_TRUE 3 ,
.Xr zt_check 3 ,
.Sh HISTORY
The
.Fn ZT_CMP_RUNE
macro and the
.Fn zt_cmp_rune
function first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_CMP_UINT.3.in 0000644 0001750 0001750 00000003054 13673206643 014602 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_CMP_UINT 3 PRM
.Sh NAME
.Nm ZT_CMP_UINT ,
.Nm zt_cmp_uint
.Nd construct a claim of a relation between two unsigned integers
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_CMP_UINT(left, rel, right) \\
zt_cmp_uint( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_unsigned((left), (#left)), \\
zt_pack_string((#rel), (#rel)), \\
zt_pack_unsigned((right), (#right)))
.Ed
.Ft zt_claim
.Fo zt_cmp_uint
.Fa "zt_location location"
.Fa "zt_value left"
.Fa "zt_value rel"
.Fa "zt_value right"
.Fc
.Sh DESCRIPTION
.Fn zt_cmp_uint
constructs a claim of a relation between two unsigned integers. It should be
used through the macro
.Fn ZT_CMP_UINT
which passes source code location and packs arguments.
.Pp
The relation must be one of
.Em == ,
.Em != ,
.Em < ,
.Em <= ,
.Em >
or
.Em >= .
.Sh IMPLEMENTATION NOTES
.Fn ZT_CMP_UINT
evaluates
.Em left
and
.Em right
exactly once.
.Sh RETURN VALUES
Both the macro and the function return a claim structure with the right
attributes set. The returned claim is usually passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr ZT_TRUE 3 ,
.Xr zt_check 3 ,
.Sh HISTORY
The
.Fn ZT_CMP_UINT
macro and the
.Fn zt_cmp_uint
function first appeared in libzt 0.1
.Pp
Since libzt 0.3
.Fn zt_cmp_uint
internally promotes
.Nm left
and
.Nm right
arguments from
.Nm ZT_UNSIGNED
to
.Nm ZT_UINTMAX .
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_CURRENT_LOCATION.3.in 0000644 0001750 0001750 00000001132 13673206643 015731 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_CURRENT_LOCATION 3 PRM
.Sh NAME
.Nm ZT_CURRENT_LOCATION
.Nd get the current location in the source file
.Sh SYNOPSIS
.In zt.h
.Fd #define ZT_CURRENT_LOCATION() zt_location_at(__FILE__, __LINE__)
.Sh DESCRIPTION
.Nm
provides
.Nm zt_location
describing the location of the source file invoking the macro.
.Sh RETURN VALUES
A
.Nm zt_location
containing the current values of
.Nm __FILE__
and
.Nm __LINE .
.Sh SEE ALSO
.Xr zt_location_at 3 ,
.Xr zt_location 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_FALSE.3.in 0000644 0001750 0001750 00000002516 13673206643 014160 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_FALSE 3 PRM
.Sh NAME
.Nm ZT_FALSE ,
.Nm zt_false
.Nd construct a claim that a value is false
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_FALSE(value) \\
zt_false( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_boolean((value), #value)) \\
.Ed
.Ft zt_claim
.Fo zt_false
.Fa "zt_location location"
.Fa "zt_value value"
.Fc
.Sh DESCRIPTION
.Fn zt_false
constructs a claim that a given value is false. It should be used through the
macro
.Fn ZT_FALSE ,
which passes source code location and packs argument.
.Pp
.Fn zt_false
can be used to check custom properties by calling arbitrary verification logic.
The disadvantage of this approach is that on failure, the error message cannot
precisely explain the problem.
.Sh IMPLEMENTATION NOTES
.Fn ZT_FALSE
evaluates
.Em value
only once.
.Sh RETURN VALUES
Both the macro and the function return a claim structure with the right
attributes set. The returned claim is usually passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_INT 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr zt_check 3 ,
.Sh HISTORY
The
.Fn ZT_FALSE
macro and the
.Fn zt_false
function first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_NOT_NULL.3.in 0000644 0001750 0001750 00000002710 13673206643 014614 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_NOT_NULL 3 PRM
.Sh NAME
.Nm ZT_NOT_NULL ,
.Nm zt_not_null
.Nd construct a claim that a pointer is not NULL
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_NOT_NULL(value) \\
zt_not_null( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_pointer((value), #value))
.Ed
.Ft zt_claim
.Fo zt_not_null
.Fa "zt_location location"
.Fa "zt_value value"
.Fc
.Sh DESCRIPTION
.Fn zt_not_null
constructs a claim that a given pointer is not NULL. It should be used through the
macro
.Fn ZT_NOT_NULL ,
which passes source code location and packs argument.
.Pp
.Fn ZT_NOT_NULL
can be useful, when coupled with
.Fn zt_assert ,
to ensure that an object was correctly produced, allocated or returned
and that the reminder of the test can inspect its properties using
.Fn zt_check .
.Sh IMPLEMENTATION NOTES
.Fn ZT_NOT_NULL
evaluates
.Em value
only once.
.Sh RETURN VALUES
Both the macro and the function return a
.Nm zt_claim
structure with the appropriate attributes set. The returned claim is usually
passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr zt_assert 3 ,
.Xr zt_check 3 ,
.Xr zt_claim 3 ,
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_INT 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NOT_NULL 3
.Xr zt_value 3 ,
.Sh HISTORY
The
.Fn ZT_NOT_NULL
macro and the
.Fn zt_not_null
function first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_NULL.3.in 0000644 0001750 0001750 00000002554 13673206643 014102 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_NULL 3 PRM
.Sh NAME
.Nm ZT_NULL ,
.Nm zt_null
.Nd construct a claim that a pointer is NULL
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_NULL(value) \\
zt_null( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_pointer((value), #value))
.Ed
.Ft zt_claim
.Fo zt_null
.Fa "zt_location location"
.Fa "zt_value value"
.Fc
.Sh DESCRIPTION
.Fn zt_null
constructs a claim that a given pointer is NULL. It should be used through the
macro
.Fn ZT_NULL ,
which passes source code location and packs argument.
.Pp
.Fn ZT_NULL
can be useful, when coupled with
.Fn zt_assert ,
to ensure that something that the reminder of the test relies on
did not happen, for example that no error had occurred.
.Sh IMPLEMENTATION NOTES
.Fn ZT_NULL
evaluates
.Em value
only once.
.Sh RETURN VALUES
Both the macro and the function return a
.Nm zt_claim
structure with the appropriate attributes set. The returned claim is usually
passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr zt_assert 3 ,
.Xr zt_check 3 ,
.Xr zt_claim 3 ,
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_INT 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3
.Xr zt_value 3 ,
.Sh HISTORY
The
.Fn ZT_NULL
macro and the
.Fn zt_null
function first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/ZT_TRUE.3.in 0000664 0001750 0001750 00000002577 13675422322 014112 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_TRUE 3 PRM
.Sh NAME
.Nm ZT_TRUE ,
.Nm zt_true
.Nd construct a claim that a value is true
.Sh SYNOPSIS
.In zt.h
.Bd -literal
#define ZT_TRUE(value) \\
zt_true( \\
ZT_CURRENT_LOCATION(), \\
zt_pack_boolean((value), #value)) \\
.Ed
.Ft zt_claim
.Fo zt_true
.Fa "zt_location location"
.Fa "zt_value value"
.Fc
.Sh DESCRIPTION
.Fn zt_true
constructs a claim that a given value is true. It should be used through the
macro
.Fn ZT_TRUE ,
which passes source code location and packs argument.
.Pp
.Fn zt_true
can be used to check custom properties by calling arbitrary verification logic.
The disadvantage of this approach is that on failure, the error message cannot
precisely explain the problem.
.Sh IMPLEMENTATION NOTES
.Fn ZT_TRUE
evaluates
.Em value
only once.
.Sh RETURN VALUES
Both the macro and the function return a
.Nm zt_claim
structure with the appropriate attributes set. The returned claim is usually
passed to
.Fn zt_check
or to
.Fn zt_assert .
.Sh SEE ALSO
.Xr zt_assert 3 ,
.Xr zt_check 3 ,
.Xr zt_claim 3 ,
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_RUNE 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_INT 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3
.Xr zt_value 3 ,
.Sh HISTORY
The
.Fn ZT_TRUE
macro and the
.Fn zt_true
function first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/libzt-test.1.in 0000644 0001750 0001750 00000000763 13673206643 015012 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt LIBZT-TEST 1 PRM
.Sh NAME
.Nm libzt-test
.Nd test suite for libzt
.Sh SYNOPSIS
.Nm libzt-test
.Sh DESCRIPTION
.Nm
is a binary with internal test suite for libzt.
.Pp
The program takes no options and executes all tests sequentially.
Upon success the message
.Qq libzt self-test successful
is printed to standard output.
.Sh EXIT STATUS
.Ex -std
.Sh HISTORY
The
.Nm
program first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/libzt.3.in 0000644 0001750 0001750 00000003125 13673206643 014032 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt libzt 3 PRM
.Sh NAME
.Nm libzt
.Nd Library for unit testing C
.Sh LIBRARY
Library for unit testing C (-lzt)
.Sh SYNOPSIS
.In zt.h
.Sh DESCRIPTION
The
.Nm
library offers routines for writing C unit tests. It is focusing on simplicity,
robustness and correctness, offering facilities for:
.Bl -dash
.It
Defining test suites and test cases.
.It
Asserting relations between booleans, integers, strings and characters.
Asserting properties of booleans and pointers.
.It
Creating command line interface that allows enumerating and invoking tests.
The output of test programs integrates well with
.Em make .
.El
.Pp
The library code is portable between a wide range of C compilers and operating
systems. All library code is covered by a self-test test suite. The library
never allocates memory or uses the file system which makes it suitable for
working on embedded targets.
.Sh EXAMPLES
The following fragment demonstrates a simple test program, comprised of a
single test suite with a single test case checking the relations between two
integers.
.Bd -literal -offset indent
#include
static void test_math(zt_t t)
{
zt_check(t, ZT_CMP_INT(2 + 2, ==, 4));
}
static void test_suite(zt_visitor v)
{
ZT_VISIT_TEST_CASE(v, test_math);
}
int main(int argc, char** argv, char** envp)
{
return zt_main(argc, argv, envp, test_suite);
}
.Ed
.Sh SEE ALSO
.Xr zt_main 3 ,
.Xr ZT_VISIT_TEST_CASE 3 ,
.Xr ZT_VISIT_TEST_SUITE 3 ,
.Xr zt_check 3 ,
.Xr ZT_CMP_INT 3
.Sh HISTORY
.Nm
version 0.1 was first released in 2020
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_check.3.in 0000664 0001750 0001750 00000005441 13675422322 014501 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_CHECK 3 PRM
.Sh NAME
.Nm zt_check ,
.Nm zt_assert
.Nd verify a test claim
.Sh SYNOPSIS
.In zt.h
.Ft void
.Fo zt_check
.Fa "zt_t t"
.Fa "zt_claim claim"
.Fc
.Ft void
.Fo zt_assert
.Fa "zt_t t"
.Fa "zt_claim claim"
.Fc
.Sh DESCRIPTION
Both
.Fn zt_check
and
.Fn zt_assert
verify a claim, encompassing a function with arguments, and is meant to
be used inside test functions.
.Pp
The first argument is a pointer to opaque type encapsulating test outcome.
The second argument is usually constructed with a helper macro, such as
.Fn ZT_CMP_TRUE
or
.Fn ZT_CMP_FALSE .
.Pp
If the claim holds then happens and execution continues normally.
If the claim does not hold then the test is marked as failed and
a diagnostic message is printed to
.Em stderr .
.Pp
The only difference between
.Fn zt_check
and
.Fn zt_assert
is that the former allows the test to continue executing while the latter
performs a non-local exit from the test function. Note that only the
currently executing test function is affected. Other tests cases and test suites will still execute normally.
.Pp
.Fn zt_check
should be used when it is safe to execute remainder of the test even if the
claim is not true. This approach allows each failure to be accompanied by as
much diagnostic output as possible, without causing the test program to
crash.
.Pp
.Fn zt_assert
should be used when it is not safe or meaningless to execute remainder of the
test on failure.
.Sh IMPLEMENTATION NOTES
Non-local exit from
.Fn zt_assert
is implemented using
.Fn siglongjump .
One should not depend on neither C++ destructors nor the GCC cleanup function extension for correct resource management.
.Sh RETURN VALUES
Neither function return anything. Failures are remembered inside the opaque
.Nm zt_test
structure passed by pointer (aka
.Nm zt_t )
as the first argument.
.Sh EXAMPLES
A minimal test program that looks up the UNIX user
.Em root
and measures several properties of the returned record.
.Bd -literal -offset indent
#include
#include
#include
static void test_root_user(zt_t t) {
struct passwd *p = getpwnam("root");
zt_assert(t, ZT_NOT_NULL(p));
zt_check(t, ZT_CMP_CSTR(p->pw_name, ==, "root"));
zt_check(t, ZT_CMP_INT(p->pw_uid, ==, 0));
zt_check(t, ZT_CMP_INT(p->pw_gid, ==, 0));
}
static void test_suite(zt_visitor v) {
ZT_VISIT_TEST_CASE(v, test_root_user);
}
int main(int argc, char** argv, char** envp) {
return zt_main(argc, argv, envp, test_suite);
}
.Ed
.Sh SEE ALSO
.Xr ZT_CMP_BOOL 3 ,
.Xr ZT_CMP_CSTR 3 ,
.Xr ZT_CMP_INT 3 ,
.Xr ZT_CMP_PTR 3 ,
.Xr ZT_CMP_UINT 3 ,
.Xr ZT_FALSE 3 ,
.Xr ZT_NOT_NULL 3 ,
.Xr ZT_NULL 3 ,
.Xr ZT_TRUE 3
.Sh HISTORY
The
.Fn zt_check
and the
.Fn zt_assert
functions first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_claim.3.in 0000644 0001750 0001750 00000005003 13673206643 014505 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_claim 3 PRM
.Sh NAME
.Nm zt_claim
.Nd structure capturing unevaluated assertion
.Sh SYNOPSIS
.In zt.h
.Vt typedef struct zt_claim { ... } zt_claim;
.Bl -column "struct zt_verifier *(*)(void) " "make_verifier " Description"
.It Sy Type Ta Sy Member Ta Sy Description
.It Vt struct zt_verifier *(*)(void) Ta make_verifier Ta Verifier factory
.It Vt zt_value[3] Ta args Ta verifier arguments
.It Vt zt_location Ta location Ta origin of the claim
.El
.Sh DESCRIPTION
.Nm
binds a verifier factory function with concrete arguments. This allows the
entire claim to be passed around and evaluated on demand. In case of failure
the location where the claim was made can be referenced for construction of
error messages.
.Sh IMPLEMENTATION NOTES
The verification system is comprised of the following chain of cooperating
elements. For example a trivial integer relationship assertion behaves as
follows.
.Fn ZT_CMP_INT ,
or another similar macro, invokes
.Fn zt_cmp_int ,
providing source code location as
.Nm zt_location ,
and packaging specific types into common variant type
.Nm zt_value .
The result is a
.Nm zt_claim
which is then passed to
.Fn zt_assert
or
.Fn zt_check
for evaluation.
.Pp
The roles of all the essential types and functions is summarized below.
.Bl -bullet
.It
.Nm zt_value
captures values expressed in a test case
.It
.Nm zt_claim
transports up to three values and an opaque verifier
.It
.Fn zt_check
and
.Fn zt_assert
validate the claim by instantiating
.Nm zt_verifier.
.It
.Nm zt_verifier
(private) wraps a verification function, including the arity and expected
kind of each argument.
.It
.Nm zt_arg_info
(private) pairs expected argument kind with a customized error message used
on kind mismatch.
.It
.Fn zt_verify_claim
(private) ensures verifier function arity and argument kind matches what is
encoded in the claim and invokes the verifier function.
.It
The specific verifier function inspects the argument and performs the actual
verification of the desired property that the test is measuring.
.It
.Nm zt_test
(private) keeps track of test outcome, provides a stream for writing error
messages and assists in performing non-local exit.
.El
.Sh SEE ALSO
.Xr zt_assert 3 ,
.Xr zt_check 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh BUGS
Part of the API is private which prevents third party verification functions
from being written. This is done on purpose to to allow for some more
experimentation before stabilizing the interface.
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_location.3.in 0000644 0001750 0001750 00000001556 13673206643 015241 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_location 3 PRM
.Sh NAME
.Nm zt_location
.Nd description of a specific line in a source file
.Sh SYNOPSIS
.In zt.h
.Vt typedef struct zt_location { ... } zt_location;
.Sh DESCRIPTION
.Nm
contains a file name and a line number.
.Bl -column "const char * " "fname " Description"
.It Sy Type Ta Sy Entry Ta Sy Description
.It Vt const char * Ta filename Ta Name of the source file, from __FILE__
.It Vt int Ta lineno Ta Number of the line in said file, from __LINE__
.El
.Pp
Use
.Fn ZT_CURRENT_LOCATION
macro to obtain a location describing the current file and line number.
.Sh IMPLEMENTATION NOTES
.Nm
is used to report the location of failing test checks and assertions.
.Sh SEE ALSO
.Xr ZT_CURRENT_LOCATION 3 ,
.Xr zt_location_at 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_location_at.3.in 0000644 0001750 0001750 00000002002 13673206643 015710 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_location_at 3 PRM
.Sh NAME
.Nm zt_location_at
.Nd pack file name and line number into a location value
.Sh SYNOPSIS
.In zt.h
.Ft zt_location
.Fo zt_location_at
.Fa "const char* fname"
.Fa "int lineno"
.Fc
.Sh DESCRIPTION
.Nm
packs both arguments into a
.Nm zt_location .
It exists to facilitate packing a
.Nm zt_claim
value without any temporary variables. It is useful for support of C compilers
that do not support structure literals.
.Pp
For convenient definition of the current file and line number use the macro
.Fn ZT_CURRENT_LOCATION
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Pp
The fname argument is retained by the value and is typically a constant string
literal produced by the preprocessor.
.Sh RETURN VALUES
A
.Nm zt_location
containing the given file name and line number.
.Sh SEE ALSO
.Xr ZT_CURRENT_LOCATION 3 ,
.Xr zt_location 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_main.3.in 0000644 0001750 0001750 00000001402 13673206643 014343 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_main 3 PRM
.Sh NAME
.Nm zt_main
.Nd command line interface for running tests
.Sh SYNOPSIS
.In zt.h
.Ft int
.Fo zt_main
.Fa "int argc"
.Fa "char **argv"
.Fa "char **envp"
.Fa "zt_test_suite_func tsuite"
.Fc
.Sh DESCRIPTION
.Nm
takes familiar arguments as well as a single test suite function.
Depending on command line arguments some or all tests are
enumerated and printed or executed.
.Sh RETURN VALUES
When tests are executed the return value is
.Nm EXIT_SUCCESS
or
.Nm EXIT_FAILURE .
If tests are only listed the return value is always
.Nm EXIT_SUCCESS .
.Sh SEE ALSO
.Xr ZT_VISIT_TEST_CASE 3 ,
.Xr ZT_VISIT_TEST_SUITE 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_boolean.3.in 0000644 0001750 0001750 00000001577 13673206643 016051 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_boolean 3 PRM
.Sh NAME
.Nm zt_pack_boolean
.Nd pack a boolean into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_boolean
.Fa "bool value"
.Fa "const char *source"
.Fc
.Sh DESCRIPTION
.Nm
packs a boolean, as well as the string describing the expression evaluated to
obtain it, into a variant-like
.Ft zt_value .
The source argument is retained by the value and is typically a constant
string literal produced by the preprocessor.
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Sh RETURN VALUES
The packed value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_boolean 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_integer 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_integer.3.in 0000644 0001750 0001750 00000002334 13673206643 016057 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_integer 3 PRM
.Sh NAME
.Nm zt_pack_integer
.Nd pack an integer into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_integer
.Fa "intmax_t value"
.Fa "const char *source"
.Fc
.Sh DESCRIPTION
.Nm
packs an integer, as well as the string describing the expression evaluated to
obtain it, into a variant-like
.Ft zt_value .
The source argument is retained by the value and is typically a constant
string literal produced by the preprocessor.
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Sh RETURN VALUES
The packed value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_integer 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_integer 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Pp
In libzt 0.3 the type of the first argument changed to
.Nm intmax_t ,
to accommodate for wider values. The resulting value structure encodes the
new corresponding kind,
.Nm ZT_INTMAX .
Note that
.Nm zt_value
objects created by programs compiled with earlier versions of libzt
are still valid and are internally promoted to the wider type.
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_nothing.3.in 0000644 0001750 0001750 00000001220 13673206643 016061 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_nothing 3 PRM
.Sh NAME
.Nm zt_pack_nothing
.Nd pack nothing into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_nothing
.Fa "void"
.Fc
.Sh DESCRIPTION
.Nm
returns an initialized, empty value.
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Sh RETURN VALUES
The empty value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_integer 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_pointer.3.in 0000644 0001750 0001750 00000001626 13673206643 016105 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_pointer 3 PRM
.Sh NAME
.Nm zt_pack_pointer
.Nd pack an opaque pointer into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_pointer
.Fa "const void *value"
.Fa "const char *source"
.Fc
.Sh DESCRIPTION
.Nm
packs an opaque pointer, as well as the string describing the expression
evaluated to obtain it, into a variant-like
.Ft zt_value .
The source argument is retained by the value and is typically a constant
string literal produced by the preprocessor.
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Sh RETURN VALUES
The packed value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_pointer 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_pointer 3 ,
.Xr zt_pack_pointer 3 ,
.Xr zt_pack_pointer 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_rune.3.in 0000644 0001750 0001750 00000002021 13673206643 015364 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_rune 3 PRM
.Sh NAME
.Nm zt_pack_rune
.Nd pack a character into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_rune
.Fa "int value"
.Fa "const char *source"
.Fc
.Sh DESCRIPTION
.Nm
packs a rune, as well as the string describing the expression evaluated to
obtain it, into a variant-like
.Ft zt_value .
The source argument is retained by the value and is typically a constant string
literal produced by the preprocessor.
.Pp
Runes are generalized characters. Unlike char, they are never negative and can
be though of as Unicode code points.
.Sh IMPLEMENTATION NOTES
.Fn zt_pack_rune
compensates for signed negative characters by masking them with 0xFF.
.Sh RETURN VALUES
The packed value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_integer 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_integer 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_string.3.in 0000644 0001750 0001750 00000002106 13673206643 015725 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_string 3 PRM
.Sh NAME
.Nm zt_pack_string
.Nd pack an C string into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_string
.Fa "const char *value"
.Fa "const char *source"
.Fc
.Sh DESCRIPTION
.Nm
packs an C string, as well as the string describing the expression evaluated to
obtain it, into a variant-like
.Ft zt_value .
The source argument is retained by the value and is typically a constant string
literal produced by the preprocessor.
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Pp
Memory referenced by the string is not copied. It is assumed that the memory
reference stays valid during the execution of the verification of an assertion
that relies on the
.Nm zt_value .
.Sh RETURN VALUES
The packed value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_pack_unsigned.3.in 0000644 0001750 0001750 00000002366 13673206643 016243 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_pack_unsigned 3 PRM
.Sh NAME
.Nm zt_pack_unsigned
.Nd pack an unsigned integer into a variant
.Sh SYNOPSIS
.In zt.h
.Ft zt_value
.Fo zt_pack_unsigned
.Fa "uintmax_t value"
.Fa "const char *source"
.Fc
.Sh DESCRIPTION
.Nm
packs an unsigned integer, as well as the string describing the expression
evaluated to obtain it, into a variant-like
.Ft zt_value .
The source argument is retained by the value and is typically a constant string
literal produced by the preprocessor.
.Sh IMPLEMENTATION NOTES
.Nm
is only provided as a static inline function.
.Sh RETURN VALUES
The packed value.
.Sh SEE ALSO
.Xr zt_pack_nothing 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_rune 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_unsigned 3 ,
.Xr zt_pack_string 3 ,
.Xr zt_pack_pointer 3
.Xr zt_value 3 ,
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Pp
In libzt 0.3 the type of the first argument changed to
.Nm uintmax_t ,
to accommodate for wider values. The resulting value structure encodes the
new corresponding kind,
.Nm ZT_UINTMAX .
Note that
.Nm zt_value
objects created by programs compiled with earlier versions of libzt
are still valid and are internally promoted to the wider type.
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_test.3.in 0000644 0001750 0001750 00000001405 13673206643 014401 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_test 3 PRM
.Sh NAME
.Nm zt_test , zt_t
.Nd private representation of test state
.Sh SYNOPSIS
.Vt struct zt_test
.Vt typedef struct zt_test *zt_t
.Sh DESCRIPTION
.Nm
is an opaque type that holds test state during execution. The test type is
passed as an argument to each test function. It is further passed to both
.Fn zt_check
and
.Fn zt_assert
functions, to alter test state.
.Pp
.Nm zt_t
is is a typedef that cuts the test case boilerplate size.
.Pp
Internally
.Nm
stores the outcome of the test as well as data required for non-local exit,
necessary when
.Fn zt_assert
fails.
.Sh HISTORY
.Nm zt_test
first appeared in libzt 0.1,
.Nm zt_t
first appeared in libzt 0.2.
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_test_case_func.3.in 0000644 0001750 0001750 00000001176 13673206643 016414 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_test_case_func 3 PRM
.Sh NAME
.Nm zt_test_case_func
.Nd type of pointer to a test case function
.Sh SYNOPSIS
.Ft typedef void
.Fo (*zt_test_case_func)
.Fa "zt_t"
.Fc
.Sh DESCRIPTION
.Nm
is a pointer to a function implementing a single test case.
.Sh IMPLEMENTATION NOTES
The
.Nm zt_test
pointer (aka
.Nm zt_t )
argument is meant to be passed to
.Fn zt_check
and
.Fn zt_assert
to alter the outcome of the test.
.Sh SEE ALSO
.Xr zt_test 3 ,
.Xr zt_visit_test_case 3 ,
.Xr zt_visit_test_suite 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_test_suite_func.3.in 0000644 0001750 0001750 00000001373 13673206643 016631 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_test_suite_func 3 PRM
.Sh NAME
.Nm zt_test_suite_func
.Nd type of pointer to a test suite function
.Sh SYNOPSIS
.Ft typedef void
.Fo (*zt_test_suite_func)
.Fa "zt_visitor"
.Fc
.Sh DESCRIPTION
.Nm
is a pointer to a function implementing a test suite, which groups any number
of test cases and other test suites.
.Pp
A single test suite, passed as an argument to
.Fn zt_main ,
is used to enumerate and discover all the tests in a given test program.
.Sh IMPLEMENTATION NOTES
The
.Nm zt_visitor
argument is used to implement the test case and test suite enumeration system.
.Sh SEE ALSO
.Xr zt_main 3 ,
.Xr zt_visitor 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_value.3.in 0000644 0001750 0001750 00000005265 13673206643 014546 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_value 3 PRM
.Sh NAME
.Nm zt_value , zt_value_kind ,
.Nd variant type for passing data into claim verifiers
.Sh SYNOPSIS
.In zt.h
.Vt typedef struct zt_value { ... } zt_value;
.Bl -column "zt_value_kind " "unsigned_integer " Description"
.It Sy Type Ta Sy Entry Ta Sy Description
.It Vt zt_value_kind Ta kind Ta Discriminator for the union
.It Vt const char * Ta source Ta Source code used to compute the value
.It Vt union { ... } Ta as Ta Union containing the actual value
.It Vt bool Ta as.boolean Ta Value when used as ZT_BOOLEAN
.It Vt int Ta as.integer Ta Value when used as ZT_INTEGER
.It Vt unsigned Ta as.unsigned_integer Ta Value when used as ZT_UNSIGNED
.It Vt int Ta as.rune Ta Value when used as ZT_RUNE
.It Vt const char * Ta as.string Ta Value when used as ZT_STRING
.It Vt const void * Ta as.pointer Ta Value when used as ZT_POINTER
.It Vt intmax_t Ta as.intmax Ta Value when used as ZT_INTMAX
.It Vt uintmax_t Ta as.uintmax Ta Value when used as ZT_UINTMAX
.El
.Pp
.Vt typedef enum zt_value_kind { ... } zt_value_kind;
.Bl -column "ZT_NOTHING " " Description"
.It Sy Kind Ta Sy Description
.It Vt ZT_NOTHING Ta Placeholder for unused values
.It Vt ZT_BOOLEAN Ta zt_value.as.boolean is valid
.It Vt ZT_INTEGER Ta zt_value.as.integer is valid (deprecated)
.It Vt ZT_UNSIGNED Ta zt_value.as.unsigned_integer is valid (deprecated)
.It Vt ZT_RUNE Ta zt_value.as.rune is valid
.It Vt ZT_STRING Ta zt_value.as.string is valid
.It Vt ZT_POINTER Ta zt_value.as.pointer is valid
.It Vt ZT_INTMAX Ta zt_value.as.intmax is valid
.It Vt ZT_UINTMAX Ta zt_value.as.uintmax is valid
.El
.Sh DESCRIPTION
.Nm zt_value
is a variant-like type that is used to pass values around libzt internals.
It is comprised of the
.Em kind
enumeration, the
.Em as
union
as well as the
.Em source
string.
.Pp
.Nm zt_value_kind
describes type of verification function arguments.
.Sh IMPLEMENTATION NOTES
.Nm zt_value
exists to pass packed values of several types from the test source code,
through the
.Nm zt_claim
type and into private verification functions that determine test outcome.
.Pp
Tests using binary relations encode the operator as an argument of kind
.Em ZT_STRING .
.Sh BUGS
On some architectures
.Nm ZT_INTEGER
and
.Nm ZT_UNSIGNED
are too short to handle
.Nm size_t
and
.Nm ssize_t
values correctly. They are now deprecated and automatically promoted to
.Nm ZT_INTMAX
and
.Nm ZT_UINTMAX
respectively.
.Sh SEE ALSO
.Xr zt_visit_test_case 3 ,
.Xr zt_visit_test_suite 3
.Sh HISTORY
.Nm zt_value
and
.Nm zt_value_kind
first appeared in libzt 0.1
.Pp
.Nm ZT_INTMAX ,
.Nm ZT_UINTMAX
and the corresponding union members first appeared in libzt 0.3.
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_visit_test_case.3.in 0000644 0001750 0001750 00000004225 13673206643 016615 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt ZT_VISIT_TEST_CASE 3 PRM
.Sh NAME
.Nm zt_visit_test_case ,
.Nm ZT_VISIT_TEST_CASE ,
.Nm zt_visit_test_suite ,
.Nm ZT_VISIT_TEST_SUITE
.Nd discover test cases and their structure
.Sh SYNOPSIS
.In zt.h
.Ft void
.Fo zt_visit_test_case
.Fa "zt_visitor v"
.Fa "zt_test_case_func func"
.Fa "const char *name"
.Fc
.Fd #define ZT_VISIT_TEST_CASE(v, tcase) zt_visit_test_case(v, tcase, #tcase)
.Ft void
.Fo zt_visit_test_case
.Fa "zt_visitor v"
.Fa "zt_test_suite_func func"
.Fa "const char *name"
.Fc
.Fd #define ZT_VISIT_TEST_SUITE(v, tsuite) zt_visit_test_suite(v, tsuite, #tsuite)
.Sh DESCRIPTION
.Fn zt_visit_test_case
and
.Fn zt_visit_test_suite ,
or more usually - under their macro from
.Fn ZT_VISIT_TEST_CASE
and
.Fn ZT_VISIT_TEST_SUITE ,
are used to implement discovery for test suites and test cases. Test suites are
represented as functions that visit other test suites and test cases. Test
cases are represented as functions that execute actual test code.
.Pp
The macros are provided as convenience to avoid having to invent names.
.Pp
Typically the main test suite is passed as an argument to
.Fn zt_main
which handles the rest of the discovery, and if necessary, execution.
.Sh RETURN VALUES
Visit functions do not return any value.
.Sh EXAMPLES
The following example shows how to create a test suite with two test cases. A
suite can contain any number of nested suites and test cases.
.Bd -literal -offset indent
#include
static void test_foo(zt_t t) {
printf("foo invoked\\n");
}
static void suite_inner(zt_visitor v) {
ZT_VISIT_TEST_CASE(v, test_foo);
}
static void test_bar(zt_t t) {
printf("bar invoked\\n");
}
static void main_suite(zt_visitor v) {
ZT_VISIT_TEST_SUITE(v, suite_inner);
ZT_VISIT_TEST_CASE(v, test_bar);
}
int main(int argc, char** argv, char** envp) {
return zt_main(argc, argv, envp, main_suite);
}
.Ed
.Sh SEE ALSO
.Xr zt_main 3 ,
.Xr zt_test_suite_func 3 ,
.Xr zt_test_case_func 3 ,
.Sh HISTORY
The
.Fn zt_visit_test_case
and the
.Fn zt_visit_test_suite
functions, as well as the corresponding macros, first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/man/zt_visitor.3.in 0000644 0001750 0001750 00000002633 13673206643 015125 0 ustar zyga zyga .Dd January 12, 2020
.Os libzt @VERSION@
.Dt zt_visitor 3 PRM
.Sh NAME
.Nm zt_visitor , zt_visitor_vtab
.Nd interface for discovering test suites and test cases
.Sh SYNOPSIS
.In zt.h
.Vt typedef struct zt_visitor { ... } zt_visitor;
.Bl -column "struct zt_visitor_vtab * " "vtab " Description"
.It Sy Type Ta Sy Entry Ta Sy Description
.It Vt void * Ta id Ta Object implementing the interface
.It Vt struct zt_visitor_vtab * Ta vtab Ta Table of interface functions
.El
.Sh DESCRIPTION
.Nm
is an interface for exploring test suites and test cases. The visitor type is
used as an argument to all test suites. Test suites can enumerate test cases
and other test suites. It is a part of the implementation and is not expected
to be implemented by library users.
.Pp
.Nm zt_visitor_vtab
is an opaque type comprised of functions that define the interface. The
interface is only used internally so the implementation is private.
.Sh IMPLEMENTATION NOTES
Interface values combine an object pointer with a function table pointer and
are passed by value.
.Pp
An interface can use the NULL pointer as an object pointer if there is no need
to refer to any data specific to an instance. The function table pointer cannot
be null as it defines the unique aspect of the implementation.
.Sh SEE ALSO
.Xr zt_visit_test_case 3 ,
.Xr zt_visit_test_suite 3
.Sh HISTORY
.Nm
first appeared in libzt 0.1
.Sh AUTHORS
.An "Zygmunt Krynicki" Aq Mt me@zygoon.pl
libzt_0.3.1/z.mk 0000644 0001750 0001750 00000010376 13675422347 012255 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
NAME ?= $(error define NAME - the name of the project)
VERSION ?= $(error define VERSION - the static version of the project)
# Speed up make by removing suffix rules.
.SUFFIXES:
# The location of the source code.
srcdir ?= .
# Version of the zmk library.
ZMK.Version = 0.3.6
# Location of include files used by the makefile system. Normally this is the
# zmk subdirectory of /usr/include, as this is where make is importing things
# from.
ZMK.z.mk := $(lastword $(MAKEFILE_LIST))
ZMK.Path ?= $(or $(patsubst %/,%,$(dir $(ZMK.z.mk))),.)
# Modules and templates present in the package
ZMK.modules = \
AllClean \
Configure \
Coverity \
Directories \
Directory \
GitVersion \
Header \
InstallUninstall \
Library.A \
Library.DyLib \
Library.So \
ManPage \
OS \
ObjectGroup \
PVS \
Program \
Program.Test \
Script \
Symlink \
Tarball \
Tarball.Src \
Toolchain \
toolchain.Clang \
toolchain.GCC \
toolchain.Tcc \
toolchain.Watcom \
internalTest
# Manual pages present in the package.
ZMK.manPages = \
zmk.AllClean.5 \
zmk.Configure.5 \
zmk.Directories.5 \
zmk.OS.5 \
zmk.Program.5 \
zmk.Script.5 \
zmk.Toolchain.5
# Files belonging to ZMK that need to be distributed in third-party release tarballs.
ZMK.DistFiles = z.mk $(addprefix zmk/,$(foreach m,$(ZMK.modules),$m.mk) pvs-filter.awk)
# If zmk is provided externally add rules to copy it to the source tree and
# make the distclean target remove it from the tree.
ifneq ($(ZMK.Path),$(srcdir))
$(srcdir)/zmk:
install -d $@
$(srcdir)/zmk/%: $(ZMK.Path)/zmk/% | $(srcdir)/zmk
install -m 644 $< $@
$(srcdir)/z.mk: $(ZMK.Path)/z.mk
install -m 644 $< $@
distclean::
rm -rf $(srcdir)/zmk
rm -f $(srcdir)/z.mk
rm -f configure
endif
# ZMK Copyright Banner. Do not remove.
# You are not allowed to remove or alter this while staying compliant with the LGPL license.
MAKECMDGOALS ?=
ifeq ($(MAKECMDGOALS),)
$(info z.mk v$(ZMK.Version), Copyright (c) 2019-2020 Zygmunt Krynicki)
endif
# Meta-targets that don't have specific specific commands
.PHONY: $(sort all clean coverage fmt static-check check install uninstall dist distclean)
# Run static checks when checking
check:: static-check
# Default goal is to build everything, regardless of declaration order
.DEFAULT_GOAL = all
# Display diagnostic messages when DEBUG has specific items.
ZMK.comma=,
DEBUG ?=
DEBUG := $(subst $(ZMK.comma), ,$(DEBUG))
# Define the module and template system.
ZMK.ImportedModules ?=
ZMK.expandStack = 0
ZMK.nesting.0 = > #
ZMK.nesting.1 = ... > #
ZMK.nesting.2 = ... ... > #
ZMK.nesting.3 = ... ... ... > #
ZMK.nesting.4 = ... ... ... ... > #
define ZMK.Import
ifeq (,$1)
$$(error incorrect call to ZMK.Import, expected module name)
endif
ifeq (,$$(filter $1,$$(ZMK.ImportedModules)))
$$(if $$(findstring import,$$(DEBUG)),$$(info DEBUG: importing »$1«))
ZMK.ImportedModules += $1
include $$(ZMK.Path)/zmk/$1.mk
endif
endef
ZMK.variablesShown =
define ZMK.showVariable
ifeq (,$$(findstring $1,$$(ZMK.variablesShown)))
$$(info DEBUG: $$(ZMK.nesting.$$(ZMK.expandStack))$1=$$($1))
ZMK.variablesShown += $1
endif
endef
define ZMK.Expand
ifeq (,$1)
$$(error incorrect call to ZMK.Expand, expected module name)
endif
ifeq (,$2)
$$(error incorrect call to ZMK.Expand, expected variable name)
endif
$$(eval $$(call ZMK.Import,$1))
$$(if $$(findstring expand,$$(DEBUG)),$$(info DEBUG: $$(ZMK.nesting.$$(ZMK.expandStack))expanding template $1("$2")))
ZMK.expandStack := $$(shell expr $$(ZMK.expandStack) + 1)
$$(eval $$(call $1.Template,$2))
ZMK.expandStack := $$(shell expr $$(ZMK.expandStack) - 1)
$$(if $$(findstring expand,$$(DEBUG)),$$(foreach n,$$($1.Variables),$$(eval $$(call ZMK.showVariable,$2.$$n))))
endef
libzt_0.3.1/zmk/AllClean.mk 0000644 0001750 0001750 00000001343 13675422347 014252 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
AllClean.Variables=
define AllClean.Template
all:: $1
clean::
rm -f $1
endef
libzt_0.3.1/zmk/Configure.mk 0000644 0001750 0001750 00000035123 13675422347 014523 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# Is zmk debugging enabled for this module?
Configure.debug ?= $(findstring configure,$(DEBUG))
# Configuration system defaults, also changed by GNUMakefile.configure.mk
Configure.HostArchTriplet ?=
Configure.BuildArchTriplet ?=
Configure.DependencyTracking ?= yes
Configure.MaintainerMode ?= yes
Configure.SilentRules ?=
Configure.ProgramPrefix ?=
Configure.ProgramSuffix ?=
Configure.ProgramTransformName ?=
Configure.Configured ?=
Configure.Options ?=
# Include optional generated makefile from the configuration system.
# This makefile can only set one of the variables listed above.
-include GNUmakefile.configure.mk
$(if $(Configure.debug),$(foreach v,$(filter Configure.%,$(.VARIABLES)),$(info DEBUG: $v=$($v))))
# ZMK provides a custom configuration script, this is is the full text
define Configure.script
#!/bin/sh
# Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# This script was automatically generated by zmk version $(ZMK.Version).
while [ "$$#" -ge 1 ]; do
case "$$1" in
-h|--help)
echo "Usage: ./configure [OPTIONS]"
echo
echo "Compilation options:"
echo " --build=GNU_TRIPLET Describe the build machine with the given GNU_TRIPLET"
echo " --host=GNU_TRIPLET Describe the host machine with the given GNU_TRIPLET"
echo " --enable-dependency-tracking"
echo " Track dependencies between files (implicit)"
echo " --disable-dependency-tracking"
echo " Do not generate or use dependency data during builds"
echo " --enable-maintainer-mode Enable maintainer mode (implicit)"
echo " --disable-maintainer-mode Disable maintainer mode"
echo
echo "Build-time directory selection:"
echo " --prefix=PREFIX Set prefix for all directories to PREFIX"
echo " --exec-prefix=PREFIX Set prefix for libraries and programs to PREFIX"
echo
echo " --bindir=DIR Install user programs to DIR"
echo " --sbindir=DIR Install super-user programs to DIR"
echo " --libdir=DIR Install runtime and development libraries to DIR"
echo " --libexecdir=DIR Install library-internal programs to DIR"
echo " --includedir=DIR Install development header files to DIR"
echo " --mandir=DIR Install manual pages to DIR"
echo " --infodir=DIR Install GNU info pages to DIR"
echo " --sysconfdir=DIR Install system configuration files to DIR"
echo " --datadir=DIR Install read-only data files to DIR"
echo
echo " --localstatedir=DIR Store persistent state specific to a machine in DIR"
echo " --runstatedir=DIR Store ephemeral state specific to a machine in DIR"
echo " --sharedstatedir=DIR Store state shared across machines in DIR"
echo
echo "Options for altering program names:"
echo " --program-prefix=PREFIX Put PREFIX before installed program names"
echo " --program-suffix=SUFFIX Put SUFFIX after installed program names"
echo " --program-transform-name=PROGRAM"
echo " Use sed PROGRAM to transform installed program names"
echo
echo "Miscellaneous options:"
echo " --enable-option-checking Report unrecognized configuration options (implicit)"
echo " --disable-option-checking Ignore unrecognized configuration options"
echo " --enable-silent-rules Do not display commands while building"
echo " --disable-silent-rules Display commands while building (implicit)"
echo
echo "Memorized environment variables:"
echo " CC Name of the C compiler"
echo " CXX Name of the C++ compiler"
echo " CFLAGS Options for the C compiler"
echo " CXXFLAGS Options for the C++ compiler"
echo " CPPFLAGS Options for the preprocessor"
echo " LDFLAGS Options for the linker"
exit 0
;;
--version)
echo "z.mk configure script version $(ZMK.Version)"
exit 0
;;
*)
break
;;
esac
done
{
# Given key=value or key="value value", print the value
rhs() {
echo "$$*" | cut -d '=' -f 2- | sed -e 's/^"//' -e 's/"$$//'
}
echo "# Generated by zmk configuration script version $(ZMK.Version)"
echo "# ./configure $$*"
configureOptions="$$*"
echo
echo "# Location of the source code."
if [ -n "$${srcdir:-}" ]; then
echo "srcdir=$$srcdir"
else
echo "srcdir=$$(dirname "$$0")"
fi
echo
echo "# Set VPATH for make (for out-of-tree builds)."
echo "VPATH=\$$(srcdir)"
while [ "$$#" -ge 1 ]; do
case "$$1" in
--build=*) buildArchTriplet="$$(rhs "$$1")" && shift ;;
--host=*) hostArchTriplet="$$(rhs "$$1")" && shift ;;
--enable-dependency-tracking) dependencyTracking=yes && shift ;;
--disable-dependency-tracking) dependencyTracking=no && shift ;;
--enable-maintainer-mode) maintainerMode=yes && shift ;;
--disable-maintainer-mode) maintainerMode=no && shift ;;
--enable-silent-rules) silentRules=yes && shift ;;
--disable-silent-rules) silentRules=no && shift ;;
--enable-option-checking) disableOptionChecking=no && shift ;;
--disable-option-checking) disableOptionChecking=yes && shift ;;
--program-prefix=*) programPrefix="$$(rhs "$$1")" && shift ;;
--program-suffix=*) programSuffix="$$(rhs "$$1")" && shift ;;
--program-transform-name=*) programTransformName="$$(rhs "$$1")" && shift ;;
--exec-prefix=*) exec_prefix="$$(rhs "$$1")" && shift ;;
--prefix=*) prefix="$$(rhs "$$1")" && shift ;;
--bindir=*) bindir="$$(rhs "$$1")" && shift ;;
--sbindir=*) sbindir="$$(rhs "$$1")" && shift ;;
--libdir=*) libdir="$$(rhs "$$1")" && shift ;;
--libexecdir=*) libexecdir="$$(rhs "$$1")" && shift ;;
--datadir=*) datadir="$$(rhs "$$1")" && shift ;;
--includedir=*) includedir="$$(rhs "$$1")" && shift ;;
--infodir=*) infodir="$$(rhs "$$1")" && shift ;;
--mandir=*) mandir="$$(rhs "$$1")" && shift ;;
--sysconfdir=*) sysconfdir="$$(rhs "$$1")" && shift ;;
--localstatedir=*) localstatedir="$$(rhs "$$1")" && shift ;;
--runstatedir=*) runstatedir="$$(rhs "$$1")" && shift ;;
--sharedstatedir=*) sharedstatedir="$$(rhs "$$1")" && shift ;;
CC=*) CC="$$(rhs "$$1")" && shift ;;
CXX=*) CXX="$$(rhs "$$1")" && shift ;;
CFLAGS=*) CFLAGS="$$(rhs "$$1")" && shift ;;
OBJCFLAGS=*) OBJCFLAGS="$$(rhs "$$1")" && shift ;;
CXXFLAGS=*) CXXFLAGS="$$(rhs "$$1")" && shift ;;
CPPFLAGS=*) CPPFLAGS="$$(rhs "$$1")" && shift ;;
LDFLAGS=*) LDFLAGS="$$(rhs "$$1")" && shift ;;
*)
if [ "$${disableOptionChecking:-}" != yes ]; then
echo "configure: unknown option $$1" >&2
configureFailed=1
fi
shift
;;
esac
done
echo
echo "# Build and host architecture triplets."
echo "# Note that those impact compiler selection unless overridden."
test -n "$${buildArchTriplet:-}" && echo "Configure.BuildArchTriplet=$$buildArchTriplet" || echo "# Configure.BuildArchTriplet was not specified."
test -n "$${hostArchTriplet:-}" && echo "Configure.HostArchTriplet=$$hostArchTriplet" || echo "# Configure.HostArchTriplet was not specified."
echo
echo "# Build-time configuration of application directories."
test -n "$${prefix:-}" && echo "prefix=$$prefix" || echo "# prefix was not specified."
test -n "$${exec_prefix:-}" && echo "exec_prefix=$$exec_prefix" || echo "# exec_prefix was not specified."
test -n "$${bindir:-}" && echo "bindir=$$bindir" || echo "# bindir was not specified."
test -n "$${sbindir:-}" && echo "sbindir=$$sbindir" || echo "# sbindir was not specified."
test -n "$${datadir:-}" && echo "datadir=$$datadir" || echo "# datadir was not specified."
test -n "$${includedir:-}" && echo "includedir=$$includedir" || echo "# includedir was not specified."
test -n "$${infodir:-}" && echo "infodir=$$infodir" || echo "# infodir was not specified."
test -n "$${libdir:-}" && echo "libdir=$$libdir" || echo "# libdir was not specified."
test -n "$${libexecdir:-}" && echo "libexecdir=$$libexecdir" || echo "# libexecdir was not specified."
test -n "$${localstatedir:-}" && echo "localstatedir=$$localstatedir" || echo "# localstatedir was not specified."
test -n "$${mandir:-}" && echo "mandir=$$mandir" || echo "# mandir was not specified."
test -n "$${runstatedir:-}" && echo "runstatedir=$$runstatedir" || echo "# runstatedir was not specified."
test -n "$${sharedstatedir:-}" && echo "sharedstatedir=$$sharedstatedir" || echo "# sharedstatedir was not specified."
test -n "$${sysconfdir:-}" && echo "sysconfdir=$$sysconfdir" || echo "# sysconfdir was not specified."
echo
echo "# Inherited environment variables and overrides."
test -n "$$CC" && echo "CC=$$CC" || echo "# CC was not specified."
test -n "$$CXX" && echo "CXX=$$CXX" || echo "# CXX was not specified."
test -n "$$CFLAGS" && echo "CFLAGS=$$CFLAGS" || echo "# CFLAGS was not specified."
test -n "$$CXXFLAGS" && echo "CXXFLAGS=$$CXXFLAGS" || echo "# CXXFLAGS was not specified."
test -n "$$OBJCFLAGS" && echo "OBJCFLAGS=$$OBJCFLAGS" || echo "# OBJCFLAGS was not specified."
test -n "$$CPPFLAGS" && echo "CPPFLAGS=$$CPPFLAGS" || echo "# CPPFLAGS was not specified."
test -n "$$LDFLAGS" && echo "LDFLAGS=$$LDFLAGS" || echo "# LDFLAGS was not specified."
echo
echo "# Track dependencies between objects and source and header files."
case "$${dependencyTracking:-implicit}" in
yes)
echo "Configure.DependencyTracking=yes"
;;
no)
echo "Configure.DependencyTracking="
;;
implicit)
echo "# Configure.DependencyTracking was not specified."
;;
esac
echo
echo "# Additional options for package maintainers."
case "$${maintainerMode:-implicit}" in
yes)
echo "Configure.MaintainerMode=yes"
;;
no)
echo "Configure.MaintainerMode="
;;
implicit)
echo "# Configure.MaintainerMode was not specified."
;;
esac
echo
echo "# Silence shell commands used by make."
case "$${silentRules:-implicit}" in
yes)
echo "Configure.SilentRules=yes"
;;
no)
echo "Configure.SilentRules="
;;
implicit)
echo "# Configure.SilentRules was not specified."
;;
esac
echo
echo "# Program name customization options."
test -n "$${programPrefix:-}" && echo "Configure.ProgramPrefix=$$programPrefix" || echo "# Configure.ProgramPrefix was not specified."
test -n "$${programSuffix:-}" && echo "Configure.ProgramSuffix=$$programSuffix" || echo "# Configure.ProgramSuffix was not specified."
test -n "$${programTransformName:-}" && echo "Configure.ProgramTransformName=$$programTransformName" || echo "# Configure.ProgramTransformName was not specified."
echo
echo "# Remember that the configuration script was executed."
echo "Configure.Configured=yes"
echo "Configure.Options=$$configureOptions"
} > "$${ZMK_CONFIGURE_MAKEFILE:=GNUmakefile.configure.mk}"
if [ "$${configureFailed:-0}" -eq 1 ]; then
rm -f "$${ZMK_CONFIGURE_MAKEFILE}"
exit 1
fi
if [ ! -e Makefile ] && [ ! -e GNUmakefile ]; then
ln -s "$$(dirname "$$0")"/GNUmakefile GNUmakefile
fi
endef
# In maintainer mode the configure script is automatically updated.
ifeq ($(Configure.MaintainerMode),yes)
configure: export ZMK_CONFIGURE_SCRIPT = $(Configure.script)
configure: $(ZMK.Path)/z.mk $(wildcard $(ZMK.Path)/zmk/*.mk)
@echo "$${ZMK_CONFIGURE_SCRIPT}" >$@
chmod +x $@
# In maintainer mode, re-configure in response to updates to the configuration script.
ifeq ($(Configure.Configured),yes)
GNUmakefile.configure.mk: configure
@echo "re-configuring, $< script is newer than $@"
./$< $(Configure.Options)
endif # !configured
endif # !maintainer mode
distclean::
rm -f GNUmakefile.configure.mk
libzt_0.3.1/zmk/Coverity.mk 0000644 0001750 0001750 00000001710 13675422347 014401 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
Coverity.Sources ?= $(error define Coverity.Sources - the list of source files to analyze with Coverity)
clean::
rm -rf cov-int
rm -f $(NAME)-$(VERSION)-coverity.tar.gz
cov-int: $(Coverity.Sources) $(MAKEFILE_LIST)
cov-build --dir $@ $(MAKE)
$(NAME)-$(VERSION)-coverity.tar.gz: cov-int
tar zcf $@ $<
libzt_0.3.1/zmk/Directories.mk 0000644 0001750 0001750 00000004647 13675422347 015065 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# Is zmk debugging enabled for this module?
Directories.debug ?= $(findstring directories,$(DEBUG))
# Installation prefix.
prefix ?= /usr/local
$(if $(Directories.debug),$(info DEBUG: prefix=$(prefix)))
exec_prefix ?= $(prefix)
# Relevant UNIX-y directories.
bindir ?= $(exec_prefix)/bin
sbindir ?= $(exec_prefix)/sbin
libexecdir ?= $(exec_prefix)/libexec
datarootdir ?= $(prefix)/share
datadir ?= $(datarootdir)
sysconfdir ?= $(prefix)/etc
sharedstatedir ?= $(prefix)/com
localstatedir ?= $(prefix)/var
runstatedir ?= $(localstatedir)/run
includedir ?= $(prefix)/include
infodir ?= $(datarootdir)info
libdir ?= $(exec_prefix)/lib
localedir ?= $(datarootdir)/locale
mandir ?= $(datarootdir)/man
man1dir ?= $(mandir)/man1
man2dir ?= $(mandir)/man2
man3dir ?= $(mandir)/man3
man4dir ?= $(mandir)/man4
man5dir ?= $(mandir)/man5
man6dir ?= $(mandir)/man6
man7dir ?= $(mandir)/man7
man8dir ?= $(mandir)/man8
man9dir ?= $(mandir)/man9
# List of standard directories. Those are created with a single rule below, and
# can be safely used as a order-only dependency.
Directories.POSIX = \
$(prefix) $(exec_prefix) $(bindir) $(sbindir) $(libexecdir) \
$(datarootdir) $(datadir) $(sysconfdir) $(sharedstatedir) \
$(localstatedir) $(runstatedir) $(includedir) \
$(infodir) $(libdir) $(localedir) $(mandir) $(man1dir) \
$(man2dir) $(man3dir) $(man4dir) $(man5dir) $(man6dir) $(man7dir) \
$(man8dir) $(man9dir)
# If NAME is defined, also define docdir.
ifneq ($(value NAME),$$(error define NAME - the name of the project))
docdir ?= $(datarootdir)/doc/$(NAME)
Directories.POSIX += $(docdir)
endif
$(if $(Directories.debug),$(info DEBUG: Directories.POSIX=$(Directories.POSIX)))
# Provide implicit rules for all the well-known directories.
$(foreach d,$(Directories.POSIX),$(eval $(call ZMK.Expand,Directory,$d))) libzt_0.3.1/zmk/Directory.mk 0000644 0001750 0001750 00000004515 13675422347 014547 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# List of directories that need to be created and have corresponding rules.
# Those are automatically handled, on demand, by expanding the Directory
# template. That template handles order-only dependencies on the parent
# directory, so, for example, creating /usr/share/man/man5 automatically
# depends on /usr/share/man, and so on.
Directory.known =
Directory.debug ?= $(findstring directory,$(DEBUG))
# Define DESTDIR to an empty value so that make --warn-undefined-variables
# does not complain about it.
ifeq ($(origin DESTDIR),undefined)
DESTDIR ?=
else
$(DESTDIR):
mkdir -p $@
# Warn if DESTDIR is defined in a makefile. This is probably a mistake.
ifeq ($(origin DESTDIR),file)
$(warning DESTDIR should be set only through environment variable, not in a makefile)
endif
endif
$(if $(Directory.debug),$(info DEBUG: DESTDIR=$(DESTDIR)))
# Plain directory. This template is used by other parts of ZMK.
Directory.Variables=
define Directory.Template
ifneq ($1,/)
$1.cleaned=$$(patsubst %/,%,$1)
else
$1.cleaned=$1
endif
ifneq ($$($1.cleaned),.)
ifneq ($$($1.cleaned),/)
ifeq (,$$(filter $$($1.cleaned),$$(Directory.known)))
$1.parentDir = $$(patsubst %/,%,$$(dir $$($1.cleaned)))
ifneq (,$$($1.parentDir))
ifeq (,$$(filter $$($1.parentDir),$$(Directory.known)))
$$(eval $$(call ZMK.Expand,Directory,$$($1.parentDir)))
endif # !parent known
endif # !parent empty
Directory.known += $$($1.cleaned)
ifeq (/,$$(patsubst /%,/,$$($1.cleaned)))
# Absolute directories respect DESTDIR
$$(DESTDIR)$$($1.cleaned): | $$(DESTDIR)$$($1.parentDir)
install -d $$@
else
# Relative directories do not observe DESTDIR
$$($1.cleaned): | $$($1.parentDir)
install -d $$@
endif # !absolute
endif # !known
endif # !.
endif # !/
endef
libzt_0.3.1/zmk/GitVersion.mk 0000644 0001750 0001750 00000005747 13675422347 014704 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# Craft a better version if we have Git.
GitVersion.debug ?= $(findstring version,$(DEBUG))
GitVersion.versionFilePresent = $(if $(wildcard $(srcdir)/.version),yes)
GitVersion.gitAvailable ?= $(if $(shell command -v git 2>/dev/null),yes)
GitVersion.gitMetaDataPresent ?= $(if $(wildcard $(srcdir)/.git),yes)
GitVersion.versionFromMakefile := $(strip $(VERSION))
GitVersion.versionFromFile =
GitVersion.versionFromGit =
GitVersion.Active =
ifeq (yes,$(GitVersion.versionFilePresent))
# Note that we never generate this file from any rule in zmk!
# If the source tree contains the .version file then it is authoritative.
GitVersion.versionFromFile:=$(shell cat $(srcdir)/.version 2>/dev/null)
else
ifeq (yes,$(and $(GitVersion.gitAvailable),$(GitVersion.gitMetaDataPresent)))
# If we have the git program and the .git directory then we can also ask git.
GitVersion.versionFromGit=$(shell GIT_DIR=$(srcdir)/.git git describe --abbrev=10 --tags 2>/dev/null | sed -e 's/^v//')
ifneq (,$(value CI))
# If we are in CI and git version was empty then perhaps this is a shallow clone?
ifeq (,$(GitVersion.versionFromGit))
$(error zmk cannot compute project version from git, did the CI system use a shallow clone?))
endif # ! git version
endif # ! CI
endif # version from git
endif # !version from version file
# If we have a version from git, offer a rule that writes it to the source
# tree. This file is picked up by the Tarball.Src module and internally renamed
# to .version inside the archive. When we see the .version file we do not look
# for git information anymore, as it may no longer be the "same" git history.
ifneq (,$(GitVersion.versionFromGit))
$(srcdir)/.version-from-git: $(srcdir)/.git
echo $(GitVersion.versionFromGit) >$@
endif
# Set the new effective VERSION.
VERSION=$(or $(GitVersion.versionFromFile),$(GitVersion.versionFromGit),$(GitVersion.versionFromMakefile))
# If the effective version is different from the version in the makefile then
# set the active flag. This information is used by the Tarball.Src module.
ifneq ($(VERSION),$(GitVersion.versionFromMakefile))
GitVersion.Active = yes
endif
$(if $(GitVersion.debug),$(foreach v,versionFilePresent gitAvailable gitMetaDataPresent versionFromMakefile versionFromFile versionFromGit Active,$(info DEBUG: GitVersion.$v=$(GitVersion.$v))))
$(if $(GitVersion.debug),$(info DEBUG: effective VERSION=$(VERSION)))
libzt_0.3.1/zmk/Header.mk 0000644 0001750 0001750 00000001521 13675422347 013765 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
Header.Variables=
define Header.Template
$1.InstallDir = $(includedir)
$1.InstallMode = 0644
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
endef
libzt_0.3.1/zmk/InstallUninstall.mk 0000644 0001750 0001750 00000003151 13675422347 016076 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
# A file that gets installed to a desired location. The location can be set
# using the .InstallDir instance variable. The special value of noinst prevents
# installation. This template is used by other parts of ZMK, to install
# components they produce.
InstallUninstall.Variables=InstallDir InstallName InstallMode
define InstallUninstall.Template
$1.InstallDir ?= $$(error define $1.InstallDir - the destination directory, or noinst to skip installation)
$1.InstallMode ?= 0644
$1.InstallName ?= $$(notdir $1)
# Unless we don't want to install the file, look below.
ifneq ($$($1.InstallDir),noinst)
install:: $$(DESTDIR)$$($1.InstallDir)/$$($1.InstallName)
uninstall::
rm -f $$(DESTDIR)$$($1.InstallDir)/$$($1.InstallName)
$$(eval $$(call ZMK.Expand,Directory,$$($1.InstallDir)))
$$(DESTDIR)$$($1.InstallDir)/$$($1.InstallName): $1 | $$(DESTDIR)$$($1.InstallDir)
$$(strip install -m $$($1.InstallMode) $$^ $$@)
endif # noinst
endef
libzt_0.3.1/zmk/Library.A.mk 0000644 0001750 0001750 00000002265 13675422347 014366 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Toolchain))
Library.A.Variables=Sources Objects
define Library.A.Template
ifneq ($$(suffix $1),.a)
$$(error library name $1 must end with ".a")
endif
# Compile library objects.
$$(eval $$(call ZMK.Expand,ObjectGroup,$1))
# Create library archive.
$1: $$($1.Objects)
$$(AR) $$(ARFLAGS) $$@ $$^
# Install library archive.
$1.InstallDir ?= $$(libdir)
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
# React to "all" and "clean".
$$(eval $$(call ZMK.Expand,AllClean,$1))
endef
libzt_0.3.1/zmk/Library.DyLib.mk 0000644 0001750 0001750 00000004037 13675422347 015210 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Toolchain))
Library.DyLib.Variables=Sources ExportList
define Library.DyLib.Template
# Compile library objects.
$1: CFLAGS += -fpic
$1: CXXFLAGS += -fpic
$1: OBJCFLAGS += -fpic
$$(eval $$(call ZMK.Expand,ObjectGroup,$1))
# We are building a dynamic library.
$1: LDFLAGS += -dynamiclib
# Provide current and compatibility version
# TODO: this is preliminary, implement the real thing
$1: LDFLAGS += -compatibility_version 1.0 -current_version 1.0
# If we have a list of exported symbols then switch symbol
# visibility to hidden and pass the list to the linker.
$1.ExportList ?= $$(warning should define $1.ExportList)
ifneq (,$$($1.ExportList))
$1: $$($1.ExportList)
$1: LDFLAGS += -fvisibility=hidden
$1: LDFLAGS += -exported_symbols_list=$$($1.ExportList)
endif
# Link library objects.
$1: $$($1.Objects)
$$(strip $$(if $$($1.ObjectsObjC),$$(LINK.m),$$(if $$($1.ObjectsCxx),$$(LINK.cc),$$(LINK.o))) -o $$@ $$(filter %.o,$$^) $$(LDLIBS))
# Install library binary.
$1.InstallDir ?= $$(libdir)
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
# React to "all" and "clean".
$$(eval $$(call ZMK.Expand,AllClean,$1))
# Create symlink (alias) to the versioned library.
$1.alias ?= $$(basename $$(basename $1)).dylib
$$($1.alias).InstallDir ?= $$($1.InstallDir)
$$($1.alias).SymlinkTarget = $1
$$(eval $$(call ZMK.Expand,Symlink,$$($1.alias)))
endef
libzt_0.3.1/zmk/Library.So.mk 0000644 0001750 0001750 00000004655 13675422347 014574 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Toolchain))
Library.So.Variables=Sources SoName InstallDir VersionScript
define Library.So.Template
# Compile library objects.
$1: CFLAGS += -fpic
$1: CXXFLAGS += -fpic
$1: OBJCFLAGS += -fpic
$$(eval $$(call ZMK.Expand,ObjectGroup,$1))
# Watcom doesn't build dynamic libraries.
ifneq (,$$(Toolchain.$$(if $$($1.ObjectsObjC),CC,$$(if $$($1.ObjectsCxx),CXX,CC)).IsWatcom))
$$(error Watcom does not support shared libraries))
endif # watcom
# We are building a shared library.
$1: LDFLAGS += -shared
# If we have a soname then store it in the shared library.
$1.SoName ?= $1
ifneq (,$$($1.SoName))
$1: LDFLAGS += -Wl,-soname=$$($1.SoName)
endif # soname
#
# If we have a version script switch symbol visibility to hidden
# and use the version script to define precise version mapping.
$1.VersionScript ?= $$(warning define $1.VersionScript - the name of a ELF symbol map)
ifneq (,$$($1.VersionScript))
# Tcc does not support version scripts.
#
ifeq (,$$(Toolchain.$$(if $$($1.ObjectsObjC),CC,$$(if $$($1.ObjectsCxx),CXX,CC)).IsTcc))
$1: $$($1.VersionScript)
$1: LDFLAGS += -fvisibility=hidden
$1: LDFLAGS += -Wl,--version-script=$$($1.VersionScript)
endif # !tcc
endif # VersionScript
# Link library objects.
$1: $$($1.Objects)
$$(strip $$(if $$($1.ObjectsObjC),$$(LINK.m),$$(if $$($1.ObjectsCxx),$$(LINK.cc),$$(LINK.o))) -o $$@ $$(filter %.o,$$^) $$(LDLIBS))
# Install library binary.
$1.InstallDir ?= $$(libdir)
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
# React to "all" and "clean".
$$(eval $$(call ZMK.Expand,AllClean,$1))
# Create symlink (alias) to the versioned library.
$1.alias = $$(basename $1)
$$($1.alias).InstallDir ?= $$($1.InstallDir)
$$($1.alias).SymlinkTarget = $1
$$(eval $$(call ZMK.Expand,Symlink,$$($1.alias)))
endef
libzt_0.3.1/zmk/ManPage.mk 0000644 0001750 0001750 00000002535 13675422347 014113 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
# GNU man can be used to perform rudimentary validation of manual pages.
#ifneq ($(and $(shell command -v man 2>/dev/null),$(shell man --help 2>&1 | grep -F -- --warning)),)
#static-check-manpages:
# LC_ALL=C MANROFFSEQ='' MANWIDTH=80 man --warnings -E UTF-8 -l -Tutf8 -Z $^ 2>&1 >/dev/null | diff -u - /dev/null
#static-check:: static-check-manpages
#endif
ManPage.Variables=Section
define ManPage.Template
$1.Section ?= $$(patsubst .%,%,$$(suffix $1))
$1.InstallDir = $$(if $$(man$$($1.Section)dir),$$(man$$($1.Section)dir),$$(error unknown section $$($1.Section)))
$1.InstallMode = 0644
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
static-check-manpages: $1
endef
libzt_0.3.1/zmk/OS.mk 0000644 0001750 0001750 00000003172 13675422347 013122 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# Is zmk debugging enabled for this module?
OS.debug ?= $(findstring os,$(DEBUG))
# OS.Kernel is the name of the operating system kernel.
# There are multiple possibilities but most common include
# Linux, Darwin and Windows_NT.
ifeq ($(origin OS),environment)
OS.Kernel = $(findstring $(OS),Windows_NT)
else
OS.Kernel := $(shell uname -s)
endif
# Format of the executable programs used by the OS.
# In general all systems fall into one of the three
# possible formats: ELF, Mach-O, PE and MZ (though unlikely).
# Many UNIX systems, apart from Darwin, use elf.
ifneq (,$(findstring $(OS.Kernel),Linux FreeBSD NetBSD OpenBSD GNU GNU/kFreeBSD SunOS Haiku))
OS.ImageFormat = ELF
endif
ifeq ($(OS.Kernel),Darwin)
OS.ImageFormat = Mach-O
endif
ifeq ($(OS.Kernel),Windows_NT)
OS.ImageFormat = PE
endif
OS.ImageFormat ?= $(error unsupported operating system kernel $(OS.Kernel))
$(if $(OS.debug),$(info DEBUG: OS.Kernel=$(OS.Kernel)))
$(if $(OS.debug),$(info DEBUG: OS.ImageFormat=$(OS.ImageFormat)))
libzt_0.3.1/zmk/ObjectGroup.mk 0000644 0001750 0001750 00000003267 13675422347 015031 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Toolchain))
$(eval $(call ZMK.Import,OS))
ObjectGroup.Variables=Sources Objects ObjectsC ObjectsCxx ObjectsObjC
define ObjectGroup.Template
$1.Sources ?= $$(error define $1.Sources - the list of source files to compile)
$1.ObjectsC ?= $$(addsuffix .o,$$(addprefix $1-,$$(basename $$(filter %.c,$$($1.Sources)))))
$1.ObjectsCxx ?= $$(addsuffix .o,$$(addprefix $1-,$$(basename $$(filter %.cpp,$$($1.Sources)))))
$1.ObjectsObjC ?= $$(addsuffix .o,$$(addprefix $1-,$$(basename $$(filter %.m,$$($1.Sources)))))
$1.Objects ?= $$(strip $$($1.ObjectsC) $$($1.ObjectsCxx) $$($1.ObjectsObjC))
# This is how to compile each type of source files.
$$($1.ObjectsC): $1-%.o: %.c
$$(strip $$(COMPILE.c) -o $$@ $$<)
$$($1.ObjectsCxx): $1-%.o: %.cpp
$$(strip $$(COMPILE.cc) -o $$@ $$<)
$$($1.ObjectsObjC): $1-%.o: %.m
$$(strip $$(COMPILE.m) -o $$@ $$<)
clean::
rm -f $$($1.Objects)
ifneq (,$$(Toolchain.DependencyTracking))
rm -f $$($1.Objects:.o=.d)
endif
ifneq (,$$(Toolchain.DependencyTracking))
-include $$($1.Objects:.o=.d)
endif
endef
libzt_0.3.1/zmk/PVS.mk 0000644 0001750 0001750 00000003647 13675422347 013260 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
PVS.Sources ?= $(error define PVS.Sources - the list of source files to analyze with PVS Studio)
PLOG_CONVERTER_FLAGS ?=
# If we have pvs-studio then run it during static checks.
ifneq (,$(shell command -v pvs-studio 2>/dev/null))
static-check:: static-check-pvs
endif
.PHONY: static-check-pvs
static-check-pvs: $(addsuffix .PVS-Studio.log,$(PVS.Sources))
$(strip plog-converter \
--settings $(srcdir)/.pvs-studio.cfg \
$(PLOG_CONVERTER_FLAGS) \
--srcRoot $(srcdir) \
--renderTypes errorfile $^ | srcdir=$(srcdir) abssrcdir=$(abspath $(srcdir)) awk -f $(ZMK.Path)/zmk/pvs-filter.awk)
pvs-report: $(addsuffix .PVS-Studio.log,$(PVS.Sources))
$(strip plog-converter \
--settings $(srcdir)/.pvs-studio.cfg \
$(PLOG_CONVERTER_FLAGS) \
--srcRoot $(srcdir) \
--projectName $(NAME) \
--projectVersion $(VERSION) \
--renderTypes fullhtml \
--output $@ \
$^)
%.c.PVS-Studio.log: %.c.i ~/.config/PVS-Studio/PVS-Studio.lic | %.c
$(strip pvs-studio \
--cfg $(srcdir)/.pvs-studio.cfg \
--i-file $< \
--source-file $(firstword $|) \
--output-file $@)
%.c.i: %.c
$(strip $(CC) $(CPPFLAGS) $< -E -o $@)
%.cpp.i: %.cpp
$(strip $(CXX) $(CPPFLAGS) $< -E -o $@)
%.m.i: %.m
$(strip $(CC) $(CPPFLAGS) $< -E -o $@)
clean::
rm -f *.i
rm -f *.PVS-Studio.log
rm -rf pvs-report
libzt_0.3.1/zmk/Program.Test.mk 0000644 0001750 0001750 00000005576 13675422347 015140 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Toolchain))
$(eval $(call ZMK.Import,OS))
# xcrun is the helper for accessing toolchain programs on MacOS
# It is defined as empty for non-Darwin build environments.
xcrun ?=
ifeq ($(OS.Kernel),Darwin)
# MacOS uses xcrun helper for some toolchain binaries.
xcrun := xcrun
endif
clean::
rm -f *.profdata *.profraw
Program.Test.Variables=Sources SourcesCoverage InstallDir InstallMode
define Program.Test.Template
$1.SourcesCoverage ?= $$(error define $1.SourcesCoverage - the list of source files to include in coverage analysis)
$$(eval $$(call ZMK.Expand,Program,$1))
# If we are using gcc or clang, build with debugging symbols.
ifneq (,$$(or $$(Toolchain.IsGcc),$$(Toolchain.IsClang)))
$1$$(exe): CFLAGS += -g
endif
# If we are not cross-compiling, run the test program on "make check"
check:: $1$$(exe)
ifneq (,$$(Toolchain.IsCross))
echo "not executing test program $$<$$(exe) when cross-compiling"
else
./$$<
endif
# If we are not cross-compiling, and stars align, support coverage analysis.
ifeq (,$$(Toolchain.IsCross))
# Support coverage analysis when building with clang and supplied with llvm
# or when using xcrun.
ifneq (,$$(or $$(xcrun),$$(and $$(Toolchain.IsClang),$$(shell command -v llvm-cov 2>/dev/null),$$(shell command -v llvm-profdata 2>/dev/null))))
# Build test program with code coverage measurements and show them via "coverage" target.
$1$$(exe): CFLAGS += -fcoverage-mapping -fprofile-instr-generate
$1$$(exe): LDFLAGS += -fcoverage-mapping -fprofile-instr-generate
$1.profraw: %.profraw: %
LLVM_PROFILE_FILE=$$@ ./$$^
$1.profdata: %.profdata: %.profraw
$$(strip $$(xcrun) llvm-profdata merge -sparse $$< -o $$@)
coverage:: $1.profdata
$$(strip $$(xcrun) llvm-cov show ./$1$$(exe) -instr-profile=$$< $$(addprefix $$(srcdir)/,$$($1.sources_coverage)))
.PHONY: coverage-todo
coverage-todo:: $1.profdata
$$(strip $$(xcrun) llvm-cov show ./$1$$(exe) -instr-profile=$$< -region-coverage-lt=100 $$(addprefix $$(srcdir)/,$$($1.sources_coverage)))
.PHONY: coverage-report
coverage-report:: $1.profdata
$$(strip $$(xcrun) llvm-cov report ./$1$$(exe) -instr-profile=$$< $$(addprefix $$(srcdir)/,$$($1.sources_coverage)))
endif # can use llvm-cov
endif # not-cross-compiling
endef
libzt_0.3.1/zmk/Program.mk 0000644 0001750 0001750 00000003517 13675422347 014213 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Toolchain))
$(eval $(call ZMK.Import,OS))
Program.Variables=Sources InstallDir InstallMode Linker
define Program.Template
# Compile program objects.
$$(eval $$(call ZMK.Expand,ObjectGroup,$1))
$1.Linker ?= $$(if $$($1.ObjectsObjC),$$(CC),$$(if $$($1.ObjectsCxx),$$(CXX),$$(CC)))
# Link program objects.
ifneq (,$$($1.ObjectsObjC))
$1$$(exe): LDLIBS += -lobjc
endif # no objective C objects
$1$$(exe): $$($1.Objects)
$$(strip $$(if $$($1.ObjectsObjC),$$(LINK.m),$$(if $$($1.ObjectsCxx),$$(LINK.cc),$$(LINK.o))) -o $$@ $$^ $$(LDLIBS))
# Install program binary.
$1.InstallDir ?= $$(bindir)
$1.InstallMode ?= 0755
$1.InstallName ?= $$(if $$(Configure.ProgramTransformName),$$(shell echo '$$(Configure.ProgramPrefix)$$(notdir $1)$$(Configure.ProgramSuffix)' | sed -e '$$(Configure.ProgramTransformName)'),$$(Configure.ProgramPrefix)$$(notdir $1)$$(Configure.ProgramSuffix))
$1$$(exe).InstallDir ?= $$($1.InstallDir)
$1$$(exe).InstallMode ?= $$($1.InstallMode)
$1$$(exe).InstallName ?= $$($1.InstallName)
$$(eval $$(call ZMK.Expand,InstallUninstall,$1$$(exe)))
# React to "all" and "clean".
$$(eval $$(call ZMK.Expand,AllClean,$1$$(exe)))
endef
libzt_0.3.1/zmk/Script.mk 0000644 0001750 0001750 00000003116 13675422347 014043 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
ZMK.shellcheck ?= $(shell command -v shellcheck 2>/dev/null)
static-check-shellcheck:
ifneq (,$(ZMK.shellcheck))
$(ZMK.shellcheck) $^
else
@echo "ZMK: install shellcheck to analyze $^"
endif
static-check:: static-check-shellcheck
Script.Variables=Interpreter InstallDir InstallMode
define Script.Template
$1.InstallDir ?= $$(bindir)
$1.InstallMode ?= 0755
$1.InstallName ?= $$(if $$(Configure.ProgramTransformName),$$(shell echo '$$(Configure.ProgramPrefix)$$(notdir $1)$$(Configure.ProgramSuffix)' | sed -e '$$(Configure.ProgramTransformName)'),$$(Configure.ProgramPrefix)$$(notdir $1)$$(Configure.ProgramSuffix))
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
$1.Interpreter ?= $$(if $$(suffix $1),$$(patsubst .%,%,$$(suffix $1)),$$(error define $1.Interpreter - the script interpreter name, sh, bash or other))
ifneq ($$(findstring $$($1.Interpreter),sh bash),)
static-check-shellcheck: $1
endif
endef
libzt_0.3.1/zmk/Symlink.mk 0000644 0001750 0001750 00000004321 13675422347 014224 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# Symbolic link. Gets installed to the desired location. The location can be
# set using the .InstallDir instance variable. The special value of noinst
# prevents installation. This template is used by other parts of ZMK, to
# install components they produce.
Symlink.Variables=SymlinkTarget InstallDir InstallName
define Symlink.Template
$1.InstallDir ?= $$(error define $1.InstallDir - the destination directory, or noinst to skip installation)
$1.SymlinkTarget ?= $$(error define $1.SymlinkTarget - the target of the symbolic link)
$1.InstallName ?= $$(notdir $1)
$1.sourceDir = $$(patsubst %/,%,$$(dir $1))
# Create the directory where the symbolic link is built in.
$$(eval $$(call ZMK.Expand,Directory,$$($1.sourceDir)))
# Create the symbolic link in the build directory.
$1: | $$($1.sourceDir)
$$(strip ln -s $$($1.SymlinkTarget) $$@)
# React to "all" and "clean" targets.
$$(eval $$(call ZMK.Expand,AllClean,$1))
# Unless we don't want to install the file, look below.
ifneq ($$($1.InstallDir),noinst)
# Create the directory where the symbolic link is installed to.
$1.targetDir = $$(patsubst %/,%,$$(dir $$($1.InstallDir)/$1))
$$(eval $$(call ZMK.Expand,Directory,$$($1.targetDir)))
# Create the symbolic link in the install directory.
$$(DESTDIR)$$($1.targetDir)/$$($1.InstallName):| $$(DESTDIR)$$($1.targetDir)
$$(strip ln -s $$($1.SymlinkTarget) $$@)
# React to "install" and "uninstall" targets.
install:: $$(DESTDIR)$$($1.targetDir)/$$($1.InstallName)
uninstall::
rm -f $$(DESTDIR)$$($1.targetDir)/$$($1.InstallName)
else # noinst
$1.targetDir = noinst
endif # !noinst
endef
libzt_0.3.1/zmk/Tarball.Src.mk 0000644 0001750 0001750 00000003212 13675422347 014703 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
%.asc: %
gpg --detach-sign --armor $<
Tarball.Src.Variables=Name Files Sign
define Tarball.Src.Template
$1.Name ?= $$(patsubst %.tar$$(suffix $1),%,$1)
$1.Files ?= $$(error define $1.Files - the list of files to include in the tarball)
$1.Files += $$(ZMK.DistFiles)
# Sign archives that are not git snapshots and if CI is unset
$1.Sign ?= $$(if $$(or $$(value CI),$$(and $$(filter GitVersion,$$(ZMK.ImportedModules)),$$(GitVersion.Active))),,yes)
# If the Configure module is imported then include the configure script.
ifneq (,$$(filter Configure,$$(ZMK.ImportedModules)))
$1.Files += configure
endif
# If the GitVersion module is imported then put the .version-from-git file
# inside the source archive. This way the GitVersion module will not attempt to
# refer to git after the archive is extracted for installation later.
ifneq (,$$(filter GitVersion,$$(ZMK.ImportedModules)))
$1.Files += .version-from-git
endif
ifneq (,$$($1.Sign))
dist:: $1.asc
endif
$$(eval $$(call ZMK.Expand,Tarball,$1))
endef
libzt_0.3.1/zmk/Tarball.mk 0000644 0001750 0001750 00000003157 13675422347 014165 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,OS))
_bsd_tar_options ?=
_tar_compress_flag ?=
# If using a Mac, filter out extended meta-data files.
ifeq ($(OS.Kernel),Darwin)
_bsd_tar_options := --no-mac-metadata
endif
%.tar.gz: _tar_compress_flag=z
%.tar.bz2: _tar_compress_flag=j
%.tar.xz: _tar_compress_flag=J
Tarball.Variables=Name Files
define Tarball.Template
$1.Name ?= $$(patsubst %.tar$$(suffix $1),%,$1)
$1.Files ?= $$(error define $1.Files - the list of files to include in the tarball)
dist:: $1
$1: $$(sort $$(addprefix $$(srcdir)/,$$($1.Files)))
ifneq ($(shell tar --version 2>&1 | grep GNU),)
tar -$$(or $$(_tar_compress_flag),a)cf $$@ -C $$(srcdir) --xform='s@^@$$($1.Name)/@g' --xform='s@.version-from-git@.version@' $$(patsubst $$(srcdir)/%,%,$$^)
else
tar $$(strip $$(_bsd_tar_options) -$$(or $$(_tar_compress_flag),a)cf) $$@ -C $$(srcdir) -s '@.@$$($1.Name)/~@' -s '@.version-from-git@.version@' $$(patsubst $$(srcdir)/%,%,$$^)
endif
endef
libzt_0.3.1/zmk/Toolchain.mk 0000644 0001750 0001750 00000006677 13675422347 014536 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
$(eval $(call ZMK.Import,OS))
$(eval $(call ZMK.Import,Configure))
# Compiler defaults unless changed by GNUmakefile.configure.mk
ifeq ($(OS.Kernel),SunOS)
# Solaris doesn't seem to provide any aliases or symlinks for gcc but make wants to call it "cc".
CC := gcc
endif
CPPFLAGS ?=
CFLAGS ?=
CXXFLAGS ?=
OBJCFLAGS ?=
ARFLAGS = -cr
TARGET_ARCH ?=
LDLIBS ?=
LDFLAGS ?=
# The exe variable expands to .exe when the compiled binary should have such suffix.
exe ?=
# Is zmk debugging enabled for this module?
Toolchain.debug ?= $(findstring toolchain,$(DEBUG))
# What is the image format used by the C compiler?
# If we are not cross compiling then image format is native.
Toolchain.CC.ImageFormat ?= $(OS.ImageFormat)
# What is the image format used by the C++ compiler?
Toolchain.CXX.ImageFormat ?= $(OS.ImageFormat)
# Is the C compiler a cross-compiler?
Toolchain.CC.IsCross ?=
# Is the C++ compiler a cross-compiler?
Toolchain.CXX.IsCross ?=
# Should compiling produce dependency information for make?
Toolchain.DependencyTracking ?= $(Configure.DependencyTracking)
# Deduce the kind of the selected compiler. Some build rules or compiler
# options depend on the compiler used. As an alternative we could look at
# preprocessor macros but this way seems sufficient for now.
Toolchain.cc ?= $(shell sh -c "command -v $(CC)")
Toolchain.cxx ?= $(shell sh -c "command -v $(CXX)")
# When CC or CXX point to platform default compiler alias, resolve
# them to the real value, which is better to identify the toolchain.
Toolchain.cc := $(if $(findstring $(Toolchain.cc),/usr/bin/cc),$(realpath $(Toolchain.cc)),$(Toolchain.cc))
Toolchain.cxx := $(if $(findstring $(Toolchain.cxx),/usr/bin/c++ /usr/bin/g++),$(realpath $(Toolchain.cxx)),$(Toolchain.cxx))
# Import toolchain-specific knowledge.
$(eval $(call ZMK.Import,toolchain.GCC))
$(eval $(call ZMK.Import,toolchain.Clang))
$(eval $(call ZMK.Import,toolchain.Watcom))
$(eval $(call ZMK.Import,toolchain.Tcc))
# Is either the C or C++ compiler a cross compiler?
Toolchain.IsCross ?= $(or $(Toolchain.CC.IsCross),$(Toolchain.CXX.IsCross))
# Is the image format between C and C++ uniform?
ifeq ($(Toolchain.CC.ImageFormat),$(Toolchain.CXX.ImageFormat))
Toolchain.ImageFormat = $(Toolchain.CC.ImageFormat)
else
Toolchain.ImageFormat = Mixed
endif
# If dependency tracking is enabled, pass extra options to the compiler, to
# generate dependency data at the same time as compiling object files.
ifneq (,$(and $(Toolchain.DependencyTracking),$(or $(Toolchain.IsGcc),$(Toolchain.IsClang))))
CPPFLAGS += -MMD
$(if $(Toolchain.debug),$(info DEBUG: compiling object files will generate make dependency information))
endif
$(if $(Toolchain.debug),$(foreach v,CC CXX CPP CFLAGS CXXFLAGS CPPFLAGS OBJCFLAGS ARFLAGS TARGET_ARCH LDLIBS LDFLAGS $(sort $(filter Toolchain.%,$(.VARIABLES))),$(info DEBUG: $v=$($v))))
libzt_0.3.1/zmk/internalTest.mk 0000644 0001750 0001750 00000002211 13675422347 015246 0 ustar zyga zyga # NOTE: This file is not a part of the public ZMK API.
# It is used by zmk self-test suite and it is provided here for convenience.
# Tests are grouped under the "t" target
.PHONY: t
t::
# Find the path of the zmk installation
ZMK.Path := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
# Put extra test tools on PATH
export PATH := $(ZMK.Path)/tests/bin:$(PATH)
# Make overrides can be used in order to test specific behavior
ZMK.makeOverrides ?=
# Make target can be customized for each log file.
# For default logic, see the rule below.
ZMK.makeTarget ?=
# Tests print a header, unless silent mode is used
# Tests do not use localization
# Tests always remake targets
# Tests print commands instead of invoking them
# Tests do not mention directory changes
# Tests warn about undefined variables
%.log: MAKEFLAGS=Bn
%.log: Test.mk Makefile $(ZMK.Path)/z.mk $(wildcard $(ZMK.Path)/zmk/*.mk)
$(strip LANG=C $(MAKE) $(ZMK.makeOverrides) -I $(ZMK.Path) \
--warn-undefined-variables \
--always-make \
--dry-run \
$(or $(ZMK.makeTarget),$(firstword $(subst -, ,$*))) >$@ 2>&1) || true
configure: $(ZMK.Path)/zmk/internalTest.mk
c::
rm -f *.log
libzt_0.3.1/zmk/pvs-filter.awk 0000644 0001750 0001750 00000002472 13675422347 015051 0 ustar zyga zyga # Copyright 2019-2020 Zygmunt Krynicki.
#
# This file is part of zmk.
#
# Zmk is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Zmk is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Zmk. If not, see .
# Awk script for taming the output of plog-converter.
# Requires $srcdir and $abssrcdir environment variables.
BEGIN {
FAILED=0;
SRCDIR=ENVIRON["srcdir"];
NSKIP=length(ENVIRON["abssrcdir"]);
# print(sprintf("nskip %d", NSKIP));
}
# Skip the annoying URL notice.
/^www\.viva64\.com\/en\/w:1:1/ { next }
# We know this is an open source project.
/^.*: error: V1042 .*$/ { next }
# Pick up warnings and errors. Use relative file names.
# The +1 below is because awk uses 1-based indexing.
/^.*: (warning|error):/ {
FAILED=1;
# print($0);
print(sprintf("%s%s", SRCDIR, substr($0, NSKIP + 2)));
}
# Exit if warnings or errors were reported.
END { if (FAILED) exit(1); }
libzt_0.3.1/zmk/toolchain.Clang.mk 0000644 0001750 0001750 00000000423 13675422347 015600 0 ustar zyga zyga # Are we using Clang?
Toolchain.CC.IsClang=$(if $(findstring clang,$(Toolchain.cc)),yes)
Toolchain.CXX.IsClang=$(if $(findstring clang,$(Toolchain.cxx)),yes)
Toolchain.IsClang=$(and $(Toolchain.CC.IsClang),$(Toolchain.CXX.IsClang))
# TODO: handle cross compiling with clang.
libzt_0.3.1/zmk/toolchain.GCC.mk 0000644 0001750 0001750 00000005704 13675422347 015157 0 ustar zyga zyga # Are we using GCC?
Toolchain.CC.IsGcc=$(if $(findstring gcc,$(Toolchain.cc)),yes)
Toolchain.CXX.IsGcc=$(if $(and $(if $(findstring clang++,$(Toolchain.cxx)),,not-clang++),$(findstring g++,$(Toolchain.cxx))),yes)
Toolchain.IsGcc=$(and $(Toolchain.CC.IsGcc),$(Toolchain.CXX.IsGcc))
# Logic specific to gcc
ifneq (,$(Toolchain.CC.IsGcc))
# If we are configured then check for cross compilation by mismatch of host and
# build triplets. When this happens set CC. This is important for
# autoconf/automake compatibility.
ifneq (,$(and $(Configure.Configured),$(Configure.HostArchTriplet),$(Configure.BuildArchTriplet)))
ifneq ($(Configure.BuildArchTriplet),$(Configure.HostArchTriplet))
CC = $(Configure.HostArchTriplet)-gcc
$(if $(Toolchain.debug),$(info DEBUG: gcc cross-compiler selected CC=$(CC)))
endif # !cross-compiling
endif # !configured
# Indirection for testability.
Toolchain.cc.dumpmachine ?= $(shell $(CC) -dumpmachine)
Toolchain.gcc.dumpmachine ?= $(shell gcc -dumpmachine)
# Are we targeting Windows with mingw?
ifneq (,$(findstring mingw,$(Toolchain.cc.dumpmachine)))
exe = .exe
Toolchain.CC.ImageFormat = PE
$(if $(Toolchain.debug),$(info DEBUG: .exe suffix enabled because $(CC) -dumpmachine mentions mingw))
endif # !mingw
# Are we targeting Linux?
ifneq (,$(findstring linux,$(Toolchain.cc.dumpmachine)))
Toolchain.CC.ImageFormat = ELF
endif # !linux
# Is gcc cross-compiling?
ifneq ($(Toolchain.gcc.dumpmachine),$(Toolchain.cc.dumpmachine))
Toolchain.CC.IsCross = yes
$(if $(Toolchain.debug),$(info DEBUG: cross-compiling because gcc -dumpmachine and $(CC) -dumpmachine differ))
endif # !cross
endif # !cc=gcc
# Logic specific to g++
ifneq (,$(Toolchain.CXX.IsGcc))
# If we are configured then check for cross compilation by mismatch of host and
# build triplets. When this happens set CXX. This is important for
# autoconf/automake compatibility.
ifneq (,$(and $(Configure.Configured),$(Configure.HostArchTriplet),$(Configure.BuildArchTriplet)))
ifneq ($(Configure.BuildArchTriplet),$(Configure.HostArchTriplet))
CXX = $(Configure.HostArchTriplet)-g++
$(if $(Toolchain.debug),$(info DEBUG: g++ cross-compiler selected CXX=$(CXX)))
endif # !cross-compiling
endif # !configured
# Indirection for testability.
Toolchain.cxx.dumpmachine ?= $(shell $(CXX) -dumpmachine)
Toolchain.g++.dumpmachine ?= $(shell g++ -dumpmachine)
# Are we targeting Windows with mingw?
ifneq (,$(findstring mingw,$(Toolchain.cxx.dumpmachine)))
exe = .exe
Toolchain.CXX.ImageFormat = PE
$(if $(Toolchain.debug),$(info DEBUG: .exe suffix enabled because $(CXX) -dumpmachine mentions mingw))
endif # !mingw
# Are we targeting Linux?
ifneq (,$(findstring linux,$(Toolchain.cxx.dumpmachine)))
Toolchain.CXX.ImageFormat = ELF
endif # !linux
# Is g++ cross compiling?
ifneq ($(Toolchain.g++.dumpmachine),$(Toolchain.cxx.dumpmachine))
Toolchain.CXX.IsCross = yes
$(if $(Toolchain.debug),$(info DEBUG: cross-compiling because g++ -dumpmachine and $(CXX) -dumpmachine differ))
endif # !cross
endif # !cxx=gcc
libzt_0.3.1/zmk/toolchain.Tcc.mk 0000644 0001750 0001750 00000000131 13675422347 015261 0 ustar zyga zyga # Is CC the tcc compiler?
Toolchain.CC.IsTcc=$(if $(findstring tcc,$(Toolchain.cc)),yes)
libzt_0.3.1/zmk/toolchain.Watcom.mk 0000644 0001750 0001750 00000003533 13675422347 016013 0 ustar zyga zyga # Are we using the open Watcom compiler?
Toolchain.CC.IsWatcom=$(if $(findstring watcom,$(Toolchain.cc)),yes)
Toolchain.CXX.IsWatcom=$(if $(findstring watcom,$(Toolchain.cxx)),yes)
Toolchain.IsWatcom=$(and $(Toolchain.CC.IsWatcom),$(Toolchain.CXX.IsWatcom))
# Logic specific to Watcom compiler.
ifneq (,$(Toolchain.CC.IsWatcom))
# Are we building for DOS or 16bit Windows?
ifneq (,$(or $(findstring dos,$(Toolchain.cc)),$(findstring win16,$(Toolchain.cc))))
exe = .exe
Toolchain.CC.ImageFormat = MZ
Toolchain.CC.IsCross = yes
$(if $(Toolchain.debug),$(info DEBUG: .exe suffix enabled because $(CC) name))
$(if $(Toolchain.debug),$(info DEBUG: cross-compiling because Watcom targets DOS))
endif # !cc win16 || dos
# Are we building for 32bit Windows?
ifneq (,$(findstring win32,$(Toolchain.cc)))
exe = .exe
Toolchain.CC.ImageFormat = PE
Toolchain.CC.IsCross = yes
$(if $(Toolchain.debug),$(info DEBUG: .exe suffix enabled because $(CC) name))
$(if $(Toolchain.debug),$(info DEBUG: cross-compiling because Watcom targets Windows))
endif # !cc win32
endif # !cc Watcom
# Logic specific to Watcom
ifneq (,$(Toolchain.CXX.IsWatcom))
# Are we building for DOS or 16bit Windows?
ifneq (,$(or $(findstring dos,$(Toolchain.cxx)),$(findstring win16,$(Toolchain.cxx))))
exe = .exe
Toolchain.CXX.ImageFormat = MZ
Toolchain.CXX.IsCross = yes
$(if $(Toolchain.debug),$(info DEBUG: .exe suffix enabled because $(CXX) name))
$(if $(Toolchain.debug),$(info DEBUG: cross-compiling because Watcom targets DOS))
endif # !cxx win16 || dos
# Are we building for 32bit Windows?
ifneq (,$(findstring win32,$(Toolchain.cxx)))
exe = .exe
Toolchain.CXX.ImageFormat = PE
Toolchain.CXX.IsCross = yes
$(if $(Toolchain.debug),$(info DEBUG: .exe suffix enabled because $(CXX) name))
$(if $(Toolchain.debug),$(info DEBUG: cross-compiling because Watcom targets Windows))
endif # !cxx win32
endif # !cxx Watcom
libzt_0.3.1/zt-test.c 0000664 0001750 0001750 00000227423 13675422322 013227 0 ustar zyga zyga /* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
*
* Copyright 2019-2020 Zygmunt Krynicki.
*
* This file is part of libzt.
*
* Libzt is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* Libzt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Libzt. If not, see . */
#ifdef __linux__
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#endif
#include
#include
#include
#define ZT_SELF_TEST_BUILD
#include "zt.c"
/* internal self-test helpers */
static FILE* selftest_temporary_file(void)
{
FILE* f;
#if defined(__linux__)
/* Hardened version for Linux. */
char tmpl[PATH_MAX];
const char* tmp_dir_name;
int fd;
tmp_dir_name = getenv("TMPDIR");
if (tmp_dir_name == NULL) {
tmp_dir_name = "/tmp";
}
#if defined(O_TMPFILE)
fd = open(tmp_dir_name, O_TMPFILE | O_RDWR | O_EXCL, 0600);
if (fd < 0) {
if (errno != EOPNOTSUPP) {
perror("cannot open temporary file via O_TMPFILE");
exit(1);
}
}
tmpl[0] = '\0';
#else
fd = -1;
#endif
if (fd < 0) {
int n = snprintf(tmpl, sizeof tmpl - 1, "%s/libzt-test.XXXXXX", tmp_dir_name);
if (n < 0 || (size_t)n >= sizeof tmpl - 1) {
perror("cannot format temporary file name");
exit(1);
}
fd = mkostemp(tmpl, O_CLOEXEC);
}
if (fd < 0) {
perror("cannot open temporary file");
exit(1);
}
if (tmpl[0] != '\0' && unlink(tmpl) < 0) {
perror("cannot unlink temporary file");
exit(1);
}
f = fdopen(fd, "w+");
#else
/* Portable version. */
f = tmpfile();
#endif
if (f == NULL) {
perror("cannot open temporary file");
exit(1);
}
return f;
}
static zt_test selftest_make_test(void)
{
zt_test t;
memset(&t, 0, sizeof t);
t.location.fname = "file.c";
t.location.lineno = 13;
t.stream = selftest_temporary_file();
return t;
}
static void selftest_close_test(zt_t t)
{
fclose(t->stream);
t->stream = NULL;
}
static void selftest_quote_str(FILE* stream, const char* str)
{
/* self-test quote function uses single-quotes. Meanwhile the production
* quote function uses double quotes. This allows one to quote the other
* without unnecessary escaping. */
fputs("\'", stream);
for (;;) {
int c = *str;
if (c == '\0') {
break;
}
str++;
switch (c) {
case '\'':
fputs("\\'", stream);
break;
case '\n':
fputs("\\n", stream);
break;
case '\r':
fputs("\\r", stream);
break;
case '\t':
fputs("\\t", stream);
break;
case '\v':
fputs("\\v", stream);
break;
default:
if (isprint(c)) {
fputc(c, stream);
} else {
fprintf(stream, "\\%#04x", c);
}
break;
}
}
fputs("\'", stream);
}
#define selftest_stream_eq(stream, expected) \
selftest_stream_eq_at( \
stream, __FILE__, __LINE__, "%s", expected)
static void selftest_stream_eq_at(FILE* stream, const char* file,
int lineno, const char* fmt, ...)
{
size_t nread;
int nfmt;
char buf1[1024], buf2[1024];
size_t buf1_size = sizeof buf1;
size_t buf2_size = sizeof buf2;
va_list ap;
if (fseek(stream, 0, SEEK_SET) < 0) {
perror("cannot seek in test stream");
exit(1);
}
nread = fread(buf1, 1, buf1_size - 1, stream);
if (nread == 0 && !feof(stream) && ferror(stream) != 0) {
perror("cannot read from test stream");
exit(1);
}
if (nread == buf1_size - 1 && !feof(stream)) {
fprintf(stderr, "insufficient space to read entire stream\n");
exit(1);
}
buf1[nread] = '\0';
va_start(ap, fmt);
nfmt = vsnprintf(buf2, buf2_size, fmt, ap);
va_end(ap);
if (nfmt < 0) {
perror("cannot format expected stream contents");
exit(1);
}
if ((size_t)nfmt >= buf2_size) {
fprintf(stderr, "insufficient space to format expected stream contents\n");
exit(1);
}
buf2[nfmt] = '\0';
if (strcmp(buf1, buf2) != 0) {
fprintf(stderr, "%s:%d: error: stream content mismatch ", file, lineno);
selftest_quote_str(stderr, buf1);
fprintf(stderr, " ( <- actual) != ");
selftest_quote_str(stderr, buf2);
fprintf(stderr, " ( <- expected)\n");
exit(1);
}
}
/* library version */
static void test_MAJOR_MINOR_VERSION(void)
{
assert(ZT_MAJOR_VERSION == 0);
assert(ZT_MINOR_VERSION == 3);
}
/* packing arguments */
static void test_pack_boolean(void)
{
zt_value v;
v = zt_pack_boolean(true, "true");
assert(zt_value_kind_of(v) == ZT_BOOLEAN);
assert(v.as.boolean == true);
assert(strcmp(zt_source_of(v), "true") == 0);
v = zt_pack_boolean(false, "false");
assert(zt_value_kind_of(v) == ZT_BOOLEAN);
assert(v.as.boolean == false);
assert(strcmp(zt_source_of(v), "false") == 0);
}
static void test_pack_rune(void)
{
zt_value v;
v = zt_pack_rune('a', "'a'");
assert(zt_value_kind_of(v) == ZT_RUNE);
assert(v.as.rune == 'a');
assert(strcmp(zt_source_of(v), "'a'") == 0);
v = zt_pack_rune('\x80', "'\\x80'");
assert(zt_value_kind_of(v) == ZT_RUNE);
assert(v.as.rune == 0x80);
assert(strcmp(zt_source_of(v), "'\\x80'") == 0);
v = zt_pack_rune('\x01', "'\\x01'");
assert(v.as.rune == 0x01);
v = zt_pack_rune('\x80', "'\\x80'");
assert(v.as.rune == 0x80);
v = zt_pack_rune('\xFF', "'\\xFF'");
assert(v.as.rune == 0xFF);
}
static void test_pack_integer(void)
{
zt_value v;
v = zt_pack_integer(42, "42");
assert(zt_value_kind_of(v) == ZT_INTMAX);
assert(v.as.intmax == 42);
assert(strcmp(zt_source_of(v), "42") == 0);
}
static void test_pack_unsigned(void)
{
zt_value v;
v = zt_pack_unsigned(42U, "42U");
assert(zt_value_kind_of(v) == ZT_UINTMAX);
assert(v.as.uintmax == 42U);
assert(strcmp(zt_source_of(v), "42U") == 0);
}
static void test_pack_string(void)
{
zt_value v;
v = zt_pack_string("foo", "\"foo\"");
assert(zt_value_kind_of(v) == ZT_STRING);
assert(strcmp(v.as.string, "foo") == 0);
assert(strcmp(zt_source_of(v), "\"foo\"") == 0);
}
static void test_pack_pointer(void)
{
zt_value v;
v = zt_pack_pointer(NULL, "NULL");
assert(zt_value_kind_of(v) == ZT_POINTER);
assert(v.as.pointer == NULL);
assert(strcmp(zt_source_of(v), "NULL") == 0);
}
static void test_promote_value(void)
{
zt_value v;
v.kind = ZT_INTEGER;
v.as.integer = -1;
v.source = "-1";
zt_promote_value(&v);
assert(zt_value_kind_of(v) == ZT_INTMAX);
assert(v.as.intmax == -1);
assert(strcmp(zt_source_of(v), "-1") == 0);
v.kind = ZT_UNSIGNED;
v.as.unsigned_integer = 1U;
v.source = "1U";
zt_promote_value(&v);
assert(zt_value_kind_of(v) == ZT_UINTMAX);
assert(v.as.uintmax == 1U);
assert(strcmp(zt_source_of(v), "1U") == 0);
}
/* binary relation */
static void test_find_binary_relation(void)
{
assert(zt_find_binary_relation("==") == ZT_REL_EQ);
assert(zt_find_binary_relation("!=") == ZT_REL_NE);
assert(zt_find_binary_relation("<=") == ZT_REL_LE);
assert(zt_find_binary_relation(">=") == ZT_REL_GE);
assert(zt_find_binary_relation("<") == ZT_REL_LT);
assert(zt_find_binary_relation(">") == ZT_REL_GT);
assert(zt_find_binary_relation("potato") == ZT_REL_INVALID);
}
static void test_invert_binary_relation(void)
{
assert(zt_invert_binary_relation(ZT_REL_EQ) == ZT_REL_NE);
assert(zt_invert_binary_relation(ZT_REL_NE) == ZT_REL_EQ);
assert(zt_invert_binary_relation(ZT_REL_LE) == ZT_REL_GT);
assert(zt_invert_binary_relation(ZT_REL_GE) == ZT_REL_LT);
assert(zt_invert_binary_relation(ZT_REL_LT) == ZT_REL_GE);
assert(zt_invert_binary_relation(ZT_REL_GT) == ZT_REL_LE);
assert(zt_invert_binary_relation(ZT_REL_INVALID) == ZT_REL_INVALID);
assert(zt_invert_binary_relation(1000) == ZT_REL_INVALID);
}
static void test_binary_relation_as_text(void)
{
assert(strcmp(zt_binary_relation_as_text(ZT_REL_EQ), "==") == 0);
assert(strcmp(zt_binary_relation_as_text(ZT_REL_NE), "!=") == 0);
assert(strcmp(zt_binary_relation_as_text(ZT_REL_LE), "<=") == 0);
assert(strcmp(zt_binary_relation_as_text(ZT_REL_GE), ">=") == 0);
assert(strcmp(zt_binary_relation_as_text(ZT_REL_LT), "<") == 0);
assert(strcmp(zt_binary_relation_as_text(ZT_REL_GT), ">") == 0);
assert(strcmp(zt_binary_relation_as_text(ZT_REL_INVALID), "invalid") == 0);
assert(strcmp(zt_binary_relation_as_text(1000), "invalid") == 0);
}
/* boolean formatting */
static void test_boolean_as_text(void)
{
assert(strcmp(zt_boolean_as_text(true), "true") == 0);
assert(strcmp(zt_boolean_as_text(false), "false") == 0);
}
/* claim verification */
static bool selftest_passing_verify0_called;
static bool selftest_passing_verify0(zt_t t)
{
assert(t != NULL);
selftest_passing_verify0_called = true;
return true;
}
static bool selftest_passing_verify1_called;
static bool selftest_passing_verify1(zt_t t, ZT_UNUSED zt_value arg1)
{
(void)arg1;
assert(t != NULL);
selftest_passing_verify1_called = true;
return true;
}
static bool selftest_passing_verify2_called;
static bool selftest_passing_verify2(zt_t t, ZT_UNUSED zt_value arg1, ZT_UNUSED zt_value arg2)
{
(void)arg1;
(void)arg2;
assert(t != NULL);
selftest_passing_verify2_called = true;
return true;
}
static bool selftest_passing_verify3_called;
static bool selftest_passing_verify3(zt_t t, ZT_UNUSED zt_value arg1, ZT_UNUSED zt_value arg2, ZT_UNUSED zt_value arg3)
{
(void)arg1;
(void)arg2;
(void)arg3;
assert(t != NULL);
selftest_passing_verify3_called = true;
return true;
}
static zt_verifier selftest_passing_verifier0(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args0 = selftest_passing_verify0;
verifier.nargs = 0;
return verifier;
}
static zt_verifier selftest_passing_verifier1(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args1 = selftest_passing_verify1;
verifier.nargs = 1;
verifier.arg_infos[0].kind = ZT_INTMAX;
verifier.arg_infos[0].kind_mismatch_msg = "arg[0] type mismatch";
return verifier;
}
static zt_verifier selftest_passing_verifier2(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args2 = selftest_passing_verify2;
verifier.nargs = 2;
verifier.arg_infos[0].kind = ZT_INTMAX;
verifier.arg_infos[0].kind_mismatch_msg = "arg[0] type mismatch";
verifier.arg_infos[1].kind = ZT_INTMAX;
verifier.arg_infos[1].kind_mismatch_msg = "arg[1] type mismatch";
return verifier;
}
static zt_verifier selftest_passing_verifier3(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = selftest_passing_verify3;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_INTMAX;
verifier.arg_infos[0].kind_mismatch_msg = "arg[0] type mismatch";
verifier.arg_infos[1].kind = ZT_INTMAX;
verifier.arg_infos[1].kind_mismatch_msg = "arg[1] type mismatch";
verifier.arg_infos[2].kind = ZT_INTMAX;
verifier.arg_infos[2].kind_mismatch_msg = "arg[2] type mismatch";
return verifier;
}
static void test_verify_claim0(void)
{
zt_claim claim;
bool result;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify0_called = true;
claim.make_verifier = selftest_passing_verifier0;
result = zt_verify_claim(&t, &claim);
assert(result == true);
assert(selftest_passing_verify0_called == true);
selftest_close_test(&t);
}
static void test_verify_claim1(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_integer(123, "arg0");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify0_called = true;
claim.make_verifier = selftest_passing_verifier1;
result = zt_verify_claim(&t, &claim);
assert(result == true);
assert(selftest_passing_verify1_called == true);
selftest_close_test(&t);
}
static void test_verify_claim2(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_integer(123, "arg0");
claim.args[1] = zt_pack_integer(123, "arg1");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify2_called = true;
claim.make_verifier = selftest_passing_verifier2;
result = zt_verify_claim(&t, &claim);
assert(result == true);
assert(selftest_passing_verify2_called == true);
selftest_close_test(&t);
}
static void test_verify_claim3(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_integer(123, "arg0");
claim.args[1] = zt_pack_integer(123, "arg1");
claim.args[2] = zt_pack_integer(123, "arg2");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify3_called = true;
claim.make_verifier = selftest_passing_verifier3;
result = zt_verify_claim(&t, &claim);
assert(result == true);
assert(selftest_passing_verify3_called == true);
selftest_close_test(&t);
}
static zt_verifier selftest_bogus_verifier4(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.nargs = 4;
return verifier;
}
static void test_verify_bogus_claim4(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.make_verifier = selftest_bogus_verifier4;
claim.location.fname = "file.c";
claim.location.lineno = 13;
result = zt_verify_claim(&t, &claim);
assert(result == false);
selftest_stream_eq(t.stream, "file.c:13: unsupported number of arguments: 4\n");
selftest_close_test(&t);
}
static void test_verify_mismatch_claim1of1(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_unsigned(123U, "arg0");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify1_called = false;
claim.make_verifier = selftest_passing_verifier1;
result = zt_verify_claim(&t, &claim);
assert(result == false);
assert(selftest_passing_verify1_called == false);
selftest_stream_eq(t.stream, "file.c:13: arg[0] type mismatch\n");
selftest_close_test(&t);
}
static void test_verify_mismatch_claim1of2(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_unsigned(123U, "arg0");
claim.args[1] = zt_pack_integer(123, "arg1");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify2_called = false;
claim.make_verifier = selftest_passing_verifier2;
result = zt_verify_claim(&t, &claim);
assert(result == false);
assert(selftest_passing_verify2_called == false);
selftest_stream_eq(t.stream, "file.c:13: arg[0] type mismatch\n");
selftest_close_test(&t);
}
static void test_verify_mismatch_claim2of2(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_integer(123, "arg0");
claim.args[1] = zt_pack_unsigned(123U, "arg1");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify2_called = false;
claim.make_verifier = selftest_passing_verifier2;
result = zt_verify_claim(&t, &claim);
assert(result == false);
assert(selftest_passing_verify2_called == false);
selftest_stream_eq(t.stream, "file.c:13: arg[1] type mismatch\n");
selftest_close_test(&t);
}
static void test_verify_mismatch_claim1of3(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_unsigned(123U, "arg0");
claim.args[1] = zt_pack_integer(123, "arg1");
claim.args[2] = zt_pack_integer(123, "arg2");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify3_called = false;
claim.make_verifier = selftest_passing_verifier3;
result = zt_verify_claim(&t, &claim);
assert(result == false);
assert(selftest_passing_verify3_called == false);
selftest_stream_eq(t.stream, "file.c:13: arg[0] type mismatch\n");
selftest_close_test(&t);
}
static void test_verify_mismatch_claim2of3(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_integer(123, "arg0");
claim.args[1] = zt_pack_unsigned(123U, "arg1");
claim.args[2] = zt_pack_integer(123, "arg2");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify3_called = false;
claim.make_verifier = selftest_passing_verifier3;
result = zt_verify_claim(&t, &claim);
assert(result == false);
assert(selftest_passing_verify3_called == false);
selftest_stream_eq(t.stream, "file.c:13: arg[1] type mismatch\n");
selftest_close_test(&t);
}
static void test_verify_mismatch_claim3of3(void)
{
bool result;
zt_claim claim;
zt_test t = selftest_make_test();
memset(&claim, 0, sizeof claim);
claim.args[0] = zt_pack_integer(123, "arg0");
claim.args[1] = zt_pack_integer(123, "arg1");
claim.args[2] = zt_pack_unsigned(123U, "arg2");
claim.location.fname = "file.c";
claim.location.lineno = 13;
selftest_passing_verify3_called = false;
claim.make_verifier = selftest_passing_verifier3;
result = zt_verify_claim(&t, &claim);
assert(result == false);
assert(selftest_passing_verify3_called == false);
selftest_stream_eq(t.stream, "file.c:13: arg[2] type mismatch\n");
selftest_close_test(&t);
}
/* verifier for true and verify true. */
static void test_verifier_for_true(void)
{
zt_verifier v = zt_verifier_for_true();
assert(v.nargs == 1);
assert(v.func.args1 == zt_verify_true);
assert(v.arg_infos[0].kind == ZT_BOOLEAN);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg, "value is not a boolean") == 0);
assert(v.arg_infos[1].kind == ZT_NOTHING);
assert(v.arg_infos[1].kind_mismatch_msg == NULL);
assert(v.arg_infos[2].kind == ZT_NOTHING);
assert(v.arg_infos[2].kind_mismatch_msg == NULL);
}
static void test_verify_true(void)
{
zt_test t;
/* passing */
t = selftest_make_test();
assert(zt_verify_true(&t, zt_pack_boolean(true, "errno == EPERM")) == true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing */
t = selftest_make_test();
assert(zt_verify_true(&t, zt_pack_boolean(false, "fd < 0")) == false);
selftest_stream_eq(t.stream, "file.c:13: assertion failed because fd < 0 is false\n");
selftest_close_test(&t);
}
/* verifier for false and verify false. */
static void test_verifier_for_false(void)
{
zt_verifier v = zt_verifier_for_false();
assert(v.nargs == 1);
assert(v.func.args1 == zt_verify_false);
assert(v.arg_infos[0].kind == ZT_BOOLEAN);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg, "value is not a boolean") == 0);
assert(v.arg_infos[1].kind == ZT_NOTHING);
assert(v.arg_infos[1].kind_mismatch_msg == NULL);
assert(v.arg_infos[2].kind == ZT_NOTHING);
assert(v.arg_infos[2].kind_mismatch_msg == NULL);
}
static void test_verify_false(void)
{
zt_test t;
/* passing */
t = selftest_make_test();
assert(zt_verify_false(&t, zt_pack_boolean(false, "errno == 0")) == true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing */
t = selftest_make_test();
assert(zt_verify_false(&t, zt_pack_boolean(true, "errno == 0")) == false);
selftest_stream_eq(t.stream, "file.c:13: assertion failed because errno == 0 is true\n");
selftest_close_test(&t);
}
/* verifier for boolean relation. */
static void test_verifier_for_boolean_relation(void)
{
zt_verifier v = zt_verifier_for_boolean_relation();
assert(v.nargs == 3);
assert(v.func.args3 == zt_verify_boolean_relation);
assert(v.arg_infos[0].kind == ZT_BOOLEAN);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"left hand side is not a boolean")
== 0);
assert(v.arg_infos[1].kind == ZT_STRING);
assert(strcmp(v.arg_infos[1].kind_mismatch_msg, "relation is not a string") == 0);
assert(v.arg_infos[2].kind == ZT_BOOLEAN);
assert(strcmp(v.arg_infos[2].kind_mismatch_msg,
"right hand side is not a boolean")
== 0);
}
static void test_verify_boolean_relation(void)
{
zt_test t;
/* passing == */
t = selftest_make_test();
assert(zt_verify_boolean_relation(&t, zt_pack_boolean(true, "L"),
zt_pack_string("==", "=="), zt_pack_boolean(true, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing != */
t = selftest_make_test();
assert(zt_verify_boolean_relation(&t, zt_pack_boolean(true, "L"),
zt_pack_string("!=", "!="), zt_pack_boolean(false, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing == */
t = selftest_make_test();
assert(!zt_verify_boolean_relation(&t, zt_pack_boolean(true, "L"),
zt_pack_string("==", "=="), zt_pack_boolean(false, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L == R failed because true != false\n");
selftest_close_test(&t);
t = selftest_make_test();
assert(!zt_verify_boolean_relation(&t, zt_pack_boolean(false, "L"),
zt_pack_string("==", "=="), zt_pack_boolean(true, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L == R failed because false != true\n");
selftest_close_test(&t);
/* failing != */
t = selftest_make_test();
assert(!zt_verify_boolean_relation(&t, zt_pack_boolean(false, "L"),
zt_pack_string("!=", "!="), zt_pack_boolean(false, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R failed because false == false\n");
selftest_close_test(&t);
/* unsupported relation */
t = selftest_make_test();
assert(!zt_verify_boolean_relation(&t, zt_pack_boolean(true, "L"),
zt_pack_string("~", "~"), zt_pack_boolean(true, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L ~ R uses unsupported relation\n");
selftest_close_test(&t);
/* inconsistent relation */
t = selftest_make_test();
assert(!zt_verify_boolean_relation(&t, zt_pack_boolean(true, "L"),
zt_pack_string("!=", "=="), zt_pack_boolean(true, "R")));
selftest_stream_eq(
t.stream, "file.c:13: L == R uses inconsistent relation !=\n");
selftest_close_test(&t);
}
/* verifier for rune relation. */
static void test_verifier_for_rune_relation(void)
{
zt_verifier v = zt_verifier_for_rune_relation();
assert(v.nargs == 3);
assert(v.func.args3 == zt_verify_rune_relation);
assert(v.arg_infos[0].kind == ZT_RUNE);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"left hand side is not a rune")
== 0);
assert(v.arg_infos[1].kind == ZT_STRING);
assert(strcmp(v.arg_infos[1].kind_mismatch_msg, "relation is not a string") == 0);
assert(v.arg_infos[2].kind == ZT_RUNE);
assert(strcmp(v.arg_infos[2].kind_mismatch_msg,
"right hand side is not a rune")
== 0);
}
static void test_verify_rune_relation(void)
{
zt_test t;
/* passing == */
t = selftest_make_test();
assert(zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("==", "=="), zt_pack_rune('a', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('\0', "L"),
zt_pack_string("==", "=="), zt_pack_rune('\0', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('\xFF', "L"),
zt_pack_string("==", "=="), zt_pack_rune('\xFF', "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing != */
t = selftest_make_test();
assert(zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("!=", "!="), zt_pack_rune('b', "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing <= */
t = selftest_make_test();
assert(zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("<=", "<="), zt_pack_rune('a', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("<=", "<="), zt_pack_rune('b', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('\0', "L"),
zt_pack_string("<=", "<="), zt_pack_rune('\xFF', "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing < */
t = selftest_make_test();
assert(zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("<", "<"), zt_pack_rune('b', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('\0', "L"),
zt_pack_string("<", "<"), zt_pack_rune('\xFF', "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing >= */
t = selftest_make_test();
assert(zt_verify_rune_relation(&t, zt_pack_rune('\xFF', "L"),
zt_pack_string(">=", ">="), zt_pack_rune('\xFF', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('b', "L"),
zt_pack_string(">=", ">="), zt_pack_rune('a', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('b', "L"),
zt_pack_string(">=", ">="), zt_pack_rune('b', "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing > */
t = selftest_make_test();
assert(zt_verify_rune_relation(&t, zt_pack_rune('b', "L"),
zt_pack_string(">", ">"), zt_pack_rune('a', "R")));
assert(zt_verify_rune_relation(&t, zt_pack_rune('\xFF', "L"),
zt_pack_string(">", ">"), zt_pack_rune('a', "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing == */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("==", "=="), zt_pack_rune('b', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L == R failed because 'a' != 'b'\n");
selftest_close_test(&t);
/* failing != */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("!=", "!="), zt_pack_rune('a', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R failed because 'a' == 'a'\n");
selftest_close_test(&t);
/* failing < */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('b', "L"),
zt_pack_string("<", "<"), zt_pack_rune('a', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L < R failed because 'b' >= 'a'\n");
selftest_close_test(&t);
/* failing <= */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('c', "L"),
zt_pack_string("<=", "<="), zt_pack_rune('b', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L <= R failed because 'c' > 'b'\n");
selftest_close_test(&t);
/* failing > */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string(">", ">"), zt_pack_rune('a', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L > R failed because 'a' <= 'a'\n");
selftest_close_test(&t);
/* failing >= */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string(">=", ">="), zt_pack_rune('b', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L >= R failed because 'a' < 'b'\n");
selftest_close_test(&t);
/* unsupported relation */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("~", "~"), zt_pack_rune('b', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L ~ R uses unsupported relation\n");
selftest_close_test(&t);
/* inconsistent relation */
t = selftest_make_test();
assert(!zt_verify_rune_relation(&t, zt_pack_rune('a', "L"),
zt_pack_string("==", "!="), zt_pack_rune('b', "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R uses inconsistent relation ==\n");
selftest_close_test(&t);
}
/* verifier for integer relation. */
static void test_verifier_for_integer_relation(void)
{
zt_verifier v = zt_verifier_for_integer_relation();
assert(v.nargs == 3);
assert(v.func.args3 == zt_verify_integer_relation);
assert(v.arg_infos[0].kind == ZT_INTMAX);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"left hand side is not an integer")
== 0);
assert(v.arg_infos[1].kind == ZT_STRING);
assert(strcmp(v.arg_infos[1].kind_mismatch_msg, "relation is not a string") == 0);
assert(v.arg_infos[2].kind == ZT_INTMAX);
assert(strcmp(v.arg_infos[2].kind_mismatch_msg,
"right hand side is not an integer")
== 0);
}
static void test_verify_integer_relation(void)
{
zt_test t;
/* passing == */
t = selftest_make_test();
assert(zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string("==", "=="), zt_pack_integer(1, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MAX, "L"),
zt_pack_string("==", "=="), zt_pack_integer(INT_MAX, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MIN, "L"),
zt_pack_string("==", "=="), zt_pack_integer(INT_MIN, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing != */
t = selftest_make_test();
assert(zt_verify_integer_relation(&t, zt_pack_integer(0, "L"),
zt_pack_string("!=", "!="), zt_pack_integer(-1, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MIN, "L"),
zt_pack_string("!=", "!="), zt_pack_integer(INT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing <= */
t = selftest_make_test();
assert(zt_verify_integer_relation(&t, zt_pack_integer(-1, "L"),
zt_pack_string("<=", "<="), zt_pack_integer(-1, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(-1, "L"),
zt_pack_string("<=", "<="), zt_pack_integer(0, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MIN, "L"),
zt_pack_string("<=", "<="), zt_pack_integer(INT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing < */
t = selftest_make_test();
assert(zt_verify_integer_relation(&t, zt_pack_integer(-1, "L"),
zt_pack_string("<", "<"), zt_pack_integer(0, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(0, "L"),
zt_pack_string("<", "<"), zt_pack_integer(1, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MIN, "L"),
zt_pack_string("<", "<"), zt_pack_integer(0, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MIN, "L"),
zt_pack_string("<", "<"), zt_pack_integer(INT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing >= */
t = selftest_make_test();
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MAX, "L"),
zt_pack_string(">=", ">="), zt_pack_integer(INT_MAX, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MAX, "L"),
zt_pack_string(">=", ">="), zt_pack_integer(INT_MIN, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MAX, "L"),
zt_pack_string(">=", ">="), zt_pack_integer(INT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing > */
t = selftest_make_test();
assert(zt_verify_integer_relation(&t, zt_pack_integer(2, "L"),
zt_pack_string(">", ">"), zt_pack_integer(1, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MAX, "L"),
zt_pack_string(">", ">"), zt_pack_integer(INT_MIN, "R")));
assert(zt_verify_integer_relation(&t, zt_pack_integer(INT_MAX, "L"),
zt_pack_string(">", ">"), zt_pack_integer(0, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing == */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string("==", "=="), zt_pack_integer(2, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L == R failed because 1 != 2\n");
selftest_close_test(&t);
/* failing != */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string("!=", "!="), zt_pack_integer(1, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R failed because 1 == 1\n");
selftest_close_test(&t);
/* failing < */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string("<", "<"), zt_pack_integer(1, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L < R failed because 1 >= 1\n");
selftest_close_test(&t);
/* failing <= */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(3, "L"),
zt_pack_string("<=", "<="), zt_pack_integer(2, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L <= R failed because 3 > 2\n");
selftest_close_test(&t);
/* failing > */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string(">", ">"), zt_pack_integer(1, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L > R failed because 1 <= 1\n");
selftest_close_test(&t);
/* failing >= */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string(">=", ">="), zt_pack_integer(2, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L >= R failed because 1 < 2\n");
selftest_close_test(&t);
/* unsupported relation */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string("~", "~"), zt_pack_integer(2, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L ~ R uses unsupported relation\n");
selftest_close_test(&t);
/* inconsistent relation */
t = selftest_make_test();
assert(!zt_verify_integer_relation(&t, zt_pack_integer(1, "L"),
zt_pack_string("==", "!="), zt_pack_integer(2, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R uses inconsistent relation ==\n");
selftest_close_test(&t);
}
/* verifier for unsigned relation. */
static void test_verifier_for_unsigned_relation(void)
{
zt_verifier v = zt_verifier_for_unsigned_relation();
assert(v.nargs == 3);
assert(v.func.args3 == zt_verify_unsigned_relation);
assert(v.arg_infos[0].kind == ZT_UINTMAX);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"left hand side is not an unsigned integer")
== 0);
assert(v.arg_infos[1].kind == ZT_STRING);
assert(strcmp(v.arg_infos[1].kind_mismatch_msg,
"relation is not a string")
== 0);
assert(v.arg_infos[2].kind == ZT_UINTMAX);
assert(strcmp(v.arg_infos[2].kind_mismatch_msg,
"right hand side is not an unsigned integer")
== 0);
}
static void test_verify_unsigned_relation(void)
{
zt_test t;
/* passing == */
t = selftest_make_test();
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string("==", "=="), zt_pack_unsigned(1U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(UINT_MAX, "L"),
zt_pack_string("==", "=="), zt_pack_unsigned(UINT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing != */
t = selftest_make_test();
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(0U, "L"),
zt_pack_string("!=", "!="), zt_pack_unsigned(1U, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing <= */
t = selftest_make_test();
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(0U, "L"),
zt_pack_string("<=", "<="), zt_pack_unsigned(0U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(0U, "L"),
zt_pack_string("<=", "<="), zt_pack_unsigned(UINT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing < */
t = selftest_make_test();
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(0U, "L"),
zt_pack_string("<", "<"), zt_pack_unsigned(1U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(0U, "L"),
zt_pack_string("<", "<"), zt_pack_unsigned(UINT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing >= */
t = selftest_make_test();
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(0U, "L"),
zt_pack_string(">=", ">="), zt_pack_unsigned(0U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(UINT_MAX, "L"),
zt_pack_string(">=", ">="), zt_pack_unsigned(0U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(UINT_MAX, "L"),
zt_pack_string(">=", ">="), zt_pack_unsigned(UINT_MAX, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* passing > */
t = selftest_make_test();
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(2U, "L"),
zt_pack_string(">", ">"), zt_pack_unsigned(1U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(UINT_MAX, "L"),
zt_pack_string(">", ">"), zt_pack_unsigned(0U, "R")));
assert(zt_verify_unsigned_relation(&t, zt_pack_unsigned(UINT_MAX, "L"),
zt_pack_string(">", ">"), zt_pack_unsigned(0U, "R")));
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing == */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string("==", "=="), zt_pack_unsigned(2U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L == R failed because 1 != 2\n");
selftest_close_test(&t);
/* failing != */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string("!=", "!="), zt_pack_unsigned(1U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R failed because 1 == 1\n");
selftest_close_test(&t);
/* failing < */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string("<", "<"), zt_pack_unsigned(1U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L < R failed because 1 >= 1\n");
selftest_close_test(&t);
/* failing <= */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(3U, "L"),
zt_pack_string("<=", "<="), zt_pack_unsigned(2U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L <= R failed because 3 > 2\n");
selftest_close_test(&t);
/* failing > */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string(">", ">"), zt_pack_unsigned(1U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L > R failed because 1 <= 1\n");
selftest_close_test(&t);
/* failing >= */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string(">=", ">="), zt_pack_unsigned(2U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L >= R failed because 1 < 2\n");
selftest_close_test(&t);
/* unsupported relation */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string("~", "~"), zt_pack_unsigned(2U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L ~ R uses unsupported relation\n");
selftest_close_test(&t);
/* inconsistent relation */
t = selftest_make_test();
assert(!zt_verify_unsigned_relation(&t, zt_pack_unsigned(1U, "L"),
zt_pack_string("==", "!="), zt_pack_unsigned(2U, "R")));
selftest_stream_eq(
t.stream, "file.c:13: assertion L != R uses inconsistent relation ==\n");
selftest_close_test(&t);
}
/* verifier for string relation. */
static void test_verifier_for_string_relation(void)
{
zt_verifier v = zt_verifier_for_string_relation();
assert(v.nargs == 3);
assert(v.func.args3 == zt_verify_string_relation);
assert(v.arg_infos[0].kind == ZT_STRING);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"left hand side is not a string")
== 0);
assert(v.arg_infos[1].kind == ZT_STRING);
assert(strcmp(v.arg_infos[1].kind_mismatch_msg, "relation is not a string") == 0);
assert(v.arg_infos[2].kind == ZT_STRING);
assert(strcmp(v.arg_infos[2].kind_mismatch_msg,
"right hand side is not a string")
== 0);
}
static void test_verify_string_relation(void)
{
zt_test t;
/* NULL on the left side */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string(NULL, "left"),
zt_pack_string("==", "=="),
zt_pack_string("abc", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left == right failed because left hand side is NULL\n");
selftest_close_test(&t);
/* NULL on the right side */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("==", "=="),
zt_pack_string(NULL, "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left == right failed because right hand side is NULL\n");
selftest_close_test(&t);
/* passing == */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("==", "=="),
zt_pack_string("abc", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing == */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("==", "=="),
zt_pack_string("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left == right failed because \"abc\" != \"xyz\"\n");
selftest_close_test(&t);
/* passing != */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("!=", "!="),
zt_pack_string("xyz", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing != */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("!=", "!="),
zt_pack_string("abc", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left != right failed because \"abc\" == \"abc\"\n");
selftest_close_test(&t);
/* passing < */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("<", "<"),
zt_pack_string("xyz", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing < */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("<", "<"),
zt_pack_string("abc", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left < right failed because \"abc\" >= \"abc\"\n");
selftest_close_test(&t);
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("xyz", "left"),
zt_pack_string("<", "<"),
zt_pack_string("abc", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left < right failed because \"xyz\" >= \"abc\"\n");
selftest_close_test(&t);
/* passing <= */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("<=", "<="),
zt_pack_string("xyz", "right"))
== true);
selftest_stream_eq(t.stream, "");
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("<=", "<="),
zt_pack_string("abc", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing <= */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("xyz", "left"),
zt_pack_string("<=", "<="),
zt_pack_string("abc", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left <= right failed because \"xyz\" > \"abc\"\n");
selftest_close_test(&t);
/* passing > */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("xyz", "left"),
zt_pack_string(">", ">"),
zt_pack_string("abc", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing > */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string(">", ">"),
zt_pack_string("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left > right failed because \"abc\" <= \"xyz\"\n");
selftest_close_test(&t);
/* passing >= */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("xyz", "left"),
zt_pack_string(">=", ">="),
zt_pack_string("abc", "right"))
== true);
selftest_stream_eq(t.stream, "");
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string(">=", ">="),
zt_pack_string("abc", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing >= */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string(">=", ">="),
zt_pack_string("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left >= right failed because \"abc\" < \"xyz\"\n");
selftest_close_test(&t);
/* unsupported relation */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("~", "~"),
zt_pack_string("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left ~ right uses unsupported relation\n");
selftest_close_test(&t);
/* inconsistent relation */
t = selftest_make_test();
assert(zt_verify_string_relation(&t, zt_pack_string("abc", "left"),
zt_pack_string("==", "!="),
zt_pack_string("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left != right uses inconsistent relation ==\n");
selftest_close_test(&t);
}
static void test_verifier_for_pointer_relation(void)
{
zt_verifier v = zt_verifier_for_pointer_relation();
assert(v.nargs == 3);
assert(v.func.args3 == zt_verify_pointer_relation);
assert(v.arg_infos[0].kind == ZT_POINTER);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"left hand side is not a pointer")
== 0);
assert(v.arg_infos[1].kind == ZT_STRING);
assert(strcmp(v.arg_infos[1].kind_mismatch_msg, "relation is not a string") == 0);
assert(v.arg_infos[2].kind == ZT_POINTER);
assert(strcmp(v.arg_infos[2].kind_mismatch_msg,
"right hand side is not a pointer")
== 0);
}
static void test_verify_pointer_relation(void)
{
zt_test t;
const char* non_null_ptr = "";
/* passing == */
t = selftest_make_test();
assert(zt_verify_pointer_relation(&t, zt_pack_pointer(NULL, "left"),
zt_pack_string("==", "=="),
zt_pack_pointer(NULL, "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing == */
t = selftest_make_test();
assert(zt_verify_pointer_relation(&t, zt_pack_pointer(NULL, "left"),
zt_pack_string("==", "=="),
zt_pack_pointer(non_null_ptr, "right"))
== false);
selftest_stream_eq_at(
t.stream, __FILE__, __LINE__, "file.c:13: assertion left == right failed because %p != %p\n", NULL, non_null_ptr);
selftest_close_test(&t);
/* passing != */
t = selftest_make_test();
assert(zt_verify_pointer_relation(&t, zt_pack_pointer("abc", "left"),
zt_pack_string("!=", "!="),
zt_pack_pointer("xyz", "right"))
== true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing != */
t = selftest_make_test();
assert(zt_verify_pointer_relation(&t, zt_pack_pointer(non_null_ptr, "left"),
zt_pack_string("!=", "!="),
zt_pack_pointer(non_null_ptr, "right"))
== false);
selftest_stream_eq_at(
t.stream, __FILE__, __LINE__, "file.c:13: assertion left != right failed because %p == %p\n", non_null_ptr, non_null_ptr);
selftest_close_test(&t);
/* unsupported relation */
t = selftest_make_test();
assert(zt_verify_pointer_relation(&t, zt_pack_pointer("abc", "left"),
zt_pack_string("~", "~"),
zt_pack_pointer("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left ~ right uses unsupported relation\n");
selftest_close_test(&t);
/* inconsistent relation */
t = selftest_make_test();
assert(zt_verify_pointer_relation(&t, zt_pack_pointer("abc", "left"),
zt_pack_string("==", "!="),
zt_pack_pointer("xyz", "right"))
== false);
selftest_stream_eq(
t.stream, "file.c:13: assertion left != right uses inconsistent relation ==\n");
selftest_close_test(&t);
}
/* verifier for null. */
static void test_verifier_for_null(void)
{
zt_verifier v = zt_verifier_for_null();
assert(v.nargs == 1);
assert(v.func.args1 == zt_verify_null);
assert(v.arg_infos[0].kind == ZT_POINTER);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"argument is not a pointer")
== 0);
assert(v.arg_infos[1].kind == ZT_NOTHING);
assert(v.arg_infos[1].kind_mismatch_msg == NULL);
assert(v.arg_infos[2].kind == ZT_NOTHING);
assert(v.arg_infos[2].kind_mismatch_msg == NULL);
}
static void test_verify_null(void)
{
zt_test t;
void* p;
/* passing NULL */
p = NULL;
t = selftest_make_test();
assert(zt_verify_null(&t, zt_pack_pointer(p, "p")) == true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing non-NULL */
p = &p;
t = selftest_make_test();
assert(zt_verify_null(&t, zt_pack_pointer(p, "p")) == false);
selftest_stream_eq_at(
t.stream, __FILE__, __LINE__, "file.c:13: assertion p == NULL failed because %p != NULL\n", p);
selftest_close_test(&t);
}
/* verifier for not-null. */
static void test_verifier_for_not_null(void)
{
zt_verifier v = zt_verifier_for_not_null();
assert(v.nargs == 1);
assert(v.func.args1 == zt_verify_not_null);
assert(v.arg_infos[0].kind == ZT_POINTER);
assert(strcmp(v.arg_infos[0].kind_mismatch_msg,
"argument is not a pointer")
== 0);
assert(v.arg_infos[1].kind == ZT_NOTHING);
assert(v.arg_infos[1].kind_mismatch_msg == NULL);
assert(v.arg_infos[2].kind == ZT_NOTHING);
assert(v.arg_infos[2].kind_mismatch_msg == NULL);
}
static void test_verify_not_null(void)
{
zt_test t;
void* p;
/* passing non-NULL */
p = &p;
t = selftest_make_test();
assert(zt_verify_not_null(&t, zt_pack_pointer(p, "p")) == true);
selftest_stream_eq(t.stream, "");
selftest_close_test(&t);
/* failing NULL */
p = NULL;
t = selftest_make_test();
assert(zt_verify_not_null(&t, zt_pack_pointer(p, "p")) == false);
selftest_stream_eq(t.stream, "file.c:13: assertion p != NULL failed\n");
selftest_close_test(&t);
}
/* all the claim macros */
static void test_ZT_TRUE(void)
{
zt_claim claim = ZT_TRUE(1 > 0);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_true);
assert(zt_value_kind_of(claim.args[0]) == ZT_BOOLEAN);
assert(claim.args[0].as.boolean == true);
assert(strcmp(zt_source_of(claim.args[0]), "1 > 0") == 0);
}
static void test_ZT_FALSE(void)
{
zt_claim claim = ZT_FALSE(0 < 1);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_false);
assert(zt_value_kind_of(claim.args[0]) == ZT_BOOLEAN);
assert(claim.args[0].as.boolean == true);
assert(strcmp(zt_source_of(claim.args[0]), "0 < 1") == 0);
}
static void test_ZT_CMP_BOOL(void)
{
zt_claim claim = ZT_CMP_BOOL(true, ==, 1 == 1);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_boolean_relation);
assert(zt_value_kind_of(claim.args[0]) == ZT_BOOLEAN);
assert(claim.args[0].as.boolean == true);
assert(strcmp(zt_source_of(claim.args[0]), "true") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_STRING);
assert(strcmp(claim.args[1].as.string, "==") == 0);
assert(strcmp(zt_source_of(claim.args[1]), "==") == 0);
assert(zt_value_kind_of(claim.args[2]) == ZT_BOOLEAN);
assert(claim.args[2].as.boolean == true);
assert(strcmp(zt_source_of(claim.args[2]), "1 == 1") == 0);
}
static void test_ZT_CMP_RUNE(void)
{
char a, b;
zt_claim claim;
a = 'a';
b = 'b';
claim = ZT_CMP_RUNE(a, ==, b);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_rune_relation);
assert(zt_value_kind_of(claim.args[0]) == ZT_RUNE);
assert(claim.args[0].as.integer == 'a');
assert(strcmp(zt_source_of(claim.args[0]), "a") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_STRING);
assert(strcmp(claim.args[1].as.string, "==") == 0);
assert(strcmp(zt_source_of(claim.args[1]), "==") == 0);
assert(zt_value_kind_of(claim.args[2]) == ZT_RUNE);
assert(claim.args[2].as.integer == 'b');
assert(strcmp(zt_source_of(claim.args[2]), "b") == 0);
}
static void test_ZT_CMP_INT(void)
{
int a, b;
zt_claim claim;
a = 1;
b = -2;
claim = ZT_CMP_INT(a, ==, b);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_integer_relation);
assert(zt_value_kind_of(claim.args[0]) == ZT_INTMAX);
assert(claim.args[0].as.integer == 1);
assert(strcmp(zt_source_of(claim.args[0]), "a") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_STRING);
assert(strcmp(claim.args[1].as.string, "==") == 0);
assert(strcmp(zt_source_of(claim.args[1]), "==") == 0);
assert(zt_value_kind_of(claim.args[2]) == ZT_INTMAX);
assert(claim.args[2].as.integer == -2);
assert(strcmp(zt_source_of(claim.args[2]), "b") == 0);
}
static inline zt_value zt_pack_legacy_integer(int value, const char* source)
{
zt_value v;
v.as.integer = value;
v.source = source;
v.kind = ZT_INTEGER;
return v;
}
static void test_zt_cmp_int_legacy(void)
{
int a, b;
zt_claim claim;
zt_value left, rel, right;
a = 1;
b = -2;
left = zt_pack_legacy_integer(a, "a");
rel = zt_pack_string("==", "==");
right = zt_pack_legacy_integer(b, "b");
claim = zt_cmp_int(ZT_CURRENT_LOCATION(), left, rel, right);
assert(left.kind == ZT_INTEGER);
assert(right.kind == ZT_INTEGER);
assert(claim.args[0].kind == ZT_INTMAX);
assert(claim.args[2].kind == ZT_INTMAX);
}
static void test_ZT_CMP_UINT(void)
{
unsigned int a, b;
zt_claim claim;
a = 1;
b = 2;
claim = ZT_CMP_UINT(a, ==, b);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_unsigned_relation);
assert(zt_value_kind_of(claim.args[0]) == ZT_UINTMAX);
assert(claim.args[0].as.unsigned_integer == 1);
assert(strcmp(zt_source_of(claim.args[0]), "a") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_STRING);
assert(strcmp(claim.args[1].as.string, "==") == 0);
assert(strcmp(zt_source_of(claim.args[1]), "==") == 0);
assert(zt_value_kind_of(claim.args[2]) == ZT_UINTMAX);
assert(claim.args[2].as.unsigned_integer == 2);
assert(strcmp(zt_source_of(claim.args[2]), "b") == 0);
}
static inline zt_value zt_pack_legacy_unsigned(unsigned value, const char* source)
{
zt_value v;
v.source = source;
v.as.unsigned_integer = value;
v.kind = ZT_UNSIGNED;
return v;
}
static void test_zt_cmp_uint_legacy(void)
{
unsigned int a, b;
zt_claim claim;
zt_value left, rel, right;
a = 1;
b = 2;
left = zt_pack_legacy_unsigned(a, "a");
rel = zt_pack_string("==", "==");
right = zt_pack_legacy_unsigned(b, "b");
claim = zt_cmp_uint(ZT_CURRENT_LOCATION(), left, rel, right);
assert(left.kind == ZT_UNSIGNED);
assert(right.kind == ZT_UNSIGNED);
assert(claim.args[0].kind == ZT_UINTMAX);
assert(claim.args[2].kind == ZT_UINTMAX);
}
static void test_ZT_CMP_CSTR(void)
{
const char *a, *b;
zt_claim claim;
a = "foo";
b = "bar";
claim = ZT_CMP_CSTR(a, ==, b);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_string_relation);
assert(zt_value_kind_of(claim.args[0]) == ZT_STRING);
assert(strcmp(claim.args[0].as.string, "foo") == 0);
assert(strcmp(zt_source_of(claim.args[0]), "a") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_STRING);
assert(strcmp(claim.args[1].as.string, "==") == 0);
assert(strcmp(zt_source_of(claim.args[1]), "==") == 0);
assert(zt_value_kind_of(claim.args[2]) == ZT_STRING);
assert(strcmp(claim.args[2].as.string, "bar") == 0);
assert(strcmp(zt_source_of(claim.args[2]), "b") == 0);
}
static void test_ZT_CMP_PTR(void)
{
int life = 42, not_life = 13;
int *a, *b;
zt_claim claim;
a = &life;
b = ¬_life;
claim = ZT_CMP_PTR(a, ==, b);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_pointer_relation);
assert(zt_value_kind_of(claim.args[0]) == ZT_POINTER);
assert(claim.args[0].as.pointer == &life);
assert(strcmp(zt_source_of(claim.args[0]), "a") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_STRING);
assert(strcmp(claim.args[1].as.string, "==") == 0);
assert(strcmp(zt_source_of(claim.args[1]), "==") == 0);
assert(zt_value_kind_of(claim.args[2]) == ZT_POINTER);
assert(claim.args[2].as.pointer == ¬_life);
assert(strcmp(zt_source_of(claim.args[2]), "b") == 0);
}
static void test_ZT_NULL(void)
{
void* p = NULL;
zt_claim claim = ZT_NULL(p);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_null);
assert(zt_value_kind_of(claim.args[0]) == ZT_POINTER);
assert(claim.args[0].as.pointer == NULL);
assert(strcmp(zt_source_of(claim.args[0]), "p") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_NOTHING);
assert(zt_source_of(claim.args[1]) == NULL);
assert(zt_value_kind_of(claim.args[2]) == ZT_NOTHING);
assert(zt_source_of(claim.args[2]) == NULL);
}
static void test_ZT_NOT_NULL(void)
{
void* p = &p;
zt_claim claim = ZT_NOT_NULL(p);
assert(strcmp(claim.location.fname, __FILE__) == 0);
assert(claim.location.lineno == __LINE__ - 2);
assert(claim.make_verifier == zt_verifier_for_not_null);
assert(zt_value_kind_of(claim.args[0]) == ZT_POINTER);
assert(claim.args[0].as.pointer == &p);
assert(strcmp(zt_source_of(claim.args[0]), "p") == 0);
assert(zt_value_kind_of(claim.args[1]) == ZT_NOTHING);
assert(zt_source_of(claim.args[1]) == NULL);
assert(zt_value_kind_of(claim.args[2]) == ZT_NOTHING);
assert(zt_source_of(claim.args[2]) == NULL);
}
static void test_quote_string(void)
{
FILE* f = selftest_temporary_file();
zt_quote_string(f, "abc \n\r\t\v\b double:\" single:' hex:\x07 123");
selftest_stream_eq(f, "\"abc \\n\\r\\t\\v\\b double:\\\" single:' hex:\\0x07 123\"");
fclose(f);
}
static void test_quote_rune(void)
{
FILE* f = selftest_temporary_file();
zt_quote_rune(f, '"');
selftest_stream_eq(f, "'\"'");
fclose(f);
f = selftest_temporary_file();
zt_quote_rune(f, '\'');
selftest_stream_eq(f, "'\\\''");
fclose(f);
}
static bool selftest_stub_nested_test_case_visited;
static void selftest_stub_nested_test_case(zt_t t)
{
assert(t != NULL);
selftest_stub_nested_test_case_visited = true;
}
static bool selftest_stub_nested_test_suite_visited;
static void selftest_stub_nested_test_suite(zt_visitor visitor)
{
assert(visitor.id != NULL);
assert(visitor.vtab != NULL);
selftest_stub_nested_test_suite_visited = true;
ZT_VISIT_TEST_CASE(visitor, selftest_stub_nested_test_case);
}
static bool selftest_stub_test_case_visited;
static void selftest_stub_test_case(zt_t t)
{
assert(t != NULL);
selftest_stub_test_case_visited = true;
}
static bool selftest_stub_test_suite_visited;
static void selftest_stub_test_suite(zt_visitor visitor)
{
assert(visitor.id != NULL);
assert(visitor.vtab != NULL);
selftest_stub_test_suite_visited = true;
ZT_VISIT_TEST_CASE(visitor, selftest_stub_test_case);
ZT_VISIT_TEST_SUITE(visitor, selftest_stub_nested_test_suite);
}
static void test_lister_visitor_visit_suite(void)
{
FILE* f = selftest_temporary_file();
zt_test_lister lister;
zt_visitor visitor;
memset(&lister, 0, sizeof lister);
lister.stream = f;
visitor = zt_visitor_from_test_lister(&lister);
selftest_stub_nested_test_suite_visited = false;
selftest_stub_nested_test_case_visited = false;
selftest_stub_test_suite_visited = false;
selftest_stub_test_case_visited = false;
ZT_VISIT_TEST_SUITE(visitor, selftest_stub_test_suite);
/* test suites are visited, test cases are not. */
assert(selftest_stub_test_suite_visited == true);
assert(selftest_stub_nested_test_suite_visited == true);
assert(selftest_stub_test_case_visited == false);
assert(selftest_stub_nested_test_case_visited == false);
selftest_stream_eq(
f, ""
"- selftest_stub_test_suite\n"
" - selftest_stub_test_case\n"
" - selftest_stub_nested_test_suite\n"
" - selftest_stub_nested_test_case\n");
fclose(f);
}
static void test_runner_visitor_visit_suite(void)
{
FILE* stream_out = selftest_temporary_file();
FILE* stream_err = selftest_temporary_file();
zt_test_runner runner;
zt_visitor visitor;
memset(&runner, 0, sizeof runner);
runner.stream_out = stream_out;
runner.stream_err = stream_err;
visitor = zt_visitor_from_test_runner(&runner);
selftest_stub_nested_test_suite_visited = false;
selftest_stub_nested_test_case_visited = false;
selftest_stub_test_suite_visited = false;
selftest_stub_test_case_visited = false;
ZT_VISIT_TEST_SUITE(visitor, selftest_stub_test_suite);
/* test suites and test cases are all visited. */
assert(selftest_stub_test_suite_visited == true);
assert(selftest_stub_nested_test_suite_visited == true);
assert(selftest_stub_test_case_visited == true);
assert(selftest_stub_nested_test_case_visited == true);
selftest_stream_eq(stream_out, "");
selftest_stream_eq(stream_err, "");
fclose(stream_out);
fclose(stream_err);
}
static bool selftest_case_pending_visited;
static void selftest_case_pending(zt_t t)
{
selftest_case_pending_visited = true;
assert(t->outcome == ZT_PENDING);
}
static void test_runner_visitor_visit_case_outcome_pending(void)
{
FILE* stream_out = selftest_temporary_file();
FILE* stream_err = selftest_temporary_file();
zt_test_runner runner;
zt_visitor visitor;
memset(&runner, 0, sizeof runner);
runner.stream_out = stream_out;
runner.stream_err = stream_err;
visitor = zt_visitor_from_test_runner(&runner);
selftest_case_pending_visited = false;
ZT_VISIT_TEST_CASE(visitor, selftest_case_pending);
assert(selftest_case_pending_visited == true);
selftest_stream_eq(stream_out, "");
selftest_stream_eq(stream_err, "");
assert(runner.num_passed == 1);
assert(runner.num_failed == 0);
fclose(stream_out);
fclose(stream_err);
}
static bool selftest_case_passed_visited;
static void selftest_case_passed(zt_t t)
{
selftest_case_passed_visited = true;
t->outcome = ZT_PASSED;
}
static void test_runner_visitor_visit_case_outcome_passed(void)
{
FILE* stream_out = selftest_temporary_file();
FILE* stream_err = selftest_temporary_file();
zt_test_runner runner;
zt_visitor visitor;
memset(&runner, 0, sizeof runner);
runner.stream_out = stream_out;
runner.stream_err = stream_err;
visitor = zt_visitor_from_test_runner(&runner);
selftest_case_passed_visited = false;
ZT_VISIT_TEST_CASE(visitor, selftest_case_passed);
assert(selftest_case_passed_visited == true);
selftest_stream_eq(stream_out, "");
selftest_stream_eq(stream_err, "");
assert(runner.num_passed == 1);
assert(runner.num_failed == 0);
fclose(stream_out);
fclose(stream_err);
}
static bool selftest_case_failed_visited;
static void selftest_case_failed(zt_t t)
{
selftest_case_failed_visited = true;
t->outcome = ZT_FAILED;
}
static void test_runner_visitor_visit_case_outcome_failed(void)
{
FILE* stream_out = selftest_temporary_file();
FILE* stream_err = selftest_temporary_file();
zt_test_runner runner;
zt_visitor visitor;
memset(&runner, 0, sizeof runner);
runner.stream_out = stream_out;
runner.stream_err = stream_err;
visitor = zt_visitor_from_test_runner(&runner);
selftest_case_failed_visited = false;
ZT_VISIT_TEST_CASE(visitor, selftest_case_failed);
assert(selftest_case_failed_visited == true);
selftest_stream_eq(stream_out, "");
selftest_stream_eq(stream_err, "");
assert(runner.num_passed == 0);
assert(runner.num_failed == 1);
fclose(stream_out);
fclose(stream_err);
}
static bool selftest_case_bogus_outcome_visited;
static void selftest_case_bogus_outcome(zt_t t)
{
selftest_case_bogus_outcome_visited = true;
t->outcome = 42;
}
static void test_runner_visitor_visit_case_outcome_bogus(void)
{
FILE* stream_out = selftest_temporary_file();
FILE* stream_err = selftest_temporary_file();
zt_test_runner runner;
zt_visitor visitor;
memset(&runner, 0, sizeof runner);
runner.stream_out = stream_out;
runner.stream_err = stream_err;
visitor = zt_visitor_from_test_runner(&runner);
selftest_case_bogus_outcome_visited = false;
ZT_VISIT_TEST_CASE(visitor, selftest_case_bogus_outcome);
assert(selftest_case_bogus_outcome_visited == true);
selftest_stream_eq(stream_out, "");
selftest_stream_eq(stream_err, "- selftest_case_bogus_outcome - unexpected outcome code 42\n");
assert(runner.num_passed == 0);
assert(runner.num_failed == 1);
fclose(stream_out);
fclose(stream_err);
}
static void test_main_listing_tests(void)
{
char* test_argv[] = { "a.out", "-l" };
int exit_code;
zt_mock_stdout = selftest_temporary_file();
zt_mock_stderr = selftest_temporary_file();
exit_code = zt_main(2, test_argv, NULL, selftest_stub_test_suite);
assert(exit_code == 0);
selftest_stream_eq(
zt_mock_stdout, ""
"- selftest_stub_test_case\n"
"- selftest_stub_nested_test_suite\n"
" - selftest_stub_nested_test_case\n");
selftest_stream_eq(
zt_mock_stderr, "");
fclose(zt_mock_stdout);
fclose(zt_mock_stderr);
zt_mock_stdout = NULL;
zt_mock_stderr = NULL;
}
static void selftest_passing_check(zt_t t)
{
zt_check(t, ZT_TRUE(1));
zt_check(t, ZT_CMP_INT(1, ==, 1));
}
static void selftest_failing_check(zt_t t)
{
zt_check(t, ZT_TRUE(0));
zt_check(t, ZT_CMP_INT(1, !=, 1));
}
static void selftest_passing_assert(zt_t t)
{
zt_assert(t, ZT_TRUE(1));
}
static void selftest_failing_assert(zt_t t)
{
zt_assert(t, ZT_TRUE(0));
}
static void selftest_empty_suite(ZT_UNUSED zt_visitor v)
{
(void)v;
}
static void selftest_passing_suite(zt_visitor v)
{
ZT_VISIT_TEST_CASE(v, selftest_passing_check);
ZT_VISIT_TEST_CASE(v, selftest_passing_assert);
ZT_VISIT_TEST_SUITE(v, selftest_empty_suite);
}
static void selftest_failing_suite(zt_visitor v)
{
ZT_VISIT_TEST_CASE(v, selftest_failing_check);
ZT_VISIT_TEST_CASE(v, selftest_failing_assert);
ZT_VISIT_TEST_SUITE(v, selftest_empty_suite);
}
static void test_main_running_passing_tests(void)
{
char* test_argv[] = { "a.out" };
int exit_code;
zt_mock_stdout = selftest_temporary_file();
zt_mock_stderr = selftest_temporary_file();
exit_code = zt_main(1, test_argv, NULL, selftest_passing_suite);
assert(exit_code == EXIT_SUCCESS);
selftest_stream_eq(zt_mock_stdout, "");
selftest_stream_eq(zt_mock_stderr, "");
fclose(zt_mock_stdout);
fclose(zt_mock_stderr);
zt_mock_stdout = NULL;
zt_mock_stderr = NULL;
}
static void test_main_verbosely_running_passing_tests(void)
{
char* test_argv[] = { "a.out", "-v" };
int exit_code;
zt_mock_stdout = selftest_temporary_file();
zt_mock_stderr = selftest_temporary_file();
exit_code = zt_main(2, test_argv, NULL, selftest_passing_suite);
assert(exit_code == EXIT_SUCCESS);
selftest_stream_eq(
zt_mock_stdout,
"- selftest_passing_check ok\n"
"- selftest_passing_assert ok\n"
"+ selftest_empty_suite\n");
selftest_stream_eq(zt_mock_stderr, "");
fclose(zt_mock_stdout);
fclose(zt_mock_stderr);
zt_mock_stdout = NULL;
zt_mock_stderr = NULL;
}
static void test_main_verbosely_running_failing_tests(void)
{
char* test_argv[] = { "a.out", "-v" };
int exit_code;
zt_mock_stdout = selftest_temporary_file();
zt_mock_stderr = selftest_temporary_file();
exit_code = zt_main(2, test_argv, NULL, selftest_failing_suite);
assert(exit_code == EXIT_FAILURE);
selftest_stream_eq(
zt_mock_stdout,
"- selftest_failing_check failed\n"
"- selftest_failing_assert failed\n"
"+ selftest_empty_suite\n");
selftest_stream_eq_at(
zt_mock_stderr, __FILE__, __LINE__,
"%s:%d: assertion failed because 0 is false\n"
"%s:%d: assertion 1 != 1 failed because 1 == 1\n"
"%s:%d: assertion failed because 0 is false\n",
__FILE__, __LINE__ - 93, __FILE__, __LINE__ - 92, __FILE__, __LINE__ - 82);
fclose(zt_mock_stdout);
fclose(zt_mock_stderr);
zt_mock_stdout = NULL;
zt_mock_stderr = NULL;
}
static void selftest_mixed_suite(zt_visitor v)
{
ZT_VISIT_TEST_SUITE(v, selftest_passing_suite);
ZT_VISIT_TEST_SUITE(v, selftest_failing_suite);
ZT_VISIT_TEST_CASE(v, selftest_case_bogus_outcome);
}
static void test_main_verbosely_running_mixed_tests(void)
{
char* test_argv[] = { "a.out", "-v" };
int exit_code;
zt_mock_stdout = selftest_temporary_file();
zt_mock_stderr = selftest_temporary_file();
exit_code = zt_main(2, test_argv, NULL, selftest_mixed_suite);
assert(exit_code == EXIT_FAILURE);
selftest_stream_eq(
zt_mock_stdout,
"+ selftest_passing_suite\n"
" - selftest_passing_check ok\n"
" - selftest_passing_assert ok\n"
" + selftest_empty_suite\n"
"+ selftest_failing_suite\n"
" - selftest_failing_check failed\n"
" - selftest_failing_assert failed\n"
" + selftest_empty_suite\n"
"- selftest_case_bogus_outcome outcome code 42 (?)\n");
/* ignore stderr as we just care about the -v output. */
fclose(zt_mock_stdout);
fclose(zt_mock_stderr);
zt_mock_stdout = NULL;
zt_mock_stderr = NULL;
}
static void test_stdout_stderr(void)
{
assert(zt_stdout() == stdout);
assert(zt_stderr() == stderr);
}
int main(ZT_UNUSED int argc, ZT_UNUSED char** argv, ZT_UNUSED char** envp)
{
(void)argc;
(void)argv;
(void)envp;
test_MAJOR_MINOR_VERSION();
test_pack_boolean();
test_pack_rune();
test_pack_integer();
test_pack_unsigned();
test_pack_string();
test_pack_pointer();
test_promote_value();
test_find_binary_relation();
test_invert_binary_relation();
test_binary_relation_as_text();
test_boolean_as_text();
test_verify_claim0();
test_verify_claim1();
test_verify_claim2();
test_verify_claim3();
test_verify_bogus_claim4();
test_verify_mismatch_claim1of1();
test_verify_mismatch_claim1of2();
test_verify_mismatch_claim2of2();
test_verify_mismatch_claim1of3();
test_verify_mismatch_claim2of3();
test_verify_mismatch_claim3of3();
test_verifier_for_true();
test_verify_true();
test_verifier_for_false();
test_verify_false();
test_verifier_for_boolean_relation();
test_verify_boolean_relation();
test_verifier_for_rune_relation();
test_verify_rune_relation();
test_verifier_for_integer_relation();
test_verify_integer_relation();
test_verifier_for_unsigned_relation();
test_verify_unsigned_relation();
test_verifier_for_string_relation();
test_verify_string_relation();
test_verifier_for_pointer_relation();
test_verify_pointer_relation();
test_verifier_for_null();
test_verify_null();
test_verifier_for_not_null();
test_verify_not_null();
test_ZT_TRUE();
test_ZT_FALSE();
test_ZT_CMP_BOOL();
test_ZT_CMP_RUNE();
test_ZT_CMP_INT();
test_zt_cmp_int_legacy();
test_ZT_CMP_UINT();
test_zt_cmp_uint_legacy();
test_ZT_CMP_CSTR();
test_ZT_CMP_PTR();
test_ZT_NULL();
test_ZT_NOT_NULL();
test_quote_string();
test_quote_rune();
test_lister_visitor_visit_suite();
test_runner_visitor_visit_suite();
test_runner_visitor_visit_case_outcome_pending();
test_runner_visitor_visit_case_outcome_passed();
test_runner_visitor_visit_case_outcome_failed();
test_runner_visitor_visit_case_outcome_bogus();
test_main_listing_tests();
test_main_running_passing_tests();
test_main_verbosely_running_passing_tests();
test_main_verbosely_running_failing_tests();
test_main_verbosely_running_mixed_tests();
test_stdout_stderr();
printf("libzt self-test successful\n");
return 0;
}
libzt_0.3.1/zt.c 0000664 0001750 0001750 00000110513 13675422322 012241 0 ustar zyga zyga /* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
*
* Copyright 2019-2020 Zygmunt Krynicki.
*
* This file is part of libzt.
*
* Libzt is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* Libzt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Libzt. If not, see . */
#include "zt.h"
#include
#include
#include
#include
#include
#include
#include
#if !defined(__GNUC__) && !defined(__clang__)
#define ZT_UNUSED
#define ZT_FORMAT_PRINTF(a, b)
#else
#define ZT_UNUSED __attribute__((unused))
#define ZT_FORMAT_PRINTF(a, b) __attribute__((format(printf, a, b)))
#endif
static void zt_logv(FILE* stream, zt_location loc, const char* fmt, va_list ap);
static void zt_logf(FILE* stream, zt_location loc, const char* fmt, ...) ZT_FORMAT_PRINTF(3, 4);
static void zt_logv(FILE* stream, zt_location loc, const char* fmt, va_list ap)
{
if (stream != NULL) {
if (loc.fname != NULL && loc.lineno != 0) {
fprintf(stream, "%s:%d: ", loc.fname, loc.lineno);
}
vfprintf(stream, fmt, ap);
fprintf(stream, "\n");
}
}
static void zt_logf(FILE* stream, zt_location loc, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
zt_logv(stream, loc, fmt, ap);
va_end(ap);
}
static inline zt_value_kind zt_value_kind_of(zt_value value)
{
return value.kind;
}
static inline const char* zt_source_of(zt_value value)
{
return value.source;
}
zt_value zt_pack_rune(int value, const char* source)
{
zt_value v;
/* Rune is meant to be an unsigned value but for practicality the pack
helper is defined to take an integer. Negative values can arise when
a non-7-bit byte is encoded in the string and the architecture uses
signed characters. To counter this treat negative values as if they were
created by sign-extending a signed character and cast to unsigned
character. */
if (value < 0) {
value &= 0xFF;
}
v.as.rune = value;
v.source = source;
v.kind = ZT_RUNE;
return v;
}
static void zt_promote_value(zt_value* v)
{
switch (v->kind) {
case ZT_INTEGER:
v->as.intmax = v->as.integer;
v->kind = ZT_INTMAX;
break;
case ZT_UNSIGNED:
v->as.uintmax = v->as.unsigned_integer;
v->kind = ZT_UINTMAX;
break;
default:
break;
}
}
/** zt_binary_relation describes one of typical binary relations. */
typedef enum zt_binary_relation {
ZT_REL_INVALID,
ZT_REL_EQ,
ZT_REL_NE,
ZT_REL_LE,
ZT_REL_GE,
ZT_REL_LT,
ZT_REL_GT
} zt_binary_relation;
/** zt_find_binary_relation finds a binary relation given operator name. */
static zt_binary_relation zt_find_binary_relation(const char* rel)
{
if (strcmp(rel, "==") == 0) {
return ZT_REL_EQ;
}
if (strcmp(rel, "!=") == 0) {
return ZT_REL_NE;
}
if (strcmp(rel, "<=") == 0) {
return ZT_REL_LE;
}
if (strcmp(rel, ">=") == 0) {
return ZT_REL_GE;
}
if (strcmp(rel, "<") == 0) {
return ZT_REL_LT;
}
if (strcmp(rel, ">") == 0) {
return ZT_REL_GT;
}
return ZT_REL_INVALID;
}
/** zt_invert_binary_relation returns the inverted relation. */
static zt_binary_relation zt_invert_binary_relation(zt_binary_relation rel)
{
switch (rel) {
default:
case ZT_REL_INVALID:
return ZT_REL_INVALID;
case ZT_REL_EQ:
return ZT_REL_NE;
case ZT_REL_NE:
return ZT_REL_EQ;
case ZT_REL_LE:
return ZT_REL_GT;
case ZT_REL_GE:
return ZT_REL_LT;
case ZT_REL_LT:
return ZT_REL_GE;
case ZT_REL_GT:
return ZT_REL_LE;
}
}
/** zt_binary_relation_as_text returns text representation of a relation. */
static const char* zt_binary_relation_as_text(zt_binary_relation rel)
{
switch (rel) {
default:
case ZT_REL_INVALID:
return "invalid";
case ZT_REL_EQ:
return "==";
case ZT_REL_NE:
return "!=";
case ZT_REL_LE:
return "<=";
case ZT_REL_GE:
return ">=";
case ZT_REL_LT:
return "<";
case ZT_REL_GT:
return ">";
}
}
static bool zt_relation_inconsistent(zt_value rel)
{
return strcmp(rel.as.string, zt_source_of(rel)) != 0;
}
static void zt_quote_rune_inner(FILE* stream, int c, int quote)
{
switch (c) {
case '\'':
fputs(quote != '\'' ? "'" : "\\'", stream);
break;
case '"':
fputs(quote != '\"' ? "\"" : "\\\"", stream);
break;
case '\n':
fputs("\\n", stream);
break;
case '\r':
fputs("\\r", stream);
break;
case '\t':
fputs("\\t", stream);
break;
case '\v':
fputs("\\v", stream);
break;
case '\b':
fputs("\\b", stream);
break;
default:
if (isprint(c)) {
fputc(c, stream);
} else {
fprintf(stream, "\\%#04x", c);
}
break;
}
}
static void zt_quote_rune(FILE* stream, int c)
{
fputc('\'', stream);
zt_quote_rune_inner(stream, c, '\'');
fputc('\'', stream);
}
static void zt_quote_string(FILE* stream, const char* str)
{
fputs("\"", stream);
for (;;) {
int c = *str;
str++;
if (c == '\0') {
break;
}
zt_quote_rune_inner(stream, c, '"');
}
fputs("\"", stream);
}
/** zt_outcome describes outcome of a single test. */
typedef enum zt_outcome {
ZT_PENDING,
ZT_PASSED,
ZT_FAILED
} zt_outcome;
typedef struct zt_test {
#if defined(_WIN32) || defined(__WATCOMC__)
jmp_buf jump_buffer;
#else
sigjmp_buf jump_buffer;
#endif
const char* name;
FILE* stream;
zt_location location; /** location of the last verified claim. */
zt_outcome outcome;
} zt_test;
typedef struct zt_visitor_vtab {
void (*visit_case)(void*, zt_test_case_func, const char* name);
void (*visit_suite)(void*, zt_test_suite_func, const char* name);
} zt_visitor_vtab;
typedef struct zt_test_lister {
FILE* stream;
int nesting;
} zt_test_lister;
typedef struct zt_test_runner {
FILE* stream_out;
FILE* stream_err;
int nesting;
int num_passed;
int num_failed;
bool verbose;
} zt_test_runner;
/** zt_verify0_func is a type of verification function with no arguments. */
typedef bool (*zt_verify0_func)(struct zt_test*);
/** zt_verify1_func is a type of verification function with one argument. */
typedef bool (*zt_verify1_func)(struct zt_test*, zt_value);
/** zt_verify2_func is a type of verification function with two arguments. */
typedef bool (*zt_verify2_func)(struct zt_test*, zt_value, zt_value);
/** zt_verify3_func is a type of verification function with three arguments. */
typedef bool (*zt_verify3_func)(struct zt_test*, zt_value, zt_value, zt_value);
/**
* zt_arg_info describes expected kind of arguments for verification
* functions.
*
* Because verification functions use value variants as arguments there is an
* additional layer that describes the desired type of each value. If the
* actual value is of another kind a kind mismatch message contains useful
* explanation about what is necessary.
**/
typedef struct zt_arg_info {
const char* kind_mismatch_msg; /**< failure message on kind mismatch. */
zt_value_kind kind; /**< expected kind of argument value. */
} zt_arg_info;
/**
* zt_verifier describes a verification function for a given claim.
*
* Verifiers are used to check if some property holds. For example, _not null_,
* _integer value greater or equal than_, _has string prefix_ are all
* verifiers.
*
* Verifiers are like functions, they don't contain specific values yet, those
* are provided by the claim type below.
**/
typedef struct zt_verifier {
union {
zt_verify0_func args0; /**< function pointer if nargs==0 */
zt_verify1_func args1; /**< function pointer if nargs==1 */
zt_verify2_func args2; /**< function pointer if nargs==2 */
zt_verify3_func args3; /**< function pointer if nargs==3 */
} func; /**< union storing typed function pointer. */
size_t nargs; /**< number of arguments of the referenced function. */
zt_arg_info arg_infos[3]; /**< arguments for the referenced function. */
} zt_verifier;
void zt_visit_test_suite(zt_visitor v, zt_test_suite_func func,
const char* name)
{
v.vtab->visit_suite(v.id, func, name);
}
void zt_visit_test_case(zt_visitor v, zt_test_case_func func,
const char* name)
{
v.vtab->visit_case(v.id, func, name);
}
/* Lister visitor */
static zt_visitor zt_visitor_from_test_lister(zt_test_lister* lister);
static void zt_test_lister__visit_suite(void* id, zt_test_suite_func func,
const char* name)
{
zt_test_lister* lister = (zt_test_lister*)id;
(void)func;
fprintf(lister->stream, "%*c %s\n", lister->nesting * 3, '-', name);
lister->nesting++;
func(zt_visitor_from_test_lister(lister));
lister->nesting--;
}
static void zt_test_lister__visit_case(void* id, ZT_UNUSED zt_test_case_func func,
const char* name)
{
zt_test_lister* lister = (zt_test_lister*)id;
(void)func;
fprintf(lister->stream, "%*c %s\n", lister->nesting * 3, '-', name);
}
static const zt_visitor_vtab zt_test_lister__visitor_vtab = {
/* .visit_case = */ zt_test_lister__visit_case,
/* .visit_suite = */ zt_test_lister__visit_suite,
};
static zt_visitor zt_visitor_from_test_lister(zt_test_lister* lister)
{
zt_visitor visitor;
memset(&visitor, 0, sizeof visitor);
visitor.id = lister;
visitor.vtab = &zt_test_lister__visitor_vtab;
return visitor;
}
/** zt_list_tests_from lists tests from given suite to a given file. */
static void zt_list_tests_from(FILE* stream, zt_test_suite_func tsuite)
{
zt_test_lister lister;
memset(&lister, 0, sizeof lister);
lister.stream = stream;
tsuite(zt_visitor_from_test_lister(&lister));
}
/* Runner visitor */
static zt_visitor zt_visitor_from_test_runner(zt_test_runner* runner);
static void zt_runner_visitor__visit_suite(void* id, zt_test_suite_func func,
const char* name)
{
zt_test_runner* runner = (zt_test_runner*)id;
if (runner->verbose && runner->stream_out) {
fprintf(runner->stream_out, "%*c %s\n", runner->nesting * 3, '+', name);
}
runner->nesting++;
func(zt_visitor_from_test_runner(runner));
runner->nesting--;
}
static void zt_runner_visitor__visit_case(void* id, zt_test_case_func func,
const char* name)
{
zt_test_runner* runner = (zt_test_runner*)id;
zt_test test;
int jump_result;
memset(&test, 0, sizeof test);
test.stream = runner->stream_err;
test.outcome = ZT_PENDING;
#if defined(_WIN32) || defined(__WATCOMC__)
jump_result = setjmp(test.jump_buffer);
#else
jump_result = sigsetjmp(test.jump_buffer, 1);
#endif
if (jump_result == 0) {
if (runner->verbose && runner->stream_out) {
fprintf(runner->stream_out, "%*c %s", runner->nesting * 3, '-', name);
}
func(&test);
}
switch (test.outcome) {
case ZT_PENDING:
case ZT_PASSED:
if (runner->verbose && runner->stream_out) {
fprintf(runner->stream_out, " ok\n");
}
runner->num_passed++;
break;
case ZT_FAILED:
if (runner->verbose && runner->stream_out) {
fprintf(runner->stream_out, " failed\n");
}
runner->num_failed++;
break;
default:
if (runner->verbose && runner->stream_out) {
fprintf(runner->stream_out, " outcome code %d (?)\n", test.outcome);
}
if (runner->stream_err) {
fprintf(runner->stream_err, "%*c %s - unexpected outcome code %d\n",
runner->nesting * 3, '-', name, test.outcome);
}
runner->num_failed++;
break;
}
}
static const zt_visitor_vtab zt_test_runner__visitor_vtab = {
/* .visit_case = */ zt_runner_visitor__visit_case,
/* .visit_suite = */ zt_runner_visitor__visit_suite,
};
static zt_visitor zt_visitor_from_test_runner(zt_test_runner* runner)
{
zt_visitor visitor;
visitor.id = runner;
visitor.vtab = &zt_test_runner__visitor_vtab;
return visitor;
}
/** zt_run_tests_from runs tests from given suite and returns the outcome. */
static zt_outcome zt_run_tests_from(FILE* stream_out, FILE* stream_err, bool verbose,
void (*test_suite_func)(zt_visitor))
{
zt_test_runner runner;
memset(&runner, 0, sizeof runner);
runner.stream_out = stream_out;
runner.stream_err = stream_err;
runner.verbose = verbose;
test_suite_func(zt_visitor_from_test_runner(&runner));
if (runner.num_failed > 0) {
return ZT_FAILED;
}
return ZT_PASSED;
}
/* claim verifier and test failure */
static bool zt_verify_claim(zt_test* test, const zt_claim* claim)
{
zt_verifier verifier = claim->make_verifier();
test->location = claim->location;
switch (verifier.nargs) {
case 0:
return verifier.func.args0(test);
case 1:
if (zt_value_kind_of(claim->args[0]) != verifier.arg_infos[0].kind) {
zt_logf(test->stream, test->location, "%s", verifier.arg_infos[0].kind_mismatch_msg);
return false;
}
return verifier.func.args1(test, claim->args[0]);
case 2:
if (zt_value_kind_of(claim->args[0]) != verifier.arg_infos[0].kind) {
zt_logf(test->stream, test->location, "%s", verifier.arg_infos[0].kind_mismatch_msg);
return false;
}
if (zt_value_kind_of(claim->args[1]) != verifier.arg_infos[1].kind) {
zt_logf(test->stream, test->location, "%s", verifier.arg_infos[1].kind_mismatch_msg);
return false;
}
return verifier.func.args2(test, claim->args[0], claim->args[1]);
case 3:
if (zt_value_kind_of(claim->args[0]) != verifier.arg_infos[0].kind) {
zt_logf(test->stream, test->location, "%s", verifier.arg_infos[0].kind_mismatch_msg);
return false;
}
if (zt_value_kind_of(claim->args[1]) != verifier.arg_infos[1].kind) {
zt_logf(test->stream, test->location, "%s", verifier.arg_infos[1].kind_mismatch_msg);
return false;
}
if (zt_value_kind_of(claim->args[2]) != verifier.arg_infos[2].kind) {
zt_logf(test->stream, test->location, "%s", verifier.arg_infos[2].kind_mismatch_msg);
return false;
}
return verifier.func.args3(test, claim->args[0], claim->args[1],
claim->args[2]);
default:
zt_logf(test->stream, test->location, "unsupported number of arguments: %" PRIuMAX,
(uintmax_t)verifier.nargs);
return false;
}
}
/* check and assert */
void zt_check(zt_test* test, zt_claim claim)
{
if (!zt_verify_claim(test, &claim)) {
test->outcome = ZT_FAILED;
}
}
void zt_assert(zt_test* test, zt_claim claim)
{
if (!zt_verify_claim(test, &claim)) {
test->outcome = ZT_FAILED;
#if defined(_WIN32) || defined(__WATCOMC__)
longjmp(test->jump_buffer, 1);
#else
siglongjmp(test->jump_buffer, 1);
#endif
/* TODO: in C++ mode throw an exception. */
}
}
/* main */
#ifdef ZT_SELF_TEST_BUILD
static FILE* zt_mock_stdout = NULL;
static FILE* zt_mock_stderr = NULL;
#endif
static FILE* zt_stdout(void)
{
#ifdef ZT_SELF_TEST_BUILD
if (zt_mock_stdout != NULL) {
return zt_mock_stdout;
}
#endif
return stdout;
}
static FILE* zt_stderr(void)
{
#ifdef ZT_SELF_TEST_BUILD
if (zt_mock_stderr != NULL) {
return zt_mock_stderr;
}
#endif
return stderr;
}
int zt_main(int argc, char** argv, ZT_UNUSED char** envp,
zt_test_suite_func tsuite)
{
(void)envp;
if (argc == 2 && strcmp(argv[1], "-l") == 0) {
zt_list_tests_from(zt_stdout(), tsuite);
return EXIT_SUCCESS;
} else {
bool verbose = argc == 2 && strcmp(argv[1], "-v") == 0;
return zt_run_tests_from(
zt_stdout(), zt_stderr(), verbose, tsuite)
== ZT_PASSED
? EXIT_SUCCESS
: EXIT_FAILURE;
}
}
/* verifiers and verification functions */
static bool zt_verify_true(zt_test* test, zt_value value)
{
if (value.as.boolean) {
return true;
}
zt_logf(test->stream, test->location, "assertion failed because %s is false", zt_source_of(value));
return false;
}
static zt_verifier zt_verifier_for_true(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args1 = zt_verify_true;
verifier.nargs = 1;
verifier.arg_infos[0].kind = ZT_BOOLEAN;
verifier.arg_infos[0].kind_mismatch_msg = "value is not a boolean";
return verifier;
}
zt_claim zt_true(zt_location location, zt_value value)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_true;
claim.args[0] = value;
return claim;
}
static bool zt_verify_false(zt_test* test, zt_value value)
{
if (!value.as.boolean) {
return true;
}
zt_logf(test->stream, test->location, "assertion failed because %s is true", zt_source_of(value));
return false;
}
static zt_verifier zt_verifier_for_false(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args1 = zt_verify_false;
verifier.nargs = 1;
verifier.arg_infos[0].kind = ZT_BOOLEAN;
verifier.arg_infos[0].kind_mismatch_msg = "value is not a boolean";
return verifier;
}
zt_claim zt_false(zt_location location, zt_value value)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_false;
claim.args[0] = value;
return claim;
}
static const char* zt_boolean_as_text(bool b)
{
return b ? "true" : "false";
}
static bool zt_verify_boolean_relation(zt_test* test, zt_value left, zt_value rel,
zt_value right)
{
zt_binary_relation bin_rel;
if (zt_relation_inconsistent(rel)) {
zt_logf(test->stream, test->location, "%s %s %s uses inconsistent relation %s",
zt_source_of(left), zt_source_of(rel), zt_source_of(right), rel.as.string);
return false;
}
bin_rel = zt_find_binary_relation(rel.as.string);
switch (bin_rel) {
case ZT_REL_EQ:
if (left.as.boolean == right.as.boolean) {
return true;
}
break;
case ZT_REL_NE:
if (left.as.boolean != right.as.boolean) {
return true;
}
break;
default:
zt_logf(test->stream, test->location, "assertion %s %s %s uses unsupported relation",
zt_source_of(left), rel.as.string, zt_source_of(right));
return false;
}
zt_logf(test->stream, test->location, "assertion %s %s %s failed because %s %s %s",
zt_source_of(left), zt_binary_relation_as_text(bin_rel),
zt_source_of(right),
zt_boolean_as_text(left.as.boolean),
zt_binary_relation_as_text(zt_invert_binary_relation(bin_rel)),
zt_boolean_as_text(right.as.boolean));
return false;
}
static zt_verifier zt_verifier_for_boolean_relation(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = zt_verify_boolean_relation;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_BOOLEAN;
verifier.arg_infos[0].kind_mismatch_msg = "left hand side is not a boolean";
verifier.arg_infos[1].kind = ZT_STRING;
verifier.arg_infos[1].kind_mismatch_msg = "relation is not a string";
verifier.arg_infos[2].kind = ZT_BOOLEAN;
verifier.arg_infos[2].kind_mismatch_msg = "right hand side is not a boolean";
return verifier;
}
zt_claim zt_cmp_bool(zt_location location, zt_value left, zt_value rel, zt_value right)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_boolean_relation;
claim.args[0] = left;
claim.args[1] = rel;
claim.args[2] = right;
return claim;
}
/**
* zt_verify_rune_relation verifies a relation between two runes.
*
* Relation is one of: ==, !=, <=, =>, < and >.
**/
static bool zt_verify_rune_relation(zt_test* test, zt_value left, zt_value rel,
zt_value right)
{
zt_binary_relation bin_rel;
if (zt_relation_inconsistent(rel)) {
zt_logf(test->stream, test->location, "assertion %s %s %s uses inconsistent relation %s",
zt_source_of(left), zt_source_of(rel), zt_source_of(right), rel.as.string);
return false;
}
bin_rel = zt_find_binary_relation(rel.as.string);
switch (bin_rel) {
case ZT_REL_EQ:
if (left.as.rune == right.as.rune) {
return true;
}
break;
case ZT_REL_NE:
if (left.as.rune != right.as.rune) {
return true;
}
break;
case ZT_REL_LE:
if (left.as.rune <= right.as.rune) {
return true;
}
break;
case ZT_REL_GE:
if (left.as.rune >= right.as.rune) {
return true;
}
break;
case ZT_REL_LT:
if (left.as.rune < right.as.rune) {
return true;
}
break;
case ZT_REL_GT:
if (left.as.rune > right.as.rune) {
return true;
}
break;
case ZT_REL_INVALID:
zt_logf(test->stream, test->location, "assertion %s %s %s uses unsupported relation",
zt_source_of(left), zt_source_of(rel), zt_source_of(right));
return false;
}
if (test->stream) {
const zt_location loc = test->location;
FILE* stream = test->stream;
fprintf(stream, "%s:%d: ", loc.fname, loc.lineno);
fprintf(stream, "assertion %s %s %s failed because ",
zt_source_of(left), zt_binary_relation_as_text(bin_rel),
zt_source_of(right));
zt_quote_rune(stream, left.as.rune);
fprintf(stream, " %s ", zt_binary_relation_as_text(zt_invert_binary_relation(bin_rel)));
zt_quote_rune(stream, right.as.rune);
fprintf(stream, "\n");
}
return false;
}
/**
* zt_verifier_for_rune_relation returns a verifier for rune relations.
*
* The returned verifier is used to implement ZT_CMP_RUNE().
**/
static zt_verifier zt_verifier_for_rune_relation(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = zt_verify_rune_relation;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_RUNE;
verifier.arg_infos[0].kind_mismatch_msg = "left hand side is not a rune";
verifier.arg_infos[1].kind = ZT_STRING;
verifier.arg_infos[1].kind_mismatch_msg = "relation is not a string";
verifier.arg_infos[2].kind = ZT_RUNE;
verifier.arg_infos[2].kind_mismatch_msg = "right hand side is not a rune";
return verifier;
}
zt_claim zt_cmp_rune(zt_location location, zt_value left, zt_value rel, zt_value right)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_rune_relation;
claim.args[0] = left;
claim.args[1] = rel;
claim.args[2] = right;
return claim;
}
/**
* zt_verify_integer_relation verifies a relation between two signed integers.
*
* Relation is one of: ==, !=, <=, =>, < and >.
**/
static bool zt_verify_integer_relation(zt_test* test, zt_value left, zt_value rel,
zt_value right)
{
zt_binary_relation bin_rel;
if (zt_relation_inconsistent(rel)) {
zt_logf(test->stream, test->location, "assertion %s %s %s uses inconsistent relation %s",
zt_source_of(left), zt_source_of(rel), zt_source_of(right), rel.as.string);
return false;
}
bin_rel = zt_find_binary_relation(rel.as.string);
switch (bin_rel) {
case ZT_REL_EQ:
if (left.as.intmax == right.as.intmax) {
return true;
}
break;
case ZT_REL_NE:
if (left.as.intmax != right.as.intmax) {
return true;
}
break;
case ZT_REL_LE:
if (left.as.intmax <= right.as.intmax) {
return true;
}
break;
case ZT_REL_GE:
if (left.as.intmax >= right.as.intmax) {
return true;
}
break;
case ZT_REL_LT:
if (left.as.intmax < right.as.intmax) {
return true;
}
break;
case ZT_REL_GT:
if (left.as.intmax > right.as.intmax) {
return true;
}
break;
case ZT_REL_INVALID:
zt_logf(test->stream, test->location, "assertion %s %s %s uses unsupported relation",
zt_source_of(left), zt_source_of(rel), zt_source_of(right));
return false;
}
zt_logf(test->stream, test->location, "assertion %s %s %s failed because %jd %s %jd",
zt_source_of(left), zt_source_of(rel), zt_source_of(right),
left.as.intmax, zt_binary_relation_as_text(zt_invert_binary_relation(bin_rel)),
right.as.intmax);
return false;
}
/**
* zt_verifier_for_integer_relation returns a verifier for integer relations.
*
* The returned verifier is used to implement ZT_CMP_INT().
**/
static zt_verifier zt_verifier_for_integer_relation(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = zt_verify_integer_relation;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_INTMAX;
verifier.arg_infos[0].kind_mismatch_msg = "left hand side is not an integer";
verifier.arg_infos[1].kind = ZT_STRING;
verifier.arg_infos[1].kind_mismatch_msg = "relation is not a string";
verifier.arg_infos[2].kind = ZT_INTMAX;
verifier.arg_infos[2].kind_mismatch_msg = "right hand side is not an integer";
return verifier;
}
zt_claim zt_cmp_int(zt_location location, zt_value left, zt_value rel, zt_value right)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_integer_relation;
claim.args[0] = left;
claim.args[1] = rel;
claim.args[2] = right;
zt_promote_value(&claim.args[0]);
zt_promote_value(&claim.args[2]);
return claim;
}
/**
* zt_verify_unsigned_relation verifies a relation between two unsigned values.
*
* Relation is one of: ==, !=, <=, =>, < and >.
**/
static bool zt_verify_unsigned_relation(zt_test* test, zt_value left, zt_value rel,
zt_value right)
{
zt_binary_relation bin_rel;
if (zt_relation_inconsistent(rel)) {
zt_logf(test->stream, test->location, "assertion %s %s %s uses inconsistent relation %s",
zt_source_of(left), zt_source_of(rel), zt_source_of(right), rel.as.string);
return false;
}
bin_rel = zt_find_binary_relation(rel.as.string);
switch (bin_rel) {
case ZT_REL_EQ:
if (left.as.uintmax == right.as.uintmax) {
return true;
}
break;
case ZT_REL_NE:
if (left.as.uintmax != right.as.uintmax) {
return true;
}
break;
case ZT_REL_LE:
if (left.as.uintmax <= right.as.uintmax) {
return true;
}
break;
case ZT_REL_GE:
if (left.as.uintmax >= right.as.uintmax) {
return true;
}
break;
case ZT_REL_LT:
if (left.as.uintmax < right.as.uintmax) {
return true;
}
break;
case ZT_REL_GT:
if (left.as.uintmax > right.as.uintmax) {
return true;
}
break;
case ZT_REL_INVALID:
zt_logf(test->stream, test->location, "assertion %s %s %s uses unsupported relation",
zt_source_of(left), rel.as.string, zt_source_of(right));
return false;
}
zt_logf(test->stream, test->location, "assertion %s %s %s failed because %ju %s %ju",
zt_source_of(left), rel.as.string, zt_source_of(right),
left.as.uintmax,
zt_binary_relation_as_text(zt_invert_binary_relation(bin_rel)),
right.as.uintmax);
return false;
}
/**
* zt_verifier_for_unsigned_relation returns a verifier for unsigned relations.
*
* The returned verifier is used to implement ZT_CMP_UINT().
*/
static zt_verifier zt_verifier_for_unsigned_relation(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = zt_verify_unsigned_relation;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_UINTMAX;
verifier.arg_infos[0].kind_mismatch_msg = "left hand side is not an unsigned integer";
verifier.arg_infos[1].kind = ZT_STRING;
verifier.arg_infos[1].kind_mismatch_msg = "relation is not a string";
verifier.arg_infos[2].kind = ZT_UINTMAX;
verifier.arg_infos[2].kind_mismatch_msg = "right hand side is not an unsigned integer";
return verifier;
}
zt_claim zt_cmp_uint(zt_location location, zt_value left, zt_value rel, zt_value right)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_unsigned_relation;
claim.args[0] = left;
claim.args[1] = rel;
claim.args[2] = right;
zt_promote_value(&claim.args[0]);
zt_promote_value(&claim.args[2]);
return claim;
}
static bool zt_verify_string_relation(zt_test* test, zt_value left, zt_value rel,
zt_value right)
{
zt_binary_relation bin_rel;
int cmp;
if (zt_relation_inconsistent(rel)) {
zt_logf(test->stream, test->location, "assertion %s %s %s uses inconsistent relation %s",
zt_source_of(left), zt_source_of(rel), zt_source_of(right), rel.as.string);
return false;
}
bin_rel = zt_find_binary_relation(rel.as.string);
if (left.as.string == NULL) {
zt_logf(test->stream, test->location, "assertion %s %s %s failed because left hand side is NULL", zt_source_of(left),
rel.as.string, zt_source_of(right));
return false;
}
if (right.as.string == NULL) {
zt_logf(test->stream, test->location, "assertion %s %s %s failed because right hand side is NULL", zt_source_of(left),
rel.as.string, zt_source_of(right));
return false;
}
cmp = strcmp(left.as.string, right.as.string);
switch (bin_rel) {
case ZT_REL_EQ:
if (cmp == 0) {
return true;
}
break;
case ZT_REL_NE:
if (cmp != 0) {
return true;
}
break;
case ZT_REL_LE:
if (cmp <= 0) {
return true;
}
break;
case ZT_REL_GE:
if (cmp >= 0) {
return true;
}
break;
case ZT_REL_LT:
if (cmp < 0) {
return true;
}
break;
case ZT_REL_GT:
if (cmp > 0) {
return true;
}
break;
case ZT_REL_INVALID:
zt_logf(test->stream, test->location, "assertion %s %s %s uses unsupported relation",
zt_source_of(left), zt_source_of(rel), zt_source_of(right));
return false;
}
if (test->stream) {
const zt_location loc = test->location;
FILE* stream = test->stream;
fprintf(stream, "%s:%d: ", loc.fname, loc.lineno);
fprintf(stream, "assertion %s %s %s failed because ", zt_source_of(left),
rel.as.string, zt_source_of(right));
zt_quote_string(stream, left.as.string);
fprintf(stream, " %s ", zt_binary_relation_as_text(zt_invert_binary_relation(bin_rel)));
zt_quote_string(stream, right.as.string);
fprintf(stream, "\n");
}
return false;
}
/**
* zt_verifier_for_string_relation returns a verifier for string relations.
*
* The returned verifier is used to implement ZT_CMP_CSTR().
*/
static zt_verifier zt_verifier_for_string_relation(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = zt_verify_string_relation;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_STRING;
verifier.arg_infos[0].kind_mismatch_msg = "left hand side is not a string";
verifier.arg_infos[1].kind = ZT_STRING;
verifier.arg_infos[1].kind_mismatch_msg = "relation is not a string";
verifier.arg_infos[2].kind = ZT_STRING;
verifier.arg_infos[2].kind_mismatch_msg = "right hand side is not a string";
return verifier;
}
zt_claim zt_cmp_cstr(zt_location location, zt_value left, zt_value rel, zt_value right)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_string_relation;
claim.args[0] = left;
claim.args[1] = rel;
claim.args[2] = right;
return claim;
}
static bool zt_verify_null(zt_test* test, zt_value value)
{
if (value.as.pointer == NULL) {
return true;
}
zt_logf(test->stream, test->location, "assertion %s == NULL failed because %p != NULL",
zt_source_of(value), value.as.pointer);
return false;
}
static zt_verifier zt_verifier_for_null(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args1 = zt_verify_null;
verifier.nargs = 1;
verifier.arg_infos[0].kind = ZT_POINTER;
verifier.arg_infos[0].kind_mismatch_msg = "argument is not a pointer";
return verifier;
}
zt_claim zt_null(zt_location location, zt_value value)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_null;
claim.args[0] = value;
return claim;
}
static bool zt_verify_not_null(zt_test* test, zt_value value)
{
if (value.as.pointer != NULL) {
return true;
}
zt_logf(test->stream, test->location, "assertion %s != NULL failed", zt_source_of(value));
return false;
}
static zt_verifier zt_verifier_for_not_null(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args1 = zt_verify_not_null;
verifier.nargs = 1;
verifier.arg_infos[0].kind = ZT_POINTER;
verifier.arg_infos[0].kind_mismatch_msg = "argument is not a pointer";
return verifier;
}
zt_claim zt_not_null(zt_location location, zt_value value)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_not_null;
claim.args[0] = value;
return claim;
}
static bool zt_verify_pointer_relation(zt_test* test, zt_value left, zt_value rel,
zt_value right)
{
zt_binary_relation bin_rel;
if (zt_relation_inconsistent(rel)) {
zt_logf(test->stream, test->location, "assertion %s %s %s uses inconsistent relation %s",
zt_source_of(left), zt_source_of(rel), zt_source_of(right), rel.as.string);
return false;
}
bin_rel = zt_find_binary_relation(rel.as.string);
switch (bin_rel) {
case ZT_REL_EQ:
if (left.as.pointer == right.as.pointer) {
return true;
}
break;
case ZT_REL_NE:
if (left.as.pointer != right.as.pointer) {
return true;
}
break;
default:
zt_logf(test->stream, test->location, "assertion %s %s %s uses unsupported relation",
zt_source_of(left), zt_source_of(rel), zt_source_of(right));
return false;
}
zt_logf(test->stream, test->location, "assertion %s %s %s failed because %p %s %p",
zt_source_of(left), rel.as.string, zt_source_of(right),
left.as.pointer,
zt_binary_relation_as_text(zt_invert_binary_relation(bin_rel)),
right.as.pointer);
return false;
}
static zt_verifier zt_verifier_for_pointer_relation(void)
{
zt_verifier verifier;
memset(&verifier, 0, sizeof verifier);
verifier.func.args3 = zt_verify_pointer_relation;
verifier.nargs = 3;
verifier.arg_infos[0].kind = ZT_POINTER;
verifier.arg_infos[0].kind_mismatch_msg = "left hand side is not a pointer";
verifier.arg_infos[1].kind = ZT_STRING;
verifier.arg_infos[1].kind_mismatch_msg = "relation is not a string";
verifier.arg_infos[2].kind = ZT_POINTER;
verifier.arg_infos[2].kind_mismatch_msg = "right hand side is not a pointer";
return verifier;
}
zt_claim zt_cmp_ptr(zt_location location, zt_value left, zt_value rel, zt_value right)
{
zt_claim claim;
memset(&claim, 0, sizeof claim);
claim.location = location;
claim.make_verifier = zt_verifier_for_pointer_relation;
claim.args[0] = left;
claim.args[1] = rel;
claim.args[2] = right;
return claim;
}
libzt_0.3.1/zt.h 0000664 0001750 0001750 00000015062 13675422322 012251 0 ustar zyga zyga /* Copyright 2019-2020 Zygmunt Krynicki.
*
* This file is part of libzt.
*
* Libzt is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* Libzt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Libzt. If not, see . */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include
#include
#include
#include
#define ZT_MAJOR_VERSION 0
#define ZT_MINOR_VERSION 3
struct zt_test;
typedef struct zt_test* zt_t;
struct zt_visitor_vtab;
typedef struct zt_visitor {
void* id;
const struct zt_visitor_vtab* vtab;
} zt_visitor;
typedef void (*zt_test_case_func)(zt_t);
typedef void (*zt_test_suite_func)(zt_visitor);
int zt_main(int argc, char** argv, char** envp, zt_test_suite_func tsuite);
void zt_visit_test_suite(zt_visitor v, zt_test_suite_func func, const char* name);
void zt_visit_test_case(zt_visitor v, zt_test_case_func func, const char* name);
#define ZT_VISIT_TEST_SUITE(v, tsuite) zt_visit_test_suite(v, tsuite, #tsuite)
#define ZT_VISIT_TEST_CASE(v, tcase) zt_visit_test_case(v, tcase, #tcase)
typedef enum zt_value_kind {
ZT_NOTHING,
ZT_BOOLEAN,
ZT_RUNE, /* Rune is a more practical character type. */
ZT_INTEGER, /* Deprecated. Promoted to ZT_INTMAX */
ZT_UNSIGNED, /* Deprecated. Promoted to ZT_UINTMAX */
ZT_STRING,
ZT_POINTER,
ZT_INTMAX,
ZT_UINTMAX
} zt_value_kind;
typedef struct zt_value {
union {
bool boolean;
int rune;
int integer;
unsigned unsigned_integer;
const char* string;
const void* pointer;
intmax_t intmax;
uintmax_t uintmax;
} as;
const char* source;
zt_value_kind kind;
} zt_value;
static inline zt_value zt_pack_nothing(void)
{
zt_value v;
zt_value_kind kind = ZT_NOTHING;
v.source = NULL;
v.kind = kind;
return v;
}
static inline zt_value zt_pack_boolean(bool value, const char* source)
{
zt_value v;
v.as.boolean = value;
v.source = source;
v.kind = ZT_BOOLEAN;
return v;
}
zt_value zt_pack_rune(int value, const char* source);
static inline zt_value zt_pack_integer(intmax_t value, const char* source)
{
zt_value v;
v.as.intmax = value;
v.source = source;
v.kind = ZT_INTMAX;
return v;
}
static inline zt_value zt_pack_unsigned(uintmax_t value, const char* source)
{
zt_value v;
v.source = source;
v.as.uintmax = value;
v.kind = ZT_UINTMAX;
return v;
}
static inline zt_value zt_pack_string(const char* value, const char* source)
{
zt_value v;
v.as.string = value;
v.source = source;
v.kind = ZT_STRING;
return v;
}
static inline zt_value zt_pack_pointer(const void* value, const char* source)
{
zt_value v;
v.as.pointer = value;
v.source = source;
v.kind = ZT_POINTER;
return v;
}
typedef struct zt_location {
const char* fname;
int lineno;
} zt_location;
static inline zt_location zt_location_at(const char* fname, int lineno)
{
zt_location loc;
loc.fname = fname;
loc.lineno = lineno;
return loc;
}
#define ZT_CURRENT_LOCATION() zt_location_at(__FILE__, __LINE__)
struct zt_verifier;
typedef struct zt_claim {
struct zt_verifier (*make_verifier)(void);
zt_value args[3];
zt_location location;
} zt_claim;
void zt_check(zt_t test, zt_claim claim);
void zt_assert(zt_t test, zt_claim claim);
zt_claim zt_true(zt_location location, zt_value value);
zt_claim zt_false(zt_location location, zt_value value);
zt_claim zt_cmp_bool(zt_location location, zt_value left, zt_value rel, zt_value right);
zt_claim zt_cmp_rune(zt_location location, zt_value left, zt_value rel, zt_value right);
zt_claim zt_cmp_int(zt_location location, zt_value left, zt_value rel, zt_value right);
zt_claim zt_cmp_ptr(zt_location location, zt_value left, zt_value rel, zt_value right);
zt_claim zt_cmp_uint(zt_location location, zt_value left, zt_value rel, zt_value right);
zt_claim zt_cmp_cstr(zt_location location, zt_value left, zt_value rel, zt_value right);
zt_claim zt_null(zt_location location, zt_value value);
zt_claim zt_not_null(zt_location location, zt_value value);
#define ZT_TRUE(value) \
zt_true( \
ZT_CURRENT_LOCATION(), \
zt_pack_boolean((value), #value))
#define ZT_FALSE(value) \
zt_false( \
ZT_CURRENT_LOCATION(), \
zt_pack_boolean((value), #value))
#define ZT_CMP_BOOL(left, rel, right) \
zt_cmp_bool( \
ZT_CURRENT_LOCATION(), \
zt_pack_boolean((left), #left), \
zt_pack_string(#rel, #rel), \
zt_pack_boolean((right), #right))
#define ZT_CMP_RUNE(left, rel, right) \
zt_cmp_rune( \
ZT_CURRENT_LOCATION(), \
zt_pack_rune((left), #left), \
zt_pack_string(#rel, #rel), \
zt_pack_rune((right), #right))
#define ZT_CMP_INT(left, rel, right) \
zt_cmp_int( \
ZT_CURRENT_LOCATION(), \
zt_pack_integer((left), #left), \
zt_pack_string(#rel, #rel), \
zt_pack_integer((right), #right))
#define ZT_CMP_UINT(left, rel, right) \
zt_cmp_uint( \
ZT_CURRENT_LOCATION(), \
zt_pack_unsigned((left), #left), \
zt_pack_string(#rel, #rel), \
zt_pack_unsigned((right), #right))
#define ZT_CMP_CSTR(left, rel, right) \
zt_cmp_cstr( \
ZT_CURRENT_LOCATION(), \
zt_pack_string((left), #left), \
zt_pack_string(#rel, #rel), \
zt_pack_string((right), #right))
#define ZT_CMP_PTR(left, rel, right) \
zt_cmp_ptr( \
ZT_CURRENT_LOCATION(), \
zt_pack_pointer((left), #left), \
zt_pack_string(#rel, #rel), \
zt_pack_pointer((right), #right))
#define ZT_NULL(value) \
zt_null( \
ZT_CURRENT_LOCATION(), \
zt_pack_pointer((value), #value))
#define ZT_NOT_NULL(value) \
zt_not_null( \
ZT_CURRENT_LOCATION(), \
zt_pack_pointer((value), #value))
#ifdef __cplusplus
}
#endif