All checks were successful
Release Pipeline / upload-assets (metadata@.service, systemd/metadata@.service) (push) Successful in 4s
Release Pipeline / upload-assets (run-dnsmasq-in-netns.sh, scripts/run-dnsmasq-in-netns.sh) (push) Successful in 4s
Release Pipeline / build (agent, amd64, linux) (push) Successful in 0s
Release Pipeline / build (metadata, amd64, linux) (push) Successful in 0s
Release Pipeline / checksums (push) Successful in 4s
Release Pipeline / set-release-target (push) Successful in 2s
Release Pipeline / upload-assets (agent.service, systemd/agent.service) (push) Successful in 4s
Release Pipeline / upload-assets (dnsmasq@.service, systemd/dnsmasq@.service) (push) Successful in 4s
Release Pipeline / release (push) Successful in 11s
Release Pipeline / publish (push) Successful in 0s
Release Pipeline / build (push) Successful in 1m30s
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"log/slog"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.g3e.fr/syonad/two/pkg/worker"
|
|
)
|
|
|
|
type fakeServer struct {
|
|
called atomic.Bool
|
|
err error
|
|
}
|
|
|
|
func (f *fakeServer) Shutdown(context.Context) error {
|
|
f.called.Store(true)
|
|
return f.err
|
|
}
|
|
|
|
func discardLogger() *slog.Logger {
|
|
return slog.New(slog.NewTextHandler(io.Discard, nil))
|
|
}
|
|
|
|
func TestShutdown_DrainReussi(t *testing.T) {
|
|
q := worker.New(10)
|
|
q.Start(2)
|
|
|
|
var done atomic.Int32
|
|
for range 3 {
|
|
q.Submit(func() {
|
|
time.Sleep(20 * time.Millisecond)
|
|
done.Add(1)
|
|
})
|
|
}
|
|
|
|
api, prom := &fakeServer{}, &fakeServer{}
|
|
servers := map[string]httpShutdowner{"api": api, "prometheus": prom}
|
|
|
|
if !shutdown(discardLogger(), q, servers, 5*time.Second) {
|
|
t.Fatal("un drainage réussi doit autoriser la fermeture de la base")
|
|
}
|
|
if !api.called.Load() || !prom.called.Load() {
|
|
t.Error("tous les serveurs HTTP doivent être arrêtés")
|
|
}
|
|
if got := done.Load(); got != 3 {
|
|
t.Errorf("les 3 tâches devaient se terminer, %d terminées", got)
|
|
}
|
|
}
|
|
|
|
func TestShutdown_TimeoutLaisseLaBaseIntacte(t *testing.T) {
|
|
q := worker.New(10)
|
|
q.Start(1)
|
|
q.Submit(func() { time.Sleep(2 * time.Second) })
|
|
|
|
var buf strings.Builder
|
|
log := slog.New(slog.NewTextHandler(&buf, nil))
|
|
|
|
if shutdown(log, q, map[string]httpShutdowner{}, 50*time.Millisecond) {
|
|
t.Fatal("un drainage incomplet ne doit pas autoriser la fermeture de la base")
|
|
}
|
|
if !strings.Contains(buf.String(), "leaving database untouched") {
|
|
t.Errorf("le dépassement devrait être logué, obtenu %q", buf.String())
|
|
}
|
|
}
|
|
|
|
func TestShutdown_ErreurServeurNEmpechePasLeDrainage(t *testing.T) {
|
|
q := worker.New(10)
|
|
q.Start(1)
|
|
|
|
var buf strings.Builder
|
|
log := slog.New(slog.NewTextHandler(&buf, nil))
|
|
servers := map[string]httpShutdowner{
|
|
"api": &fakeServer{err: errors.New("boom")},
|
|
"prometheus": &fakeServer{},
|
|
}
|
|
|
|
if !shutdown(log, q, servers, 5*time.Second) {
|
|
t.Fatal("une erreur d'arrêt HTTP ne doit pas empêcher le drainage")
|
|
}
|
|
if !strings.Contains(buf.String(), "http server shutdown") {
|
|
t.Errorf("l'erreur devrait être loguée, obtenu %q", buf.String())
|
|
}
|
|
}
|
|
|
|
func TestShutdown_SansServeur(t *testing.T) {
|
|
q := worker.New(10)
|
|
q.Start(1)
|
|
|
|
if !shutdown(discardLogger(), q, map[string]httpShutdowner{}, 5*time.Second) {
|
|
t.Fatal("l'absence de serveur ne doit pas empêcher un arrêt propre")
|
|
}
|
|
}
|