jldb/fstore/store-harness_test.go

137 lines
2.6 KiB
Go
Raw Normal View History

2023-10-13 09:43:27 +00:00
package fstore
import (
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
)
func TestStoreHarness(t *testing.T) {
StoreTestHarness{}.Run(t)
}
type StoreTestHarness struct{}
func (h StoreTestHarness) Run(t *testing.T) {
val := reflect.ValueOf(h)
typ := val.Type()
for i := 0; i < typ.NumMethod(); i++ {
method := typ.Method(i)
if !strings.HasPrefix(method.Name, "Test") {
continue
}
t.Run(method.Name, func(t *testing.T) {
t.Parallel()
rootDir := t.TempDir()
primary, err := Open(Config{
RootDir: rootDir,
Primary: true,
WALSegMinCount: 1,
WALSegMaxAgeSec: 1,
WALSegGCAgeSec: 2,
})
if err != nil {
t.Fatal(err)
}
defer primary.Close()
mux := http.NewServeMux()
mux.HandleFunc("/rep/", primary.Handle)
testServer := httptest.NewServer(mux)
defer testServer.Close()
rootDir2 := t.TempDir()
secondary, err := Open(Config{
RootDir: rootDir2,
Primary: false,
PrimaryEndpoint: testServer.URL + "/rep/",
})
if err != nil {
t.Fatal(err)
}
defer secondary.Close()
val.MethodByName(method.Name).Call([]reflect.Value{
reflect.ValueOf(t),
reflect.ValueOf(primary),
reflect.ValueOf(secondary),
})
})
}
}
func (StoreTestHarness) TestBasic(t *testing.T, primary, secondary *Store) {
stateChan := make(chan map[string]string, 1)
go func() {
stateChan <- primary.WriteRandomFor(4 * time.Second)
}()
state := <-stateChan
secondary.WaitForParity(primary)
primary.AssertState(t, state)
secondary.AssertState(t, state)
}
func (StoreTestHarness) TestWriteThenFollow(t *testing.T, primary, secondary *Store) {
secondary.Close()
stateChan := make(chan map[string]string, 1)
go func() {
stateChan <- primary.WriteRandomFor(4 * time.Second)
}()
state := <-stateChan
var err error
secondary, err = Open(secondary.conf)
if err != nil {
t.Fatal(err)
}
secondary.WaitForParity(primary)
primary.AssertState(t, state)
secondary.AssertState(t, state)
}
func (StoreTestHarness) TestCloseAndOpenFollowerConcurrently(t *testing.T, primary, secondary *Store) {
secondary.Close()
stateChan := make(chan map[string]string, 1)
go func() {
stateChan <- primary.WriteRandomFor(8 * time.Second)
}()
var err error
for i := 0; i < 4; i++ {
time.Sleep(time.Second)
secondary, err = Open(secondary.conf)
if err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
secondary.Close()
}
secondary, err = Open(secondary.conf)
if err != nil {
t.Fatal(err)
}
state := <-stateChan
secondary.WaitForParity(primary)
primary.AssertState(t, state)
secondary.AssertState(t, state)
}