LCOV - code coverage report
Current view: top level - src/test - llmq_chainlock_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 92 95 96.8 %
Date: 2026-06-25 07:23:43 Functions: 52 52 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <test/util/llmq_tests.h>
       6             : #include <test/util/setup_common.h>
       7             : 
       8             : #include <streams.h>
       9             : #include <util/strencodings.h>
      10             : 
      11             : #include <chainlock/chainlock.h>
      12             : 
      13             : #include <boost/test/unit_test.hpp>
      14             : 
      15             : using chainlock::ChainLockSig;
      16             : using namespace llmq;
      17             : using namespace llmq::testutils;
      18             : 
      19         146 : BOOST_FIXTURE_TEST_SUITE(llmq_chainlock_tests, BasicTestingSetup)
      20             : 
      21         149 : BOOST_AUTO_TEST_CASE(chainlock_construction_test)
      22             : {
      23             :     // Test default constructor
      24           1 :     ChainLockSig clsig1;
      25           1 :     BOOST_CHECK(clsig1.IsNull());
      26           1 :     BOOST_CHECK_EQUAL(clsig1.getHeight(), -1);
      27           1 :     BOOST_CHECK(clsig1.getBlockHash().IsNull());
      28           1 :     BOOST_CHECK(!clsig1.getSig().IsValid());
      29             : 
      30             :     // Test parameterized constructor
      31           1 :     int32_t height = 12345;
      32           1 :     uint256 blockHash = GetTestBlockHash(1);
      33           1 :     CBLSSignature sig = CreateRandomBLSSignature();
      34             : 
      35           1 :     ChainLockSig clsig2(height, blockHash, sig);
      36           1 :     BOOST_CHECK(!clsig2.IsNull());
      37           1 :     BOOST_CHECK_EQUAL(clsig2.getHeight(), height);
      38           1 :     BOOST_CHECK(clsig2.getBlockHash() == blockHash);
      39           1 :     BOOST_CHECK(clsig2.getSig() == sig);
      40           1 : }
      41             : 
      42         149 : BOOST_AUTO_TEST_CASE(chainlock_null_test)
      43             : {
      44           1 :     ChainLockSig clsig;
      45             : 
      46             :     // Default constructed should be null
      47           1 :     BOOST_CHECK(clsig.IsNull());
      48             : 
      49             :     // With height set but null hash, should not be null
      50           1 :     clsig = ChainLockSig(100, uint256(), CBLSSignature());
      51           1 :     BOOST_CHECK(!clsig.IsNull());
      52             : 
      53             :     // With valid data should not be null
      54           1 :     clsig = CreateChainLock(100, GetTestBlockHash(1));
      55           1 :     BOOST_CHECK(!clsig.IsNull());
      56           1 : }
      57             : 
      58         149 : BOOST_AUTO_TEST_CASE(chainlock_serialization_test)
      59             : {
      60             :     // Test with valid chainlock
      61           1 :     ChainLockSig clsig = CreateChainLock(67890, GetTestBlockHash(42));
      62             : 
      63             :     // Test serialization preserves all fields
      64           1 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
      65           1 :     ss << clsig;
      66             : 
      67           1 :     ChainLockSig deserialized;
      68           1 :     ss >> deserialized;
      69             : 
      70           1 :     BOOST_CHECK_EQUAL(clsig.getHeight(), deserialized.getHeight());
      71           1 :     BOOST_CHECK(clsig.getBlockHash() == deserialized.getBlockHash());
      72           1 :     BOOST_CHECK(clsig.getSig() == deserialized.getSig());
      73           1 :     BOOST_CHECK_EQUAL(clsig.IsNull(), deserialized.IsNull());
      74           1 : }
      75             : 
      76         149 : BOOST_AUTO_TEST_CASE(chainlock_tostring_test)
      77             : {
      78             :     // Test null chainlock
      79           1 :     ChainLockSig nullClsig;
      80           1 :     std::string nullStr = nullClsig.ToString();
      81           1 :     BOOST_CHECK(!nullStr.empty());
      82             : 
      83             :     // Test valid chainlock
      84           1 :     int32_t height = 123456;
      85           1 :     uint256 blockHash = GetTestBlockHash(789);
      86           1 :     ChainLockSig clsig = CreateChainLock(height, blockHash);
      87             : 
      88           1 :     std::string str = clsig.ToString();
      89           1 :     BOOST_CHECK(!str.empty());
      90             : 
      91             :     // ToString should contain height and hash info
      92           1 :     BOOST_CHECK(str.find(strprintf("%d", height)) != std::string::npos);
      93           1 :     BOOST_CHECK(str.find(blockHash.ToString().substr(0, 10)) != std::string::npos);
      94           1 : }
      95             : 
      96         149 : BOOST_AUTO_TEST_CASE(chainlock_edge_cases_test)
      97             : {
      98             :     // Test with edge case heights
      99           1 :     ChainLockSig clsig1 = CreateChainLock(0, GetTestBlockHash(1));
     100           1 :     BOOST_CHECK_EQUAL(clsig1.getHeight(), 0);
     101           1 :     BOOST_CHECK(!clsig1.IsNull());
     102             : 
     103           1 :     ChainLockSig clsig2 = CreateChainLock(std::numeric_limits<int32_t>::max(), GetTestBlockHash(2));
     104           1 :     BOOST_CHECK_EQUAL(clsig2.getHeight(), std::numeric_limits<int32_t>::max());
     105             : 
     106             :     // Test serialization with extreme values
     107           1 :     CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION);
     108           1 :     ss1 << clsig1;
     109           1 :     ChainLockSig clsig1_deserialized;
     110           1 :     ss1 >> clsig1_deserialized;
     111           1 :     BOOST_CHECK_EQUAL(clsig1.getHeight(), clsig1_deserialized.getHeight());
     112             : 
     113           1 :     CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
     114           1 :     ss2 << clsig2;
     115           1 :     ChainLockSig clsig2_deserialized;
     116           1 :     ss2 >> clsig2_deserialized;
     117           1 :     BOOST_CHECK_EQUAL(clsig2.getHeight(), clsig2_deserialized.getHeight());
     118           1 : }
     119             : 
     120         149 : BOOST_AUTO_TEST_CASE(chainlock_comparison_test)
     121             : {
     122             :     // Create identical chainlocks
     123           1 :     int32_t height = 5000;
     124           1 :     uint256 blockHash = GetTestBlockHash(10);
     125           1 :     CBLSSignature sig = CreateRandomBLSSignature();
     126             : 
     127           1 :     ChainLockSig clsig1(height, blockHash, sig);
     128           1 :     ChainLockSig clsig2(height, blockHash, sig);
     129             : 
     130             :     // Verify getters return same values
     131           1 :     BOOST_CHECK_EQUAL(clsig1.getHeight(), clsig2.getHeight());
     132           1 :     BOOST_CHECK(clsig1.getBlockHash() == clsig2.getBlockHash());
     133           1 :     BOOST_CHECK(clsig1.getSig() == clsig2.getSig());
     134             : 
     135             :     // Different chainlocks
     136           1 :     ChainLockSig clsig3(height + 1, blockHash, sig);
     137           1 :     BOOST_CHECK(clsig1.getHeight() != clsig3.getHeight());
     138             : 
     139           1 :     ChainLockSig clsig4(height, GetTestBlockHash(11), sig);
     140           1 :     BOOST_CHECK(clsig1.getBlockHash() != clsig4.getBlockHash());
     141           1 : }
     142             : 
     143         149 : BOOST_AUTO_TEST_CASE(chainlock_malformed_data_test)
     144             : {
     145             :     // Test deserialization of truncated data
     146           1 :     ChainLockSig clsig = CreateChainLock(1000, GetTestBlockHash(5));
     147             : 
     148           1 :     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     149           1 :     ss << clsig;
     150             : 
     151             :     // Truncate the stream
     152           1 :     std::string data = ss.str();
     153          15 :     for (size_t truncateAt = 1; truncateAt < data.size(); truncateAt += 10) {
     154          14 :         CDataStream truncated(std::vector<unsigned char>(data.begin(), data.begin() + truncateAt), SER_NETWORK,
     155             :                               PROTOCOL_VERSION);
     156             : 
     157          14 :         ChainLockSig deserialized;
     158             :         try {
     159          14 :             truncated >> deserialized;
     160             :             // If no exception, verify it's either complete or default
     161           0 :             if (truncateAt < sizeof(int32_t)) {
     162           0 :                 BOOST_CHECK(deserialized.IsNull());
     163           0 :             }
     164          14 :         } catch (const std::exception&) {
     165             :             // Expected for most truncation points
     166          14 :         }
     167          14 :     }
     168          15 : }
     169             : 
     170         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16