package sm2

import (
	"fmt"
	"io"
	"testing"
	"time"

	"xdx.jelly/xgcl/grand"
)

// Sign 50000, used time: 1085 ms, 46082 pcs/s
// verify 50000, used time: 3368 ms, 14845 pcs/s
func TestSpeedSign(t *testing.T) {
	e := grand.GetRandom(ByteSize())
	k := grand.GetRandom(ByteSize())
	buf := grand.GetRandom(ByteSize())
	d, _ := GenPrivateKey(buf)

	var sig *Signature
	cnt := 50000
	start := time.Now()
	for i := 0; i < cnt; i++ {
		sig, _ = Sign(e, k, d)
	}
	end := time.Now()
	elapsed := end.Sub(start)
	fmt.Printf("Sign %d, used time: %d ms, %d pcs/s\n", cnt, elapsed.Milliseconds(), int(float64(cnt)/float64(elapsed.Milliseconds())*1000))

	pk := GenPublicKey(d)

	start = time.Now()
	for i := 0; i < cnt; i++ {
		_ = Verify(e, pk, sig)
	}
	end = time.Now()
	elapsed = end.Sub(start)
	fmt.Printf("verify %d, used time: %d ms, %d pcs/s\n", cnt, elapsed.Milliseconds(), int(float64(cnt)/float64(elapsed.Milliseconds())*1000))

}

func TestSpeedEnc(t *testing.T) {
	fmt.Println("SM2加密性能测试")
	for i := 0; i < 3; i++ {
		fmt.Printf("第%d次测试: \n", i+1)
		sk, err := GenerateKey(Curve(), grand.Reader)
		if err != nil {
			t.Fatal(err)
		}
		pk := &sk.PublicKey
		data := make([]byte, 128*1024)
		if _, err := io.ReadFull(grand.Reader, data); err != nil {
			t.Fatal(err)
		}

		cnt := 8000
		start := time.Now()
		for i := 0; i < cnt; i++ {
			cipher, err := Encrypt(pk, data, grand.GetRandom(32))
			if err != nil {
				t.Fatal(err)
			}
			_ = cipher
		}
		end := time.Now()
		elapsed := end.Sub(start)
		fmt.Printf("加密数据: %dKB\n", len(data)/1024)
		fmt.Printf("循环次数: %d\n", cnt)
		fmt.Printf("耗时时间(秒): %f\n", float64(elapsed.Seconds()))
		fmt.Printf("加密速率: %.2f Kbps\n", float64(8*len(data)*cnt)/(1024*elapsed.Seconds()))
		fmt.Println()
	}
}

func TestSpeedDec(t *testing.T) {
	fmt.Println("")
	fmt.Println("SM2: 解密性能测试")
	fmt.Println("测试结果: ")
	fmt.Println("")
	sk, err := GenerateKey(Curve(), grand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	pk := &sk.PublicKey

	data := make([]byte, 128*1024)
	if _, err := io.ReadFull(grand.Reader, data); err != nil {
		t.Fatal(err)
	}

	cipher, _ := Encrypt(pk, data, grand.GetRandom(32))
	cnt := 1000
	start := time.Now()
	for i := 0; i < cnt; i++ {
		decryptedData, err := Decrypt(sk, cipher)
		if err != nil {
			t.Fatal(err)
		}
		_ = decryptedData
	}
	end := time.Now()
	elapsed := end.Sub(start)
	fmt.Printf("解密数据: %dKB\n", len(data)/1024)
	fmt.Printf("解密结果: 成功\n")
	fmt.Printf("耗时时间(单位: 秒): %f\n", float64(elapsed.Seconds())/float64(cnt))
	fmt.Printf("解密速率: %f Mbps\n", float64(8*len(data)*cnt)/(1024*1024*elapsed.Seconds()))
	fmt.Println()

}
