1package app
2
3import (
4 "context"
5 "testing"
6
7 "github.com/bnema/zerowrap"
8 "github.com/stretchr/testify/assert"
9
10 "github.com/bnema/gordon/internal/domain"
11)
12
13type startupRecoveryFakeConfigService struct {
14 calls *[]string
15 routes []domain.Route
16}
17
18var _ startupConfigService = (*startupRecoveryFakeConfigService)(nil)
19
20func (f *startupRecoveryFakeConfigService) GetRoutes(_ context.Context) []domain.Route {
21 *f.calls = append(*f.calls, "routes")
22 return append([]domain.Route(nil), f.routes...)
23}
24
25type startupRecoveryFakeContainerService struct {
26 calls *[]string
27 syncErr error
28 autoStartErr error
29 autoStartCtx context.Context
30 autoStartRoutes []domain.Route
31 startMonitorCtx context.Context
32}
33
34var _ startupContainerService = (*startupRecoveryFakeContainerService)(nil)
35
36func (f *startupRecoveryFakeContainerService) SyncContainers(_ context.Context) error {
37 *f.calls = append(*f.calls, "sync")
38 return f.syncErr
39}
40
41func (f *startupRecoveryFakeContainerService) AutoStart(ctx context.Context, routes []domain.Route) error {
42 *f.calls = append(*f.calls, "autostart")
43 f.autoStartCtx = ctx
44 f.autoStartRoutes = append([]domain.Route(nil), routes...)
45 return f.autoStartErr
46}
47
48func (f *startupRecoveryFakeContainerService) StartMonitor(ctx context.Context) {
49 *f.calls = append(*f.calls, "monitor")
50 f.startMonitorCtx = ctx
51}
52
53func TestSyncAndRecoverConfiguredRoutes_HappyPath(t *testing.T) {
54 ctx := context.Background()
55 routes := []domain.Route{{Domain: "app.example.com", Image: "reg.example.com/app:latest", HTTPS: true}}
56 calls := make([]string, 0, 4)
57
58 configSvc := &startupRecoveryFakeConfigService{
59 calls: &calls,
60 routes: routes,
61 }
62 containerSvc := &startupRecoveryFakeContainerService{calls: &calls}
63
64 syncAndRecoverConfiguredRoutes(ctx, configSvc, containerSvc, zerowrap.Default())
65
66 assert.Equal(t, []string{"sync", "routes", "autostart", "monitor"}, calls)
67 assert.Equal(t, routes, containerSvc.autoStartRoutes)
68 assert.True(t, domain.IsInternalDeploy(containerSvc.autoStartCtx))
69 assert.False(t, domain.IsInternalDeploy(ctx))
70 assert.False(t, domain.IsInternalDeploy(containerSvc.startMonitorCtx))
71}
72
73func TestSyncAndRecoverConfiguredRoutes_SyncFailureStillRecoversAndStartsMonitor(t *testing.T) {
74 ctx := context.Background()
75 routes := []domain.Route{{Domain: "app.example.com", Image: "reg.example.com/app:latest", HTTPS: true}}
76 calls := make([]string, 0, 4)
77
78 configSvc := &startupRecoveryFakeConfigService{
79 calls: &calls,
80 routes: routes,
81 }
82 containerSvc := &startupRecoveryFakeContainerService{
83 calls: &calls,
84 syncErr: assert.AnError,
85 }
86
87 assert.NotPanics(t, func() {
88 syncAndRecoverConfiguredRoutes(ctx, configSvc, containerSvc, zerowrap.Default())
89 })
90
91 assert.Equal(t, []string{"sync", "routes", "autostart", "monitor"}, calls)
92 assert.Equal(t, routes, containerSvc.autoStartRoutes)
93 assert.True(t, domain.IsInternalDeploy(containerSvc.autoStartCtx))
94 assert.False(t, domain.IsInternalDeploy(containerSvc.startMonitorCtx))
95}
96
97func TestSyncAndRecoverConfiguredRoutes_AutoStartFailureStillStartsMonitor(t *testing.T) {
98 ctx := context.Background()
99 routes := []domain.Route{{Domain: "app.example.com", Image: "reg.example.com/app:latest", HTTPS: true}}
100 calls := make([]string, 0, 4)
101
102 configSvc := &startupRecoveryFakeConfigService{
103 calls: &calls,
104 routes: routes,
105 }
106 containerSvc := &startupRecoveryFakeContainerService{
107 calls: &calls,
108 autoStartErr: assert.AnError,
109 }
110
111 assert.NotPanics(t, func() {
112 syncAndRecoverConfiguredRoutes(ctx, configSvc, containerSvc, zerowrap.Default())
113 })
114
115 assert.Equal(t, []string{"sync", "routes", "autostart", "monitor"}, calls)
116 assert.Equal(t, routes, containerSvc.autoStartRoutes)
117 assert.True(t, domain.IsInternalDeploy(containerSvc.autoStartCtx))
118 assert.False(t, domain.IsInternalDeploy(containerSvc.startMonitorCtx))
119}