Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f91c4a4
test(framework): fix test quality issues in framework unit tests
Little-Peony Apr 6, 2026
73f7b45
test(plugins): fix test quality issues in plugins unit tests
Little-Peony Apr 6, 2026
e2791ed
test(actuator): remove obsolete moreThanFrozenNumber test in FreezeBa…
Little-Peony Apr 6, 2026
da3f072
test(framework): fix test cleanup and solidity node shutdown
Little-Peony Apr 7, 2026
ba66167
test(framework): replace bare Executors with ExecutorServiceManager a…
Little-Peony Apr 23, 2026
2d53fd1
test(framework): unify app context fixtures in service tests
Little-Peony Apr 7, 2026
deca321
style(test): fix import order to satisfy checkstyle
Little-Peony Apr 8, 2026
86e6ff9
chore(config): remove /.dev/ from .gitignore
Little-Peony Apr 8, 2026
259ebe5
style(test): fix import order in SolidityNodeTest
Little-Peony Apr 8, 2026
de963b4
test(framework): use assertSame for exception identity check in Solid…
Little-Peony Apr 8, 2026
e119ff5
fix(net): guard relay nodes in peer connection
Little-Peony Apr 8, 2026
46bc238
test(framework,plugins): fix flaky tests in bandwidth, stats and db-move
Little-Peony Apr 8, 2026
d6b5d1b
refactor(framework): promote relayNodes to instance field in PeerConn…
Little-Peony Apr 8, 2026
74fb935
refactor(tvm): optimize energy cost calculation for vote witness opcode
yanghang8612 Mar 31, 2026
3f22472
fix(framework): replace while(true) with while(flag) in SolidityNode
Little-Peony Apr 13, 2026
9afd976
fix(framework): add null/0 return after while(flag) loops in Solidity…
Little-Peony Apr 13, 2026
0a6eece
fix(test): add comments
Little-Peony Apr 13, 2026
d66aba6
test(framework): address PR review comments on test code quality
Little-Peony Apr 14, 2026
c928e68
fix: use Assert.assertThrows to replace try/catch
Little-Peony Apr 14, 2026
d62242e
fix: pr review
Little-Peony Apr 14, 2026
1fbcf9b
test(framework): replace Assert.fail with throws Exception in test me…
Little-Peony Apr 16, 2026
1e16b42
test(framework): address PR review nits in BlockEventGetTest and Peer…
Little-Peony Apr 22, 2026
2d89ad2
refactor(framework): address shutdown correctness issues from PR review
Little-Peony Apr 23, 2026
a15ab66
refactor(framework): address PR review nits from bladehan1
Little-Peony Apr 23, 2026
a1cb84e
refactor(net): revert relayNodes to local variable in setChannel
Little-Peony Apr 23, 2026
3d60e7c
style(net): add empty line before setChannel method in PeerConnection
Little-Peony Apr 24, 2026
30bb478
fix(backup): restore restart loop, fix channel visibility race only
Little-Peony Apr 24, 2026
a2c731a
fix(test): remove stale relayNodes field injection in PeerManagerTest
Little-Peony Apr 24, 2026
bb7c299
fix(test): fix flaky tests without changing production logic
Little-Peony Apr 27, 2026
a418fb8
fix(test): restore BackupServerTest to original intent with members a…
Little-Peony Apr 27, 2026
6038488
ci: retrigger CI after network failure on runner
Little-Peony Apr 27, 2026
4eb5804
Merge branch 'develop' into fix_tests_v2
Little-Peony Apr 28, 2026
9105c7b
Merge branch 'develop' into fix_tests_v2
Little-Peony Apr 28, 2026
7b99ba0
fix(test): add more test cases for SolidityNode.java to increase test…
Little-Peony Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions framework/src/main/java/org/tron/program/SolidityNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL;

