debian-forge-composer/internal/test/apicall.go
Brian C. Lane 7a4bb863dd Update deprecated io/ioutil functions
ioutil has been deprecated since go 1.16, this fixes all of the
deprecated functions we are using:

ioutil.ReadFile -> os.ReadFile
ioutil.ReadAll -> io.ReadAll
ioutil.WriteFile -> os.WriteFile
ioutil.TempFile -> os.CreateTemp
ioutil.TempDir -> os.MkdirTemp

All of the above are a simple name change, the function arguments and
results are exactly the same as before.

ioutil.ReadDir -> os.ReadDir

now returns a os.DirEntry but the IsDir and Name functions work the
same. The difference is that the FileInfo must be retrieved with the
Info() function which can also return an error.

These were identified by running:
golangci-lint run --build-tags=integration ./...
2023-03-07 09:22:23 -08:00

98 lines
2.3 KiB
Go

package test
import (
"bytes"
"context"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// APICall is a small function object for testing HTTP APIs
type APICall struct {
// http.Handler to run the call against
Handler http.Handler
// HTTP method, e.g. http.MethodPatch
Method string
// Request Path
Path string
// Request body. If nil, an empty body is sent
RequestBody RequestBody
// Request header. If nil, default header is sent
Header http.Header
// Request context. If nil, default context is used
Context context.Context
// Status that's expected to be received. If set to 0, the status is not checked
ExpectedStatus int
// Validator for the response body. If set to nil, the body is not validated
ExpectedBody BodyValidator
}
// Do performs the request as defined in the APICall struct.
//
// If any errors occur when doing the request, or any of the validators fail, t.FailNow() is called
// Note that HTTP error status is not checked if ExpectedStatus == 0
//
// The result of the HTTP call is returned
func (a APICall) Do(t *testing.T) APICallResult {
t.Helper()
var bodyReader io.Reader
if a.RequestBody != nil {
bodyReader = bytes.NewReader(a.RequestBody.Body())
}
req := httptest.NewRequest(a.Method, a.Path, bodyReader)
if a.Context != nil {
req = req.WithContext(a.Context)
}
req.Header = a.Header
if req.Header == nil {
req.Header = http.Header{}
}
if a.RequestBody != nil && a.RequestBody.ContentType() != "" {
req.Header.Set("Content-Type", a.RequestBody.ContentType())
}
respRecorder := httptest.NewRecorder()
a.Handler.ServeHTTP(respRecorder, req)
resp := respRecorder.Result()
body, err := io.ReadAll(resp.Body)
require.NoErrorf(t, err, "%s: could not read response body", a.Path)
if a.ExpectedStatus != 0 {
assert.Equalf(t, a.ExpectedStatus, resp.StatusCode, "%s: SendHTTP failed for path", a.Path)
}
if a.ExpectedBody != nil {
err = a.ExpectedBody.Validate(body)
require.NoError(t, err, "%s: cannot validate response body", a.Path)
}
return APICallResult{
Body: body,
StatusCode: resp.StatusCode,
}
}
// APICallResult holds a parsed response for an APICall
type APICallResult struct {
// Full body as read from the server
Body []byte
// Status code returned from the server
StatusCode int
}