Skip to content

Commit

Permalink
Bitfinex: Add TestGetErrResp
Browse files Browse the repository at this point in the history
Also turns the WS field parsing errors into a common error const
  • Loading branch information
gbjk committed Oct 21, 2023
1 parent 6aa9a77 commit d10684d
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 11 deletions.
33 changes: 33 additions & 0 deletions exchanges/bitfinex/bitfinex_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bitfinex

import (
"bufio"
"context"
"errors"
"log"
Expand Down Expand Up @@ -1870,6 +1871,38 @@ func TestCancelMultipleOrdersV2(t *testing.T) {
}
}

func TestGetErrResp(t *testing.T) {
t.Parallel()
fixture, err := os.Open("testdata/getErrResp.json")
if !assert.NoError(t, err, "Opening fixture should not error") {
t.FailNow()
}
s := bufio.NewScanner(fixture)
seen := 0
for s.Scan() {
testErr := b.getErrResp(s.Bytes())
seen++
switch seen {
case 1: // no event
assert.ErrorIs(t, testErr, errParsingWSField, "Message with no event Should get correct error type")
assert.ErrorContains(t, testErr, "'event'", "Message with no event error should contain missing field name")
assert.ErrorContains(t, testErr, "nightjar", "Message with no event error should contain the message")
case 2: // with {} for event
assert.NoError(t, testErr, "Message with '{}' for event field should not error")
case 3: // event != 'error'
assert.NoError(t, testErr, "Message with non-'error' event field should not error")
case 4: // event="error"
assert.ErrorIs(t, testErr, errUnknownError, "error without a message should throw unknown error")
assert.ErrorContains(t, testErr, "code: 0", "error without a code should throw code 0")
case 5: // Fully formatted
assert.ErrorContains(t, testErr, "redcoats", "message field should be in the error")
assert.ErrorContains(t, testErr, "code: 42", "code field should be in the error")
}
}
assert.NoError(t, s.Err(), "Fixture Scanner should not error")
assert.NoError(t, fixture.Close(), "Closing the fixture file should not error")
}

// setupWs is a helper function to connect both auth and normal websockets
// It will skip the test if websockets are not enabled
// It's up to the test to skip if it requires creds, though
Expand Down
1 change: 1 addition & 0 deletions exchanges/bitfinex/bitfinex_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var (
errNoSeqNo = errors.New("no sequence number")
errUnknownError = errors.New("unknown error")
errParamNotAllowed = errors.New("param not allowed")
errParsingWSField = errors.New("error parsing WS field")
)

