Initial commit: stalwart-migrator design and scaffolding
In-place upgrade tool for Stalwart Mail Server (0.15.5 -> latest) with checkpointed rollback and post-migration validation. Design stage; see ARCHITECTURE.md.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
package recovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestMain lets this test binary also act as a fake Stalwart binary for
|
||||
// subprocess tests - the standard os/exec "helper process" technique (see
|
||||
// Go's own os/exec_test.go). When STALWART_MIGRATOR_TEST_HELPER=1 is set,
|
||||
// the binary runs a minimal HTTP server on STALWART_MIGRATOR_TEST_PORT
|
||||
// until it receives SIGTERM (or, if STALWART_MIGRATOR_TEST_IGNORE_SIGTERM=1,
|
||||
// ignores SIGTERM to exercise the SIGKILL escalation path) instead of
|
||||
// running the actual test suite. This avoids needing a real Stalwart binary
|
||||
// - or a fabricated stand-in for its HTTP behavior - anywhere in these
|
||||
// tests: it's real net/http and real process signaling, just running under
|
||||
// this package's own compiled binary.
|
||||
func TestMain(m *testing.M) {
|
||||
if os.Getenv("STALWART_MIGRATOR_TEST_HELPER") == "1" {
|
||||
runFakeStalwartServer()
|
||||
return
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func runFakeStalwartServer() {
|
||||
port := os.Getenv("STALWART_MIGRATOR_TEST_PORT")
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:"+port)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "fake stalwart: listen:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
srv := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})}
|
||||
go srv.Serve(ln)
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
if os.Getenv("STALWART_MIGRATOR_TEST_IGNORE_SIGTERM") == "1" {
|
||||
signal.Ignore(syscall.SIGTERM)
|
||||
select {} // block forever; the test must SIGKILL this process itself
|
||||
}
|
||||
signal.Notify(sigCh, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
os.Exit(0)
|
||||
}
|
||||
Reference in New Issue
Block a user