func generateRandomBlockData(txCount, isrCount, evdCount, msgCount, maxSize int) Data {
	var out Data
	out.Txs = generateRandomlySizedContiguousShares(txCount, maxSize)
	out.IntermediateStateRoots = generateRandomISR(isrCount)
	out.Evidence = generateIdenticalEvidence(evdCount)
	out.Messages = generateRandomlySizedMessages(msgCount, maxSize)
	return out
}
generateRandomBlockData returns randomly generated block data for testing purposes
package types
import (
	"bytes"
	"context"
	"fmt"
	"math"
	"math/rand"
	"reflect"
	"sort"
	"testing"
	"time"
	"github.com/celestiaorg/nmt/namespace"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tendermint/tendermint/internal/libs/protoio"
	tmbytes "github.com/tendermint/tendermint/libs/bytes"
	"github.com/tendermint/tendermint/pkg/consts"
	"github.com/tendermint/tendermint/pkg/da"
)
type Splitter interface {
	SplitIntoShares() NamespacedShares
}
func TestMakeShares(t *testing.T) {
	reservedTxNamespaceID := append(bytes.Repeat([]byte{0}, 7), 1)
	reservedEvidenceNamespaceID := append(bytes.Repeat([]byte{0}, 7), 3)
	val := NewMockPV()
	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
	vote1 := makeVote(t, val, "chainID", 0, 10, 2, 1, blockID, defaultVoteTime)
	vote2 := makeVote(t, val, "chainID", 0, 10, 2, 1, blockID2, defaultVoteTime)
	testEvidence := &DuplicateVoteEvidence{
		VoteA: vote1,
		VoteB: vote2,
	}
	protoTestEvidence, err := EvidenceToProto(testEvidence)
	if err != nil {
		t.Error(err)
	}
	testEvidenceBytes, err := protoio.MarshalDelimited(protoTestEvidence)
	largeTx := Tx(bytes.Repeat([]byte("large Tx"), 50))
	largeTxLenDelimited, _ := largeTx.MarshalDelimited()
	smolTx := Tx("small Tx")
	smolTxLenDelimited, _ := smolTx.MarshalDelimited()
	msg1 := Message{
		NamespaceID: namespace.ID("8bytesss"),
		Data:        []byte("some data"),
	}
	msg1Marshaled, _ := msg1.MarshalDelimited()
	if err != nil {
		t.Fatalf("Could not encode evidence: %v, error: %v\n", testEvidence, err)
	}
	type args struct {
		data Splitter
	}
	tests := []struct {
		name string
		args args
		want NamespacedShares
	}{
		{
			name: "evidence",
			args: args{
				data: &EvidenceData{
					Evidence: []Evidence{testEvidence},
				},
			},
			want: NamespacedShares{
				NamespacedShare{
					Share: append(
						append(reservedEvidenceNamespaceID, byte(0)),
						testEvidenceBytes[:consts.TxShareSize]...,
					),
					ID: reservedEvidenceNamespaceID,
				},
				NamespacedShare{
					Share: append(
						append(reservedEvidenceNamespaceID, byte(0)),
						zeroPadIfNecessary(testEvidenceBytes[consts.TxShareSize:], consts.TxShareSize)...,
					),
					ID: reservedEvidenceNamespaceID,
				},
			},
		},
		{"small LL Tx",
			args{
				data: Txs{smolTx},
			},
			NamespacedShares{
				NamespacedShare{
					Share: append(
						append(reservedTxNamespaceID, byte(0)),
						zeroPadIfNecessary(smolTxLenDelimited, consts.TxShareSize)...,
					),
					ID: reservedTxNamespaceID,
				},
			},
		},
		{"one large LL Tx",
			args{
				data: Txs{largeTx},
			},
			NamespacedShares{
				NamespacedShare{
					Share: append(
						append(reservedTxNamespaceID, byte(0)),
						largeTxLenDelimited[:consts.TxShareSize]...,
					),
					ID: reservedTxNamespaceID,
				},
				NamespacedShare{
					Share: append(
						append(reservedTxNamespaceID, byte(0)),
						zeroPadIfNecessary(largeTxLenDelimited[consts.TxShareSize:], consts.TxShareSize)...,
					),
					ID: reservedTxNamespaceID,
				},
			},
		},
		{"large then small LL Tx",
			args{
				data: Txs{largeTx, smolTx},
			},
			NamespacedShares{
				NamespacedShare{
					Share: append(
						append(reservedTxNamespaceID, byte(0)),
						largeTxLenDelimited[:consts.TxShareSize]...,
					),
					ID: reservedTxNamespaceID,
				},
				NamespacedShare{
					Share: append(
						append(
							reservedTxNamespaceID,
							byte(len(largeTxLenDelimited)-consts.TxShareSize+consts.NamespaceSize+consts.ShareReservedBytes),
						),
						zeroPadIfNecessary(
							append(largeTxLenDelimited[consts.TxShareSize:], smolTxLenDelimited...),
							consts.TxShareSize,
						)...,
					),
					ID: reservedTxNamespaceID,
				},
			},
		},
		{"ll-app message",
			args{
				data: Messages{[]Message{msg1}},
			},
			NamespacedShares{
				NamespacedShare{
					Share: append(
						[]byte(msg1.NamespaceID),
						zeroPadIfNecessary(msg1Marshaled, consts.MsgShareSize)...,
					),
					ID: msg1.NamespaceID,
				},
			},
		},
	}
	for i, tt := range tests {
		tt := tt  
		i := i
		t.Run(tt.name, func(t *testing.T) {
			got := tt.args.data.SplitIntoShares()
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("%v: makeShares() = \n%+v\nwant\n%+v\n", i, got, tt.want)
			}
		})
	}
}
func Test_zeroPadIfNecessary(t *testing.T) {
	type args struct {
		share []byte
		width int
	}
	tests := []struct {
		name string
		args args
		want []byte
	}{
		{"pad", args{[]byte{1, 2, 3}, 6}, []byte{1, 2, 3, 0, 0, 0}},
		{"not necessary (equal to shareSize)", args{[]byte{1, 2, 3}, 3}, []byte{1, 2, 3}},
		{"not necessary (greater shareSize)", args{[]byte{1, 2, 3}, 2}, []byte{1, 2, 3}},
	}
	for _, tt := range tests {
		tt := tt  
		t.Run(tt.name, func(t *testing.T) {
			if got := zeroPadIfNecessary(tt.args.share, tt.args.width); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("zeroPadIfNecessary() = %v, want %v", got, tt.want)
			}
		})
	}
}
func Test_appendToSharesOverwrite(t *testing.T) {
	var shares NamespacedShares
	newShare := generateRandomNamespacedShares(1, consts.MsgShareSize+1)[0]
	extraCopy := make([]byte, consts.MsgShareSize)
	copy(extraCopy, newShare.Share[:consts.MsgShareSize])
	appendToShares(shares, newShare.ID, newShare.Share)
	assert.Equal(t, extraCopy, []byte(newShare.Share[:consts.MsgShareSize]))
}
func TestDataFromSquare(t *testing.T) {
	type test struct {
		name     string
		txCount  int
		isrCount int
		evdCount int
		msgCount int
		maxSize  int  
	}
	tests := []test{
		{"one of each random small size", 1, 1, 1, 1, 40},
		{"one of each random large size", 1, 1, 1, 1, 400},
		{"many of each random large size", 10, 10, 10, 10, 40},
		{"many of each random large size", 10, 10, 10, 10, 400},
		{"only transactions", 10, 0, 0, 0, 400},
		{"only intermediate state roots", 0, 10, 0, 0, 400},
		{"only evidence", 0, 0, 10, 0, 400},
		{"only messages", 0, 0, 0, 10, 400},
	}
	for _, tc := range tests {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			data := generateRandomBlockData(
				tc.txCount,
				tc.isrCount,
				tc.evdCount,
				tc.msgCount,
				tc.maxSize,
			)
			shares, _ := data.ComputeShares()
			rawShares := shares.RawShares()
			squareSize := uint64(math.Sqrt(float64(len(shares))))
			eds, err := da.ExtendShares(squareSize, rawShares)
			require.NoError(t, err)
			res, err := DataFromSquare(eds)
			if err != nil {
				t.Fatal(err)
			}
			for i := 0; i < len(data.Evidence.Evidence); i++ {
				inputEvidence := data.Evidence.Evidence[i].(*DuplicateVoteEvidence)
				resultEvidence := res.Evidence.Evidence[i].(*DuplicateVoteEvidence)
				assert.Equal(t, inputEvidence.String(), resultEvidence.String())
			}
			data.Evidence = EvidenceData{}
			res.Evidence = EvidenceData{}
			assert.Equal(t, data, res)
		})
	}
}
func TestFuzz_DataFromSquare(t *testing.T) {
	t.Skip()
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()
	for {
		select {
		case <-ctx.Done():
			return
		default:
			TestDataFromSquare(t)
		}
	}
}
func Test_processContiguousShares(t *testing.T) {
	const exactTxShareSize = consts.TxShareSize - 1
	type test struct {
		name    string
		txSize  int
		txCount int
	}
	tests := []test{
		{"single small tx", 10, 1},
		{"many small txs", 10, 10},
		{"single big tx", 1000, 1},
		{"many big txs", 1000, 10},
		{"single exact size tx", exactTxShareSize, 1},
		{"many exact size txs", exactTxShareSize, 10},
	}
	for _, tc := range tests {
		tc := tc
		t.Run(fmt.Sprintf("%s idendically sized ", tc.name), func(t *testing.T) {
			txs := generateRandomContiguousShares(tc.txCount, tc.txSize)
			shares := txs.SplitIntoShares()
			parsedTxs, err := processContiguousShares(shares.RawShares())
			if err != nil {
				t.Error(err)
			}
			for i := 0; i < len(txs); i++ {
				assert.Equal(t, []byte(txs[i]), parsedTxs[i])
			}
		})
		t.Run(fmt.Sprintf("%s randomly sized", tc.name), func(t *testing.T) {
			txs := generateRandomlySizedContiguousShares(tc.txCount, tc.txSize)
			shares := txs.SplitIntoShares()
			parsedTxs, err := processContiguousShares(shares.RawShares())
			if err != nil {
				t.Error(err)
			}
			for i := 0; i < len(txs); i++ {
				assert.Equal(t, []byte(txs[i]), parsedTxs[i])
			}
		})
	}
}
func TestFuzz_processContiguousShares(t *testing.T) {
	t.Skip()
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()
	for {
		select {
		case <-ctx.Done():
			return
		default:
			Test_processContiguousShares(t)
		}
	}
}
func Test_parseMsgShares(t *testing.T) {
	const exactMsgShareSize = consts.MsgShareSize - 2
	type test struct {
		name     string
		msgSize  int
		msgCount int
	}
	tests := []test{
		{"single small msg", 1, 1},
		{"many small msgs", 4, 10},
		{"single big msg", 1000, 1},
		{"many big msgs", 1000, 10},
		{"single exact size msg", exactMsgShareSize, 1},
		{"many exact size msgs", exactMsgShareSize, 10},
	}
	for _, tc := range tests {
		tc := tc
		t.Run(fmt.Sprintf("%s idendically sized ", tc.name), func(t *testing.T) {
			rawmsgs := make([]Message, tc.msgCount)
			for i := 0; i < tc.msgCount; i++ {
				rawmsgs[i] = generateRandomMessage(tc.msgSize)
			}
			msgs := Messages{MessagesList: rawmsgs}
			shares := msgs.SplitIntoShares()
			parsedMsgs, err := parseMsgShares(shares.RawShares())
			if err != nil {
				t.Error(err)
			}
			for i := 0; i < len(msgs.MessagesList); i++ {
				assert.Equal(t, msgs.MessagesList[i].NamespaceID, parsedMsgs[i].NamespaceID)
				assert.Equal(t, msgs.MessagesList[i].Data, parsedMsgs[i].Data)
			}
		})
		t.Run(fmt.Sprintf("%s randomly sized", tc.name), func(t *testing.T) {
			msgs := generateRandomlySizedMessages(tc.msgCount, tc.msgSize)
			shares := msgs.SplitIntoShares()
			parsedMsgs, err := parseMsgShares(shares.RawShares())
			if err != nil {
				t.Error(err)
			}
			for i := 0; i < len(msgs.MessagesList); i++ {
				assert.Equal(t, msgs.MessagesList[i].NamespaceID, parsedMsgs[i].NamespaceID)
				assert.Equal(t, msgs.MessagesList[i].Data, parsedMsgs[i].Data)
			}
		})
	}
}
func Test_parseDelimiter(t *testing.T) {
	for i := uint64(0); i < 100; i++ {
		tx := generateRandomContiguousShares(1, int(i))[0]
		input, err := tx.MarshalDelimited()
		if err != nil {
			panic(err)
		}
		res, txLen, err := parseDelimiter(input)
		if err != nil {
			panic(err)
		}
		assert.Equal(t, i, txLen)
		assert.Equal(t, []byte(tx), res)
	}
}