package exchain

import (
	nebulav1 "github.com/exchain/go-exchain/exchain/protocol/gen/go/nebula/v1"
	"github.com/golang/protobuf/proto"
	"testing"
)

// todo: tx press test.
// limit, market, cancel 100w, each block 10w.
// serialize and unserialize.
func BenchmarkLimitTxSerialize(b *testing.B) {
	b.StopTimer()
	count := 100000
	txs := TestMakeTxs(nebulav1.TxType_LimitTx, count)
	b.StartTimer()
	// benchmark limit tx serialize and unserialize.
	for i := 0; i < b.N; i++ {
		tx := txs.Txs[i%count]
		d, err := proto.Marshal(tx)
		if err != nil {
			b.Fatal(err)
		}
		ntx := new(nebulav1.Transaction)
		err = proto.Unmarshal(d, ntx)
		if ntx.TxType != tx.TxType {
			b.Fatal("unserialize tx type error")
		}
	}
}

func BenchmarkMarketTxSerialize(b *testing.B) {
	b.StopTimer()
	count := 100000
	txs := TestMakeTxs(nebulav1.TxType_MarketTx, count)
	b.StartTimer()
	// benchmark market tx serialize and unserialize.
	for i := 0; i < b.N; i++ {
		tx := txs.Txs[i%count]
		d, err := proto.Marshal(tx)
		if err != nil {
			b.Fatal(err)
		}
		ntx := new(nebulav1.Transaction)
		err = proto.Unmarshal(d, ntx)
		if ntx.TxType != tx.TxType {
			b.Fatal("unserialize tx type error")
		}
	}
}

func BenchmarkCancelTxSerialize(b *testing.B) {
	b.StopTimer()
	count := 100000
	txs := TestMakeTxs(nebulav1.TxType_CancelTx, count)
	b.StartTimer()
	// benchmark cancel tx serialize and unserialize.
	for i := 0; i < b.N; i++ {
		tx := txs.Txs[i%count]
		d, err := proto.Marshal(tx)
		if err != nil {
			b.Fatal(err)
		}
		ntx := new(nebulav1.Transaction)
		err = proto.Unmarshal(d, ntx)
		if ntx.TxType != tx.TxType {
			b.Fatal("unserialize tx type error")
		}
	}
}

func BenchmarkTxlistSerialize(b *testing.B) {
	b.StopTimer()
	count := 1000000
	txs := TestRandomTxs(count)
	b.StartTimer()
	// benchmark tx list serialize and unserialize.
	for i := 0; i < b.N; i++ {
		d, err := proto.Marshal(&txs)
		if err != nil {
			b.Fatal(err)
		}
		ntxs := new(nebulav1.TransactionList)
		err = proto.Unmarshal(d, ntxs)
		if len(ntxs.Txs) != len(txs.Txs) {
			b.Fatal("unserialize tx list error")
		}
	}
}

func BenchmarkBlockSerialize(b *testing.B) {
	// benchmark block serialize and unserialize.
	for i := 0; i < b.N; i++ {
		b.StopTimer()
		txcount := 100000
		block := TestMakeBlock(txcount)
		b.StartTimer()
		d, err := proto.Marshal(block)
		if err != nil {
			b.Fatal(err)
		}
		nblock := new(nebulav1.Block)
		err = proto.Unmarshal(d, nblock)
		if len(nblock.Transactions.Txs) != len(block.Transactions.Txs) {
			b.Fatal("unserialize block error")
		}
	}
}
