mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-29 15:29:14 +01:00
[tests] check v0.17.1 and v0.18.1 backwards compatibility
This commit is contained in:
@@ -35,6 +35,7 @@ cache:
|
|||||||
- $TRAVIS_BUILD_DIR/depends/built
|
- $TRAVIS_BUILD_DIR/depends/built
|
||||||
- $TRAVIS_BUILD_DIR/depends/sdk-sources
|
- $TRAVIS_BUILD_DIR/depends/sdk-sources
|
||||||
- $TRAVIS_BUILD_DIR/ci/scratch/.ccache
|
- $TRAVIS_BUILD_DIR/ci/scratch/.ccache
|
||||||
|
- $TRAVIS_BUILD_DIR/releases/$HOST
|
||||||
# macOS
|
# macOS
|
||||||
- $HOME/Library/Caches/Homebrew
|
- $HOME/Library/Caches/Homebrew
|
||||||
- /usr/local/Homebrew
|
- /usr/local/Homebrew
|
||||||
@@ -108,7 +109,7 @@ jobs:
|
|||||||
FILE_ENV="./ci/test/00_setup_env_i686_centos.sh"
|
FILE_ENV="./ci/test/00_setup_env_i686_centos.sh"
|
||||||
|
|
||||||
- stage: test
|
- stage: test
|
||||||
name: 'x86_64 Linux [GOAL: install] [bionic] [uses qt5 dev package and some depends packages] [unsigned char]'
|
name: 'x86_64 Linux [GOAL: install] [bionic] [previous releases, uses qt5 dev package and some depends packages] [unsigned char]'
|
||||||
env: >-
|
env: >-
|
||||||
FILE_ENV="./ci/test/00_setup_env_native_qt5.sh"
|
FILE_ENV="./ci/test/00_setup_env_native_qt5.sh"
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ If the repository is not a fresh git clone, you might have to clean files from p
|
|||||||
|
|
||||||
The ci needs to perform various sysadmin tasks such as installing packages or writing to the user's home directory.
|
The ci needs to perform various sysadmin tasks such as installing packages or writing to the user's home directory.
|
||||||
While most of the actions are done inside a docker container, this is not possible for all. Thus, cache directories,
|
While most of the actions are done inside a docker container, this is not possible for all. Thus, cache directories,
|
||||||
such as the depends cache or ccache, are mounted as read-write into the docker container. While it should be fine to run
|
such as the depends cache, previous release binaries, or ccache, are mounted as read-write into the docker container. While it should be fine to run
|
||||||
the ci system locally on you development box, the ci scripts can generally be assumed to have received less review and
|
the ci system locally on you development box, the ci scripts can generally be assumed to have received less review and
|
||||||
testing compared to other parts of the codebase. If you want to keep the work tree clean, you might want to run the ci
|
testing compared to other parts of the codebase. If you want to keep the work tree clean, you might want to run the ci
|
||||||
system in a virtual machine with a Linux operating system of your choice.
|
system in a virtual machine with a Linux operating system of your choice.
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export HOST=${HOST:-$("$BASE_ROOT_DIR/depends/config.guess")}
|
|||||||
export USE_BUSY_BOX=${USE_BUSY_BOX:-false}
|
export USE_BUSY_BOX=${USE_BUSY_BOX:-false}
|
||||||
export RUN_UNIT_TESTS=${RUN_UNIT_TESTS:-true}
|
export RUN_UNIT_TESTS=${RUN_UNIT_TESTS:-true}
|
||||||
export RUN_FUNCTIONAL_TESTS=${RUN_FUNCTIONAL_TESTS:-true}
|
export RUN_FUNCTIONAL_TESTS=${RUN_FUNCTIONAL_TESTS:-true}
|
||||||
|
export TEST_PREVIOUS_RELEASES=${TEST_PREVIOUS_RELEASES:-false}
|
||||||
export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
|
export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
|
||||||
export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed}
|
export CONTAINER_NAME=${CONTAINER_NAME:-ci_unnamed}
|
||||||
export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04}
|
export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04}
|
||||||
@@ -50,6 +51,7 @@ export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache}
|
|||||||
export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
|
export DEPENDS_DIR=${DEPENDS_DIR:-$BASE_ROOT_DIR/depends}
|
||||||
# Folder where the build is done (bin and lib).
|
# Folder where the build is done (bin and lib).
|
||||||
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
|
export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_SCRATCH_DIR/out/$HOST}
|
||||||
|
export PREVIOUS_RELEASES_DIR=${PREVIOUS_RELEASES_DIR:-$BASE_ROOT_DIR/releases/$HOST}
|
||||||
export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks}
|
export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks}
|
||||||
export WINEDEBUG=${WINEDEBUG:-fixme-all}
|
export WINEDEBUG=${WINEDEBUG:-fixme-all}
|
||||||
export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git procps}
|
export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 rsync git procps}
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libhar
|
|||||||
export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
|
export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
|
||||||
export TEST_RUNNER_EXTRA="--coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
|
export TEST_RUNNER_EXTRA="--coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
|
||||||
export GOAL="install"
|
export GOAL="install"
|
||||||
|
export TEST_PREVIOUS_RELEASES=true
|
||||||
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\""
|
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\""
|
||||||
|
|||||||
@@ -40,12 +40,13 @@ fi
|
|||||||
|
|
||||||
mkdir -p "${BASE_SCRATCH_DIR}"
|
mkdir -p "${BASE_SCRATCH_DIR}"
|
||||||
mkdir -p "${CCACHE_DIR}"
|
mkdir -p "${CCACHE_DIR}"
|
||||||
|
mkdir -p "${PREVIOUS_RELEASES_DIR}"
|
||||||
|
|
||||||
export ASAN_OPTIONS="detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1"
|
export ASAN_OPTIONS="detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1"
|
||||||
export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan"
|
export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan"
|
||||||
export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:log_path=${BASE_SCRATCH_DIR}/sanitizer-output/tsan"
|
export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:log_path=${BASE_SCRATCH_DIR}/sanitizer-output/tsan"
|
||||||
export UBSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1"
|
export UBSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1"
|
||||||
env | grep -E '^(BITCOIN_CONFIG|BASE_|QEMU_|CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS)' | tee /tmp/env
|
env | grep -E '^(BITCOIN_CONFIG|BASE_|QEMU_|CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS|TEST_PREVIOUS_RELEASES|PREVIOUS_RELEASES_DIR)' | tee /tmp/env
|
||||||
if [[ $HOST = *-mingw32 ]]; then
|
if [[ $HOST = *-mingw32 ]]; then
|
||||||
DOCKER_ADMIN="--cap-add SYS_ADMIN"
|
DOCKER_ADMIN="--cap-add SYS_ADMIN"
|
||||||
elif [[ $BITCOIN_CONFIG = *--with-sanitizers=*address* ]]; then # If ran with (ASan + LSan), Docker needs access to ptrace (https://github.com/google/sanitizers/issues/764)
|
elif [[ $BITCOIN_CONFIG = *--with-sanitizers=*address* ]]; then # If ran with (ASan + LSan), Docker needs access to ptrace (https://github.com/google/sanitizers/issues/764)
|
||||||
@@ -62,6 +63,7 @@ if [ -z "$RUN_CI_ON_HOST" ]; then
|
|||||||
--mount type=bind,src=$BASE_ROOT_DIR,dst=/ro_base,readonly \
|
--mount type=bind,src=$BASE_ROOT_DIR,dst=/ro_base,readonly \
|
||||||
--mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR \
|
--mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR \
|
||||||
--mount type=bind,src=$DEPENDS_DIR,dst=$DEPENDS_DIR \
|
--mount type=bind,src=$DEPENDS_DIR,dst=$DEPENDS_DIR \
|
||||||
|
--mount type=bind,src=$PREVIOUS_RELEASES_DIR,dst=$PREVIOUS_RELEASES_DIR \
|
||||||
-w $BASE_ROOT_DIR \
|
-w $BASE_ROOT_DIR \
|
||||||
--env-file /tmp/env \
|
--env-file /tmp/env \
|
||||||
--name $CONTAINER_NAME \
|
--name $CONTAINER_NAME \
|
||||||
|
|||||||
@@ -35,3 +35,8 @@ if [ -z "$NO_DEPENDS" ]; then
|
|||||||
fi
|
fi
|
||||||
DOCKER_EXEC $SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
|
DOCKER_EXEC $SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
|
||||||
fi
|
fi
|
||||||
|
if [ "$TEST_PREVIOUS_RELEASES" = "true" ]; then
|
||||||
|
BEGIN_FOLD previous-versions
|
||||||
|
DOCKER_EXEC contrib/devtools/previous_release.sh -b -t "$PREVIOUS_RELEASES_DIR" v0.17.1 v0.18.1
|
||||||
|
END_FOLD
|
||||||
|
fi
|
||||||
|
|||||||
78
test/functional/feature_backwards_compatibility.py
Executable file
78
test/functional/feature_backwards_compatibility.py
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2018-2019 The Bitcoin Core developers
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
"""Backwards compatibility functional test
|
||||||
|
|
||||||
|
Test various backwards compatibility scenarios. Download the previous node binaries:
|
||||||
|
|
||||||
|
contrib/devtools/previous_release.sh -b v0.18.1 v0.17.1
|
||||||
|
|
||||||
|
Due to RPC changes introduced in various versions the below tests
|
||||||
|
won't work for older versions without some patches or workarounds.
|
||||||
|
|
||||||
|
Use only the latest patch version of each release, unless a test specifically
|
||||||
|
needs an older patch version.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from test_framework.test_framework import BitcoinTestFramework, SkipTest
|
||||||
|
|
||||||
|
from test_framework.util import (
|
||||||
|
assert_equal,
|
||||||
|
sync_blocks
|
||||||
|
)
|
||||||
|
|
||||||
|
class BackwardsCompatibilityTest(BitcoinTestFramework):
|
||||||
|
def set_test_params(self):
|
||||||
|
self.setup_clean_chain = True
|
||||||
|
self.num_nodes = 4
|
||||||
|
# Add new version after each release:
|
||||||
|
self.extra_args = [
|
||||||
|
[], # Pre-release: use to mine blocks
|
||||||
|
[], # Pre-release: use to receive coins, swap wallets, etc
|
||||||
|
[], # v0.18.1
|
||||||
|
[] # v0.17.1
|
||||||
|
]
|
||||||
|
|
||||||
|
def setup_nodes(self):
|
||||||
|
if os.getenv("TEST_PREVIOUS_RELEASES") == "false":
|
||||||
|
raise SkipTest("backwards compatibility tests")
|
||||||
|
|
||||||
|
releases_path = os.getenv("PREVIOUS_RELEASES_DIR") or os.getcwd() + "/releases"
|
||||||
|
if not os.path.isdir(releases_path):
|
||||||
|
if os.getenv("TEST_PREVIOUS_RELEASES") == "true":
|
||||||
|
raise AssertionError("TEST_PREVIOUS_RELEASES=1 but releases missing: " + releases_path)
|
||||||
|
raise SkipTest("This test requires binaries for previous releases")
|
||||||
|
|
||||||
|
self.add_nodes(self.num_nodes, extra_args=self.extra_args, versions=[
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
180100,
|
||||||
|
170100
|
||||||
|
], binary=[
|
||||||
|
self.options.bitcoind,
|
||||||
|
self.options.bitcoind,
|
||||||
|
releases_path + "/v0.18.1/bin/bitcoind",
|
||||||
|
releases_path + "/v0.17.1/bin/bitcoind"
|
||||||
|
], binary_cli=[
|
||||||
|
self.options.bitcoincli,
|
||||||
|
self.options.bitcoincli,
|
||||||
|
releases_path + "/v0.18.1/bin/bitcoin-cli",
|
||||||
|
releases_path + "/v0.17.1/bin/bitcoin-cli"
|
||||||
|
])
|
||||||
|
|
||||||
|
self.start_nodes()
|
||||||
|
|
||||||
|
def run_test(self):
|
||||||
|
self.nodes[0].generate(101)
|
||||||
|
|
||||||
|
sync_blocks(self.nodes)
|
||||||
|
|
||||||
|
# Sanity check the test framework:
|
||||||
|
res = self.nodes[self.num_nodes - 1].getblockchaininfo()
|
||||||
|
assert_equal(res['blocks'], 101)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
BackwardsCompatibilityTest().main()
|
||||||
@@ -369,7 +369,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||||||
|
|
||||||
# Public helper methods. These can be accessed by the subclass test scripts.
|
# Public helper methods. These can be accessed by the subclass test scripts.
|
||||||
|
|
||||||
def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None):
|
def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None, binary_cli=None, versions=None):
|
||||||
"""Instantiate TestNode objects.
|
"""Instantiate TestNode objects.
|
||||||
|
|
||||||
Should only be called once after the nodes have been specified in
|
Should only be called once after the nodes have been specified in
|
||||||
@@ -380,11 +380,17 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||||||
extra_confs = [[]] * num_nodes
|
extra_confs = [[]] * num_nodes
|
||||||
if extra_args is None:
|
if extra_args is None:
|
||||||
extra_args = [[]] * num_nodes
|
extra_args = [[]] * num_nodes
|
||||||
|
if versions is None:
|
||||||
|
versions = [None] * num_nodes
|
||||||
if binary is None:
|
if binary is None:
|
||||||
binary = [self.options.bitcoind] * num_nodes
|
binary = [self.options.bitcoind] * num_nodes
|
||||||
|
if binary_cli is None:
|
||||||
|
binary_cli = [self.options.bitcoincli] * num_nodes
|
||||||
assert_equal(len(extra_confs), num_nodes)
|
assert_equal(len(extra_confs), num_nodes)
|
||||||
assert_equal(len(extra_args), num_nodes)
|
assert_equal(len(extra_args), num_nodes)
|
||||||
|
assert_equal(len(versions), num_nodes)
|
||||||
assert_equal(len(binary), num_nodes)
|
assert_equal(len(binary), num_nodes)
|
||||||
|
assert_equal(len(binary_cli), num_nodes)
|
||||||
for i in range(num_nodes):
|
for i in range(num_nodes):
|
||||||
self.nodes.append(TestNode(
|
self.nodes.append(TestNode(
|
||||||
i,
|
i,
|
||||||
@@ -393,7 +399,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||||||
rpchost=rpchost,
|
rpchost=rpchost,
|
||||||
timewait=self.rpc_timeout,
|
timewait=self.rpc_timeout,
|
||||||
bitcoind=binary[i],
|
bitcoind=binary[i],
|
||||||
bitcoin_cli=self.options.bitcoincli,
|
bitcoin_cli=binary_cli[i],
|
||||||
|
version=versions[i],
|
||||||
coverage_dir=self.options.coveragedir,
|
coverage_dir=self.options.coveragedir,
|
||||||
cwd=self.options.tmpdir,
|
cwd=self.options.tmpdir,
|
||||||
extra_conf=extra_confs[i],
|
extra_conf=extra_confs[i],
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class TestNode():
|
|||||||
To make things easier for the test writer, any unrecognised messages will
|
To make things easier for the test writer, any unrecognised messages will
|
||||||
be dispatched to the RPC connection."""
|
be dispatched to the RPC connection."""
|
||||||
|
|
||||||
def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False):
|
def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None):
|
||||||
"""
|
"""
|
||||||
Kwargs:
|
Kwargs:
|
||||||
start_perf (bool): If True, begin profiling the node with `perf` as soon as
|
start_perf (bool): If True, begin profiling the node with `perf` as soon as
|
||||||
@@ -84,6 +84,7 @@ class TestNode():
|
|||||||
# For those callers that need more flexibility, they can just set the args property directly.
|
# For those callers that need more flexibility, they can just set the args property directly.
|
||||||
# Note that common args are set in the config file (see initialize_datadir)
|
# Note that common args are set in the config file (see initialize_datadir)
|
||||||
self.extra_args = extra_args
|
self.extra_args = extra_args
|
||||||
|
self.version = version
|
||||||
# Configuration for logging is set as command-line args rather than in the bitcoin.conf file.
|
# Configuration for logging is set as command-line args rather than in the bitcoin.conf file.
|
||||||
# This means that starting a bitcoind using the temp dir to debug a failed test won't
|
# This means that starting a bitcoind using the temp dir to debug a failed test won't
|
||||||
# spam debug.log.
|
# spam debug.log.
|
||||||
@@ -91,7 +92,6 @@ class TestNode():
|
|||||||
self.binary,
|
self.binary,
|
||||||
"-datadir=" + self.datadir,
|
"-datadir=" + self.datadir,
|
||||||
"-logtimemicros",
|
"-logtimemicros",
|
||||||
"-logthreadnames",
|
|
||||||
"-debug",
|
"-debug",
|
||||||
"-debugexclude=libevent",
|
"-debugexclude=libevent",
|
||||||
"-debugexclude=leveldb",
|
"-debugexclude=leveldb",
|
||||||
@@ -107,6 +107,9 @@ class TestNode():
|
|||||||
"--gen-suppressions=all", "--exit-on-first-error=yes",
|
"--gen-suppressions=all", "--exit-on-first-error=yes",
|
||||||
"--error-exitcode=1", "--quiet"] + self.args
|
"--error-exitcode=1", "--quiet"] + self.args
|
||||||
|
|
||||||
|
if self.version is None or self.version >= 190000:
|
||||||
|
self.args.append("-logthreadnames")
|
||||||
|
|
||||||
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
|
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
|
||||||
self.use_cli = use_cli
|
self.use_cli = use_cli
|
||||||
self.start_perf = start_perf
|
self.start_perf = start_perf
|
||||||
@@ -254,7 +257,11 @@ class TestNode():
|
|||||||
return
|
return
|
||||||
self.log.debug("Stopping node")
|
self.log.debug("Stopping node")
|
||||||
try:
|
try:
|
||||||
|
# Do not use wait argument when testing older nodes, e.g. in feature_backwards_compatibility.py
|
||||||
|
if self.version is None or self.version >= 180000:
|
||||||
self.stop(wait=wait)
|
self.stop(wait=wait)
|
||||||
|
else:
|
||||||
|
self.stop()
|
||||||
except http.client.CannotSendRequest:
|
except http.client.CannotSendRequest:
|
||||||
self.log.exception("Unable to stop node.")
|
self.log.exception("Unable to stop node.")
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ BASE_SCRIPTS = [
|
|||||||
'feature_assumevalid.py',
|
'feature_assumevalid.py',
|
||||||
'example_test.py',
|
'example_test.py',
|
||||||
'wallet_txn_doublespend.py',
|
'wallet_txn_doublespend.py',
|
||||||
|
'feature_backwards_compatibility.py',
|
||||||
'wallet_txn_clone.py --mineblock',
|
'wallet_txn_clone.py --mineblock',
|
||||||
'feature_notifications.py',
|
'feature_notifications.py',
|
||||||
'rpc_getblockfilter.py',
|
'rpc_getblockfilter.py',
|
||||||
|
|||||||
Reference in New Issue
Block a user