-
Notifications
You must be signed in to change notification settings - Fork 1.2k
test: add comprehensive unit tests for LLMQ subsystem #6691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4f3cde6
3e5a532
4744cfc
9a8eb89
d9ddc3f
f97c705
72cbe5f
e5431a4
e08d628
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// Copyright (c) 2025 The Dash Core developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#include <test/util/llmq_tests.h> | ||
#include <test/util/setup_common.h> | ||
|
||
#include <llmq/clsig.h> | ||
#include <streams.h> | ||
#include <util/strencodings.h> | ||
|
||
#include <boost/test/unit_test.hpp> | ||
|
||
using namespace llmq; | ||
using namespace llmq::testutils; | ||
|
||
BOOST_FIXTURE_TEST_SUITE(llmq_chainlock_tests, BasicTestingSetup) | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_construction_test) | ||
{ | ||
// Test default constructor | ||
CChainLockSig clsig1; | ||
BOOST_CHECK(clsig1.IsNull()); | ||
BOOST_CHECK_EQUAL(clsig1.getHeight(), -1); | ||
BOOST_CHECK(clsig1.getBlockHash().IsNull()); | ||
BOOST_CHECK(!clsig1.getSig().IsValid()); | ||
|
||
// Test parameterized constructor | ||
int32_t height = 12345; | ||
uint256 blockHash = GetTestBlockHash(1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: names should be named in snake_case for new code; for example: also, See doc/developer-notes.md:
|
||
CBLSSignature sig = CreateRandomBLSSignature(); | ||
|
||
CChainLockSig clsig2(height, blockHash, sig); | ||
BOOST_CHECK(!clsig2.IsNull()); | ||
BOOST_CHECK_EQUAL(clsig2.getHeight(), height); | ||
BOOST_CHECK(clsig2.getBlockHash() == blockHash); | ||
BOOST_CHECK(clsig2.getSig() == sig); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_null_test) | ||
{ | ||
CChainLockSig clsig; | ||
|
||
// Default constructed should be null | ||
BOOST_CHECK(clsig.IsNull()); | ||
|
||
// With height set but null hash, should not be null | ||
clsig = CChainLockSig(100, uint256(), CBLSSignature()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit use {}:
|
||
BOOST_CHECK(!clsig.IsNull()); | ||
|
||
// With valid data should not be null | ||
clsig = CreateChainLock(100, GetTestBlockHash(1)); | ||
BOOST_CHECK(!clsig.IsNull()); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_serialization_test) | ||
{ | ||
// Test with valid chainlock | ||
CChainLockSig clsig = CreateChainLock(67890, GetTestBlockHash(42)); | ||
|
||
// Test serialization preserves all fields | ||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); | ||
ss << clsig; | ||
|
||
CChainLockSig deserialized; | ||
ss >> deserialized; | ||
|
||
BOOST_CHECK_EQUAL(clsig.getHeight(), deserialized.getHeight()); | ||
BOOST_CHECK(clsig.getBlockHash() == deserialized.getBlockHash()); | ||
BOOST_CHECK(clsig.getSig() == deserialized.getSig()); | ||
BOOST_CHECK_EQUAL(clsig.IsNull(), deserialized.IsNull()); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_tostring_test) | ||
{ | ||
// Test null chainlock | ||
CChainLockSig nullClsig; | ||
std::string nullStr = nullClsig.ToString(); | ||
BOOST_CHECK(!nullStr.empty()); | ||
|
||
// Test valid chainlock | ||
int32_t height = 123456; | ||
uint256 blockHash = GetTestBlockHash(789); | ||
CChainLockSig clsig = CreateChainLock(height, blockHash); | ||
|
||
std::string str = clsig.ToString(); | ||
BOOST_CHECK(!str.empty()); | ||
|
||
// ToString should contain height and hash info | ||
BOOST_CHECK(str.find(strprintf("%d", height)) != std::string::npos); | ||
BOOST_CHECK(str.find(blockHash.ToString().substr(0, 10)) != std::string::npos); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_edge_cases_test) | ||
{ | ||
// Test with edge case heights | ||
CChainLockSig clsig1 = CreateChainLock(0, GetTestBlockHash(1)); | ||
BOOST_CHECK_EQUAL(clsig1.getHeight(), 0); | ||
BOOST_CHECK(!clsig1.IsNull()); | ||
|
||
CChainLockSig clsig2 = CreateChainLock(std::numeric_limits<int32_t>::max(), GetTestBlockHash(2)); | ||
BOOST_CHECK_EQUAL(clsig2.getHeight(), std::numeric_limits<int32_t>::max()); | ||
|
||
// Test serialization with extreme values | ||
CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); | ||
ss1 << clsig1; | ||
CChainLockSig clsig1_deserialized; | ||
ss1 >> clsig1_deserialized; | ||
BOOST_CHECK_EQUAL(clsig1.getHeight(), clsig1_deserialized.getHeight()); | ||
|
||
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); | ||
ss2 << clsig2; | ||
CChainLockSig clsig2_deserialized; | ||
ss2 >> clsig2_deserialized; | ||
BOOST_CHECK_EQUAL(clsig2.getHeight(), clsig2_deserialized.getHeight()); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_comparison_test) | ||
{ | ||
// Create identical chainlocks | ||
int32_t height = 5000; | ||
uint256 blockHash = GetTestBlockHash(10); | ||
CBLSSignature sig = CreateRandomBLSSignature(); | ||
|
||
CChainLockSig clsig1(height, blockHash, sig); | ||
CChainLockSig clsig2(height, blockHash, sig); | ||
|
||
// Verify getters return same values | ||
BOOST_CHECK_EQUAL(clsig1.getHeight(), clsig2.getHeight()); | ||
BOOST_CHECK(clsig1.getBlockHash() == clsig2.getBlockHash()); | ||
BOOST_CHECK(clsig1.getSig() == clsig2.getSig()); | ||
|
||
// Different chainlocks | ||
CChainLockSig clsig3(height + 1, blockHash, sig); | ||
BOOST_CHECK(clsig1.getHeight() != clsig3.getHeight()); | ||
|
||
CChainLockSig clsig4(height, GetTestBlockHash(11), sig); | ||
BOOST_CHECK(clsig1.getBlockHash() != clsig4.getBlockHash()); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(chainlock_malformed_data_test) | ||
{ | ||
// Test deserialization of truncated data | ||
CChainLockSig clsig = CreateChainLock(1000, GetTestBlockHash(5)); | ||
|
||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); | ||
ss << clsig; | ||
|
||
// Truncate the stream | ||
std::string data = ss.str(); | ||
for (size_t truncateAt = 1; truncateAt < data.size(); truncateAt += 10) { | ||
CDataStream truncated(std::vector<unsigned char>(data.begin(), data.begin() + truncateAt), SER_NETWORK, | ||
PROTOCOL_VERSION); | ||
|
||
CChainLockSig deserialized; | ||
try { | ||
truncated >> deserialized; | ||
// If no exception, verify it's either complete or default | ||
if (truncateAt < sizeof(int32_t)) { | ||
BOOST_CHECK(deserialized.IsNull()); | ||
} | ||
} catch (const std::exception&) { | ||
// Expected for most truncation points | ||
} | ||
} | ||
} | ||
|
||
BOOST_AUTO_TEST_SUITE_END() |
Uh oh!
There was an error while loading. Please reload this page.