memguard/core/buffer_test.go
2019-07-25 23:01:20 +01:00

292 lines
6.2 KiB
Go

package core
import (
"bytes"
"testing"
"unsafe"
)
func TestNewBuffer(t *testing.T) {
// Check the error case with zero length.
b, err := NewBuffer(0)
if err != ErrNullBuffer {
t.Error("expected ErrNullBuffer; got", err)
}
if b != nil {
t.Error("expected nil buffer; got", b)
}
// Check the error case with negative length.
b, err = NewBuffer(-1)
if err != ErrNullBuffer {
t.Error("expected ErrNullBuffer; got", err)
}
if b != nil {
t.Error("expected nil buffer; got", b)
}
// Test normal execution.
b, err = NewBuffer(32)
if err != nil {
t.Error("expected nil err; got", err)
}
if !b.alive {
t.Error("did not expect destroyed buffer")
}
if len(b.Data()) != 32 || cap(b.Data()) != 32 {
t.Errorf("buffer has invalid length (%d) or capacity (%d)", len(b.Data()), cap(b.Data()))
}
if !b.mutable {
t.Error("buffer is not marked mutable")
}
if len(b.memory) != roundToPageSize(32)+(2*pageSize) {
t.Error("allocated incorrect length of memory")
}
if !bytes.Equal(b.Data(), make([]byte, 32)) {
t.Error("container is not zero-filled")
}
// Check if the buffer was added to the buffers list.
if !buffers.exists(b) {
t.Error("buffer not in buffers list")
}
// Destroy the buffer.
b.Destroy()
}
func TestLotsOfAllocs(t *testing.T) {
for i := 1; i <= 16385; i++ {
b, err := NewBuffer(i)
if err != nil {
t.Error(err)
}
if !b.alive || !b.mutable {
t.Error("invalid metadata")
}
if len(b.data) != i {
t.Error("invalid data length")
}
if len(b.memory) != roundToPageSize(i)+2*pageSize {
t.Error("memory length invalid")
}
if len(b.preguard) != pageSize || len(b.postguard) != pageSize {
t.Error("guard pages length invalid")
}
if len(b.canary) != len(b.inner)-i {
t.Error("canary length invalid")
}
if len(b.inner)%pageSize != 0 {
t.Error("inner length is not multiple of page size")
}
for j := range b.data {
b.data[j] = 1
}
for j := range b.data {
if b.data[j] != 1 {
t.Error("region rw test failed")
}
}
b.Destroy()
}
}
func TestData(t *testing.T) {
b, err := NewBuffer(32)
if err != nil {
t.Error(err)
}
datasegm := b.data
datameth := b.Data()
// Check for naive equality.
if !bytes.Equal(datasegm, datameth) {
t.Error("naive equality check failed")
}
// Modify and check if the change was reflected in both.
datameth[0] = 1
datameth[31] = 1
if !bytes.Equal(datasegm, datameth) {
t.Error("modified equality check failed")
}
// Do a deep comparison.
if uintptr(unsafe.Pointer(&datameth[0])) != uintptr(unsafe.Pointer(&datasegm[0])) {
t.Error("pointer values differ")
}
if len(datameth) != len(datasegm) || cap(datameth) != cap(datasegm) {
t.Error("length or capacity values differ")
}
b.Destroy()
if b.Data() != nil {
t.Error("expected nil data slice for destroyed buffer")
}
}
func TestBufferState(t *testing.T) {
b, err := NewBuffer(32)
if err != nil {
t.Error("expected nil err; got", err)
}
if b.Mutable() != true {
t.Error("state mismatch: mutability")
}
if b.Alive() != true {
t.Error("state mismatch: alive")
}
b.Freeze()
if b.Mutable() != false {
t.Error("state mismatch: mutability")
}
if b.Alive() != true {
t.Error("state mismatch: alive")
}
b.Melt()
if b.Mutable() != true {
t.Error("state mismatch: mutability")
}
if b.Alive() != true {
t.Error("state mismatch: alive")
}
b.Destroy()
if b.Mutable() != false {
t.Error("state mismatch: mutability")
}
if b.Alive() != false {
t.Error("state mismatch: alive")
}
}
func TestDestroy(t *testing.T) {
// Allocate a new buffer.
b, err := NewBuffer(32)
if err != nil {
t.Error("expected nil err; got", err)
}
// Destroy it.
b.Destroy()
// Pick apart the destruction.
if b.Data() != nil {
t.Error("expected bytes buffer to be nil; got", b.Data())
}
if b.memory != nil {
t.Error("expected memory to be nil; got", b.memory)
}
if b.mutable || b.alive {
t.Error("buffer should be dead and immutable")
}
if b.preguard != nil || b.postguard != nil {
t.Error("guard page slice references are not nil")
}
if b.inner != nil {
t.Error("inner pages slice reference not nil")
}
if b.canary != nil {
t.Error("canary slice reference not nil")
}
// Check if the buffer was removed from the buffers list.
if buffers.exists(b) {
t.Error("buffer is still in buffers list")
}
// Call destroy again to check idempotency.
b.Destroy()
// Verify that it didn't come back to life.
if b.Data() != nil {
t.Error("expected bytes buffer to be nil; got", b.Data())
}
if b.memory != nil {
t.Error("expected memory to be nil; got", b.memory)
}
if b.mutable || b.alive {
t.Error("buffer should be dead and immutable")
}
if b.preguard != nil || b.postguard != nil {
t.Error("guard page slice references are not nil")
}
if b.inner != nil {
t.Error("inner pages slice reference not nil")
}
if b.canary != nil {
t.Error("canary slice reference not nil")
}
}
func TestBufferList(t *testing.T) {
// Create a new BufferList for testing with.
l := new(bufferList)
// Create some example buffers to test with.
a := new(Buffer)
b := new(Buffer)
// Check what Exists is saying.
if l.exists(a) || l.exists(b) {
t.Error("list is empty yet contains buffers?!")
}
// Add our two buffers to the list.
l.add(a)
if len(l.list) != 1 || l.list[0] != a {
t.Error("buffer was not added correctly")
}
l.add(b)
if len(l.list) != 2 || l.list[1] != b {
t.Error("buffer was not added correctly")
}
// Now check that they exist.
if !l.exists(a) || !l.exists(b) {
t.Error("expected buffers to be in list")
}
// Remove the buffers from the list.
l.remove(a)
if len(l.list) != 1 || l.list[0] != b {
t.Error("buffer was not removed correctly")
}
l.remove(b)
if len(l.list) != 0 {
t.Error("item was not removed correctly")
}
// Check what exists is saying now.
if l.exists(a) || l.exists(b) {
t.Error("list is empty yet contains buffers?!")
}
// Add the buffers again to test Empty.
l.add(a)
l.add(b)
bufs := l.flush()
if l.list != nil {
t.Error("list was not nullified")
}
if len(bufs) != 2 || bufs[0] != a || bufs[1] != b {
t.Error("buffers dump incorrect")
}
// Try appending again.
l.add(a)
if !l.exists(a) || l.exists(b) {
t.Error("list is in invalid state")
}
l.remove(a)
}