Home > Blockchain >  How to write a unit test for Interrupt Signal (Ctrl C) of an HTTP server?
How to write a unit test for Interrupt Signal (Ctrl C) of an HTTP server?

Time:07-28

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.

  • Related