jldb/lib/atomicheader/atomicheader_test.go

122 lines
1.8 KiB
Go

package atomicheader
import (
"errors"
"os"
"path/filepath"
"sync"
"testing"
"time"
)
func NewForTesting(t *testing.T) (*Handler, func()) {
tmpDir := t.TempDir()
f, err := os.Create(filepath.Join(tmpDir, "h"))
if err != nil {
t.Fatal(err)
}
if err := Init(f); err != nil {
t.Fatal(err)
}
h, err := Open(f)
if err != nil {
t.Fatal(err)
}
return h, func() {
f.Close()
os.RemoveAll(tmpDir)
}
}
func TestAtomicHeaderSimple(t *testing.T) {
h, cleanup := NewForTesting(t)
defer cleanup()
err := h.Write(func(page []byte) error {
for i := range page[:AvailabePageSize] {
page[i] = byte(i) % 11
}
return nil
})
if err != nil {
t.Fatal(err)
}
err = h.Read(func(page []byte) error {
for i := range page[:AvailabePageSize] {
if page[i] != byte(i)%11 {
t.Fatal(i, page[i], byte(i)%11)
}
}
return nil
})
if err != nil {
t.Fatal(err)
}
}
func TestAtomicHeaderThreaded(t *testing.T) {
h, cleanup := NewForTesting(t)
defer cleanup()
expectedValue := byte(0)
writeErr := make(chan error, 1)
stop := make(chan struct{})
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case <-stop:
writeErr <- nil
return
default:
}
err := h.Write(func(page []byte) error {
if page[0] != expectedValue {
return errors.New("Unexpected current value.")
}
expectedValue++
page[0] = expectedValue
return nil
})
if err != nil {
writeErr <- err
return
}
time.Sleep(time.Millisecond / 13)
}
}()
for i := 0; i < 2000; i++ {
time.Sleep(time.Millisecond)
err := h.Read(func(page []byte) error {
if page[0] != expectedValue {
t.Fatal(page[0], expectedValue)
}
return nil
})
if err != nil {
t.Fatal(err)
}
}
close(stop)
wg.Wait()
if err := <-writeErr; err != nil {
t.Fatal(err)
}
}