Skip to content

Commit fc80812

Browse files
committed
CRC: make a global mutex of used ports in tests
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent cf5fd4c commit fc80812

File tree

3 files changed

+51
-210
lines changed

3 files changed

+51
-210
lines changed

testnet/stacks-node/src/tests/mod.rs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
//
1414
// You should have received a copy of the GNU General Public License
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16-
use std::collections::HashMap;
16+
use std::collections::{HashMap, HashSet};
1717
use std::sync::atomic::AtomicU64;
18-
use std::sync::Arc;
18+
use std::sync::{Arc, Mutex};
1919

2020
use clarity::vm::costs::ExecutionCost;
2121
use clarity::vm::database::BurnStateDB;
@@ -99,6 +99,34 @@ lazy_static! {
9999
);
100100
}
101101

102+
lazy_static! {
103+
static ref USED_PORTS: Mutex<HashSet<u16>> = Mutex::new(HashSet::new());
104+
}
105+
106+
/// Generate a random port number between 1024 and 65534 (inclusive) and insert it into the USED_PORTS set.
107+
/// Returns the generated port number.
108+
pub fn gen_random_port() -> u16 {
109+
let mut rng = rand::thread_rng();
110+
let range_len = (1024..u16::MAX).len();
111+
loop {
112+
let port = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
113+
if insert_new_port(port) {
114+
return port;
115+
}
116+
assert!(
117+
USED_PORTS.lock().unwrap().len() < range_len,
118+
"No more available ports"
119+
);
120+
}
121+
}
122+
123+
// Add a port to the USED_PORTS set. This is used to ensure that we don't try to bind to the same port in tests
124+
// Returns true if the port was inserted, false if it was already in the set.
125+
pub fn insert_new_port(port: u16) -> bool {
126+
let mut ports = USED_PORTS.lock().unwrap();
127+
ports.insert(port)
128+
}
129+
102130
pub fn serialize_sign_sponsored_sig_tx_anchor_mode_version(
103131
payload: TransactionPayload,
104132
sender: &StacksPrivateKey,
@@ -294,14 +322,8 @@ pub fn new_test_conf() -> Config {
294322
// secretKey: "b1cf9cee5083f421c84d7cb53be5edf2801c3c78d63d53917aee0bdc8bd160ee01",
295323
// publicKey: "03e2ed46873d0db820e8c6001aabc082d72b5b900b53b7a1b9714fe7bde3037b81",
296324
// stacksAddress: "ST2VHM28V9E5QCRD6C73215KAPSBKQGPWTEE5CMQT"
297-
let mut rng = rand::thread_rng();
298-
let (rpc_port, p2p_port) = loop {
299-
let a = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
300-
let b = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
301-
if a != b {
302-
break (a, b);
303-
}
304-
};
325+
let rpc_port = gen_random_port();
326+
let p2p_port = gen_random_port();
305327

306328
let mut conf = Config::default();
307329
conf.node.working_dir = format!(
@@ -328,7 +350,7 @@ pub fn new_test_conf() -> Config {
328350

329351
/// Randomly change the config's network ports to new ports.
330352
pub fn set_random_binds(config: &mut Config) {
331-
let mut rng = rand::thread_rng();
353+
// Just in case prior config was not created with `new_test_conf`, we need to add the prior generated ports
332354
let prior_rpc_port: u16 = config
333355
.node
334356
.rpc_bind
@@ -345,18 +367,10 @@ pub fn set_random_binds(config: &mut Config) {
345367
.unwrap()
346368
.parse()
347369
.unwrap();
348-
let (rpc_port, p2p_port) = loop {
349-
let a = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
350-
let b = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
351-
if a != b
352-
&& a != prior_rpc_port
353-
&& a != prior_p2p_port
354-
&& b != prior_rpc_port
355-
&& b != prior_p2p_port
356-
{
357-
break (a, b);
358-
}
359-
};
370+
insert_new_port(prior_rpc_port);
371+
insert_new_port(prior_p2p_port);
372+
let rpc_port = gen_random_port();
373+
let p2p_port = gen_random_port();
360374
let localhost = "127.0.0.1";
361375
config.node.rpc_bind = format!("{}:{}", localhost, rpc_port);
362376
config.node.p2p_bind = format!("{}:{}", localhost, p2p_port);

testnet/stacks-node/src/tests/nakamoto_integrations.rs

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ use crate::tests::neon_integrations::{
105105
test_observer, wait_for_runloop,
106106
};
107107
use crate::tests::{
108-
get_chain_info, make_contract_publish, make_contract_publish_versioned, make_stacks_transfer,
109-
to_addr,
108+
gen_random_port, get_chain_info, make_contract_publish, make_contract_publish_versioned,
109+
make_stacks_transfer, to_addr,
110110
};
111111
use crate::{tests, BitcoinRegtestController, BurnchainController, Config, ConfigFile, Keychain};
112112

@@ -3459,35 +3459,8 @@ fn follower_bootup() {
34593459
follower_conf.node.seed = vec![0x01; 32];
34603460
follower_conf.node.local_peer_seed = vec![0x02; 32];
34613461

3462-
let mut rng = rand::thread_rng();
3463-
let prior_rpc_port: u16 = naka_conf
3464-
.node
3465-
.rpc_bind
3466-
.split(":")
3467-
.last()
3468-
.unwrap()
3469-
.parse()
3470-
.unwrap();
3471-
let prior_p2p_port: u16 = naka_conf
3472-
.node
3473-
.p2p_bind
3474-
.split(":")
3475-
.last()
3476-
.unwrap()
3477-
.parse()
3478-
.unwrap();
3479-
let (rpc_port, p2p_port) = loop {
3480-
let a = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
3481-
let b = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
3482-
if a != b
3483-
&& a != prior_rpc_port
3484-
&& a != prior_p2p_port
3485-
&& b != prior_rpc_port
3486-
&& b != prior_p2p_port
3487-
{
3488-
break (a, b);
3489-
}
3490-
};
3462+
let rpc_port = gen_random_port();
3463+
let p2p_port = gen_random_port();
34913464

34923465
let localhost = "127.0.0.1";
34933466
follower_conf.node.rpc_bind = format!("{localhost}:{rpc_port}");
@@ -3836,35 +3809,8 @@ fn follower_bootup_across_multiple_cycles() {
38363809
follower_conf.node.local_peer_seed = vec![0x02; 32];
38373810
follower_conf.node.miner = false;
38383811

3839-
let mut rng = rand::thread_rng();
3840-
let prior_rpc_port: u16 = naka_conf
3841-
.node
3842-
.rpc_bind
3843-
.split(":")
3844-
.last()
3845-
.unwrap()
3846-
.parse()
3847-
.unwrap();
3848-
let prior_p2p_port: u16 = naka_conf
3849-
.node
3850-
.p2p_bind
3851-
.split(":")
3852-
.last()
3853-
.unwrap()
3854-
.parse()
3855-
.unwrap();
3856-
let (rpc_port, p2p_port) = loop {
3857-
let a = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
3858-
let b = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
3859-
if a != b
3860-
&& a != prior_rpc_port
3861-
&& a != prior_p2p_port
3862-
&& b != prior_rpc_port
3863-
&& b != prior_p2p_port
3864-
{
3865-
break (a, b);
3866-
}
3867-
};
3812+
let rpc_port = gen_random_port();
3813+
let p2p_port = gen_random_port();
38683814

38693815
let localhost = "127.0.0.1";
38703816
follower_conf.node.rpc_bind = format!("{localhost}:{rpc_port}");

testnet/stacks-node/src/tests/neon_integrations.rs

Lines changed: 8 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ use crate::neon_node::RelayerThread;
8989
use crate::operations::BurnchainOpSigner;
9090
use crate::stacks_common::types::PrivateKey;
9191
use crate::syncctl::PoxSyncWatchdogComms;
92+
use crate::tests::gen_random_port;
9293
use crate::tests::nakamoto_integrations::{get_key_for_cycle, wait_for};
9394
use crate::util::hash::{MerkleTree, Sha512Trunc256Sum};
9495
use crate::util::secp256k1::MessageSignature;
@@ -986,29 +987,7 @@ fn bitcoind_integration_test() {
986987
}
987988

988989
let (mut conf, miner_account) = neon_integration_test_conf();
989-
let mut rng = rand::thread_rng();
990-
let mut prom_port = 6000;
991-
let prior_rpc_port: u16 = conf
992-
.node
993-
.rpc_bind
994-
.split(":")
995-
.last()
996-
.unwrap()
997-
.parse()
998-
.unwrap();
999-
let prior_p2p_port: u16 = conf
1000-
.node
1001-
.p2p_bind
1002-
.split(":")
1003-
.last()
1004-
.unwrap()
1005-
.parse()
1006-
.unwrap();
1007-
// Use a non-privileged port between 1024 and 65534
1008-
while prom_port == prior_rpc_port || prom_port == prior_p2p_port {
1009-
// We should NOT match the miner's rpc or p2p binds
1010-
prom_port = rng.gen_range(1024..u16::MAX);
1011-
}
990+
let prom_port = gen_random_port();
1012991
let localhost = "127.0.0.1";
1013992
let prom_bind = format!("{localhost}:{prom_port}");
1014993
conf.node.prometheus_bind = Some(prom_bind.clone());
@@ -12490,35 +12469,8 @@ fn bitcoin_reorg_flap_with_follower() {
1249012469
follower_conf.node.seed = vec![0x01; 32];
1249112470
follower_conf.node.local_peer_seed = vec![0x02; 32];
1249212471

12493-
let mut rng = rand::thread_rng();
12494-
let prior_rpc_port: u16 = conf
12495-
.node
12496-
.rpc_bind
12497-
.split(":")
12498-
.last()
12499-
.unwrap()
12500-
.parse()
12501-
.unwrap();
12502-
let prior_p2p_port: u16 = conf
12503-
.node
12504-
.p2p_bind
12505-
.split(":")
12506-
.last()
12507-
.unwrap()
12508-
.parse()
12509-
.unwrap();
12510-
let (rpc_port, p2p_port) = loop {
12511-
let a = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
12512-
let b = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
12513-
if a != b
12514-
&& a != prior_rpc_port
12515-
&& a != prior_p2p_port
12516-
&& b != prior_rpc_port
12517-
&& b != prior_p2p_port
12518-
{
12519-
break (a, b);
12520-
}
12521-
};
12472+
let rpc_port = gen_random_port();
12473+
let p2p_port = gen_random_port();
1252212474

1252312475
let localhost = "127.0.0.1";
1252412476
follower_conf.node.rpc_bind = format!("{localhost}:{rpc_port}");
@@ -12705,35 +12657,8 @@ fn mock_miner_replay() {
1270512657
follower_conf.node.seed = vec![0x01; 32];
1270612658
follower_conf.node.local_peer_seed = vec![0x02; 32];
1270712659

12708-
let mut rng = rand::thread_rng();
12709-
let prior_rpc_port: u16 = conf
12710-
.node
12711-
.rpc_bind
12712-
.split(":")
12713-
.last()
12714-
.unwrap()
12715-
.parse()
12716-
.unwrap();
12717-
let prior_p2p_port: u16 = conf
12718-
.node
12719-
.p2p_bind
12720-
.split(":")
12721-
.last()
12722-
.unwrap()
12723-
.parse()
12724-
.unwrap();
12725-
let (rpc_port, p2p_port) = loop {
12726-
let a = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
12727-
let b = rng.gen_range(1024..u16::MAX); // use a non-privileged port between 1024 and 65534
12728-
if a != b
12729-
&& a != prior_rpc_port
12730-
&& a != prior_p2p_port
12731-
&& b != prior_rpc_port
12732-
&& b != prior_p2p_port
12733-
{
12734-
break (a, b);
12735-
}
12736-
};
12660+
let rpc_port = gen_random_port();
12661+
let p2p_port = gen_random_port();
1273712662

1273812663
let localhost = "127.0.0.1";
1273912664
follower_conf.node.rpc_bind = format!("{localhost}:{rpc_port}");
@@ -12868,29 +12793,7 @@ fn listunspent_max_utxos() {
1286812793
}
1286912794

1287012795
let (mut conf, _miner_account) = neon_integration_test_conf();
12871-
let mut rng = rand::thread_rng();
12872-
let mut prom_port = 6000;
12873-
let prior_rpc_port: u16 = conf
12874-
.node
12875-
.rpc_bind
12876-
.split(":")
12877-
.last()
12878-
.unwrap()
12879-
.parse()
12880-
.unwrap();
12881-
let prior_p2p_port: u16 = conf
12882-
.node
12883-
.p2p_bind
12884-
.split(":")
12885-
.last()
12886-
.unwrap()
12887-
.parse()
12888-
.unwrap();
12889-
// Use a non-privileged port between 1024 and 65534
12890-
while prom_port == prior_rpc_port || prom_port == prior_p2p_port {
12891-
// We should NOT match the miner's rpc or p2p binds
12892-
prom_port = rng.gen_range(1024..u16::MAX);
12893-
}
12796+
let prom_port = gen_random_port();
1289412797
let localhost = "127.0.0.1";
1289512798
let prom_bind = format!("{localhost}:{prom_port}");
1289612799
conf.node.prometheus_bind = Some(prom_bind.clone());
@@ -12938,29 +12841,7 @@ fn start_stop_bitcoind() {
1293812841
}
1293912842

1294012843
let (mut conf, _miner_account) = neon_integration_test_conf();
12941-
let mut rng = rand::thread_rng();
12942-
let mut prom_port = 6000;
12943-
let prior_rpc_port: u16 = conf
12944-
.node
12945-
.rpc_bind
12946-
.split(":")
12947-
.last()
12948-
.unwrap()
12949-
.parse()
12950-
.unwrap();
12951-
let prior_p2p_port: u16 = conf
12952-
.node
12953-
.p2p_bind
12954-
.split(":")
12955-
.last()
12956-
.unwrap()
12957-
.parse()
12958-
.unwrap();
12959-
// Use a non-privileged port between 1024 and 65534
12960-
while prom_port == prior_rpc_port || prom_port == prior_p2p_port {
12961-
// We should NOT match the miner's rpc or p2p binds
12962-
prom_port = rng.gen_range(1024..u16::MAX);
12963-
}
12844+
let prom_port = gen_random_port();
1296412845
let localhost = "127.0.0.1";
1296512846
let prom_bind = format!("{localhost}:{prom_port}");
1296612847
conf.node.prometheus_bind = Some(prom_bind.clone());

0 commit comments

Comments
 (0)