package sm4

import (
	"crypto/rand"
	"fmt"
	"testing"
	"time"
)

func TestSBox8(t *testing.T) {
	// Generate the sbox8
	sbox8 := make([]uint32, 256)
	for i := 0; i < 256; i++ {
		sbox8[i] = l(uint32(sbox[i]))
	}

	for i := 0; i < 256; i++ {
		fmt.Printf("0x%08x ", sbox8[i])
		if i > 0 && (i+1)%8 == 0 {
			fmt.Println()
		}
	}
}

func TestSBox16(t *testing.T) {
	for i := uint32(0); i < 0xffffffff; i++ {
		if lt(i) != l(tau(i)) {
			panic(fmt.Sprintf("lt(%x) != l(tau(%x))", i, i))
		}
	}
}
func BenchmarkBlock(b *testing.B) {
	var data, dst [16]byte
	var key [16]byte
	rand.Read(key[:])
	rand.Read(data[:])
	block, _ := NewCipher(key[:])

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		block.Encrypt(dst[:], data[:])
	}
	b.StopTimer()
}

func TestBlockSpeed(t *testing.T) {
	var dst, data [16 * 1000]byte
	var key [16]byte
	rand.Read(key[:])
	rand.Read(data[:])
	b, _ := NewCipher(key[:])

	times := 10000
	start := time.Now()
	for i := 0; i < times; i++ {
		for j := 0; j < len(data); j += 16 {
			b.Encrypt(data[j:], data[j:])
			// b.Encrypt(dst[j:], data[j:])
		}
	}
	end := time.Now()
	elapsed := end.Sub(start)
	t.Log("SM4 Encrypt Block: ", int(float64(times*len(data))/float64(1024*1024)/elapsed.Seconds()), "MBps")

	start = time.Now()
	for i := 0; i < times; i++ {
		for j := 0; j < 16*1000; j += 16 {
			// b.Decrypt(data[j:], data[j:])
			b.Decrypt(data[j:], dst[j:])
		}
	}
	end = time.Now()
	elapsed = end.Sub(start)
	t.Log("SM4 Encrypt Block: ", int(float64(times*len(data))/float64(1024*1024)/elapsed.Seconds()), "MBps")
}

func TestBlock(t *testing.T) {
	data := make([]byte, 16)

	encKey := make([]uint32, 32)
	decKey := make([]uint32, 32)
	expandKeyGo([]byte("1234567812345678"), encKey, decKey)
	for i := 0; i < 1000; i++ {
		encryptBlockGo(encKey, data, data)
	}

	fmt.Printf("Key:")
	for i := 0; i < 32; i++ {
		fmt.Printf("0x%08x, ", encKey[i])
	}
	fmt.Printf("cipher:")
	for i := 0; i < 16; i++ {
		fmt.Printf("%02x", data[i])
	}

}
