From e329c0ef3361d7aa3ce9e2d443b272836dcca568 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 10:46:17 +1100 Subject: [PATCH 1/2] Add a test for OutMessage.Reset. --- internal/buffer/out_message_test.go | 60 +++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/internal/buffer/out_message_test.go b/internal/buffer/out_message_test.go index 80d9485..a209617 100644 --- a/internal/buffer/out_message_test.go +++ b/internal/buffer/out_message_test.go @@ -4,16 +4,47 @@ import ( "crypto/rand" "fmt" "io" + "reflect" "testing" "unsafe" ) +func toByteSlice(p unsafe.Pointer, n int) []byte { + sh := reflect.SliceHeader{ + Data: uintptr(p), + Len: n, + Cap: n, + } + + return *(*[]byte)(unsafe.Pointer(&sh)) +} + +// fillWithGarbage writes random data to [p, p+n). +func fillWithGarbage(p unsafe.Pointer, n int) (err error) { + b := toByteSlice(p, n) + _, err = io.ReadFull(rand.Reader, b) + return +} + func randBytes(n int) (b []byte, err error) { b = make([]byte, n) _, err = io.ReadFull(rand.Reader, b) return } +// findNonZero finds the offset of the first non-zero byte in [p, p+n). If +// none, it returns n. +func findNonZero(p unsafe.Pointer, n int) int { + b := toByteSlice(p, n) + for i, x := range b { + if x != 0 { + return i + } + } + + return n +} + func TestMemclr(t *testing.T) { // All sizes up to 32 bytes. var sizes []int @@ -48,15 +79,36 @@ func TestMemclr(t *testing.T) { memclr(p, uintptr(len(b))) // Check - for i, x := range b { - if x != 0 { - t.Fatalf("non-zero byte %d at offset %d", x, i) - } + if i := findNonZero(p, len(b)); i != len(b) { + t.Fatalf("non-zero byte at offset %d", i) } }) } } +func TestOutMessageReset(t *testing.T) { + var om OutMessage + h := om.OutHeader() + + const trials = 100 + for i := 0; i < trials; i++ { + fillWithGarbage(unsafe.Pointer(h), int(unsafe.Sizeof(*h))) + + om.Reset() + if h.Len != 0 { + t.Fatalf("non-zero Len %v", h.Len) + } + + if h.Error != 0 { + t.Fatalf("non-zero Error %v", h.Error) + } + + if h.Unique != 0 { + t.Fatalf("non-zero Unique %v", h.Unique) + } + } +} + func BenchmarkOutMessageReset(b *testing.B) { // A single buffer, which should fit in some level of CPU cache. b.Run("Single buffer", func(b *testing.B) { From ad6584934652526a1757dd2e4c8ce4f4ea0a8773 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 10:51:23 +1100 Subject: [PATCH 2/2] Add a test for OutMessage.Grow. --- internal/buffer/out_message_test.go | 31 ++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/buffer/out_message_test.go b/internal/buffer/out_message_test.go index a209617..81b0192 100644 --- a/internal/buffer/out_message_test.go +++ b/internal/buffer/out_message_test.go @@ -92,7 +92,10 @@ func TestOutMessageReset(t *testing.T) { const trials = 100 for i := 0; i < trials; i++ { - fillWithGarbage(unsafe.Pointer(h), int(unsafe.Sizeof(*h))) + err := fillWithGarbage(unsafe.Pointer(h), int(unsafe.Sizeof(*h))) + if err != nil { + t.Fatalf("fillWithGarbage: %v", err) + } om.Reset() if h.Len != 0 { @@ -109,6 +112,32 @@ func TestOutMessageReset(t *testing.T) { } } +func TestOutMessageGrow(t *testing.T) { + var om OutMessage + + // Overwrite with garbage. + err := fillWithGarbage(unsafe.Pointer(&om), int(unsafe.Sizeof(om))) + if err != nil { + t.Fatalf("fillWithGarbage: %v", err) + } + + // Zero the header. + om.Reset() + + // Grow to the max size. This should zero the message. + if p := om.Grow(MaxReadSize); p == nil { + t.Fatal("Grow returned nil") + } + + // Check that everything has been zeroed. + b := om.Bytes() + for i, x := range b { + if x != 0 { + t.Fatalf("non-zero byte 0x%02x at offset %d", x, i) + } + } +} + func BenchmarkOutMessageReset(b *testing.B) { // A single buffer, which should fit in some level of CPU cache. b.Run("Single buffer", func(b *testing.B) {