mirror of
https://github.com/awnumar/memguard.git
synced 2026-02-06 17:59:49 +00:00
Memcall is not touched yet. Otherwise this replaces sentinel error values with IsX exported predicate functions. This enables more effective error handling by the users and leaves much more freedom for changing the implementation in the future without breaking API. Updates #111
191 lines
3.9 KiB
Go
191 lines
3.9 KiB
Go
package core
|
|
|
|
import (
|
|
"bytes"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestSetInterval(t *testing.T) {
|
|
if atomic.LoadUint64(&Interval) != 8 {
|
|
t.Error("default should be 8ms")
|
|
}
|
|
SetInterval(500)
|
|
if atomic.LoadUint64(&Interval) != 500 {
|
|
t.Error("value did not update")
|
|
}
|
|
SetInterval(8)
|
|
}
|
|
|
|
func TestNewCoffer(t *testing.T) {
|
|
s := NewCoffer()
|
|
|
|
// Attain a lock to halt the verify & rekey cycle.
|
|
s.RLock()
|
|
|
|
// Verify that fields are not nil.
|
|
if s.left == nil || s.right == nil {
|
|
t.Error("one or more fields are not initialised")
|
|
}
|
|
|
|
// Verify that fields are the expected sizes.
|
|
if len(s.left.Data()) != 32 {
|
|
t.Error("left side has unexpected lengths")
|
|
}
|
|
if len(s.right.Data()) != 32 {
|
|
t.Error("right size has unexpected lengths")
|
|
}
|
|
|
|
// Verify that the data fields are not zeroed.
|
|
if bytes.Equal(s.left.Data(), make([]byte, 32)) {
|
|
t.Error("left side is zeroed")
|
|
}
|
|
if bytes.Equal(s.right.Data(), make([]byte, 32)) {
|
|
t.Error("right side is zeroed")
|
|
}
|
|
|
|
s.RUnlock() // Release mutex to allow destruction.
|
|
s.Destroy()
|
|
}
|
|
|
|
func TestCofferInitialise(t *testing.T) {
|
|
s := NewCoffer()
|
|
|
|
// Get the value stored inside.
|
|
view, err := s.View()
|
|
if err != nil {
|
|
t.Error("unexpected error")
|
|
}
|
|
value := make([]byte, 32)
|
|
copy(value, view.Data())
|
|
view.Destroy()
|
|
|
|
// Re-initialise the buffer with a new value.
|
|
if err := s.Initialise(); err != nil {
|
|
t.Error("unexpected error;", err)
|
|
}
|
|
|
|
// Get the new value stored inside.
|
|
view, err = s.View()
|
|
if err != nil {
|
|
t.Error("unexpected error")
|
|
}
|
|
newValue := make([]byte, 32)
|
|
copy(newValue, view.Data())
|
|
view.Destroy()
|
|
|
|
// Compare them.
|
|
if bytes.Equal(value, newValue) {
|
|
t.Error("value was not refreshed")
|
|
}
|
|
|
|
s.Destroy()
|
|
|
|
// Check error condition.
|
|
if err := s.Initialise(); !IsCofferExpired(err) {
|
|
t.Error("expected ErrCofferExpired; got", err)
|
|
}
|
|
}
|
|
|
|
func TestCofferView(t *testing.T) {
|
|
s := NewCoffer()
|
|
|
|
// Get the value stored inside.
|
|
view, err := s.View()
|
|
if err != nil {
|
|
t.Error("unexpected error")
|
|
}
|
|
if view == nil {
|
|
t.Error("returned object is nil")
|
|
}
|
|
|
|
// Some sanity checks on the inner value.
|
|
if view.Data() == nil || len(view.Data()) != 32 {
|
|
t.Error("unexpected data; got", view.Data())
|
|
}
|
|
if bytes.Equal(view.Data(), make([]byte, 32)) {
|
|
t.Error("value inside coffer is zero")
|
|
}
|
|
|
|
// Destroy our temporary view of the coffer's contents.
|
|
view.Destroy()
|
|
|
|
s.Destroy()
|
|
|
|
// Check error condition.
|
|
view, err = s.View()
|
|
if !IsCofferExpired(err) {
|
|
t.Error("expected ErrCofferExpired; got", err)
|
|
}
|
|
if view != nil {
|
|
t.Error("expected nil buffer object")
|
|
}
|
|
}
|
|
|
|
func TestCofferRekey(t *testing.T) {
|
|
s := NewCoffer()
|
|
|
|
// Halt the rekey cycle.
|
|
s.RLock()
|
|
|
|
// Remember the value stored inside.
|
|
view, err := s.View()
|
|
if err != nil {
|
|
t.Error("unexpected error;", err)
|
|
}
|
|
orgValue := make([]byte, 32)
|
|
copy(orgValue, view.Data())
|
|
view.Destroy()
|
|
|
|
// Remember the value of the partitions.
|
|
left := make([]byte, 32)
|
|
right := make([]byte, 32)
|
|
copy(left, s.left.Data())
|
|
copy(right, s.right.Data())
|
|
|
|
// Manually re-key before we continue.
|
|
s.RUnlock()
|
|
s.Rekey()
|
|
s.RLock()
|
|
|
|
// Get another view of the contents.
|
|
view, err = s.View()
|
|
if err != nil {
|
|
t.Error("unexpected error;", err)
|
|
}
|
|
newValue := make([]byte, 32)
|
|
copy(newValue, view.Data())
|
|
view.Destroy()
|
|
|
|
// Compare the values.
|
|
if !bytes.Equal(orgValue, newValue) {
|
|
t.Error("value inside coffer changed!!")
|
|
}
|
|
|
|
// Compare the partition values.
|
|
if bytes.Equal(left, s.left.Data()) || bytes.Equal(right, s.right.Data()) {
|
|
t.Error("partition values did not change")
|
|
}
|
|
|
|
s.RUnlock() // Release lock to allow destruction.
|
|
s.Destroy()
|
|
|
|
if err := s.Rekey(); !IsCofferExpired(err) {
|
|
t.Error("expected ErrCofferExpired; got", err)
|
|
}
|
|
}
|
|
|
|
func TestCofferDestroy(t *testing.T) {
|
|
s := NewCoffer()
|
|
s.Destroy()
|
|
|
|
// Check metadata flags.
|
|
if !s.Destroyed() {
|
|
t.Error("expected destroyed")
|
|
}
|
|
|
|
// Check both partitions are destroyed.
|
|
if s.left.alive || s.right.alive {
|
|
t.Error("some partition not destroyed")
|
|
}
|
|
}
|