From b2f49bd7325989267017260a9e7c843588a8c237 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sat, 24 Mar 2018 18:37:10 -0500 Subject: [PATCH] Integration of property based testing into Bitcoin Core update copyright headers attempt to fix linting errors Fixing issue with make check classifying generator files as actual unit tests Wrapping gen files in ENABLE_PROPERTY_TESTS macro Make macro better --- configure.ac | 22 ++++++++++++ depends/Makefile | 7 ++++ depends/README.md | 1 + depends/packages/packages.mk | 2 ++ depends/packages/rapidcheck.mk | 18 ++++++++++ src/Makefile.test.include | 12 ++++++- src/test/gen/crypto_gen.cpp | 19 ++++++++++ src/test/gen/crypto_gen.h | 63 ++++++++++++++++++++++++++++++++++ src/test/key_properties.cpp | 53 ++++++++++++++++++++++++++++ 9 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 depends/packages/rapidcheck.mk create mode 100644 src/test/gen/crypto_gen.cpp create mode 100644 src/test/gen/crypto_gen.h create mode 100644 src/test/key_properties.cpp diff --git a/configure.ac b/configure.ac index 4275796b504..0b96e15b9e2 100644 --- a/configure.ac +++ b/configure.ac @@ -130,6 +130,12 @@ AC_ARG_ENABLE(gui-tests, [use_gui_tests=$enableval], [use_gui_tests=$use_tests]) +AC_ARG_WITH([rapidcheck], + [AS_HELP_STRING([--with-rapidcheck], + [enable RapidCheck property based tests (default is yes if librapidcheck is found)])], + [use_rapidcheck=$withval], + [use_rapidcheck=auto]) + AC_ARG_ENABLE(bench, AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]), [use_bench=$enableval], @@ -1134,6 +1140,22 @@ AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT ]) CXXFLAGS="${save_CXXFLAGS}" +dnl RapidCheck Property Based Testing + +enable_property_tests=no +if test "x$use_rapidcheck" = xauto; then + AC_CHECK_HEADERS([rapidcheck.h], [enable_property_tests=yes]) +elif test "x$use_rapidcheck" != xno; then + enable_property_tests=yes +fi + +RAPIDCHECK_LIBS= +if test "x$enable_property_tests" = xyes; then + RAPIDCHECK_LIBS=-lrapidcheck +fi +AC_SUBST(RAPIDCHECK_LIBS) +AM_CONDITIONAL([ENABLE_PROPERTY_TESTS], [test x$enable_property_tests = xyes]) + dnl univalue check need_bundled_univalue=yes diff --git a/depends/Makefile b/depends/Makefile index 3686aaf1f87..da81c4c7eeb 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -5,6 +5,7 @@ WORK_PATH = $(BASEDIR)/work BASE_CACHE ?= $(BASEDIR)/built SDK_PATH ?= $(BASEDIR)/SDKs NO_QT ?= +RAPIDCHECK ?= NO_WALLET ?= NO_UPNP ?= FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources @@ -93,6 +94,8 @@ qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch wallet_packages_$(NO_WALLET) = $(wallet_packages) upnp_packages_$(NO_UPNP) = $(upnp_packages) +rapidcheck_packages_$(RAPIDCHECK) = $(rapidcheck_packages) + packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) @@ -100,6 +103,10 @@ ifneq ($(qt_packages_),) native_packages += $(qt_native_packages) endif +ifeq ($(rapidcheck_packages_),) +packages += $(rapidcheck_packages) +endif + all_packages = $(packages) $(native_packages) meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk diff --git a/depends/README.md b/depends/README.md index fd343f70101..73bfc8b726f 100644 --- a/depends/README.md +++ b/depends/README.md @@ -63,6 +63,7 @@ The following can be set when running make: make FOO=bar NO_WALLET: Don't download/build/cache libs needed to enable the wallet NO_UPNP: Don't download/build/cache packages needed for enabling upnp DEBUG: disable some optimizations and enable more runtime checking + RAPIDCHECK: build rapidcheck (experimental) HOST_ID_SALT: Optional salt to use when generating host package ids BUILD_ID_SALT: Optional salt to use when generating build package ids diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 5fe6f98da24..38329d16d73 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -5,6 +5,8 @@ qt_packages = qrencode protobuf zlib qt_linux_packages:=qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans +rapidcheck_packages = rapidcheck + qt_darwin_packages=qt qt_mingw32_packages=qt diff --git a/depends/packages/rapidcheck.mk b/depends/packages/rapidcheck.mk new file mode 100644 index 00000000000..19cf1cae2ec --- /dev/null +++ b/depends/packages/rapidcheck.mk @@ -0,0 +1,18 @@ +package=rapidcheck +$(package)_version=10fc0cb +$(package)_download_path=https://github.com/MarcoFalke/rapidcheck/archive +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_sha256_hash=9640926223c00af45bce4c7df8b756b5458a89b2ba74cfe3e404467f13ce26df + +define $(package)_config_cmds + cmake -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=true . +endef + +define $(package)_build_cmds + $(MAKE) && \ + mkdir -p $($(package)_staging_dir)$(host_prefix)/include && \ + cp -a include/* $($(package)_staging_dir)$(host_prefix)/include/ && \ + cp -a extras/boost_test/include/rapidcheck/* $($(package)_staging_dir)$(host_prefix)/include/rapidcheck/ && \ + mkdir -p $($(package)_staging_dir)$(host_prefix)/lib && \ + cp -a librapidcheck.a $($(package)_staging_dir)$(host_prefix)/lib/ +endef diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 9e7d0dc745d..f515774b79c 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -8,6 +8,7 @@ TEST_SRCDIR = test TEST_BINARY=test/test_bitcoin$(EXEEXT) JSON_TEST_FILES = \ + test/data/script_tests.json \ test/data/base58_encode_decode.json \ test/data/blockfilters.json \ test/data/key_io_valid.json \ @@ -94,6 +95,15 @@ BITCOIN_TESTS =\ test/validation_block_tests.cpp \ test/versionbits_tests.cpp +if ENABLE_PROPERTY_TESTS +BITCOIN_TESTS += \ + test/key_properties.cpp + +BITCOIN_TEST_SUITE += \ + test/gen/crypto_gen.cpp \ + test/gen/crypto_gen.h +endif + if ENABLE_WALLET BITCOIN_TESTS += \ wallet/test/accounting_tests.cpp \ @@ -118,7 +128,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ diff --git a/src/test/gen/crypto_gen.cpp b/src/test/gen/crypto_gen.cpp new file mode 100644 index 00000000000..ca8c65806ff --- /dev/null +++ b/src/test/gen/crypto_gen.cpp @@ -0,0 +1,19 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + +#include + +#include +#include +#include +#include + +/** Generates 1 to 20 keys for OP_CHECKMULTISIG */ +rc::Gen> MultisigKeys() +{ + return rc::gen::suchThat(rc::gen::arbitrary>(), [](const std::vector& keys) { + return keys.size() >= 1 && keys.size() <= 15; + }); +}; diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h new file mode 100644 index 00000000000..7c2fb0350fa --- /dev/null +++ b/src/test/gen/crypto_gen.h @@ -0,0 +1,63 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_TEST_GEN_CRYPTO_GEN_H +#define BITCOIN_TEST_GEN_CRYPTO_GEN_H + +#include +#include +#include +#include +#include +#include +#include + +/** Generates 1 to 15 keys for OP_CHECKMULTISIG */ +rc::Gen> MultisigKeys(); + +namespace rc +{ +/** Generator for a new CKey */ +template <> +struct Arbitrary { + static Gen arbitrary() + { + return rc::gen::map([](int x) { + CKey key; + key.MakeNewKey(true); + return key; + }); + }; +}; + +/** Generator for a CPrivKey */ +template <> +struct Arbitrary { + static Gen arbitrary() + { + return gen::map(gen::arbitrary(), [](const CKey& key) { + return key.GetPrivKey(); + }); + }; +}; + +/** Generator for a new CPubKey */ +template <> +struct Arbitrary { + static Gen arbitrary() + { + return gen::map(gen::arbitrary(), [](const CKey& key) { + return key.GetPubKey(); + }); + }; +}; +/** Generates a arbitrary uint256 */ +template <> +struct Arbitrary { + static Gen arbitrary() + { + return rc::gen::just(GetRandHash()); + }; +}; +} //namespace rc +#endif diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp new file mode 100644 index 00000000000..14e3c853592 --- /dev/null +++ b/src/test/key_properties.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + +#include +#include