Files
fastxor/xor_test.go
2018-10-11 17:48:17 -04:00

200 lines
3.7 KiB
Go

package fastxor
import (
"bytes"
"testing"
"testing/quick"
)
func refBytes(dst, a, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
if len(dst) < n {
n = len(dst)
}
for i := 0; i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
}
func refByte(dst, a []byte, b byte) int {
n := len(a)
if len(dst) < n {
n = len(dst)
}
for i := 0; i < n; i++ {
dst[i] = a[i] ^ b
}
return n
}
func refBlock(dst, a, b []byte) {
_ = dst[15]
_ = a[15]
_ = b[15]
dst[0] = a[0] ^ b[0]
dst[1] = a[1] ^ b[1]
dst[2] = a[2] ^ b[2]
dst[3] = a[3] ^ b[3]
dst[4] = a[4] ^ b[4]
dst[5] = a[5] ^ b[5]
dst[6] = a[6] ^ b[6]
dst[7] = a[7] ^ b[7]
dst[8] = a[8] ^ b[8]
dst[9] = a[9] ^ b[9]
dst[10] = a[10] ^ b[10]
dst[11] = a[11] ^ b[11]
dst[12] = a[12] ^ b[12]
dst[13] = a[13] ^ b[13]
dst[14] = a[14] ^ b[14]
dst[15] = a[15] ^ b[15]
}
func TestBytes(t *testing.T) {
err := quick.Check(func(a, b []byte) bool {
// quadruple size to increase coverage
a = append(a, a...)
a = append(a, a...)
b = append(b, b...)
b = append(b, b...)
if len(a) < 8 {
return true
}
// shift alignment randomly
a = a[(a[0] % 8):]
dst1 := make([]byte, len(a))
dst2 := make([]byte, len(a))
Bytes(dst1, a, b)
refBytes(dst2, a, b)
return bytes.Equal(dst1, dst2)
}, &quick.Config{MaxCount: 10000})
if err != nil {
t.Error(err)
}
// test a large slice
a := make([]byte, 512-1)
for i := range a {
a[i] = byte(i)
}
Bytes(a, a, a)
if !bytes.Equal(a, make([]byte, len(a))) {
t.Error("bad xor of large slice")
}
}
func TestByte(t *testing.T) {
err := quick.Check(func(a []byte, b byte) bool {
if len(a) < 8 {
return true
}
// shift alignment randomly
a = a[(a[0] % 8):]
dst1 := make([]byte, len(a))
dst2 := make([]byte, len(a))
Byte(dst1, a, b)
refByte(dst2, a, b)
return bytes.Equal(dst1, dst2)
}, &quick.Config{MaxCount: 10000})
if err != nil {
t.Fatal(err)
}
}
func TestBlock(t *testing.T) {
err := quick.Check(func(a, b [16]byte) bool {
dst1 := make([]byte, len(a))
dst2 := make([]byte, len(a))
Block(dst1, a[:], b[:])
refBlock(dst2, a[:], b[:])
return bytes.Equal(dst1, dst2)
}, &quick.Config{MaxCount: 10000})
if err != nil {
t.Fatal(err)
}
}
func BenchmarkBytes(b *testing.B) {
benchN := func(n int) func(*testing.B) {
return func(b *testing.B) {
buf := make([]byte, n)
b.SetBytes(int64(len(buf)))
for i := 0; i < b.N; i++ {
Bytes(buf, buf, buf)
}
}
}
b.Run("16", benchN(16))
b.Run("1024", benchN(1024))
b.Run("65k", benchN(65536))
}
func BenchmarkRefBytes(b *testing.B) {
benchN := func(n int) func(*testing.B) {
return func(b *testing.B) {
buf := make([]byte, n)
b.SetBytes(int64(len(buf)))
for i := 0; i < b.N; i++ {
refBytes(buf, buf, buf)
}
}
}
b.Run("16", benchN(16))
b.Run("1024", benchN(1024))
b.Run("65k", benchN(65536))
}
func BenchmarkByte(b *testing.B) {
benchN := func(n int) func(*testing.B) {
return func(b *testing.B) {
buf := make([]byte, n)
b.SetBytes(int64(len(buf)))
for i := 0; i < b.N; i++ {
Byte(buf, buf, 'b')
}
}
}
b.Run("16", benchN(16))
b.Run("1024", benchN(1024))
b.Run("65k", benchN(65536))
}
func BenchmarkRefByte(b *testing.B) {
benchN := func(n int) func(*testing.B) {
return func(b *testing.B) {
buf := make([]byte, n)
b.SetBytes(int64(len(buf)))
for i := 0; i < b.N; i++ {
refByte(buf, buf, 'b')
}
}
}
b.Run("16", benchN(16))
b.Run("1024", benchN(1024))
b.Run("65k", benchN(65536))
}
func BenchmarkBlock(b *testing.B) {
dst := make([]byte, 16)
bufA := make([]byte, 16)
bufB := make([]byte, 16)
b.SetBytes(16)
for i := 0; i < b.N; i++ {
Block(dst, bufA, bufB)
}
}
func BenchmarkRefBlock(b *testing.B) {
buf := make([]byte, 16)
b.SetBytes(16)
for i := 0; i < b.N; i++ {
refBlock(buf, buf, buf)
}
}