github.com/vipernet-xyz/tm@v0.34.24/types/part_set_test.go (about)

     1  package types
     2  
     3  import (
     4  	"io"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/vipernet-xyz/tm/crypto/merkle"
    11  	tmrand "github.com/vipernet-xyz/tm/libs/rand"
    12  )
    13  
    14  const (
    15  	testPartSize = 65536 // 64KB ...  4096 // 4KB
    16  )
    17  
    18  func TestBasicPartSet(t *testing.T) {
    19  	// Construct random data of size partSize * 100
    20  	nParts := 100
    21  	data := tmrand.Bytes(testPartSize * nParts)
    22  	partSet := NewPartSetFromData(data, testPartSize)
    23  
    24  	assert.NotEmpty(t, partSet.Hash())
    25  	assert.EqualValues(t, nParts, partSet.Total())
    26  	assert.Equal(t, nParts, partSet.BitArray().Size())
    27  	assert.True(t, partSet.HashesTo(partSet.Hash()))
    28  	assert.True(t, partSet.IsComplete())
    29  	assert.EqualValues(t, nParts, partSet.Count())
    30  	assert.EqualValues(t, testPartSize*nParts, partSet.ByteSize())
    31  
    32  	// Test adding parts to a new partSet.
    33  	partSet2 := NewPartSetFromHeader(partSet.Header())
    34  
    35  	assert.True(t, partSet2.HasHeader(partSet.Header()))
    36  	for i := 0; i < int(partSet.Total()); i++ {
    37  		part := partSet.GetPart(i)
    38  		// t.Logf("\n%v", part)
    39  		added, err := partSet2.AddPart(part)
    40  		if !added || err != nil {
    41  			t.Errorf("failed to add part %v, error: %v", i, err)
    42  		}
    43  	}
    44  	// adding part with invalid index
    45  	added, err := partSet2.AddPart(&Part{Index: 10000})
    46  	assert.False(t, added)
    47  	assert.Error(t, err)
    48  	// adding existing part
    49  	added, err = partSet2.AddPart(partSet2.GetPart(0))
    50  	assert.False(t, added)
    51  	assert.Nil(t, err)
    52  
    53  	assert.Equal(t, partSet.Hash(), partSet2.Hash())
    54  	assert.EqualValues(t, nParts, partSet2.Total())
    55  	assert.EqualValues(t, nParts*testPartSize, partSet.ByteSize())
    56  	assert.True(t, partSet2.IsComplete())
    57  
    58  	// Reconstruct data, assert that they are equal.
    59  	data2Reader := partSet2.GetReader()
    60  	data2, err := io.ReadAll(data2Reader)
    61  	require.NoError(t, err)
    62  
    63  	assert.Equal(t, data, data2)
    64  }
    65  
    66  func TestWrongProof(t *testing.T) {
    67  	// Construct random data of size partSize * 100
    68  	data := tmrand.Bytes(testPartSize * 100)
    69  	partSet := NewPartSetFromData(data, testPartSize)
    70  
    71  	// Test adding a part with wrong data.
    72  	partSet2 := NewPartSetFromHeader(partSet.Header())
    73  
    74  	// Test adding a part with wrong trail.
    75  	part := partSet.GetPart(0)
    76  	part.Proof.Aunts[0][0] += byte(0x01)
    77  	added, err := partSet2.AddPart(part)
    78  	if added || err == nil {
    79  		t.Errorf("expected to fail adding a part with bad trail.")
    80  	}
    81  
    82  	// Test adding a part with wrong bytes.
    83  	part = partSet.GetPart(1)
    84  	part.Bytes[0] += byte(0x01)
    85  	added, err = partSet2.AddPart(part)
    86  	if added || err == nil {
    87  		t.Errorf("expected to fail adding a part with bad bytes.")
    88  	}
    89  }
    90  
    91  func TestPartSetHeaderValidateBasic(t *testing.T) {
    92  	testCases := []struct {
    93  		testName              string
    94  		malleatePartSetHeader func(*PartSetHeader)
    95  		expectErr             bool
    96  	}{
    97  		{"Good PartSet", func(psHeader *PartSetHeader) {}, false},
    98  		{"Invalid Hash", func(psHeader *PartSetHeader) { psHeader.Hash = make([]byte, 1) }, true},
    99  	}
   100  	for _, tc := range testCases {
   101  		tc := tc
   102  		t.Run(tc.testName, func(t *testing.T) {
   103  			data := tmrand.Bytes(testPartSize * 100)
   104  			ps := NewPartSetFromData(data, testPartSize)
   105  			psHeader := ps.Header()
   106  			tc.malleatePartSetHeader(&psHeader)
   107  			assert.Equal(t, tc.expectErr, psHeader.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   108  		})
   109  	}
   110  }
   111  
   112  func TestPartValidateBasic(t *testing.T) {
   113  	testCases := []struct {
   114  		testName     string
   115  		malleatePart func(*Part)
   116  		expectErr    bool
   117  	}{
   118  		{"Good Part", func(pt *Part) {}, false},
   119  		{"Too big part", func(pt *Part) { pt.Bytes = make([]byte, BlockPartSizeBytes+1) }, true},
   120  		{"Too big proof", func(pt *Part) {
   121  			pt.Proof = merkle.Proof{
   122  				Total:    1,
   123  				Index:    1,
   124  				LeafHash: make([]byte, 1024*1024),
   125  			}
   126  		}, true},
   127  	}
   128  
   129  	for _, tc := range testCases {
   130  		tc := tc
   131  		t.Run(tc.testName, func(t *testing.T) {
   132  			data := tmrand.Bytes(testPartSize * 100)
   133  			ps := NewPartSetFromData(data, testPartSize)
   134  			part := ps.GetPart(0)
   135  			tc.malleatePart(part)
   136  			assert.Equal(t, tc.expectErr, part.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   137  		})
   138  	}
   139  }
   140  
   141  func TestParSetHeaderProtoBuf(t *testing.T) {
   142  	testCases := []struct {
   143  		msg     string
   144  		ps1     *PartSetHeader
   145  		expPass bool
   146  	}{
   147  		{"success empty", &PartSetHeader{}, true},
   148  		{
   149  			"success",
   150  			&PartSetHeader{Total: 1, Hash: []byte("hash")}, true,
   151  		},
   152  	}
   153  
   154  	for _, tc := range testCases {
   155  		protoBlockID := tc.ps1.ToProto()
   156  
   157  		psh, err := PartSetHeaderFromProto(&protoBlockID)
   158  		if tc.expPass {
   159  			require.Equal(t, tc.ps1, psh, tc.msg)
   160  		} else {
   161  			require.Error(t, err, tc.msg)
   162  		}
   163  	}
   164  }
   165  
   166  func TestPartProtoBuf(t *testing.T) {
   167  	proof := merkle.Proof{
   168  		Total:    1,
   169  		Index:    1,
   170  		LeafHash: tmrand.Bytes(32),
   171  	}
   172  	testCases := []struct {
   173  		msg     string
   174  		ps1     *Part
   175  		expPass bool
   176  	}{
   177  		{"failure empty", &Part{}, false},
   178  		{"failure nil", nil, false},
   179  		{
   180  			"success",
   181  			&Part{Index: 1, Bytes: tmrand.Bytes(32), Proof: proof}, true,
   182  		},
   183  	}
   184  
   185  	for _, tc := range testCases {
   186  		proto, err := tc.ps1.ToProto()
   187  		if tc.expPass {
   188  			require.NoError(t, err, tc.msg)
   189  		}
   190  
   191  		p, err := PartFromProto(proto)
   192  		if tc.expPass {
   193  			require.NoError(t, err)
   194  			require.Equal(t, tc.ps1, p, tc.msg)
   195  		}
   196  	}
   197  }