Skip to content

Commit

Permalink
[WIP] add test case when request takes a little longer than the drain…
Browse files Browse the repository at this point in the history
… time
  • Loading branch information
norbjd committed Apr 7, 2024
1 parent c8523a9 commit 95d7576
Showing 1 changed file with 54 additions and 29 deletions.
83 changes: 54 additions & 29 deletions test/gracefulshutdown/gracefulshutdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"testing"
"time"

"golang.org/x/sync/errgroup"
"gotest.tools/v3/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
Expand Down Expand Up @@ -97,45 +98,69 @@ func TestGracefulShutdown(t *testing.T) {
}},
})

// Prepare the request to the ingress: this request will wait for slightly less than the drain time configured
requestTimeout := drainTime - (3 * time.Second)
reqURL := fmt.Sprintf("http://%s.example.com?initialTimeout=%d", name, requestTimeout.Milliseconds())
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
t.Fatal("Error making GET request:", err)
}

errs := make(chan error, 1)
var statusCode int

// Do the request asynchronously: goroutine will return only once the service has returned a response (after initialTimeout),
// or early if there is an error
go func() {
resp, err := client.Do(req)
if err != nil {
errs <- err
return
tests := []struct {
name string
requestDuration time.Duration
}{
{
name: fmt.Sprintf("do a request taking slightly less than the drain time: %s", drainTime),
requestDuration: drainTime - (3 * time.Second),
},
{
name: fmt.Sprintf("do a request taking slightly more than the drain time: %s", drainTime),
requestDuration: drainTime + (3 * time.Second),
}

Check failure on line 112 in test/gracefulshutdown/gracefulshutdown_test.go

View workflow job for this annotation

GitHub Actions / build / Build

missing ',' before newline in composite literal

Check failure on line 112 in test/gracefulshutdown/gracefulshutdown_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in composite literal

Check failure on line 112 in test/gracefulshutdown/gracefulshutdown_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

syntax error: unexpected newline in composite literal; possibly missing comma or } (typecheck)

Check failure on line 112 in test/gracefulshutdown/gracefulshutdown_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in composite literal (typecheck)
}

statusCode = resp.StatusCode
resp.Body.Close()
g := new(errgroup.Group)
statusCodes := make(map[time.Duration]int, len(tests))

errs <- nil
}()
// Run all requests asynchronously at the same time, and collect the results in statusCodes map
for _, test := range tests {
g.Go(func() error {
statusCode, err := sendRequest(name, test.requestDuration)
statusCodes[test.requestDuration] = statusCode
return err
})
}

// In parallel, delete the gateway pod:
// the 1 second sleep before the deletion is here to ensure the request has been sent by the goroutine above
// Once requests are in-flight, delete the gateway pod:
// the 1 second sleep before the deletion is here to ensure the requests have been sent by the goroutines above
time.Sleep(1 * time.Second)
if err := clients.KubeClient.CoreV1().Pods(gatewayNs).Delete(ctx, gatewayPodName, metav1.DeleteOptions{}); err != nil {
t.Fatalf("Failed to delete pod %s: %v", gatewayPodName, err)
}

// Wait until we get a response from the asynchronous request
err = <-errs
if err != nil {
// Wait until we get responses from the asynchronous requests
if err := g.Wait(); err != nil {
t.Fatal(err)
}

// The gateway has been gracefully shutdown, so the in-flight request finishes with a OK status code
assert.Equal(t, statusCode, http.StatusOK)
// The gateway has been gracefully shutdown, so the in-flight requests taking less than the drain time will finish with a OK status code
// But, requests taking more than the drain time will be terminated, thus returning a non-OK status code
for timeout, statusCode := range statusCodes {
if timeout < drainTime {
assert.Equal(t, statusCode, http.StatusOK)
} else {
assert.Equal(t, statusCode, http.StatusOK) // TODO: get the right status code
}
}
}

func sendRequest(name string, requestTimeout time.Duration) (statusCode int, err error) {
reqURL := fmt.Sprintf("http://%s.example.com?initialTimeout=%d", name, requestTimeout.Milliseconds())
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
t.Fatal("Error making GET request:", err)
}

resp, err := client.Do(req)
if err != nil {
return 0, err
}

statusCode = resp.StatusCode
resp.Body.Close()

return statusCode, nil
}

0 comments on commit 95d7576

Please sign in to comment.