import com.google.common.annotations.VisibleForTesting;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
Expand All @@ -11,6 +14,7 @@
import org.tron.common.application.ApplicationFactory;
import org.tron.common.application.TronApplicationContext;
import org.tron.common.client.DatabaseGrpcClient;
import org.tron.common.es.ExecutorServiceManager;
import org.tron.common.parameter.CommonParameter;
import org.tron.common.prometheus.Metrics;
import org.tron.core.ChainBaseManager;
Expand Down Expand Up @@ -39,6 +43,9 @@ public class SolidityNode {

private volatile boolean flag = true;

private ExecutorService getBlockEs;
private ExecutorService processBlockEs;

public SolidityNode(Manager dbManager) {
this.dbManager = dbManager;
this.chainBaseManager = dbManager.getChainBaseManager();
Expand Down Expand Up @@ -72,13 +79,26 @@ public static void start() {
appT.startup();
SolidityNode node = new SolidityNode(appT.getDbManager());
node.run();
appT.blockUntilShutdown();
awaitShutdown(appT, node);
}

@VisibleForTesting
static void awaitShutdown(Application appT, SolidityNode node) {
Comment thread
Sunny6889 marked this conversation as resolved.
try {
appT.blockUntilShutdown();
} finally {
// SolidityNode is created manually rather than managed by Spring/Application,
// so its executors must be shut down explicitly on exit.
node.shutdown();
}
}

private void run() {
try {
new Thread(this::getBlock).start();
new Thread(this::processBlock).start();
getBlockEs = ExecutorServiceManager.newSingleThreadExecutor("solid-get-block");
processBlockEs = ExecutorServiceManager.newSingleThreadExecutor("solid-process-block");
getBlockEs.execute(this::getBlock);
processBlockEs.execute(this::processBlock);
logger.info("Success to start solid node, ID: {}, remoteBlockNum: {}.", ID.get(),
remoteBlockNum);
} catch (Exception e) {
Expand All @@ -88,6 +108,15 @@ private void run() {
}
}

public void shutdown() {
flag = false;
// Signal both pools before awaiting either so they drain concurrently
getBlockEs.shutdown();
processBlockEs.shutdown();
ExecutorServiceManager.shutdownAndAwaitTermination(getBlockEs, "solid-get-block");
Comment thread
Sunny6889 marked this conversation as resolved.
ExecutorServiceManager.shutdownAndAwaitTermination(processBlockEs, "solid-process-block");
}

private void getBlock() {
long blockNum = ID.incrementAndGet();
while (flag) {
Expand Down Expand Up @@ -137,7 +166,7 @@ private void loopProcessBlock(Block block) {
}

private Block getBlockByNum(long blockNum) {
while (true) {
while (flag) {
try {
long time = System.currentTimeMillis();
Block block = databaseGrpcClient.getBlock(blockNum);
Expand All @@ -155,10 +184,11 @@ private Block getBlockByNum(long blockNum) {
sleep(exceptionSleepTime);
}
}
return null;
}

private long getLastSolidityBlockNum() {
while (true) {
while (flag) {
try {
long time = System.currentTimeMillis();
long blockNum = databaseGrpcClient.getDynamicProperties().getLastSolidityBlockNum();
Expand All @@ -171,6 +201,7 @@ private long getLastSolidityBlockNum() {
sleep(exceptionSleepTime);
}
}
return 0;
}

public void sleep(long time) {
Expand All @@ -193,4 +224,4 @@ private void resolveCompatibilityIssueIfUsingFullNodeDatabase() {
chainBaseManager.getDynamicPropertiesStore().saveLatestSolidifiedBlockNum(headBlockNum);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.tron.common;

import io.grpc.ManagedChannel;
import java.util.concurrent.TimeUnit;
import org.tron.common.application.ApplicationFactory;
import org.tron.common.application.TronApplicationContext;
import org.tron.core.config.DefaultConfig;

/**
* Shared class-level fixture for tests that manually manage a TronApplicationContext.
*/
public class ClassLevelAppContextFixture {

private TronApplicationContext context;

public TronApplicationContext createContext() {
context = new TronApplicationContext(DefaultConfig.class);
return context;
}

public TronApplicationContext createAndStart() {
createContext();
startApp();
return context;
}

public void startApp() {
ApplicationFactory.create(context).startup();
}

public TronApplicationContext getContext() {
return context;
}

public void close() {
if (context != null) {
context.close();
context = null;
}
}

public static void shutdownChannel(ManagedChannel channel) {
if (channel == null) {
return;
}
try {
channel.shutdown();
if (!channel.awaitTermination(5, TimeUnit.SECONDS)) {
channel.shutdownNow();
}
} catch (InterruptedException e) {
channel.shutdownNow();
Thread.currentThread().interrupt();
}
}

public static void shutdownChannels(ManagedChannel... channels) {
for (ManagedChannel channel : channels) {
shutdownChannel(channel);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void tearDown() {
@Test(timeout = 60_000)
public void test() throws InterruptedException {
backupServer.initServer();
// wait for the server to start
// wait for the server to start so channel is assigned before close() is called
Thread.sleep(1000);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ public synchronized void testEventParser() {

for (int i = 0; i < entryArr.size(); i++) {
JSONObject e = entryArr.getJSONObject(i);
System.out.println(e.getString("name"));
if (e.getString("name") != null) {
if (e.getString("name").equalsIgnoreCase("eventBytesL")) {
entry = e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public synchronized void testEventParser() {

ABI.Entry entry = null;
for (ABI.Entry e : abi.getEntrysList()) {
System.out.println(e.getName());
if (e.getName().equalsIgnoreCase("eventBytesL")) {
entry = e;
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package org.tron.common.logsfilter;

import java.util.concurrent.ExecutorService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.tron.common.es.ExecutorServiceManager;
import org.tron.common.logsfilter.nativequeue.NativeMessageQueue;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
Expand All @@ -13,6 +16,15 @@ public class NativeMessageQueueTest {
public String dataToSend = "################";
public String topic = "testTopic";

private ExecutorService subscriberExecutor;
private final String zmqSubscriber = "zmq-subscriber";

@After
public void tearDown() {
ExecutorServiceManager.shutdownAndAwaitTermination(subscriberExecutor, zmqSubscriber);
subscriberExecutor = null;
}

@Test
public void invalidBindPort() {
boolean bRet = NativeMessageQueue.getInstance().start(-1111, 0);
Expand All @@ -39,22 +51,23 @@ public void publishTrigger() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}

NativeMessageQueue.getInstance().publishTrigger(dataToSend, topic);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}

NativeMessageQueue.getInstance().stop();
}

public void startSubscribeThread() {
Thread thread = new Thread(() -> {
subscriberExecutor = ExecutorServiceManager.newSingleThreadExecutor(zmqSubscriber);
subscriberExecutor.execute(() -> {
try (ZContext context = new ZContext()) {
ZMQ.Socket subscriber = context.createSocket(SocketType.SUB);

Expand All @@ -70,6 +83,5 @@ public void startSubscribeThread() {
// ZMQ.Socket will be automatically closed when ZContext is closed
}
});
thread.start();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public void setUp() {
public void testSetAndGetBlockHash() {
blockFilterCapsule
.setBlockHash("e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f");
System.out.println(blockFilterCapsule);
Assert.assertEquals("e58f33f9baf9305dc6f82b9f1934ea8f0ade2defb951258d50167028c780351f",
blockFilterCapsule.getBlockHash());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
import org.tron.common.BaseTest;
import org.tron.common.parameter.CommonParameter;
import org.tron.common.runtime.RuntimeImpl;
import org.tron.common.runtime.TvmTestUtils;
import org.tron.common.utils.Commons;
Expand Down Expand Up @@ -153,8 +154,13 @@ public void testSuccess() {

@Test
public void testSuccessNoBandd() {
boolean originalDebug = CommonParameter.getInstance().isDebug();
try {
byte[] contractAddress = createContract();
// Enable debug mode to bypass CPU time limit check in Program.checkCPUTimeLimit().
// Without this, the heavy contract execution (setCoin) may exceed the time threshold
// on slow machines and cause the test to fail non-deterministically.
CommonParameter.getInstance().setDebug(true);
TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress,
"setCoin(uint256)", "50", false,
0, Commons.decodeFromBase58Check(TriggerOwnerTwoAddress));
Expand Down Expand Up @@ -185,6 +191,8 @@ public void testSuccessNoBandd() {
balance);
} catch (TronException e) {
Assert.assertNotNull(e);
} finally {
CommonParameter.getInstance().setDebug(originalDebug);
}
}

Expand Down Expand Up @@ -254,4 +262,4 @@ public void testMaxContractResultSize() {
}
Assert.assertEquals(2, maxSize);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -289,17 +289,9 @@ public void testWithCallerEnergyChangedInTx() throws Exception {

TVMTestResult result = freezeForOther(userA, contractAddr, userA, frozenBalance, 1);

System.out.println(result.getReceipt().getEnergyUsageTotal());
System.out.println(accountStore.get(userA));
System.out.println(accountStore.get(owner));

clearDelegatedExpireTime(contractAddr, userA);

result = unfreezeForOther(userA, contractAddr, userA, 1);

System.out.println(result.getReceipt().getEnergyUsageTotal());
System.out.println(accountStore.get(userA));
System.out.println(accountStore.get(owner));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@ public void testZeroLengthOneArray() {
// witness array zero, amount array non-zero
Program program = mockProgram(0, 0, 64, 1, 0);
long cost = EnergyCost.getVoteWitnessCost3(program);
// witnessArraySize = 0 * 32 + 32 = 32, witnessMemNeeded = 0 + 32 = 32
// amountArraySize = 1 * 32 + 32 = 64, amountMemNeeded = 64 + 64 = 128
// memWords = 128 / 32 = 4
// memEnergy = 3 * 4 + 4 * 4 / 512 = 12
assertEquals(30012, cost);
Expand Down
19 changes: 5 additions & 14 deletions framework/src/test/java/org/tron/common/utils/PropUtilTest.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
package org.tron.common.utils;

import java.io.File;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;

public class PropUtilTest {

@Test
public void testWriteProperty() {
public void testWriteProperty() throws Exception {
String filename = "test_prop.properties";
File file = new File(filename);
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
file.createNewFile();
PropUtil.writeProperty(filename, "key", "value");
Assert.assertTrue("value".equals(PropUtil.readProperty(filename, "key")));
PropUtil.writeProperty(filename, "key", "value2");
Expand All @@ -24,17 +19,13 @@ public void testWriteProperty() {
}

@Test
public void testReadProperty() {
public void testReadProperty() throws Exception {
String filename = "test_prop.properties";
File file = new File(filename);
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
file.createNewFile();
PropUtil.writeProperty(filename, "key", "value");
Assert.assertTrue("value".equals(PropUtil.readProperty(filename, "key")));
file.delete();
Assert.assertTrue("".equals(PropUtil.readProperty(filename, "key")));
}
}
}
Loading
Loading