86 lines
1.7 KiB
Go
86 lines
1.7 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/mail/internal/config"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestAppRunStopsComponentsOnContextCancellation(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
component := &blockingComponent{}
|
|
app := New(config.Config{ShutdownTimeout: time.Second}, component)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
done <- app.Run(ctx)
|
|
}()
|
|
|
|
require.Eventually(t, func() bool {
|
|
component.mu.Lock()
|
|
defer component.mu.Unlock()
|
|
return component.runStarted
|
|
}, time.Second, 10*time.Millisecond)
|
|
|
|
cancel()
|
|
|
|
require.Eventually(t, func() bool {
|
|
select {
|
|
case err := <-done:
|
|
return err == nil
|
|
default:
|
|
return false
|
|
}
|
|
}, time.Second, 10*time.Millisecond)
|
|
require.Equal(t, 1, component.shutdownCalls)
|
|
}
|
|
|
|
func TestAppRunReportsEarlyComponentExit(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
app := New(config.Config{ShutdownTimeout: time.Second}, componentFunc(func(context.Context) error {
|
|
return nil
|
|
}))
|
|
|
|
err := app.Run(context.Background())
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "exited without error before shutdown")
|
|
}
|
|
|
|
type blockingComponent struct {
|
|
mu sync.Mutex
|
|
runStarted bool
|
|
shutdownCalls int
|
|
}
|
|
|
|
func (component *blockingComponent) Run(ctx context.Context) error {
|
|
component.mu.Lock()
|
|
component.runStarted = true
|
|
component.mu.Unlock()
|
|
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
}
|
|
|
|
func (component *blockingComponent) Shutdown(context.Context) error {
|
|
component.shutdownCalls++
|
|
return nil
|
|
}
|
|
|
|
type componentFunc func(context.Context) error
|
|
|
|
func (fn componentFunc) Run(ctx context.Context) error {
|
|
return fn(ctx)
|
|
}
|
|
|
|
func (fn componentFunc) Shutdown(context.Context) error {
|
|
return nil
|
|
}
|