mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-07 21:47:02 +09:00
199 lines
4.6 KiB
Go
199 lines
4.6 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestAppServiceRegistry(t *testing.T) {
|
|
app := new(App)
|
|
t.Run("Register", func(t *testing.T) {
|
|
app.Register(newTestService(testTypeRunnable, "c1", nil, nil))
|
|
app.Register(newTestService(testTypeRunnable, "r1", nil, nil))
|
|
app.Register(newTestService(testTypeComponent, "s1", nil, nil))
|
|
})
|
|
t.Run("Component", func(t *testing.T) {
|
|
assert.Nil(t, app.Component("not-registered"))
|
|
for _, name := range []string{"c1", "r1", "s1"} {
|
|
s := app.Component(name)
|
|
assert.NotNil(t, s, name)
|
|
assert.Equal(t, name, s.Name())
|
|
}
|
|
})
|
|
t.Run("MustComponent", func(t *testing.T) {
|
|
for _, name := range []string{"c1", "r1", "s1"} {
|
|
assert.NotPanics(t, func() { app.MustComponent(name) }, name)
|
|
}
|
|
assert.Panics(t, func() { app.MustComponent("not-registered") })
|
|
})
|
|
t.Run("ComponentNames", func(t *testing.T) {
|
|
names := app.ComponentNames()
|
|
assert.Equal(t, names, []string{"c1", "r1", "s1"})
|
|
})
|
|
t.Run("Child MustComponent", func(t *testing.T) {
|
|
app := app.ChildApp()
|
|
app.Register(newTestService(testTypeComponent, "x1", nil, nil))
|
|
for _, name := range []string{"c1", "r1", "s1", "x1"} {
|
|
assert.NotPanics(t, func() { app.MustComponent(name) }, name)
|
|
}
|
|
assert.Panics(t, func() { app.MustComponent("not-registered") })
|
|
})
|
|
t.Run("Child ComponentNames", func(t *testing.T) {
|
|
app := app.ChildApp()
|
|
app.Register(newTestService(testTypeComponent, "x1", nil, nil))
|
|
names := app.ComponentNames()
|
|
assert.Equal(t, names, []string{"x1", "c1", "r1", "s1"})
|
|
})
|
|
t.Run("Child override", func(t *testing.T) {
|
|
app := app.ChildApp()
|
|
app.Register(newTestService(testTypeRunnable, "s1", nil, nil))
|
|
_ = app.MustComponent("s1").(*testRunnable)
|
|
})
|
|
}
|
|
|
|
func TestApp_IterateComponents(t *testing.T) {
|
|
app := new(App)
|
|
|
|
app.Register(newTestService(testTypeRunnable, "c1", nil, nil))
|
|
app.Register(newTestService(testTypeRunnable, "r1", nil, nil))
|
|
app.Register(newTestService(testTypeComponent, "s1", nil, nil))
|
|
|
|
var got []string
|
|
app.IterateComponents(func(s Component) {
|
|
got = append(got, s.Name())
|
|
})
|
|
|
|
assert.ElementsMatch(t, []string{"c1", "r1", "s1"}, got)
|
|
}
|
|
|
|
func TestAppStart(t *testing.T) {
|
|
t.Run("SuccessStartStop", func(t *testing.T) {
|
|
app := new(App)
|
|
seq := new(testSeq)
|
|
services := [...]iTestService{
|
|
newTestService(testTypeRunnable, "c1", nil, seq),
|
|
newTestService(testTypeRunnable, "r1", nil, seq),
|
|
newTestService(testTypeComponent, "s1", nil, seq),
|
|
newTestService(testTypeRunnable, "c2", nil, seq),
|
|
}
|
|
for _, s := range services {
|
|
app.Register(s)
|
|
}
|
|
ctx := context.Background()
|
|
assert.Nil(t, app.Start(ctx))
|
|
assert.Nil(t, app.Close(ctx))
|
|
|
|
var actual []testIds
|
|
for _, s := range services {
|
|
actual = append(actual, s.Ids())
|
|
}
|
|
|
|
expected := []testIds{
|
|
{1, 5, 10},
|
|
{2, 6, 9},
|
|
{3, 0, 0},
|
|
{4, 7, 8},
|
|
}
|
|
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
|
|
t.Run("InitError", func(t *testing.T) {
|
|
app := new(App)
|
|
seq := new(testSeq)
|
|
expectedErr := fmt.Errorf("testError")
|
|
services := [...]iTestService{
|
|
newTestService(testTypeRunnable, "c1", nil, seq),
|
|
newTestService(testTypeRunnable, "c2", expectedErr, seq),
|
|
}
|
|
for _, s := range services {
|
|
app.Register(s)
|
|
}
|
|
|
|
err := app.Start(context.Background())
|
|
assert.NotNil(t, err)
|
|
assert.Contains(t, err.Error(), expectedErr.Error())
|
|
|
|
var actual []testIds
|
|
for _, s := range services {
|
|
actual = append(actual, s.Ids())
|
|
}
|
|
|
|
expected := []testIds{
|
|
{1, 0, 4},
|
|
{2, 0, 3},
|
|
}
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
|
|
const (
|
|
testTypeComponent int = iota
|
|
testTypeRunnable
|
|
)
|
|
|
|
func newTestService(componentType int, name string, err error, seq *testSeq) (s iTestService) {
|
|
ts := testComponent{name: name, err: err, seq: seq}
|
|
switch componentType {
|
|
case testTypeComponent:
|
|
return &ts
|
|
case testTypeRunnable:
|
|
return &testRunnable{testComponent: ts}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type iTestService interface {
|
|
Component
|
|
Ids() (ids testIds)
|
|
}
|
|
|
|
type testIds struct {
|
|
initId int64
|
|
runId int64
|
|
closeId int64
|
|
}
|
|
|
|
type testComponent struct {
|
|
name string
|
|
err error
|
|
seq *testSeq
|
|
ids testIds
|
|
}
|
|
|
|
func (t *testComponent) Init(a *App) error {
|
|
t.ids.initId = t.seq.New()
|
|
return t.err
|
|
}
|
|
|
|
func (t *testComponent) Name() string { return t.name }
|
|
|
|
func (t *testComponent) Ids() testIds {
|
|
return t.ids
|
|
}
|
|
|
|
type testRunnable struct {
|
|
testComponent
|
|
}
|
|
|
|
func (t *testRunnable) Run(ctx context.Context) error {
|
|
t.ids.runId = t.seq.New()
|
|
return t.err
|
|
}
|
|
|
|
func (t *testRunnable) Close(ctx context.Context) error {
|
|
t.ids.closeId = t.seq.New()
|
|
return t.err
|
|
}
|
|
|
|
type testSeq struct {
|
|
seq int64
|
|
}
|
|
|
|
func (ts *testSeq) New() int64 {
|
|
return atomic.AddInt64(&ts.seq, 1)
|
|
}
|