// AccountV2Data stores account v2 data
Expand Down
21 changes: 10 additions & 11 deletions exchanges/bitfinex/bitfinex_websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,21 +426,21 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
func (b *Bitfinex) handleWSEvent(respRaw []byte) error {
event, err := jsonparser.GetUnsafeString(respRaw, "event")
if err != nil {
return fmt.Errorf("error parsing WS event name: %w from message: %s", err, respRaw)
return fmt.Errorf("%w 'event': %w from message: %s", errParsingWSField, err, respRaw)
}
switch event {
case wsEventSubscribed:
subID, err := jsonparser.GetUnsafeString(respRaw, "subId")
if err != nil {
return fmt.Errorf("error parsing WS subscribed event subId: %w from message: %s", err, respRaw)
return fmt.Errorf("%w 'subId': %w from message: %s", errParsingWSField, err, respRaw)
}
if !b.Websocket.Match.IncomingWithData("subscribe:"+subID, respRaw) {
return fmt.Errorf("%v channel subscribe listener not found", subID)
}
case wsEventUnsubscribed:
chanID, err := jsonparser.GetUnsafeString(respRaw, "chanId")
if err != nil {
return fmt.Errorf("error parsing WS unsubscribed event chanId: %w from message: %s", err, respRaw)
return fmt.Errorf("%w 'chanId': %w from message: %s", errParsingWSField, err, respRaw)
}
if !b.Websocket.Match.IncomingWithData("unsubscribe:"+chanID, respRaw) {
return fmt.Errorf("%v channel unsubscribe listener not found", chanID)
Expand All @@ -460,7 +460,7 @@ func (b *Bitfinex) handleWSEvent(respRaw []byte) error {
case wsEventAuth:
status, err := jsonparser.GetUnsafeString(respRaw, "status")
if err != nil {
return fmt.Errorf("error parsing WS auth event status: %w from message: %s", err, respRaw)
return fmt.Errorf("%w 'status': %w from message: %s", errParsingWSField, err, respRaw)
}
if status == "OK" {
var glob map[string]interface{}
Expand All @@ -472,7 +472,7 @@ func (b *Bitfinex) handleWSEvent(respRaw []byte) error {
} else {
errCode, err := jsonparser.GetInt(respRaw, "code")
if err != nil {
log.Errorf(log.ExchangeSys, "%s error parsing WS auth event error code: %s", b.Name, err)
log.Errorf(log.ExchangeSys, "%s %s 'code': %s from message: %s", b.Name, errParsingWSField, err, respRaw)
}
return fmt.Errorf("WS auth subscription error; Status: %s Error Code: %d", status, errCode)
}
Expand All @@ -482,7 +482,7 @@ func (b *Bitfinex) handleWSEvent(respRaw []byte) error {
case wsEventConf:
status, err := jsonparser.GetUnsafeString(respRaw, "status")
if err != nil {
return fmt.Errorf("error parsing WS configure channel event status: %w from message: %s", err, respRaw)
return fmt.Errorf("%w 'status': %w from message: %s", errParsingWSField, err, respRaw)
}
if status != "OK" {
return fmt.Errorf("WS configure channel error; Status: %s", status)
Expand Down Expand Up @@ -1695,7 +1695,7 @@ func (b *Bitfinex) subscribeToChan(c *stream.ChannelSubscription) error {

chanID, err := jsonparser.GetInt(respRaw, "chanId")
if err != nil {
return fmt.Errorf("%w: error parsing chanId: %w; Channel: %s Pair: %s", stream.ErrSubscriptionFailure, err, c.Channel, c.Currency)
return fmt.Errorf("%w: %w 'chanId': %w; Channel: %s Pair: %s", stream.ErrSubscriptionFailure, errParsingWSField, err, c.Channel, c.Currency)
}

c.Key = int(chanID)
Expand Down Expand Up @@ -1798,20 +1798,19 @@ func (b *Bitfinex) unsubscribeFromChan(c *stream.ChannelSubscription) error {
func (b *Bitfinex) getErrResp(resp []byte) error {
event, err := jsonparser.GetUnsafeString(resp, "event")
if err != nil {
return fmt.Errorf("error parsing WS event: %w from message: %s", err, resp)
return fmt.Errorf("%w 'event': %w from message: %s", errParsingWSField, err, resp)
}

if event != "error" {
return nil
}
errCode, err := jsonparser.GetInt(resp, "code")
if err != nil {
log.Errorf(log.ExchangeSys, "%s error parsing WS error code: %s from message: %s", b.Name, err, resp)
log.Errorf(log.ExchangeSys, "%s %s 'code': %s from message: %s", b.Name, errParsingWSField, err, resp)
}

var apiErr error
if msg, e2 := jsonparser.GetString(resp, "msg"); e2 != nil {
log.Errorf(log.ExchangeSys, "%s error parsing WS error msg: %s from message: %s", b.Name, e2, resp)
log.Errorf(log.ExchangeSys, "%s %s 'msg': %s from message: %s", b.Name, errParsingWSField, e2, resp)
apiErr = errUnknownError
} else {
apiErr = errors.New(msg)
Expand Down
5 changes: 5 additions & 0 deletions exchanges/bitfinex/testdata/getErrResp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{"bird": "great eared nightjar", "you_are_welcome":true}
{"event": {}}
{"event": "sneezegasm"}
{"event": "error"}
{"event": "error", "msg":"redcoats", "code":42}

0 comments on commit d10684d

Please sign in to comment.