Skip to content

Commit

Permalink
client and must: print errors in red (#671)
Browse files Browse the repository at this point in the history
  • Loading branch information
David Robertson authored Oct 12, 2023
1 parent 6732db1 commit 73ee61e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 41 deletions.
10 changes: 5 additions & 5 deletions client/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (c *CSAPI) LoginUser(t TestLike, localpart, password string, opts ...LoginO

body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("unable to read response body: %v", err)
fatalf(t, "unable to read response body: %v", err)
}

userID = GetJSONFieldStr(t, body, "user_id")
Expand All @@ -67,7 +67,7 @@ func (c *CSAPI) LoginUserWithRefreshToken(t TestLike, localpart, password string

body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("unable to read response body: %v", err)
fatalf(t, "unable to read response body: %v", err)
}

userID = GetJSONFieldStr(t, body, "user_id")
Expand All @@ -88,7 +88,7 @@ func (c *CSAPI) ConsumeRefreshToken(t TestLike, refreshToken string) (newAccessT

body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("unable to read response body: %v", err)
fatalf(t, "unable to read response body: %v", err)
}

newAccessToken = GetJSONFieldStr(t, body, "access_token")
Expand All @@ -112,7 +112,7 @@ func (c *CSAPI) RegisterUser(t TestLike, localpart, password string) (userID, ac

body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("unable to read response body: %v", err)
fatalf(t, "unable to read response body: %v", err)
}

userID = GetJSONFieldStr(t, body, "user_id")
Expand All @@ -132,7 +132,7 @@ func (c *CSAPI) RegisterSharedSecret(t TestLike, user, pass string, isAdmin bool
body := ParseJSON(t, resp)
nonce := gjson.GetBytes(body, "nonce")
if !nonce.Exists() {
t.Fatalf("Malformed shared secret GET response: %s", string(body))
fatalf(t, "Malformed shared secret GET response: %s", string(body))
}
mac := hmac.New(sha1.New, []byte(SharedSecret))
mac.Write([]byte(nonce.Str))
Expand Down
47 changes: 31 additions & 16 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ type TestLike interface {
Fatalf(msg string, args ...interface{})
}

const ansiRedForeground = "\x1b[31m"
const ansiResetForeground = "\x1b[39m"

// errorf is a wrapper around t.Errorf which prints the failing error message in red.
func errorf(t TestLike, format string, args ...any) {
format = ansiRedForeground + format + ansiResetForeground
t.Errorf(format, args...)
}

// fatalf is a wrapper around t.Fatalf which prints the failing error message in red.
func fatalf(t TestLike, format string, args ...any) {
format = ansiRedForeground + format + ansiResetForeground
t.Fatalf(format, args...)
}

type ctxKey string

const (
Expand Down Expand Up @@ -85,7 +100,7 @@ func (c *CSAPI) DownloadContent(t TestLike, mxcUri string) ([]byte, string) {
contentType := res.Header.Get("Content-Type")
b, err := io.ReadAll(res.Body)
if err != nil {
t.Error(err)
errorf(t, err.Error())
}
return b, contentType
}
Expand Down Expand Up @@ -285,7 +300,7 @@ func (c *CSAPI) Unsafe_SendEventUnsyncedWithTxnID(t TestLike, roomID string, e b
paths = []string{"_matrix", "client", "v3", "rooms", roomID, "state", e.Type, *e.StateKey}
}
if e.Sender != "" && e.Sender != c.UserID {
t.Fatalf("Event.Sender must not be set, as this is set by the client in use (%s)", c.UserID)
fatalf(t, "Event.Sender must not be set, as this is set by the client in use (%s)", c.UserID)
}
res := c.MustDo(t, "PUT", paths, WithJSONBody(t, e.Content))
body := ParseJSON(t, res)
Expand Down Expand Up @@ -345,7 +360,7 @@ func (c *CSAPI) GetCapabilities(t TestLike) []byte {
res := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "capabilities"})
body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("unable to read response body: %v", err)
fatalf(t, "unable to read response body: %v", err)
}
return body
}
Expand Down Expand Up @@ -439,7 +454,7 @@ func WithJSONBody(t TestLike, obj interface{}) RequestOpt {
t.Helper()
b, err := json.Marshal(obj)
if err != nil {
t.Fatalf("CSAPI.Do failed to marshal JSON body: %s", err)
fatalf(t, "CSAPI.Do failed to marshal JSON body: %s", err)
}
WithRawBody(b)(req)
}
Expand Down Expand Up @@ -471,7 +486,7 @@ func (c *CSAPI) MustDo(t TestLike, method string, paths []string, opts ...Reques
if res.StatusCode < 200 || res.StatusCode >= 300 {
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
t.Fatalf("CSAPI.MustDo %s %s returned non-2xx code: %s - body: %s", method, res.Request.URL.String(), res.Status, string(body))
fatalf(t, "CSAPI.MustDo %s %s returned non-2xx code: %s - body: %s", method, res.Request.URL.String(), res.Status, string(body))
}
return res
}
Expand All @@ -497,7 +512,7 @@ func (c *CSAPI) Do(t TestLike, method string, paths []string, opts ...RequestOpt
reqURL := c.BaseURL + "/" + strings.Join(paths, "/")
req, err := http.NewRequest(method, reqURL, nil)
if err != nil {
t.Fatalf("CSAPI.Do failed to create http.NewRequest: %s", err)
fatalf(t, "CSAPI.Do failed to create http.NewRequest: %s", err)
}
// set defaults before RequestOpts
if c.AccessToken != "" {
Expand Down Expand Up @@ -534,14 +549,14 @@ func (c *CSAPI) Do(t TestLike, method string, paths []string, opts ...RequestOpt
// Perform the HTTP request
res, err := c.Client.Do(req)
if err != nil {
t.Fatalf("CSAPI.Do response returned error: %s", err)
fatalf(t, "CSAPI.Do response returned error: %s", err)
}
// debug log the response
if c.Debug && res != nil {
var dump []byte
dump, err = httputil.DumpResponse(res, true)
if err != nil {
t.Fatalf("CSAPI.Do failed to dump response body: %s", err)
fatalf(t, "CSAPI.Do failed to dump response body: %s", err)
}
t.Logf("%s", string(dump))
}
Expand All @@ -554,7 +569,7 @@ func (c *CSAPI) Do(t TestLike, method string, paths []string, opts ...RequestOpt
if res.Body != nil {
resBody, err = io.ReadAll(res.Body)
if err != nil {
t.Fatalf("CSAPI.Do failed to read response body for RetryUntil check: %s", err)
fatalf(t, "CSAPI.Do failed to read response body for RetryUntil check: %s", err)
}
res.Body = io.NopCloser(bytes.NewBuffer(resBody))
}
Expand All @@ -565,7 +580,7 @@ func (c *CSAPI) Do(t TestLike, method string, paths []string, opts ...RequestOpt
}
// condition not satisfied, do we timeout yet?
if time.Since(now) > retryUntil.timeout {
t.Fatalf("CSAPI.Do RetryUntil: %v %v timed out after %v", method, req.URL, retryUntil.timeout)
fatalf(t, "CSAPI.Do RetryUntil: %v %v timed out after %v", method, req.URL, retryUntil.timeout)
}
t.Logf("CSAPI.Do RetryUntil: %v %v response condition not yet met, retrying", method, req.URL)
// small sleep to avoid tight-looping
Expand Down Expand Up @@ -611,10 +626,10 @@ func GetJSONFieldStr(t TestLike, body []byte, wantKey string) string {
t.Helper()
res := gjson.GetBytes(body, wantKey)
if !res.Exists() {
t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body))
fatalf(t, "JSONFieldStr: key '%s' missing from %s", wantKey, string(body))
}
if res.Str == "" {
t.Fatalf("JSONFieldStr: key '%s' is not a string, body: %s", wantKey, string(body))
fatalf(t, "JSONFieldStr: key '%s' is not a string, body: %s", wantKey, string(body))
}
return res.Str
}
Expand All @@ -625,7 +640,7 @@ func GetJSONFieldStringArray(t TestLike, body []byte, wantKey string) []string {
res := gjson.GetBytes(body, wantKey)

if !res.Exists() {
t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body))
fatalf(t, "JSONFieldStr: key '%s' missing from %s", wantKey, string(body))
}

arrLength := len(res.Array())
Expand All @@ -648,10 +663,10 @@ func ParseJSON(t TestLike, res *http.Response) []byte {
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatalf("MustParseJSON: reading HTTP response body returned %s", err)
fatalf(t, "MustParseJSON: reading HTTP response body returned %s", err)
}
if !gjson.ValidBytes(body) {
t.Fatalf("MustParseJSON: Response is not valid JSON")
fatalf(t, "MustParseJSON: Response is not valid JSON")
}
return body
}
Expand Down Expand Up @@ -725,5 +740,5 @@ func mustRespond2xx(t TestLike, res *http.Response) {
}
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
t.Fatalf("CSAPI.Must: %s %s returned non-2xx code: %s - body: %s", res.Request.Method, res.Request.URL.String(), res.Status, string(body))
fatalf(t, "CSAPI.Must: %s %s returned non-2xx code: %s - body: %s", res.Request.Method, res.Request.URL.String(), res.Status, string(body))
}
2 changes: 1 addition & 1 deletion client/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (c *CSAPI) MustSyncUntil(t TestLike, syncReq SyncReq, checks ...SyncCheckOp
}
for {
if time.Since(start) > c.SyncUntilTimeout {
t.Fatalf("%s MustSyncUntil: timed out after %v. Seen %d /sync responses. %s", c.UserID, time.Since(start), numResponsesReturned, printErrors())
fatalf(t, "%s MustSyncUntil: timed out after %v. Seen %d /sync responses. %s", c.UserID, time.Since(start), numResponsesReturned, printErrors())
}
response, nextBatch := c.MustSync(t, syncReq)
syncReq.Since = nextBatch
Expand Down
53 changes: 34 additions & 19 deletions must/must.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,26 @@ import (
"github.com/matrix-org/complement/should"
)

const ansiRedForeground = "\x1b[31m"
const ansiResetForeground = "\x1b[39m"

// errorf is a wrapper around t.Errorf which prints the failing error message in red.
func errorf(t *testing.T, format string, args ...any) {
format = ansiRedForeground + format + ansiResetForeground
t.Errorf(format, args...)
}

// fatalf is a wrapper around t.Fatalf which prints the failing error message in red.
func fatalf(t *testing.T, format string, args ...any) {
format = ansiRedForeground + format + ansiResetForeground
t.Fatalf(format, args...)
}

// NotError will ensure `err` is nil else terminate the test with `msg`.
func NotError(t *testing.T, msg string, err error) {
t.Helper()
if err != nil {
t.Fatalf("must.NotError: %s -> %s", msg, err)
fatalf(t, "must.NotError: %s -> %s", msg, err)
}
}

Expand All @@ -31,7 +46,7 @@ func ParseJSON(t *testing.T, b io.ReadCloser) gjson.Result {
t.Helper()
res, err := should.ParseJSON(b)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
return res
}
Expand All @@ -42,7 +57,7 @@ func MatchRequest(t *testing.T, req *http.Request, m match.HTTPRequest) []byte {
t.Helper()
res, err := should.MatchRequest(req, m)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
return res
}
Expand All @@ -52,7 +67,7 @@ func MatchRequest(t *testing.T, req *http.Request, m match.HTTPRequest) []byte {
func MatchSuccess(t *testing.T, res *http.Response) {
t.Helper()
if err := should.MatchSuccess(res); err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -61,7 +76,7 @@ func MatchSuccess(t *testing.T, res *http.Response) {
func MatchFailure(t *testing.T, res *http.Response) {
t.Helper()
if err := should.MatchFailure(res); err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -71,7 +86,7 @@ func MatchResponse(t *testing.T, res *http.Response, m match.HTTPResponse) []byt
t.Helper()
body, err := should.MatchResponse(res, m)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
return body
}
Expand All @@ -81,7 +96,7 @@ func MatchFederationRequest(t *testing.T, fedReq *fclient.FederationRequest, mat
t.Helper()
err := should.MatchFederationRequest(fedReq)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -91,7 +106,7 @@ func MatchGJSON(t *testing.T, jsonResult gjson.Result, matchers ...match.JSON) {
t.Helper()
err := should.MatchGJSON(jsonResult, matchers...)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -101,7 +116,7 @@ func MatchJSONBytes(t *testing.T, rawJson []byte, matchers ...match.JSON) {
t.Helper()
err := should.MatchJSONBytes(rawJson, matchers...)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -110,7 +125,7 @@ func MatchJSONBytes(t *testing.T, rawJson []byte, matchers ...match.JSON) {
func Equal[V comparable](t *testing.T, got, want V, msg string) {
t.Helper()
if got != want {
t.Errorf("Equal %s: got '%v' want '%v'", msg, got, want)
errorf(t, "Equal %s: got '%v' want '%v'", msg, got, want)
}
}

Expand All @@ -119,7 +134,7 @@ func Equal[V comparable](t *testing.T, got, want V, msg string) {
func NotEqual[V comparable](t *testing.T, got, want V, msg string) {
t.Helper()
if got == want {
t.Errorf("NotEqual %s: got '%v', want '%v'", msg, got, want)
errorf(t, "NotEqual %s: got '%v', want '%v'", msg, got, want)
}
}

Expand All @@ -128,7 +143,7 @@ func NotEqual[V comparable](t *testing.T, got, want V, msg string) {
func StartWithStr(t *testing.T, got, wantPrefix, msg string) {
t.Helper()
if !strings.HasPrefix(got, wantPrefix) {
t.Errorf("StartWithStr: %s: got '%s' without prefix '%s'", msg, got, wantPrefix)
errorf(t, "StartWithStr: %s: got '%s' without prefix '%s'", msg, got, wantPrefix)
}
}

Expand All @@ -138,7 +153,7 @@ func GetJSONFieldStr(t *testing.T, body gjson.Result, wantKey string) string {
t.Helper()
str, err := should.GetJSONFieldStr(body, wantKey)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
return str
}
Expand All @@ -149,7 +164,7 @@ func HaveInOrder[V comparable](t *testing.T, gots []V, wants []V) {
t.Helper()
err := should.HaveInOrder(gots, wants)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -160,7 +175,7 @@ func ContainSubset[V comparable](t *testing.T, larger []V, smaller []V) {
t.Helper()
err := should.ContainSubset(larger, smaller)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -171,7 +186,7 @@ func NotContainSubset[V comparable](t *testing.T, larger []V, smaller []V) {
t.Helper()
err := should.NotContainSubset(larger, smaller)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -185,7 +200,7 @@ func CheckOffAll(t *testing.T, items []interface{}, wantItems []interface{}) {
t.Helper()
err := should.CheckOffAll(items, wantItems)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
}

Expand All @@ -199,7 +214,7 @@ func CheckOffAllAllowUnwanted(t *testing.T, items []interface{}, wantItems []int
t.Helper()
result, err := should.CheckOffAllAllowUnwanted(items, wantItems)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
return result
}
Expand All @@ -212,7 +227,7 @@ func CheckOff(t *testing.T, items []interface{}, wantItem interface{}) []interfa
t.Helper()
result, err := should.CheckOff(items, wantItem)
if err != nil {
t.Fatalf(err.Error())
fatalf(t, err.Error())
}
return result
}
Expand Down

0 comments on commit 73ee61e

Please sign in to comment.