From e25989b648c4235aa5d58ee755fdca2948423db6 Mon Sep 17 00:00:00 2001 From: vividctrlalt Date: Wed, 19 Aug 2026 03:12:06 +0800 Subject: [PATCH 1/4] test: isolate VM flags, BackupServer close, and Mockito spy races --- .../org/tron/core/vm/config/ConfigLoader.java | 80 ++++++++++--------- .../common/backup/socket/BackupServer.java | 18 ++++- .../java/org/tron/common/BaseMethodTest.java | 6 ++ .../tron/common/backup/BackupServerTest.java | 10 ++- 4 files changed, 72 insertions(+), 42 deletions(-) diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 35480935742..f451bd0cf4f 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -17,44 +17,48 @@ public class ConfigLoader { // snapshot into a thread-local view instead of the process-wide global, so it cannot pollute // the flags the block-processing path reads concurrently. public static void load(StoreFactory storeFactory, boolean isolate) { - if (!disable) { - DynamicPropertiesStore ds = storeFactory.getChainBaseManager().getDynamicPropertiesStore(); - VMConfig.setVmTrace(CommonParameter.getInstance().isVmTrace()); - if (ds != null) { - VMConfig.initVmHardFork(checkForEnergyLimit(ds)); - VMConfig.Snapshot snapshot = new VMConfig.Snapshot(); - snapshot.allowMultiSign = ds.getAllowMultiSign() == 1; - snapshot.allowTvmTransferTrc10 = ds.getAllowTvmTransferTrc10() == 1; - snapshot.allowTvmConstantinople = ds.getAllowTvmConstantinople() == 1; - snapshot.allowTvmSolidity059 = ds.getAllowTvmSolidity059() == 1; - snapshot.allowShieldedTRC20Transaction = ds.getAllowShieldedTRC20Transaction() == 1; - snapshot.allowTvmIstanbul = ds.getAllowTvmIstanbul() == 1; - snapshot.allowTvmFreeze = ds.getAllowTvmFreeze() == 1; - snapshot.allowTvmVote = ds.getAllowTvmVote() == 1; - snapshot.allowTvmLondon = ds.getAllowTvmLondon() == 1; - snapshot.allowTvmCompatibleEvm = ds.getAllowTvmCompatibleEvm() == 1; - snapshot.allowHigherLimitForMaxCpuTimeOfOneTx = - ds.getAllowHigherLimitForMaxCpuTimeOfOneTx() == 1; - snapshot.allowTvmFreezeV2 = ds.supportUnfreezeDelay(); - snapshot.allowOptimizedReturnValueOfChainId = ds.getAllowOptimizedReturnValueOfChainId() == 1; - snapshot.allowDynamicEnergy = ds.getAllowDynamicEnergy() == 1; - snapshot.dynamicEnergyThreshold = ds.getDynamicEnergyThreshold(); - snapshot.dynamicEnergyIncreaseFactor = ds.getDynamicEnergyIncreaseFactor(); - snapshot.dynamicEnergyMaxFactor = ds.getDynamicEnergyMaxFactor(); - snapshot.allowTvmShanghai = ds.getAllowTvmShangHai() == 1; - snapshot.allowEnergyAdjustment = ds.getAllowEnergyAdjustment() == 1; - snapshot.allowStrictMath = ds.getAllowStrictMath() == 1; - snapshot.allowTvmCancun = ds.getAllowTvmCancun() == 1; - snapshot.disableJavaLangMath = ds.getConsensusLogicOptimization() == 1; - snapshot.allowTvmBlob = ds.getAllowTvmBlob() == 1; - snapshot.allowTvmSelfdestructRestriction = ds.getAllowTvmSelfdestructRestriction() == 1; - snapshot.allowTvmOsaka = ds.getAllowTvmOsaka() == 1; - snapshot.allowHardenResourceCalculation = ds.getAllowHardenResourceCalculation() == 1; - if (isolate) { - VMConfig.setLocalSnapshot(snapshot); - } else { - VMConfig.setGlobalSnapshot(snapshot); - } + if (disable) { + // Tests freeze flags via VMConfig.init*(). A leftover thread-local snapshot from a + // prior constant-call would otherwise keep shadowing those flags (London/Osaka flakes). + VMConfig.clearLocalSnapshot(); + return; + } + DynamicPropertiesStore ds = storeFactory.getChainBaseManager().getDynamicPropertiesStore(); + VMConfig.setVmTrace(CommonParameter.getInstance().isVmTrace()); + if (ds != null) { + VMConfig.initVmHardFork(checkForEnergyLimit(ds)); + VMConfig.Snapshot snapshot = new VMConfig.Snapshot(); + snapshot.allowMultiSign = ds.getAllowMultiSign() == 1; + snapshot.allowTvmTransferTrc10 = ds.getAllowTvmTransferTrc10() == 1; + snapshot.allowTvmConstantinople = ds.getAllowTvmConstantinople() == 1; + snapshot.allowTvmSolidity059 = ds.getAllowTvmSolidity059() == 1; + snapshot.allowShieldedTRC20Transaction = ds.getAllowShieldedTRC20Transaction() == 1; + snapshot.allowTvmIstanbul = ds.getAllowTvmIstanbul() == 1; + snapshot.allowTvmFreeze = ds.getAllowTvmFreeze() == 1; + snapshot.allowTvmVote = ds.getAllowTvmVote() == 1; + snapshot.allowTvmLondon = ds.getAllowTvmLondon() == 1; + snapshot.allowTvmCompatibleEvm = ds.getAllowTvmCompatibleEvm() == 1; + snapshot.allowHigherLimitForMaxCpuTimeOfOneTx = + ds.getAllowHigherLimitForMaxCpuTimeOfOneTx() == 1; + snapshot.allowTvmFreezeV2 = ds.supportUnfreezeDelay(); + snapshot.allowOptimizedReturnValueOfChainId = ds.getAllowOptimizedReturnValueOfChainId() == 1; + snapshot.allowDynamicEnergy = ds.getAllowDynamicEnergy() == 1; + snapshot.dynamicEnergyThreshold = ds.getDynamicEnergyThreshold(); + snapshot.dynamicEnergyIncreaseFactor = ds.getDynamicEnergyIncreaseFactor(); + snapshot.dynamicEnergyMaxFactor = ds.getDynamicEnergyMaxFactor(); + snapshot.allowTvmShanghai = ds.getAllowTvmShangHai() == 1; + snapshot.allowEnergyAdjustment = ds.getAllowEnergyAdjustment() == 1; + snapshot.allowStrictMath = ds.getAllowStrictMath() == 1; + snapshot.allowTvmCancun = ds.getAllowTvmCancun() == 1; + snapshot.disableJavaLangMath = ds.getConsensusLogicOptimization() == 1; + snapshot.allowTvmBlob = ds.getAllowTvmBlob() == 1; + snapshot.allowTvmSelfdestructRestriction = ds.getAllowTvmSelfdestructRestriction() == 1; + snapshot.allowTvmOsaka = ds.getAllowTvmOsaka() == 1; + snapshot.allowHardenResourceCalculation = ds.getAllowHardenResourceCalculation() == 1; + if (isolate) { + VMConfig.setLocalSnapshot(snapshot); + } else { + VMConfig.setGlobalSnapshot(snapshot); } } } diff --git a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java index 67739ac50d2..da721ce59d6 100644 --- a/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java +++ b/framework/src/main/java/org/tron/common/backup/socket/BackupServer.java @@ -27,7 +27,7 @@ public class BackupServer implements AutoCloseable { private BackupManager backupManager; - private Channel channel; + private volatile Channel channel; private volatile boolean shutdown = false; @@ -52,6 +52,11 @@ public void initServer() { } } + public boolean isBound() { + Channel ch = channel; + return ch != null && ch.isActive(); + } + private void start() throws Exception { NioEventLoopGroup group = new NioEventLoopGroup(1); try { @@ -77,6 +82,12 @@ public void initChannel(NioDatagramChannel ch) logger.info("Backup server started, bind port {}", port); + // close() may have raced the bind: without this, closeFuture.sync() waits forever + // because close() saw a still-null channel and skipped channel.close(). + if (shutdown) { + channel.close(); + } + channel.closeFuture().sync(); if (shutdown) { logger.info("Shutdown backup BackupServer"); @@ -95,7 +106,9 @@ public void initChannel(NioDatagramChannel ch) public void close() { logger.info("Closing backup server..."); shutdown = true; - backupManager.stop(); + // Close the datagram channel first so start() can leave closeFuture.sync(). + // BackupManager.stop() awaits its scheduler for up to 60s; doing that first + // ate the JUnit 60s timeout on slow Rocky Linux CI before the channel closed. if (channel != null) { try { channel.close().await(10, TimeUnit.SECONDS); @@ -103,6 +116,7 @@ public void close() { logger.warn("Closing backup server failed.", e); } } + backupManager.stop(); ExecutorServiceManager.shutdownAndAwaitTermination(executor, name); logger.info("Backup server closed."); } diff --git a/framework/src/test/java/org/tron/common/BaseMethodTest.java b/framework/src/test/java/org/tron/common/BaseMethodTest.java index 9ee1dfa3b36..a5f4cb23ee1 100644 --- a/framework/src/test/java/org/tron/common/BaseMethodTest.java +++ b/framework/src/test/java/org/tron/common/BaseMethodTest.java @@ -14,6 +14,8 @@ import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; +import org.tron.core.vm.config.ConfigLoader; +import org.tron.core.vm.config.VMConfig; /** * Base class for tests that need a fresh Spring context per test method. @@ -82,6 +84,10 @@ public final void destroyContext() { context.close(); // triggers appT.shutdown() via TronApplicationContext } Args.clearParam(); + // forkEvery=100 reuses this JVM/thread: drop leftover TVM flags so the next + // class does not see ConfigLoader.disable=true or a stale local snapshot. + VMConfig.clearLocalSnapshot(); + ConfigLoader.disable = false; } protected void beforeDestroy() { diff --git a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java index 50778970d87..578bcefafdf 100644 --- a/framework/src/test/java/org/tron/common/backup/BackupServerTest.java +++ b/framework/src/test/java/org/tron/common/backup/BackupServerTest.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -46,7 +47,12 @@ public void tearDown() { @Test(timeout = 60_000) public void test() throws InterruptedException { backupServer.initServer(); - // wait for the server to start so channel is assigned before close() is called - Thread.sleep(1000); + // Wait until the NioDatagramChannel is actually bound. A fixed 1s sleep is + // not enough on a loaded Rocky Linux CI worker, and close() then races bind. + long deadline = System.currentTimeMillis() + 15_000L; + while (!backupServer.isBound() && System.currentTimeMillis() < deadline) { + Thread.sleep(50); + } + Assert.assertTrue("BackupServer UDP channel did not bind", backupServer.isBound()); } } From d228cc6859b14205adcfed4b5d749543df4593a0 Mon Sep 17 00:00:00 2001 From: vividctrlalt Date: Wed, 19 Aug 2026 03:12:35 +0800 Subject: [PATCH 2/4] test: reset TVM snapshots in London tests and base classes --- .../test/java/org/tron/common/BaseTest.java | 10 +++++++ .../common/runtime/vm/AllowTvmLondonTest.java | 30 ++++++++++++------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/framework/src/test/java/org/tron/common/BaseTest.java b/framework/src/test/java/org/tron/common/BaseTest.java index 6d075a2d6aa..47f06a46c6d 100644 --- a/framework/src/test/java/org/tron/common/BaseTest.java +++ b/framework/src/test/java/org/tron/common/BaseTest.java @@ -5,6 +5,7 @@ import javax.annotation.PostConstruct; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.ClassRule; @@ -28,6 +29,8 @@ import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.peer.PeerManager; import org.tron.core.store.AccountStore; +import org.tron.core.vm.config.ConfigLoader; +import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol; /** @@ -89,10 +92,17 @@ public static String dbPath() { return null; } + @After + public void clearVmThreadLocal() { + VMConfig.clearLocalSnapshot(); + } + @AfterClass public static void destroy() { appT1.shutdown(); Args.clearParam(); + VMConfig.clearLocalSnapshot(); + ConfigLoader.disable = false; } public void closePeer() { diff --git a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java index e93eca39092..8eff7055b0c 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/AllowTvmLondonTest.java @@ -5,6 +5,7 @@ import java.util.Collections; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.encoders.Hex; +import org.junit.After; import org.junit.Assert; import org.junit.Test; import org.tron.common.runtime.TVMTestResult; @@ -30,16 +31,31 @@ function getbasefee() public returns(uint) { }*/ - @Test - public void testBaseFee() throws ContractExeException, ReceiptCheckErrException, - VMIllegalException, ContractValidateException { + private void enableLondon() { + // Drop a leftover thread-local snapshot from a prior constant-call in this JVM + // (forkEvery=100). initAllowTvmLondon() only mutates globalSnapshot. + VMConfig.clearLocalSnapshot(); ConfigLoader.disable = true; VMConfig.initAllowTvmTransferTrc10(1); VMConfig.initAllowTvmConstantinople(1); VMConfig.initAllowTvmSolidity059(1); VMConfig.initAllowTvmIstanbul(1); VMConfig.initAllowTvmLondon(1); + manager.getDynamicPropertiesStore().saveAllowTvmLondon(1); manager.getDynamicPropertiesStore().saveChangeDelegation(1); + } + + @After + public void resetVmFlags() { + VMConfig.clearLocalSnapshot(); + ConfigLoader.disable = false; + VMConfig.initAllowTvmLondon(0); + } + + @Test + public void testBaseFee() throws ContractExeException, ReceiptCheckErrException, + VMIllegalException, ContractValidateException { + enableLondon(); String contractName = "testBaseFee"; byte[] address = Hex.decode(OWNER_ADDRESS); @@ -81,13 +97,7 @@ public void testBaseFee() throws ContractExeException, ReceiptCheckErrException, @Test public void testStartWithEF() throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { - ConfigLoader.disable = true; - VMConfig.initAllowTvmTransferTrc10(1); - VMConfig.initAllowTvmConstantinople(1); - VMConfig.initAllowTvmSolidity059(1); - VMConfig.initAllowTvmIstanbul(1); - VMConfig.initAllowTvmLondon(1); - manager.getDynamicPropertiesStore().saveChangeDelegation(1); + enableLondon(); String contractName = "testStartWithEF"; byte[] address = Hex.decode(OWNER_ADDRESS); From 08e2c2dd438148bc26e4b7c9b8d07c928c348be6 Mon Sep 17 00:00:00 2001 From: vividctrlalt Date: Wed, 19 Aug 2026 03:13:20 +0800 Subject: [PATCH 3/4] test: isolate Osaka TIP-854 flags and probe UDP when picking ports --- .../vm/ValidateMultiSignContractTest.java | 20 +++++++++++++------ .../org/tron/common/utils/PublicMethod.java | 8 +++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java index d7ccab73bd9..bc351cfbba2 100644 --- a/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java +++ b/framework/src/test/java/org/tron/common/runtime/vm/ValidateMultiSignContractTest.java @@ -51,6 +51,14 @@ public void before() { dbManager.getDynamicPropertiesStore().saveTotalSignNum(5); } + private void setAllowTvmOsaka(long allow) { + // initAllowTvmOsaka mutates globalSnapshot only. A leftover thread-local view + // from a prior constant-call would hide the Osaka guard (TIP-854 flake). + VMConfig.clearLocalSnapshot(); + VMConfig.initAllowTvmOsaka(allow); + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(allow); + } + @Test public void testAddressNonExist() { byte[] hash = Hash.sha3(longData); @@ -160,7 +168,7 @@ public void testDifferentCase() { // energy formula already assumes, returning (false, empty). @Test public void testTip854RejectsMalformedCalldata() { - VMConfig.initAllowTvmOsaka(1); + setAllowTvmOsaka(1); try { // Bucket 1: 32-aligned head + sub-word trailing bytes (r=1, r=31). for (int r : new int[]{1, 31}) { @@ -187,7 +195,7 @@ public void testTip854RejectsMalformedCalldata() { Assert.assertFalse("null calldata", ret.getLeft()); Assert.assertSame(ByteUtil.EMPTY_BYTE_ARRAY, ret.getRight()); } finally { - VMConfig.initAllowTvmOsaka(0); + setAllowTvmOsaka(0); } } @@ -226,10 +234,10 @@ public void testTip854CanonicalInputUnchanged() { signs.add(Hex.toHexString(key1.sign(toSign).toByteArray())); signs.add(Hex.toHexString(key2.sign(toSign).toByteArray())); - VMConfig.initAllowTvmOsaka(0); + setAllowTvmOsaka(0); Pair pre = validateMultiSign(StringUtil.encode58Check(key.getAddress()), 2, data, signs); - VMConfig.initAllowTvmOsaka(1); + setAllowTvmOsaka(1); try { Pair post = validateMultiSign(StringUtil.encode58Check(key.getAddress()), 2, data, signs); @@ -237,7 +245,7 @@ public void testTip854CanonicalInputUnchanged() { Assert.assertArrayEquals(pre.getValue(), post.getValue()); Assert.assertArrayEquals(DataWord.ONE().getData(), post.getValue()); } finally { - VMConfig.initAllowTvmOsaka(0); + setAllowTvmOsaka(0); } } @@ -247,7 +255,7 @@ public void testTip854CanonicalInputUnchanged() { // pre-activation failure mode the TIP explicitly preserves. @Test public void testTip854PreActivationNoOp() { - VMConfig.initAllowTvmOsaka(0); + setAllowTvmOsaka(0); contract.setRepository(RepositoryImpl.createRoot(StoreFactory.getInstance())); try { Pair ret = contract.execute(new byte[(5 + 1) * 32]); diff --git a/framework/src/test/java/org/tron/common/utils/PublicMethod.java b/framework/src/test/java/org/tron/common/utils/PublicMethod.java index 90a2aae3f76..34cec3a6479 100644 --- a/framework/src/test/java/org/tron/common/utils/PublicMethod.java +++ b/framework/src/test/java/org/tron/common/utils/PublicMethod.java @@ -6,7 +6,9 @@ import com.google.protobuf.ByteString; import java.io.IOException; import java.math.BigInteger; +import java.net.DatagramSocket; import java.net.InetAddress; +import java.net.ServerSocket; import java.net.Socket; import java.util.Objects; import java.util.Random; @@ -343,8 +345,12 @@ public static int chooseRandomPort(int min, int max) { } private static boolean checkPortAvailable(int port) throws IOException { - try (java.net.ServerSocket ss = new java.net.ServerSocket(port)) { + // BackupServer binds UDP; a TCP-only probe can return a port that is still + // held by another maxParallelForks worker's NioDatagramChannel. + try (ServerSocket ss = new ServerSocket(port); + DatagramSocket ds = new DatagramSocket(port)) { ss.setReuseAddress(true); + ds.setReuseAddress(true); return true; } catch (IOException e) { return false; From a1947fd5765e3156fe996d4c33604db58e36f0b5 Mon Sep 17 00:00:00 2001 From: vividctrlalt Date: Wed, 19 Aug 2026 03:13:52 +0800 Subject: [PATCH 4/4] test: stub TransactionsMsgHandler peers with doReturn and per-case mocks --- .../TransactionsMsgHandlerTest.java | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java index ed2121d360f..a4cdcb686ea 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java @@ -80,7 +80,7 @@ public void testProcessMessage() { Item item = new Item(new TransactionMessage(trx).getMessageId(), Protocol.Inventory.InventoryType.TRX); advInvRequest.put(item, 0L); - Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest); + Mockito.doReturn(advInvRequest).when(peer).getAdvInvRequest(); List transactionList = new ArrayList<>(); transactionList.add(trx); @@ -103,7 +103,7 @@ public void testProcessMessage() { Item item1 = new Item(new TransactionMessage(trx1).getMessageId(), Protocol.Inventory.InventoryType.TRX); advInvRequest1.put(item1, 0L); - Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest1); + Mockito.doReturn(advInvRequest1).when(peer).getAdvInvRequest(); List transactionList1 = new ArrayList<>(); transactionList1.add(trx1); transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList1)); @@ -125,7 +125,7 @@ public void testProcessMessage() { Item item2 = new Item(new TransactionMessage(trx2).getMessageId(), Protocol.Inventory.InventoryType.TRX); advInvRequest2.put(item2, 0L); - Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest2); + Mockito.doReturn(advInvRequest2).when(peer).getAdvInvRequest(); try { transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList2)); } catch (Exception ep) { @@ -231,7 +231,10 @@ private void stubAdvInvRequest(PeerConnection peer, TransactionsMessage msg) { Protocol.Inventory.InventoryType.TRX); advInvRequest.put(item, 0L); } - Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest); + // doReturn avoids Mockito's when(mock.foo()) recording race when handleTransaction + // concurrently calls isBadPeer() on the same mock (Rocky CI WrongTypeOfReturnValue). + Mockito.doReturn(advInvRequest).when(peer).getAdvInvRequest(); + Mockito.doReturn(false).when(peer).isBadPeer(); } @Test @@ -324,7 +327,7 @@ public void testDuplicateTransactionRejected() throws Exception { Item item = new Item(trxMsg.getMessageId(), Protocol.Inventory.InventoryType.TRX); Map advInvRequest = new ConcurrentHashMap<>(); advInvRequest.put(item, System.currentTimeMillis()); - Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest); + Mockito.doReturn(advInvRequest).when(peer).getAdvInvRequest(); try { handler.processMessage(peer, msg); @@ -342,8 +345,6 @@ public void testInvalidSigLength() throws Exception { TransactionsMsgHandler handler = new TransactionsMsgHandler(); handler.init(); try { - PeerConnection peer = Mockito.mock(PeerConnection.class); - BalanceContract.TransferContract transferContract = BalanceContract.TransferContract .newBuilder() .setAmount(10) @@ -363,9 +364,10 @@ public void testInvalidSigLength() throws Exception { List shortList = new ArrayList<>(); shortList.add(shortSigTrx); - stubAdvInvRequest(peer, new TransactionsMessage(shortList)); + PeerConnection shortPeer = Mockito.mock(PeerConnection.class); + stubAdvInvRequest(shortPeer, new TransactionsMessage(shortList)); P2pException shortEx = Assert.assertThrows(P2pException.class, - () -> handler.processMessage(peer, new TransactionsMessage(shortList))); + () -> handler.processMessage(shortPeer, new TransactionsMessage(shortList))); Assert.assertEquals(TypeEnum.BAD_TRX, shortEx.getType()); // signature longer than 68 bytes → BAD_TRX @@ -381,9 +383,10 @@ public void testInvalidSigLength() throws Exception { List longList = new ArrayList<>(); longList.add(longSigTrx); - stubAdvInvRequest(peer, new TransactionsMessage(longList)); + PeerConnection longPeer = Mockito.mock(PeerConnection.class); + stubAdvInvRequest(longPeer, new TransactionsMessage(longList)); P2pException longEx = Assert.assertThrows(P2pException.class, - () -> handler.processMessage(peer, new TransactionsMessage(longList))); + () -> handler.processMessage(longPeer, new TransactionsMessage(longList))); Assert.assertEquals(TypeEnum.BAD_TRX, longEx.getType()); // exactly 65 bytes → passes the length check (no P2pException from check) @@ -399,8 +402,9 @@ public void testInvalidSigLength() throws Exception { List validList = new ArrayList<>(); validList.add(validSigTrx); - stubAdvInvRequest(peer, new TransactionsMessage(validList)); - handler.processMessage(peer, new TransactionsMessage(validList)); + PeerConnection validPeer = Mockito.mock(PeerConnection.class); + stubAdvInvRequest(validPeer, new TransactionsMessage(validList)); + handler.processMessage(validPeer, new TransactionsMessage(validList)); // 68 bytes (upper bound) also passes the length check Protocol.Transaction paddedSigTrx = Protocol.Transaction.newBuilder() @@ -415,8 +419,9 @@ public void testInvalidSigLength() throws Exception { List paddedList = new ArrayList<>(); paddedList.add(paddedSigTrx); - stubAdvInvRequest(peer, new TransactionsMessage(paddedList)); - handler.processMessage(peer, new TransactionsMessage(paddedList)); + PeerConnection paddedPeer = Mockito.mock(PeerConnection.class); + stubAdvInvRequest(paddedPeer, new TransactionsMessage(paddedList)); + handler.processMessage(paddedPeer, new TransactionsMessage(paddedList)); } finally { handler.close(); }