test: Updates needed after bitcoin-core/libmultiprocess#240
Upstream PR bitcoin-core/libmultiprocess#240 fixed various issues which require updates to python IPC tests. Those changes are made in this commit.
This commit is contained in:
1 parent
cb15f5a317
commit
8fe91f3719
2 files changed
+25
-36
No files matched your search
@@ -4,8 +4,6 @@
|
|||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test the IPC (multiprocess) interface."""
|
"""Test the IPC (multiprocess) interface."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import http.client
|
|
||||||
import re
|
|
||||||
|
|
||||||
from contextlib import ExitStack
|
from contextlib import ExitStack
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
@@ -86,9 +84,9 @@ class IPCInterfaceTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
def run_unclean_disconnect_test(self):
|
def run_unclean_disconnect_test(self):
|
||||||
"""Test behavior when disconnecting during an IPC call that later
|
"""Test behavior when disconnecting during an IPC call that later
|
||||||
returns a non-null interface pointer. Currently this behavior causes a
|
returns a non-null interface pointer. This used to cause a crash as
|
||||||
crash as reported https://github.com/bitcoin/bitcoin/issues/34250, but a
|
reported https://github.com/bitcoin/bitcoin/issues/34250, but now just
|
||||||
followup will change this behavior."""
|
results in a cancellation log message"""
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
self.log.info("Running disconnect during BlockTemplate.waitNext")
|
self.log.info("Running disconnect during BlockTemplate.waitNext")
|
||||||
timeout = self.rpc_timeout * 1000.0
|
timeout = self.rpc_timeout * 1000.0
|
||||||
@@ -110,28 +108,22 @@ class IPCInterfaceTest(BitcoinTestFramework):
|
|||||||
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
||||||
promise = template.waitNext(ctx, waitoptions)
|
promise = template.waitNext(ctx, waitoptions)
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
disconnected_log_check.enter_context(node.assert_debug_log(expected_msgs=["IPC server: socket disconnected"], timeout=2))
|
disconnected_log_check.enter_context(node.assert_debug_log(expected_msgs=["IPC server: socket disconnected", "canceled while executing"], timeout=2))
|
||||||
del promise
|
del promise
|
||||||
|
|
||||||
asyncio.run(capnp.run(async_routine()))
|
asyncio.run(capnp.run(async_routine()))
|
||||||
|
|
||||||
# Wait for socket disconnected log message, then generate a block to
|
# Wait for socket disconnected log message, then generate a block to
|
||||||
# cause the waitNext() call to return a new template. This will cause a
|
# cause the waitNext() call to return a new template. Look for a
|
||||||
# crash and disconnect with error output.
|
# canceled IPC log message after waitNext returns.
|
||||||
disconnected_log_check.close()
|
with node.assert_debug_log(expected_msgs=["interrupted (canceled)"], timeout=2):
|
||||||
try:
|
disconnected_log_check.close()
|
||||||
self.generate(node, 1)
|
self.generate(node, 1)
|
||||||
except (http.client.RemoteDisconnected, BrokenPipeError, ConnectionResetError):
|
|
||||||
pass
|
|
||||||
node.wait_until_stopped(expected_ret_code=(-11, -6, 1, 66), expected_stderr=re.compile(""))
|
|
||||||
self.start_node(0)
|
|
||||||
|
|
||||||
def run_thread_busy_test(self):
|
def run_thread_busy_test(self):
|
||||||
"""Test behavior when sending multiple calls to the same server thread
|
"""Test behavior when sending multiple calls to the same server thread
|
||||||
which used to cause a crash as reported
|
which used to cause a crash as reported
|
||||||
https://github.com/bitcoin/bitcoin/issues/33923 and currently causes a
|
https://github.com/bitcoin/bitcoin/issues/33923."""
|
||||||
thread busy error. A future change will make this just queue the calls
|
|
||||||
for execution and not trigger any error"""
|
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
self.log.info("Running thread busy test")
|
self.log.info("Running thread busy test")
|
||||||
timeout = self.rpc_timeout * 1000.0
|
timeout = self.rpc_timeout * 1000.0
|
||||||
@@ -151,27 +143,26 @@ class IPCInterfaceTest(BitcoinTestFramework):
|
|||||||
waitoptions.feeThreshold = 1
|
waitoptions.feeThreshold = 1
|
||||||
|
|
||||||
# Make multiple waitNext calls where the first will start to
|
# Make multiple waitNext calls where the first will start to
|
||||||
# execute, the second will be posted waiting to execute, and the
|
# execute, and the second and third will be posted waiting to
|
||||||
# third will fail to execute because the execution thread is busy.
|
# execute. Previously, the third call would fail calling
|
||||||
|
# mp::Waiter::post() because the waiting function slot is occupied,
|
||||||
|
# but now posts are queued.
|
||||||
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
||||||
promise1 = template.waitNext(ctx, waitoptions)
|
promise1 = template.waitNext(ctx, waitoptions)
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
||||||
promise2 = template.waitNext(ctx, waitoptions)
|
promise2 = template.waitNext(ctx, waitoptions)
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
try:
|
with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"], timeout=2):
|
||||||
await template.waitNext(ctx, waitoptions)
|
promise3 = template.waitNext(ctx, waitoptions)
|
||||||
except capnp.lib.capnp.KjException as e:
|
await asyncio.sleep(0.1)
|
||||||
assert_equal(e.description, "remote exception: std::exception: thread busy")
|
|
||||||
assert_equal(e.type, "FAILED")
|
|
||||||
else:
|
|
||||||
raise AssertionError("Expected thread busy exception")
|
|
||||||
|
|
||||||
# Generate a new block to make the active waitNext calls return, then clean up.
|
# Generate a new block to make the active waitNext calls return, then clean up.
|
||||||
with node.assert_debug_log(expected_msgs=["IPC server send response"], timeout=2):
|
with node.assert_debug_log(expected_msgs=["IPC server send response"], timeout=2):
|
||||||
self.generate(node, 1, sync_fun=self.no_op)
|
self.generate(node, 1, sync_fun=self.no_op)
|
||||||
await ((await promise1).result).destroy(ctx)
|
await ((await promise1).result).destroy(ctx)
|
||||||
await ((await promise2).result).destroy(ctx)
|
await ((await promise2).result).destroy(ctx)
|
||||||
|
await ((await promise3).result).destroy(ctx)
|
||||||
await template.destroy(ctx)
|
await template.destroy(ctx)
|
||||||
|
|
||||||
asyncio.run(capnp.run(async_routine()))
|
asyncio.run(capnp.run(async_routine()))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from contextlib import AsyncExitStack
|
from contextlib import AsyncExitStack
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import re
|
import platform
|
||||||
from test_framework.blocktools import NULL_OUTPOINT
|
from test_framework.blocktools import NULL_OUTPOINT
|
||||||
from test_framework.messages import (
|
from test_framework.messages import (
|
||||||
MAX_BLOCK_WEIGHT,
|
MAX_BLOCK_WEIGHT,
|
||||||
@@ -245,17 +245,15 @@ class IPCMiningTest(BitcoinTestFramework):
|
|||||||
await mining.createNewBlock(ctx, opts)
|
await mining.createNewBlock(ctx, opts)
|
||||||
raise AssertionError("createNewBlock unexpectedly succeeded")
|
raise AssertionError("createNewBlock unexpectedly succeeded")
|
||||||
except capnp.lib.capnp.KjException as e:
|
except capnp.lib.capnp.KjException as e:
|
||||||
if e.type == "DISCONNECTED":
|
if e.description == "remote exception: unknown non-KJ exception of type: kj::Exception":
|
||||||
# The remote exception isn't caught currently and leads to a
|
# macOS + REDUCE_EXPORTS bug: Cap'n Proto fails to recognize
|
||||||
# std::terminate call. Just detect and restart in this case.
|
# its own exception type and returns a generic error instead.
|
||||||
# This bug is fixed with
|
# https://github.com/bitcoin/bitcoin/pull/34422#discussion_r2863852691
|
||||||
# https://github.com/bitcoin-core/libmultiprocess/pull/218
|
# Assert this only occurs on Darwin until fixed.
|
||||||
assert_equal(e.description, "Peer disconnected.")
|
assert_equal(platform.system(), "Darwin")
|
||||||
self.nodes[0].wait_until_stopped(expected_ret_code=(-11, -6, 1, 66), expected_stderr=re.compile(""))
|
|
||||||
self.start_node(0)
|
|
||||||
else:
|
else:
|
||||||
assert_equal(e.description, "remote exception: std::exception: block_reserved_weight (0) must be at least 2000 weight units")
|
assert_equal(e.description, "remote exception: std::exception: block_reserved_weight (0) must be at least 2000 weight units")
|
||||||
assert_equal(e.type, "FAILED")
|
assert_equal(e.type, "FAILED")
|
||||||
|
|
||||||
asyncio.run(capnp.run(async_routine()))
|
asyncio.run(capnp.run(async_routine()))
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user