package healthfile_test import ( "context" "errors" "path" "sync" "testing" "time" "gitea.dwysokinski.me/twhelp/corev3/internal/health" "gitea.dwysokinski.me/twhelp/corev3/internal/health/healthfile" "gitea.dwysokinski.me/twhelp/corev3/internal/health/healthtest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestLiveObserver(t *testing.T) { t.Parallel() testObserver(t, func(t *testing.T) *healthfile.Observer { t.Helper() h := health.New( health.WithLiveCheck(healthtest.Checker{Nam: "test"}), health.WithLiveCheck(healthtest.Checker{Nam: "test2"}), ) dir := t.TempDir() livePath := path.Join(dir, "live") o := healthfile.LiveObserver(h, livePath) t.Cleanup(func() { _ = o.Close() }) return o }) } func TestReadyObserver(t *testing.T) { t.Parallel() testObserver(t, func(t *testing.T) *healthfile.Observer { t.Helper() h := health.New( health.WithReadyCheck(healthtest.Checker{Nam: "test"}), health.WithReadyCheck(healthtest.Checker{Nam: "test2"}), ) dir := t.TempDir() readyPath := path.Join(dir, "ready") o := healthfile.ReadyObserver(h, readyPath) t.Cleanup(func() { _ = o.Close() }) return o }) } func testObserver(t *testing.T, newObserver func(t *testing.T) *healthfile.Observer) { t.Helper() t.Run("standard run/close path", func(t *testing.T) { t.Parallel() o := newObserver(t) observerStopped := make(chan struct{}) go func() { defer close(observerStopped) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() _ = o.Run(ctx) }() assert.EventuallyWithT(t, func(collect *assert.CollectT) { assert.FileExists(collect, o.Path()) }, time.Second, 10*time.Millisecond) require.NoError(t, o.Close()) select { case <-observerStopped: // OK default: t.Error("Run goroutine not stopped") } }) t.Run("observer respects ctx.Done", func(t *testing.T) { t.Parallel() o := newObserver(t) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) defer cancel() require.ErrorIs(t, o.Run(ctx), context.DeadlineExceeded) }) t.Run("run can only be called once", func(t *testing.T) { t.Parallel() expectedErrs := 2 o := newObserver(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() var wg sync.WaitGroup errCh := make(chan error) for i := 1; i <= 1+expectedErrs; i++ { wg.Add(1) go func() { defer wg.Done() errCh <- o.Run(ctx) }() } go func() { wg.Wait() close(errCh) }() var cnt int for err := range errCh { if errors.Is(err, healthfile.ErrAlreadyRunning) { cnt++ } if cnt == expectedErrs { require.NoError(t, o.Close()) } } assert.Equal(t, expectedErrs, cnt) }) }