Given a small HTTP server, how can you write a unit test to make sure the interrupt is dealt with correctly?
package main
import (
"context"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func SimpleServer() {
ctx := context.Background()
server := http.Server{
Addr: ":8080",
BaseContext: func(net.Listener) context.Context { return ctx },
}
http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "pong at ", time.Now().String())
})
go server.ListenAndServe()
exitChannel := make(chan os.Signal, 1) // reserve with buffer size 1 so the notifiers aren't blocked
defer close(exitChannel)
signal.Notify(exitChannel, os.Interrupt, syscall.SIGTERM) // Docker and Kubernetes will signal with syscall.SIGTERM
<-exitChannel
fmt.Print("\n")
fmt.Println("shutting down server...")
err := server.Shutdown(ctx)
fmt.Println(err)
}
I'm wondering how to pass in this:
exitChannel <- syscall.SIGINT
or:
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
..and then somehow be notified that the server shut down.
CodePudding user response:
Instead of waiting for a signal and shutting down, you can refactor a bit to shutdown based on a signal:
exitChannel := make(chan struct{})
serverDown:=make(chan struct{})
go func() {
<-exitChannel
server.Shutdown(ctx)
}()
go func() {
server.ListenAndServe()
close(serverDown)
}()
return exitChannel, serverDown
Then, you can use the exitChannel
to terminate the server externally, and serverDown
to detect if the server shutdown. Hook up the signal channel externally, so when you receive the shutdown signal, you can write to the exitChannel
.