diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -126,6 +126,12 @@ [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], @@ -989,6 +995,22 @@ ]) 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 --- a/depends/Makefile +++ b/depends/Makefile @@ -4,6 +4,7 @@ BASE_CACHE ?= $(BASEDIR)/built SDK_PATH ?= $(BASEDIR)/SDKs NO_QT ?= +RAPIDCHECK ?= NO_WALLET ?= NO_UPNP ?= FALLBACK_DOWNLOAD_PATH ?= https://download.bitcoinabc.org/depends-sources @@ -93,6 +94,8 @@ 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 @@ 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 --- a/depends/README.md +++ b/depends/README.md @@ -39,6 +39,7 @@ 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 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -8,6 +8,8 @@ qt_i686_linux_packages:=$(qt_x86_64_linux_packages) qt_arm_linux_packages:=$(qt_x86_64_linux_packages) +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 --- /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 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -8,6 +8,7 @@ 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 \ @@ -132,6 +133,15 @@ test/work_comparator_tests.cpp \ rpc/test/server_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 \ @@ -156,7 +166,7 @@ $(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.h b/src/test/gen/crypto_gen.h new file mode 100644 --- /dev/null +++ b/src/test/gen/crypto_gen.h @@ -0,0 +1,50 @@ +// 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/gen/crypto_gen.cpp b/src/test/gen/crypto_gen.cpp new file mode 100644 --- /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/key_properties.cpp b/src/test/key_properties.cpp new file mode 100644 --- /dev/null +++ b/src/test/key_properties.cpp @@ -0,0 +1,49 @@ +// 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