tests: add locker and math tests
This commit is contained in:
@@ -21,8 +21,9 @@ type diskStore struct {
|
||||
|
||||
var _ driver.Driver = (*diskStore)(nil)
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
func Init(ctx context.Context) error {
|
||||
es.Register(ctx, "file", &diskStore{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (diskStore) Open(dsn string) (driver.EventStore, error) {
|
||||
@@ -143,7 +144,7 @@ func (es *diskStore) Load(ctx context.Context, agg event.Aggregate) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events[i], err = event.UnmarshalText(b, first+i)
|
||||
events[i], err = event.UnmarshalText(ctx, b, first+i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -193,7 +194,7 @@ func (es *diskStore) Read(ctx context.Context, streamID string, pos, count int64
|
||||
if err != nil {
|
||||
return events, err
|
||||
}
|
||||
events[i], err = event.UnmarshalText(b, start)
|
||||
events[i], err = event.UnmarshalText(ctx, b, start)
|
||||
if err != nil {
|
||||
return events, err
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ type config struct {
|
||||
}
|
||||
|
||||
var (
|
||||
Config = locker.New(&config{drivers: make(map[string]driver.Driver)})
|
||||
drivers = locker.New(&config{drivers: make(map[string]driver.Driver)})
|
||||
)
|
||||
|
||||
func Register(ctx context.Context, name string, d driver.Driver) {
|
||||
Config.Modify(ctx, func(c *config) error {
|
||||
func Register(ctx context.Context, name string, d driver.Driver) error {
|
||||
return drivers.Modify(ctx, func(c *config) error {
|
||||
if _, set := c.drivers[name]; set {
|
||||
return fmt.Errorf("driver %s already set", name)
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func Open(ctx context.Context, dsn string) (driver.EventStore, error) {
|
||||
}
|
||||
|
||||
var d driver.Driver
|
||||
Config.Modify(ctx,func(c *config) error {
|
||||
drivers.Modify(ctx,func(c *config) error {
|
||||
var ok bool
|
||||
d, ok = c.drivers[name]
|
||||
if !ok {
|
||||
|
||||
@@ -6,47 +6,42 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/matryer/is"
|
||||
|
||||
"github.com/sour-is/ev/pkg/es"
|
||||
memstore "github.com/sour-is/ev/pkg/es/driver/mem-store"
|
||||
"github.com/sour-is/ev/pkg/es/event"
|
||||
)
|
||||
|
||||
func TestES(t *testing.T) {
|
||||
is := is.New(t)
|
||||
ctx := context.Background()
|
||||
|
||||
event.Register(&ValueSet{})
|
||||
err := event.Register(ctx, &ValueSet{})
|
||||
is.NoErr(err)
|
||||
|
||||
memstore.Init(ctx)
|
||||
|
||||
es, err := es.Open(ctx, "mem:")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
is.NoErr(err)
|
||||
|
||||
thing := &Thing{Name: "time"}
|
||||
err = es.Load(ctx, thing)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
is.NoErr(err)
|
||||
|
||||
t.Log(thing.StreamVersion(), thing.Name, thing.Value)
|
||||
|
||||
err = thing.OnSetValue(time.Now().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
is.NoErr(err)
|
||||
|
||||
i, err := es.Save(ctx, thing)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
is.NoErr(err)
|
||||
|
||||
t.Log(thing.StreamVersion(), thing.Name, thing.Value)
|
||||
t.Log("Wrote: ", i)
|
||||
|
||||
events, err := es.Read(ctx, "thing-time", -1, -11)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
is.NoErr(err)
|
||||
|
||||
for i, e := range events {
|
||||
t.Logf("event %d %d - %v\n", i, e.EventMeta().Position, e)
|
||||
|
||||
@@ -2,6 +2,7 @@ package event_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/matryer/is"
|
||||
@@ -30,8 +31,10 @@ func (e *DummyEvent) SetEventMeta(eventMeta event.Meta) {
|
||||
|
||||
func TestEventEncode(t *testing.T) {
|
||||
is := is.New(t)
|
||||
ctx := context.Background()
|
||||
|
||||
event.Register(&DummyEvent{})
|
||||
err := event.Register(ctx, &DummyEvent{})
|
||||
is.NoErr(err)
|
||||
|
||||
var lis event.Events = event.NewEvents(
|
||||
&DummyEvent{Value: "testA"},
|
||||
@@ -50,7 +53,7 @@ func TestEventEncode(t *testing.T) {
|
||||
is.Equal(string(sp[2]), "event_test.DummyEvent")
|
||||
}
|
||||
|
||||
chk, err := event.DecodeEvents(blis...)
|
||||
chk, err := event.DecodeEvents(ctx, blis...)
|
||||
is.NoErr(err)
|
||||
|
||||
for i := range chk {
|
||||
|
||||
@@ -2,6 +2,7 @@ package event
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -9,11 +10,16 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sour-is/ev/pkg/locker"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
eventTypes map[string]reflect.Type
|
||||
}
|
||||
|
||||
var (
|
||||
eventTypes sync.Map
|
||||
eventTypes = locker.New(&config{eventTypes: make(map[string]reflect.Type)})
|
||||
)
|
||||
|
||||
type UnknownEvent struct {
|
||||
@@ -63,35 +69,56 @@ func (u *UnknownEvent) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
// Register a type container for Unmarshalling values into. The type must implement Event and not be a nil value.
|
||||
func Register(lis ...Event) {
|
||||
func Register(ctx context.Context, lis ...Event) error {
|
||||
for _, e := range lis {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
if e == nil {
|
||||
panic(fmt.Sprintf("can't register event.Event of type=%T with value=%v", e, e))
|
||||
return fmt.Errorf("can't register event.Event of type=%T with value=%v", e, e)
|
||||
}
|
||||
|
||||
value := reflect.ValueOf(e)
|
||||
|
||||
if value.IsNil() {
|
||||
panic(fmt.Sprintf("can't register event.Event of type=%T with value=%v", e, e))
|
||||
return fmt.Errorf("can't register event.Event of type=%T with value=%v", e, e)
|
||||
}
|
||||
|
||||
value = reflect.Indirect(value)
|
||||
|
||||
name := TypeOf(e)
|
||||
typ := value.Type()
|
||||
|
||||
eventTypes.LoadOrStore(TypeOf(e), typ)
|
||||
}
|
||||
}
|
||||
func GetContainer(s string) Event {
|
||||
if typ, ok := eventTypes.Load(s); ok {
|
||||
if typ, ok := typ.(reflect.Type); ok {
|
||||
newType := reflect.New(typ)
|
||||
newInterface := newType.Interface()
|
||||
if typ, ok := newInterface.(Event); ok {
|
||||
return typ
|
||||
}
|
||||
if err := eventTypes.Modify(ctx, func(c *config) error {
|
||||
c.eventTypes[name] = typ
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return &UnknownEvent{eventType: s}
|
||||
return nil
|
||||
}
|
||||
func GetContainer(ctx context.Context, s string) Event {
|
||||
var e Event
|
||||
|
||||
eventTypes.Modify(ctx, func(c *config) error {
|
||||
typ, ok := c.eventTypes[s]
|
||||
if !ok {
|
||||
return fmt.Errorf("not defined")
|
||||
}
|
||||
newType := reflect.New(typ)
|
||||
newInterface := newType.Interface()
|
||||
if iface, ok := newInterface.(Event); ok {
|
||||
e = iface
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed")
|
||||
})
|
||||
if e == nil {
|
||||
e = &UnknownEvent{eventType: s}
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func MarshalText(e Event) (txt []byte, err error) {
|
||||
@@ -123,7 +150,7 @@ func MarshalText(e Event) (txt []byte, err error) {
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
func UnmarshalText(txt []byte, pos uint64) (e Event, err error) {
|
||||
func UnmarshalText(ctx context.Context, txt []byte, pos uint64) (e Event, err error) {
|
||||
sp := bytes.SplitN(txt, []byte{'\t'}, 4)
|
||||
if len(sp) != 4 {
|
||||
return nil, fmt.Errorf("invalid format. expected=4, got=%d", len(sp))
|
||||
@@ -138,7 +165,7 @@ func UnmarshalText(txt []byte, pos uint64) (e Event, err error) {
|
||||
m.Position = pos
|
||||
|
||||
eventType := string(sp[2])
|
||||
e = GetContainer(eventType)
|
||||
e = GetContainer(ctx, eventType)
|
||||
|
||||
if enc, ok := e.(encoding.TextUnmarshaler); ok {
|
||||
if err = enc.UnmarshalText(sp[3]); err != nil {
|
||||
@@ -163,12 +190,12 @@ func writeMarshaler(out io.Writer, in encoding.TextMarshaler) (int, error) {
|
||||
}
|
||||
|
||||
// DecodeEvents unmarshals the byte list into Events.
|
||||
func DecodeEvents(lis ...[]byte) (Events, error) {
|
||||
func DecodeEvents(ctx context.Context, lis ...[]byte) (Events, error) {
|
||||
elis := make([]Event, len(lis))
|
||||
|
||||
var err error
|
||||
for i, txt := range lis {
|
||||
elis[i], err = UnmarshalText(txt, uint64(i))
|
||||
elis[i], err = UnmarshalText(ctx, txt, uint64(i))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user