Skip to content

Commit 48cad61

Browse files
authored
test(auto-stop): prevent test hang by ensuring proper auto-stop (#6469)
1 parent 640b198 commit 48cad61

File tree

2 files changed

+54
-65
lines changed

2 files changed

+54
-65
lines changed

framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package org.tron.core.services.stop;
22

33
import java.text.ParseException;
4+
import java.time.ZoneOffset;
45
import java.time.format.DateTimeFormatter;
56
import java.util.Date;
7+
import java.util.TimeZone;
68
import lombok.extern.slf4j.Slf4j;
79
import org.junit.Assert;
810
import org.tron.common.cron.CronExpression;
@@ -12,14 +14,14 @@
1214
public class BlockTimeStopTest extends ConditionallyStopTest {
1315
private static final DateTimeFormatter pattern = DateTimeFormatter
1416
.ofPattern("ss mm HH dd MM ? yyyy");
15-
private static final String time = localDateTime.plusSeconds(12 * 3).format(pattern);
1617

1718
private static CronExpression cronExpression;
1819

1920

2021
static {
2122
try {
22-
cronExpression = new CronExpression(time);
23+
cronExpression = new CronExpression(localDateTime.plusSeconds(12 * 3).format(pattern));
24+
cronExpression.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
2325
} catch (ParseException e) {
2426
logger.error("{}", e.getMessage());
2527
}

framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java

Lines changed: 50 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,18 @@
22

33
import com.google.common.collect.Maps;
44
import com.google.protobuf.ByteString;
5-
import java.io.File;
65
import java.io.IOException;
6+
import java.time.Instant;
77
import java.time.LocalDateTime;
8-
import java.time.ZoneId;
9-
import java.time.ZonedDateTime;
8+
import java.time.ZoneOffset;
109
import java.util.ArrayList;
11-
import java.util.Arrays;
1210
import java.util.List;
1311
import java.util.Map;
1412
import java.util.concurrent.atomic.AtomicInteger;
1513
import java.util.stream.Collectors;
1614
import java.util.stream.IntStream;
1715
import lombok.extern.slf4j.Slf4j;
1816
import org.junit.After;
19-
import org.junit.Assert;
2017
import org.junit.Before;
2118
import org.junit.ClassRule;
2219
import org.junit.Test;
@@ -25,11 +22,10 @@
2522
import org.tron.common.crypto.ECKey;
2623
import org.tron.common.parameter.CommonParameter;
2724
import org.tron.common.utils.ByteArray;
28-
import org.tron.common.utils.FileUtil;
29-
import org.tron.common.utils.LocalWitnesses;
30-
import org.tron.common.utils.PublicMethod;
3125
import org.tron.common.utils.Sha256Hash;
3226
import org.tron.common.utils.Utils;
27+
import org.tron.consensus.ConsensusDelegate;
28+
import org.tron.consensus.dpos.DposService;
3329
import org.tron.consensus.dpos.DposSlot;
3430
import org.tron.core.ChainBaseManager;
3531
import org.tron.core.Constant;
@@ -39,34 +35,31 @@
3935
import org.tron.core.config.DefaultConfig;
4036
import org.tron.core.config.args.Args;
4137
import org.tron.core.consensus.ConsensusService;
42-
import org.tron.core.db.BlockGenerate;
4338
import org.tron.core.db.Manager;
4439
import org.tron.core.net.TronNetDelegate;
4540
import org.tron.protos.Protocol;
4641

47-
@Slf4j
48-
public abstract class ConditionallyStopTest extends BlockGenerate {
42+
@Slf4j(topic = "test")
43+
public abstract class ConditionallyStopTest {
4944

5045
@ClassRule
5146
public static final TemporaryFolder temporaryFolder = new TemporaryFolder();
5247

5348
static ChainBaseManager chainManager;
5449
private static DposSlot dposSlot;
55-
56-
private final String key = PublicMethod.getRandomPrivateKey();
57-
private final byte[] privateKey = ByteArray.fromHexString(key);
58-
5950
private final AtomicInteger port = new AtomicInteger(0);
6051
protected String dbPath;
6152
protected Manager dbManager;
6253
long currentHeader = -1;
6354
private TronNetDelegate tronNetDelegate;
6455
private TronApplicationContext context;
6556

57+
private DposService dposService;
58+
private ConsensusDelegate consensusDelegate;
6659

67-
static LocalDateTime localDateTime = LocalDateTime.now();
68-
private long time = ZonedDateTime.of(localDateTime,
69-
ZoneId.systemDefault()).toInstant().toEpochMilli();
60+
private static final Instant instant = Instant.parse("2025-10-01T00:00:00Z");
61+
private final long time = instant.toEpochMilli();
62+
static LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
7063

7164
protected abstract void initParameter(CommonParameter parameter);
7265

@@ -76,6 +69,8 @@ protected void initDbPath() throws IOException {
7669
dbPath = temporaryFolder.newFolder().toString();
7770
}
7871

72+
private Map<String, String> witnesses;
73+
7974

8075
@Before
8176
public void init() throws Exception {
@@ -84,30 +79,37 @@ public void init() throws Exception {
8479
logger.info("Full node running.");
8580
Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF);
8681
Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet());
87-
82+
Args.getInstance().genesisBlock.setTimestamp(Long.toString(time));
8883
initParameter(Args.getInstance());
8984
context = new TronApplicationContext(DefaultConfig.class);
9085

9186
dbManager = context.getBean(Manager.class);
92-
setManager(dbManager);
9387
dposSlot = context.getBean(DposSlot.class);
9488
ConsensusService consensusService = context.getBean(ConsensusService.class);
9589
consensusService.start();
9690
chainManager = dbManager.getChainBaseManager();
9791
tronNetDelegate = context.getBean(TronNetDelegate.class);
92+
dposService = context.getBean(DposService.class);
93+
consensusDelegate = context.getBean(ConsensusDelegate.class);
9894
tronNetDelegate.setExit(false);
9995
currentHeader = dbManager.getDynamicPropertiesStore()
10096
.getLatestBlockHeaderNumberFromDB();
10197

102-
byte[] address = PublicMethod.getAddressByteByPrivateKey(key);
103-
ByteString addressByte = ByteString.copyFrom(address);
104-
WitnessCapsule witnessCapsule = new WitnessCapsule(addressByte);
105-
chainManager.getWitnessStore().put(addressByte.toByteArray(), witnessCapsule);
106-
chainManager.addWitness(addressByte);
107-
108-
AccountCapsule accountCapsule =
109-
new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build());
110-
chainManager.getAccountStore().put(addressByte.toByteArray(), accountCapsule);
98+
chainManager.getWitnessScheduleStore().reset();
99+
chainManager.getWitnessStore().reset();
100+
witnesses = addTestWitnessAndAccount();
101+
102+
List<ByteString> allWitnesses = new ArrayList<>();
103+
consensusDelegate.getAllWitnesses().forEach(witnessCapsule ->
104+
allWitnesses.add(witnessCapsule.getAddress()));
105+
dposService.updateWitness(allWitnesses);
106+
List<ByteString> activeWitnesses = consensusDelegate.getActiveWitnesses();
107+
activeWitnesses.forEach(address -> {
108+
WitnessCapsule witnessCapsule = consensusDelegate.getWitness(address.toByteArray());
109+
witnessCapsule.setIsJobs(true);
110+
consensusDelegate.saveWitness(witnessCapsule);
111+
});
112+
chainManager.getDynamicPropertiesStore().saveNextMaintenanceTime(time);
111113
}
112114

113115
@After
@@ -116,72 +118,57 @@ public void destroy() {
116118
context.destroy();
117119
}
118120

119-
private void generateBlock(Map<ByteString, String> witnessAndAccount) throws Exception {
121+
private void generateBlock() throws Exception {
120122

121123
BlockCapsule block =
122124
createTestBlockCapsule(
123-
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + 3000,
125+
chainManager.getNextBlockSlotTime(),
124126
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1,
125-
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(),
126-
witnessAndAccount);
127+
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString());
127128

128129
tronNetDelegate.processBlock(block, false);
130+
131+
logger.info("headerNum: {} solidityNum: {}, dbNum: {}",
132+
block.getNum(), chainManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(),
133+
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB());
129134
}
130135

131-
@Test
136+
@Test(timeout = 30_000) // milliseconds
132137
public void testStop() throws Exception {
133-
final ECKey ecKey = ECKey.fromPrivate(privateKey);
134-
Assert.assertNotNull(ecKey);
135-
byte[] address = ecKey.getAddress();
136-
WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address));
137-
chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>());
138-
chainManager.addWitness(ByteString.copyFrom(address));
139-
140-
Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey);
141-
142-
tronNetDelegate.processBlock(new BlockCapsule(block), false);
143-
144-
Map<ByteString, String> witnessAndAccount = addTestWitnessAndAccount();
145-
witnessAndAccount.put(ByteString.copyFrom(address), key);
146138
while (!tronNetDelegate.isHitDown()) {
147-
generateBlock(witnessAndAccount);
139+
generateBlock();
148140
}
149-
Assert.assertTrue(tronNetDelegate.isHitDown());
150141
check();
151142
}
152143

