2023-01-09 11:30:02 -07:00
|
|
|
package ev_test
|
2022-08-04 14:37:51 -06:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-08-14 10:56:00 -06:00
|
|
|
"encoding/json"
|
2022-08-12 15:53:16 -06:00
|
|
|
"errors"
|
2022-08-04 14:37:51 -06:00
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-08-06 09:52:36 -06:00
|
|
|
"github.com/matryer/is"
|
2022-12-19 10:50:38 -07:00
|
|
|
"go.uber.org/multierr"
|
2022-08-06 09:52:36 -06:00
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
"github.com/sour-is/ev"
|
2022-12-19 10:50:38 -07:00
|
|
|
"github.com/sour-is/ev/app/peerfinder"
|
2022-08-04 21:07:10 -06:00
|
|
|
memstore "github.com/sour-is/ev/pkg/es/driver/mem-store"
|
2022-09-06 15:31:48 -06:00
|
|
|
"github.com/sour-is/ev/pkg/es/driver/projecter"
|
2022-12-19 10:50:38 -07:00
|
|
|
resolvelinks "github.com/sour-is/ev/pkg/es/driver/resolve-links"
|
2022-09-06 15:31:48 -06:00
|
|
|
"github.com/sour-is/ev/pkg/es/driver/streamer"
|
2022-08-04 14:37:51 -06:00
|
|
|
"github.com/sour-is/ev/pkg/es/event"
|
|
|
|
)
|
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
var (
|
|
|
|
_ event.Event = (*ValueSet)(nil)
|
|
|
|
_ event.Aggregate = (*Thing)(nil)
|
|
|
|
)
|
|
|
|
|
|
|
|
type Thing struct {
|
|
|
|
Name string
|
|
|
|
Value string
|
|
|
|
|
|
|
|
event.AggregateRoot
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Thing) ApplyEvent(lis ...event.Event) {
|
|
|
|
for _, e := range lis {
|
|
|
|
switch e := e.(type) {
|
|
|
|
case *ValueSet:
|
|
|
|
a.Value = e.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func (a *Thing) OnSetValue(value string) error {
|
|
|
|
event.Raise(a, &ValueSet{Value: value})
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type ValueSet struct {
|
|
|
|
Value string
|
|
|
|
|
|
|
|
eventMeta event.Meta
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ValueSet) EventMeta() event.Meta {
|
|
|
|
if e == nil {
|
|
|
|
return event.Meta{}
|
|
|
|
}
|
|
|
|
return e.eventMeta
|
|
|
|
}
|
|
|
|
func (e *ValueSet) SetEventMeta(eventMeta event.Meta) {
|
|
|
|
if e == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
e.eventMeta = eventMeta
|
|
|
|
}
|
|
|
|
func (e *ValueSet) MarshalBinary() ([]byte, error) {
|
|
|
|
return json.Marshal(e)
|
|
|
|
}
|
|
|
|
func (e *ValueSet) UnmarshalBinary(b []byte) error {
|
|
|
|
return json.Unmarshal(b, e)
|
|
|
|
}
|
|
|
|
|
2022-08-04 14:37:51 -06:00
|
|
|
func TestES(t *testing.T) {
|
2022-08-06 09:52:36 -06:00
|
|
|
is := is.New(t)
|
2022-08-12 15:53:16 -06:00
|
|
|
|
2022-08-04 14:37:51 -06:00
|
|
|
ctx := context.Background()
|
|
|
|
|
2022-08-06 09:52:36 -06:00
|
|
|
err := event.Register(ctx, &ValueSet{})
|
|
|
|
is.NoErr(err)
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
{
|
2023-01-09 11:30:02 -07:00
|
|
|
store, err := ev.Open(ctx, "mem")
|
|
|
|
is.True(errors.Is(err, ev.ErrNoDriver))
|
2022-09-06 15:31:48 -06:00
|
|
|
is.True(store.EventStream() == nil)
|
|
|
|
}
|
2022-08-12 15:53:16 -06:00
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
{
|
2023-01-09 11:30:02 -07:00
|
|
|
_, err := ev.Open(ctx, "bogo:")
|
|
|
|
is.True(errors.Is(err, ev.ErrNoDriver))
|
2022-09-06 15:31:48 -06:00
|
|
|
}
|
2022-08-12 15:53:16 -06:00
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
store, err := ev.Open(ctx, "mem:", streamer.New(ctx), projecter.New(ctx))
|
2022-08-06 09:52:36 -06:00
|
|
|
is.NoErr(err)
|
2022-08-04 14:37:51 -06:00
|
|
|
|
|
|
|
thing := &Thing{Name: "time"}
|
2022-09-06 15:31:48 -06:00
|
|
|
err = store.Load(ctx, thing)
|
2022-08-06 09:52:36 -06:00
|
|
|
is.NoErr(err)
|
|
|
|
|
2022-08-04 14:37:51 -06:00
|
|
|
t.Log(thing.StreamVersion(), thing.Name, thing.Value)
|
|
|
|
|
|
|
|
err = thing.OnSetValue(time.Now().String())
|
2022-08-06 09:52:36 -06:00
|
|
|
is.NoErr(err)
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
thing.SetStreamID("thing-time")
|
|
|
|
i, err := store.Save(ctx, thing)
|
2022-08-06 09:52:36 -06:00
|
|
|
is.NoErr(err)
|
2022-08-04 14:37:51 -06:00
|
|
|
|
|
|
|
t.Log(thing.StreamVersion(), thing.Name, thing.Value)
|
|
|
|
t.Log("Wrote: ", i)
|
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
i, err = store.Append(ctx, "thing-time", event.NewEvents(&ValueSet{Value: "xxx"}))
|
2022-08-12 15:53:16 -06:00
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(i, uint64(1))
|
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
events, err := store.Read(ctx, "thing-time", -1, -11)
|
2022-08-06 09:52:36 -06:00
|
|
|
is.NoErr(err)
|
2022-08-04 14:37:51 -06:00
|
|
|
|
|
|
|
for i, e := range events {
|
|
|
|
t.Logf("event %d %d - %v\n", i, e.EventMeta().Position, e)
|
|
|
|
}
|
2022-08-12 15:53:16 -06:00
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
first, err := store.FirstIndex(ctx, "thing-time")
|
2022-08-12 15:53:16 -06:00
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(first, uint64(1))
|
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
last, err := store.LastIndex(ctx, "thing-time")
|
2022-08-12 15:53:16 -06:00
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(last, uint64(2))
|
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
stream := store.EventStream()
|
|
|
|
is.True(stream != nil)
|
2022-08-04 14:37:51 -06:00
|
|
|
}
|
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
func TestESOperations(t *testing.T) {
|
|
|
|
is := is.New(t)
|
|
|
|
ctx := context.Background()
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
store, err := ev.Open(ctx, "mem:", streamer.New(ctx), projecter.New(ctx))
|
2022-09-06 15:31:48 -06:00
|
|
|
is.NoErr(err)
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
thing, err := ev.Create(ctx, store, "thing-1", func(ctx context.Context, agg *Thing) error {
|
2022-09-06 15:31:48 -06:00
|
|
|
return agg.OnSetValue("foo")
|
|
|
|
})
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(thing.Version(), uint64(1))
|
|
|
|
is.Equal(thing.Value, "foo")
|
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
thing, err = ev.Update(ctx, store, "thing-1", func(ctx context.Context, agg *Thing) error {
|
2022-09-06 15:31:48 -06:00
|
|
|
return agg.OnSetValue("bar")
|
|
|
|
})
|
|
|
|
|
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(thing.Version(), uint64(2))
|
|
|
|
is.Equal(thing.Value, "bar")
|
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
thing, err = ev.Upsert(ctx, store, "thing-2", func(ctx context.Context, agg *Thing) error {
|
2022-09-06 15:31:48 -06:00
|
|
|
return agg.OnSetValue("bin")
|
|
|
|
})
|
|
|
|
|
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(thing.Version(), uint64(1))
|
|
|
|
is.Equal(thing.Value, "bin")
|
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
thing, err = ev.Upsert(ctx, store, "thing-2", func(ctx context.Context, agg *Thing) error {
|
2022-09-06 15:31:48 -06:00
|
|
|
return agg.OnSetValue("baz")
|
|
|
|
})
|
|
|
|
|
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(thing.Version(), uint64(2))
|
|
|
|
is.Equal(thing.Value, "baz")
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2022-08-14 10:56:00 -06:00
|
|
|
}
|
2022-08-04 14:37:51 -06:00
|
|
|
|
2022-09-06 15:31:48 -06:00
|
|
|
func TestUnwrap(t *testing.T) {
|
|
|
|
is := is.New(t)
|
|
|
|
|
|
|
|
err := errors.New("foo")
|
|
|
|
werr := fmt.Errorf("wrap: %w", err)
|
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
is.Equal(ev.Unwrap(werr), err)
|
|
|
|
is.Equal(ev.Unwrap("test"), "")
|
2022-09-06 15:31:48 -06:00
|
|
|
}
|
2022-12-19 10:50:38 -07:00
|
|
|
|
|
|
|
func TestUnwrapProjector(t *testing.T) {
|
|
|
|
is := is.New(t)
|
|
|
|
|
|
|
|
ctx, stop := context.WithCancel(context.Background())
|
|
|
|
defer stop()
|
|
|
|
|
2023-01-09 11:30:02 -07:00
|
|
|
es, err := ev.Open(
|
2022-12-19 10:50:38 -07:00
|
|
|
ctx,
|
|
|
|
"mem:",
|
|
|
|
resolvelinks.New(),
|
|
|
|
streamer.New(ctx),
|
|
|
|
projecter.New(
|
|
|
|
ctx,
|
|
|
|
projecter.DefaultProjection,
|
|
|
|
peerfinder.Projector,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
is.NoErr(err)
|
|
|
|
|
|
|
|
stream := es.EventStream()
|
|
|
|
is.True(stream != nil)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
ctx, stop := context.WithCancel(context.Background())
|
|
|
|
defer stop()
|
|
|
|
|
|
|
|
err := multierr.Combine(
|
2023-01-09 11:30:02 -07:00
|
|
|
ev.Init(ctx),
|
2022-12-19 10:50:38 -07:00
|
|
|
event.Init(ctx),
|
|
|
|
memstore.Init(ctx),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Run()
|
|
|
|
}
|