Merge #12775: Integration of property based testing into Bitcoin Core
b2f49bd732
Integration of property based testing into Bitcoin Core (Chris Stewart)
Pull request description:
This PR is a subset of the changes in #8469. It's meant to be easier to review. This PR contains all of the build instructions needed for travis to pass. It includes one property call `key_properties.cpp` along with a generator file called `crypto_gen.{h,cpp}`.
Tree-SHA512: 895c9d9273dcd29f696b1de8dfe1ee843095831bf1f68472844181278850bec36b20f0ba7e51e796112c5cc75cd24759f9f1771906503bbf3af16f627e18c6c9
This commit is contained in:
commit
eea87ef537
9 changed files with 196 additions and 1 deletions
22
configure.ac
22
configure.ac
|
@ -130,6 +130,12 @@ AC_ARG_ENABLE(gui-tests,
|
||||||
[use_gui_tests=$enableval],
|
[use_gui_tests=$enableval],
|
||||||
[use_gui_tests=$use_tests])
|
[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,
|
AC_ARG_ENABLE(bench,
|
||||||
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
|
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
|
||||||
[use_bench=$enableval],
|
[use_bench=$enableval],
|
||||||
|
@ -1134,6 +1140,22 @@ AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT
|
||||||
])
|
])
|
||||||
CXXFLAGS="${save_CXXFLAGS}"
|
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
|
dnl univalue check
|
||||||
|
|
||||||
need_bundled_univalue=yes
|
need_bundled_univalue=yes
|
||||||
|
|
|
@ -5,6 +5,7 @@ WORK_PATH = $(BASEDIR)/work
|
||||||
BASE_CACHE ?= $(BASEDIR)/built
|
BASE_CACHE ?= $(BASEDIR)/built
|
||||||
SDK_PATH ?= $(BASEDIR)/SDKs
|
SDK_PATH ?= $(BASEDIR)/SDKs
|
||||||
NO_QT ?=
|
NO_QT ?=
|
||||||
|
RAPIDCHECK ?=
|
||||||
NO_WALLET ?=
|
NO_WALLET ?=
|
||||||
NO_UPNP ?=
|
NO_UPNP ?=
|
||||||
FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources
|
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)
|
wallet_packages_$(NO_WALLET) = $(wallet_packages)
|
||||||
upnp_packages_$(NO_UPNP) = $(upnp_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_)
|
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)
|
native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
|
||||||
|
|
||||||
|
@ -100,6 +103,10 @@ ifneq ($(qt_packages_),)
|
||||||
native_packages += $(qt_native_packages)
|
native_packages += $(qt_native_packages)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(rapidcheck_packages_),)
|
||||||
|
packages += $(rapidcheck_packages)
|
||||||
|
endif
|
||||||
|
|
||||||
all_packages = $(packages) $(native_packages)
|
all_packages = $(packages) $(native_packages)
|
||||||
|
|
||||||
meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
|
meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
|
||||||
|
|
|
@ -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_WALLET: Don't download/build/cache libs needed to enable the wallet
|
||||||
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
|
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
|
||||||
DEBUG: disable some optimizations and enable more runtime checking
|
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
|
HOST_ID_SALT: Optional salt to use when generating host package ids
|
||||||
BUILD_ID_SALT: Optional salt to use when generating build package ids
|
BUILD_ID_SALT: Optional salt to use when generating build package ids
|
||||||
|
|
||||||
|
|
|
@ -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
|
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_darwin_packages=qt
|
||||||
qt_mingw32_packages=qt
|
qt_mingw32_packages=qt
|
||||||
|
|
||||||
|
|
18
depends/packages/rapidcheck.mk
Normal file
18
depends/packages/rapidcheck.mk
Normal file
|
@ -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
|
|
@ -8,6 +8,7 @@ TEST_SRCDIR = test
|
||||||
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
||||||
|
|
||||||
JSON_TEST_FILES = \
|
JSON_TEST_FILES = \
|
||||||
|
test/data/script_tests.json \
|
||||||
test/data/base58_encode_decode.json \
|
test/data/base58_encode_decode.json \
|
||||||
test/data/blockfilters.json \
|
test/data/blockfilters.json \
|
||||||
test/data/key_io_valid.json \
|
test/data/key_io_valid.json \
|
||||||
|
@ -95,6 +96,15 @@ BITCOIN_TESTS =\
|
||||||
test/validation_block_tests.cpp \
|
test/validation_block_tests.cpp \
|
||||||
test/versionbits_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
|
if ENABLE_WALLET
|
||||||
BITCOIN_TESTS += \
|
BITCOIN_TESTS += \
|
||||||
wallet/test/psbt_wallet_tests.cpp \
|
wallet/test/psbt_wallet_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)
|
$(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_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
|
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
|
||||||
|
|
||||||
if ENABLE_ZMQ
|
if ENABLE_ZMQ
|
||||||
|
|
19
src/test/gen/crypto_gen.cpp
Normal file
19
src/test/gen/crypto_gen.cpp
Normal file
|
@ -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 <test/gen/crypto_gen.h>
|
||||||
|
|
||||||
|
#include <key.h>
|
||||||
|
|
||||||
|
#include <rapidcheck/gen/Arbitrary.h>
|
||||||
|
#include <rapidcheck/Gen.h>
|
||||||
|
#include <rapidcheck/gen/Predicate.h>
|
||||||
|
#include <rapidcheck/gen/Container.h>
|
||||||
|
|
||||||
|
/** Generates 1 to 20 keys for OP_CHECKMULTISIG */
|
||||||
|
rc::Gen<std::vector<CKey>> MultisigKeys()
|
||||||
|
{
|
||||||
|
return rc::gen::suchThat(rc::gen::arbitrary<std::vector<CKey>>(), [](const std::vector<CKey>& keys) {
|
||||||
|
return keys.size() >= 1 && keys.size() <= 15;
|
||||||
|
});
|
||||||
|
};
|
63
src/test/gen/crypto_gen.h
Normal file
63
src/test/gen/crypto_gen.h
Normal file
|
@ -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 <key.h>
|
||||||
|
#include <random.h>
|
||||||
|
#include <uint256.h>
|
||||||
|
#include <rapidcheck/gen/Arbitrary.h>
|
||||||
|
#include <rapidcheck/Gen.h>
|
||||||
|
#include <rapidcheck/gen/Create.h>
|
||||||
|
#include <rapidcheck/gen/Numeric.h>
|
||||||
|
|
||||||
|
/** Generates 1 to 15 keys for OP_CHECKMULTISIG */
|
||||||
|
rc::Gen<std::vector<CKey>> MultisigKeys();
|
||||||
|
|
||||||
|
namespace rc
|
||||||
|
{
|
||||||
|
/** Generator for a new CKey */
|
||||||
|
template <>
|
||||||
|
struct Arbitrary<CKey> {
|
||||||
|
static Gen<CKey> arbitrary()
|
||||||
|
{
|
||||||
|
return rc::gen::map<int>([](int x) {
|
||||||
|
CKey key;
|
||||||
|
key.MakeNewKey(true);
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Generator for a CPrivKey */
|
||||||
|
template <>
|
||||||
|
struct Arbitrary<CPrivKey> {
|
||||||
|
static Gen<CPrivKey> arbitrary()
|
||||||
|
{
|
||||||
|
return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) {
|
||||||
|
return key.GetPrivKey();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Generator for a new CPubKey */
|
||||||
|
template <>
|
||||||
|
struct Arbitrary<CPubKey> {
|
||||||
|
static Gen<CPubKey> arbitrary()
|
||||||
|
{
|
||||||
|
return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) {
|
||||||
|
return key.GetPubKey();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/** Generates a arbitrary uint256 */
|
||||||
|
template <>
|
||||||
|
struct Arbitrary<uint256> {
|
||||||
|
static Gen<uint256> arbitrary()
|
||||||
|
{
|
||||||
|
return rc::gen::just(GetRandHash());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} //namespace rc
|
||||||
|
#endif
|
53
src/test/key_properties.cpp
Normal file
53
src/test/key_properties.cpp
Normal file
|
@ -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 <key.h>
|
||||||
|
|
||||||
|
#include <base58.h>
|
||||||
|
#include <script/script.h>
|
||||||
|
#include <uint256.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <utilstrencodings.h>
|
||||||
|
#include <test/test_bitcoin.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <rapidcheck/boost_test.h>
|
||||||
|
#include <rapidcheck/gen/Arbitrary.h>
|
||||||
|
#include <rapidcheck/Gen.h>
|
||||||
|
|
||||||
|
#include <test/gen/crypto_gen.h>
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup)
|
||||||
|
|
||||||
|
/** Check CKey uniqueness */
|
||||||
|
RC_BOOST_PROP(key_uniqueness, (const CKey& key1, const CKey& key2))
|
||||||
|
{
|
||||||
|
RC_ASSERT(!(key1 == key2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Verify that a private key generates the correct public key */
|
||||||
|
RC_BOOST_PROP(key_generates_correct_pubkey, (const CKey& key))
|
||||||
|
{
|
||||||
|
CPubKey pubKey = key.GetPubKey();
|
||||||
|
RC_ASSERT(key.VerifyPubKey(pubKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a CKey using the 'Set' function must give us the same key */
|
||||||
|
RC_BOOST_PROP(key_set_symmetry, (const CKey& key))
|
||||||
|
{
|
||||||
|
CKey key1;
|
||||||
|
key1.Set(key.begin(), key.end(), key.IsCompressed());
|
||||||
|
RC_ASSERT(key1 == key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a CKey, sign a piece of data, then verify it with the public key */
|
||||||
|
RC_BOOST_PROP(key_sign_symmetry, (const CKey& key, const uint256& hash))
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> vchSig;
|
||||||
|
key.Sign(hash, vchSig, 0);
|
||||||
|
const CPubKey& pubKey = key.GetPubKey();
|
||||||
|
RC_ASSERT(pubKey.Verify(hash, vchSig));
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in a new issue