153-
private Map<ByteString, String> addTestWitnessAndAccount() {
154-
chainManager.getWitnesses().clear();
155-
return IntStream.range(0, 2)
144+
private Map<String, String> addTestWitnessAndAccount() {
145+
return IntStream.range(0, 27)
156146
.mapToObj(
157147
i -> {
158148
ECKey ecKey = new ECKey(Utils.getRandom());
159149
String privateKey = ByteArray.toHexString(ecKey.getPrivKey().toByteArray());
160150
ByteString address = ByteString.copyFrom(ecKey.getAddress());
161151

162-
WitnessCapsule witnessCapsule = new WitnessCapsule(address);
152+
WitnessCapsule witnessCapsule = new WitnessCapsule(address, 27 - i, "SR" + i);
163153
chainManager.getWitnessStore().put(address.toByteArray(), witnessCapsule);
164-
chainManager.addWitness(address);
165-
166154
AccountCapsule accountCapsule =
167155
new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build());
168156
chainManager.getAccountStore().put(address.toByteArray(), accountCapsule);
169157

170-
return Maps.immutableEntry(address, privateKey);
158+
return Maps.immutableEntry(ByteArray.toHexString(ecKey.getAddress()), privateKey);
171159
})
172160
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
173161
}
174162

175163
private BlockCapsule createTestBlockCapsule(long time,
176-
long number, ByteString hash,
177-
Map<ByteString, String> witnessAddressMap) {
178-
ByteString witnessAddress = dposSlot.getScheduledWitness(dposSlot.getSlot(time));
179-
BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time,
180-
witnessAddress);
164+
long number, ByteString hash) {
165+
long slot = dposSlot.getSlot(time);
166+
ByteString witness = dposSlot.getScheduledWitness(slot);
167+
BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, witness);
181168
blockCapsule.generatedByMyself = true;
182169
blockCapsule.setMerkleRoot();
183-
blockCapsule.sign(ByteArray.fromHexString(witnessAddressMap.get(witnessAddress)));
170+
String pri = witnesses.get(ByteArray.toHexString(witness.toByteArray()));
171+
blockCapsule.sign(ByteArray.fromHexString(pri));
184172
return blockCapsule;
185173
}
186-
187174
}

0 commit comments

Comments
 (0)