Skip to content

Commit 6eac084

Browse files
committed
Replace rand() with fixed-seed RNG to make tests deterministic
1 parent 28e4abc commit 6eac084

5 files changed

Lines changed: 53 additions & 27 deletions

File tree

test/libp2p/crypto/marshaller_test.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <libp2p/crypto/common.hpp>
1212
#include <libp2p/crypto/protobuf/protobuf_key.hpp>
1313
#include "mock/libp2p/crypto/key_validator_mock.hpp"
14+
#include "testutil/libp2p/random.hpp"
1415

1516
using Buffer = std::vector<uint8_t>;
1617
using libp2p::crypto::Key;
@@ -34,9 +35,7 @@ struct KeyCase {
3435
};
3536

3637
Buffer randomBuffer(size_t size) {
37-
Buffer buf(size, 0);
38-
std::generate_n(buf.begin(), size, []() { return rand() & 0xff; });
39-
return buf;
38+
return testutil::randomBytes(size);
4039
}
4140

4241
class Pubkey : public testing::TestWithParam<KeyCase<PublicKey>> {

test/libp2p/protocol/kademlia/peer_routing_table_test.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
#include <gtest/gtest.h>
77
#include <libp2p/protocol/kademlia/impl/peer_routing_table_impl.hpp>
88
#include <qtils/test/outcome.hpp>
9+
#include <random>
910
#include <unordered_set>
1011

1112
#include <libp2p/common/literals.hpp>
1213
#include "mock/libp2p/peer/identity_manager_mock.hpp"
1314
#include "testutil/libp2p/peer.hpp"
15+
#include "testutil/libp2p/random.hpp"
1416
#include "testutil/prepare_loggers.hpp"
1517

1618
using namespace libp2p;
@@ -50,8 +52,6 @@ bool hasPeer(A &peerset, PeerId &peer) {
5052
}
5153

5254
TEST_F(PeerRoutingTableTest, BusWorks) {
53-
srand(0); // to make test deterministic
54-
5555
auto &addCh = bus_->getChannel<event::protocol::kademlia::PeerAddedChannel>();
5656
auto &remCh =
5757
bus_->getChannel<event::protocol::kademlia::PeerRemovedChannel>();
@@ -85,8 +85,6 @@ TEST_F(PeerRoutingTableTest, BusWorks) {
8585
* https://sourcegraph.com/github.com/libp2p/go-libp2p-kbucket@HEAD/-/blob/table_test.go#L168
8686
*/
8787
TEST_F(PeerRoutingTableTest, FindMultiple) {
88-
srand(0); // to make test deterministic
89-
9088
std::vector<PeerId> peers;
9189
std::generate_n(std::back_inserter(peers), 18, testutil::randomPeerId);
9290

@@ -106,7 +104,6 @@ TEST_F(PeerRoutingTableTest, FindMultiple) {
106104
*/
107105
TEST_F(PeerRoutingTableTest, RecyclingTest) {
108106
config_->maxBucketSize = 1;
109-
srand(0); // to make test deterministic
110107
auto &addCh = bus_->getChannel<event::protocol::kademlia::PeerAddedChannel>();
111108
auto &remCh =
112109
bus_->getChannel<event::protocol::kademlia::PeerRemovedChannel>();
@@ -125,7 +122,7 @@ TEST_F(PeerRoutingTableTest, RecyclingTest) {
125122
std::vector<PeerId> peers;
126123

127124
// Generate peers for first bucket, in count more than bucket capacity
128-
for (int i = 0; i < 3; ++i) {
125+
while (peers.size() != 3) {
129126
auto peer_id = testutil::randomPeerId();
130127
NodeId node_id(peer_id);
131128
if (node_id.commonPrefixLen(NodeId(self_id)) == 0) {
@@ -163,7 +160,6 @@ TEST_F(PeerRoutingTableTest, RecyclingTest) {
163160

164161
TEST_F(PeerRoutingTableTest, PreferLongLivedPeers) {
165162
config_->maxBucketSize = 2;
166-
srand(0); // to make test deterministic
167163
auto &addCh = bus_->getChannel<event::protocol::kademlia::PeerAddedChannel>();
168164
auto &remCh =
169165
bus_->getChannel<event::protocol::kademlia::PeerRemovedChannel>();
@@ -210,7 +206,6 @@ TEST_F(PeerRoutingTableTest, PreferLongLivedPeers) {
210206

211207
TEST_F(PeerRoutingTableTest, EldestRecycledIfNotPermanent) {
212208
config_->maxBucketSize = 3;
213-
srand(0); // to make test deterministic
214209

215210
std::vector<PeerId> peers;
216211

@@ -239,7 +234,6 @@ TEST_F(PeerRoutingTableTest, EldestRecycledIfNotPermanent) {
239234

240235
TEST_F(PeerRoutingTableTest, EldestPrefferedIfPermanent) {
241236
config_->maxBucketSize = 3;
242-
srand(0); // to make test deterministic
243237

244238
std::vector<PeerId> peers;
245239

@@ -272,14 +266,15 @@ TEST_F(PeerRoutingTableTest, EldestPrefferedIfPermanent) {
272266
*/
273267
TEST_F(PeerRoutingTableTest, Update) {
274268
config_->maxBucketSize = 10;
275-
srand(0); // to make test deterministic
276269

277270
std::vector<PeerId> peers;
278271
std::generate_n(std::back_inserter(peers), 100, testutil::randomPeerId);
279272

273+
std::uniform_int_distribution<size_t> dist(0, peers.size() - 1);
274+
auto& rng = testutil::getTestRng();
280275
// 10000 random updates among 100 existing peers
281276
for (int i = 0; i < 10000; i++) {
282-
int index = rand() % peers.size();
277+
size_t index = dist(rng);
283278
[[maybe_unused]] auto result = table_->update(peers[index], false);
284279
}
285280

@@ -300,7 +295,6 @@ TEST_F(PeerRoutingTableTest, Update) {
300295
*/
301296
TEST_F(PeerRoutingTableTest, Find) {
302297
config_->maxBucketSize = 10;
303-
srand(0); // to make test deterministic
304298

305299
const auto nPeers = 5;
306300

test/libp2p/transport/tcp/tcp_integration_test.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "mock/libp2p/transport/upgrader_mock.hpp"
1919
#include "testutil/gmock_actions.hpp"
2020
#include "testutil/libp2p/peer.hpp"
21+
#include "testutil/libp2p/random.hpp"
2122
#include "testutil/prepare_loggers.hpp"
2223

2324
using namespace libp2p::transport;
@@ -175,10 +176,7 @@ TEST(TCP, SingleListenerCanAcceptManyClients) {
175176
auto conn = expectConnectionValid(rconn);
176177

177178
auto readback = std::make_shared<Bytes>(kSize, 0);
178-
auto buf = std::make_shared<Bytes>(kSize, 0);
179-
std::generate(buf->begin(), buf->end(), []() {
180-
return rand(); // NOLINT
181-
});
179+
auto buf = std::make_shared<Bytes>(testutil::randomBytes(kSize));
182180

183181
EXPECT_TRUE(conn->isInitiator());
184182

@@ -335,10 +333,7 @@ TEST(TCP, OneTransportServerHandlesManyClients) {
335333
auto conn = expectConnectionValid(rconn);
336334

337335
auto readback = std::make_shared<Bytes>(kSize, 0);
338-
auto buf = std::make_shared<Bytes>(kSize, 0);
339-
std::generate(buf->begin(), buf->end(), []() {
340-
return rand(); // NOLINT
341-
});
336+
auto buf = std::make_shared<Bytes>(testutil::randomBytes(kSize));
342337

343338
EXPECT_TRUE(conn->isInitiator());
344339

test/testutil/libp2p/peer.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55
*/
66

77
#include <testutil/libp2p/peer.hpp>
8+
#include <testutil/libp2p/random.hpp>
89

910
namespace testutil {
1011

1112
PeerId randomPeerId() {
12-
std::vector<uint8_t> rand_key(32, 0);
13-
for (auto i = 0u; i < 32u; i++) {
14-
rand_key[i] = (rand() & 0xffu); // NOLINT
15-
}
13+
auto rand_key = randomBytes(32);
1614
return PeerId::fromPublicKey(libp2p::crypto::ProtobufKey{rand_key}).value();
1715
}
1816

test/testutil/libp2p/random.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright Quadrivium LLC
3+
* All Rights Reserved
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <cstdint>
10+
#include <random>
11+
#include <vector>
12+
13+
namespace testutil {
14+
15+
/**
16+
* Returns a deterministic RNG for tests. Same seed every run for reproducible
17+
* tests; avoids flaky behavior from unseeded rand().
18+
* NOTE: Shared RNG; test execution order affects the sequence (determinism
19+
* is per run, not per test).
20+
*/
21+
inline std::mt19937& getTestRng() {
22+
static std::mt19937 rng(0x42); // arbitrary fixed seed for reproducibility
23+
return rng;
24+
}
25+
26+
/**
27+
* Fills a buffer with deterministic random bytes. Use in tests instead of
28+
* rand() for reproducibility.
29+
*/
30+
inline std::vector<uint8_t> randomBytes(size_t n) {
31+
std::vector<uint8_t> buf(n);
32+
auto& rng = getTestRng();
33+
std::uniform_int_distribution<int> dist(0, 255);
34+
for (size_t i = 0; i < n; ++i) {
35+
buf[i] = static_cast<uint8_t>(dist(rng));
36+
}
37+
return buf;
38+
}
39+
40+
} // namespace testutil

0 commit comments

Comments
 (0)