137 lines
2.6 KiB
Go
137 lines
2.6 KiB
Go
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)
|
|
}
|