Add missing error checks

Adds missing error checks to godo. Ensures calls to Client.Do and json decoding are evaluated when neccessary.
This commit is contained in:
bryanl 2015-03-21 15:17:47 -04:00
parent ca5927e395
commit f1424cedf5
8 changed files with 95 additions and 34 deletions

View File

@ -252,7 +252,11 @@ func TestDomains_CreateRecordForDomainName(t *testing.T) {
mux.HandleFunc("/v2/domains/example.com/records",
func(w http.ResponseWriter, r *http.Request) {
v := new(DomainRecordEditRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, createRequest) {
@ -288,7 +292,10 @@ func TestDomains_EditRecordForDomainName(t *testing.T) {
mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) {
v := new(DomainRecordEditRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "PUT")
if !reflect.DeepEqual(v, editRequest) {

View File

@ -24,7 +24,10 @@ func TestDropletActions_Shutdown(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, request) {
@ -55,7 +58,10 @@ func TestDropletAction_PowerOff(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, request) {
@ -86,7 +92,10 @@ func TestDropletAction_PowerOn(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, request) {
@ -117,7 +126,10 @@ func TestDropletAction_Reboot(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, request) {
@ -150,7 +162,10 @@ func TestDropletAction_Restore(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
@ -185,7 +200,10 @@ func TestDropletAction_Resize(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
@ -219,7 +237,10 @@ func TestDropletAction_Rename(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
@ -251,7 +272,10 @@ func TestDropletAction_PowerCycle(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, request) {
@ -284,7 +308,10 @@ func TestDropletAction_Snapshot(t *testing.T) {
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")

View File

@ -147,7 +147,7 @@ func TestDroplets_Create(t *testing.T) {
var v map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&v)
if err != nil {
t.Fatal(err)
t.Fatalf("decode json: %v", err)
}
if !reflect.DeepEqual(v, expected) {

21
godo.go
View File

@ -223,7 +223,9 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
return nil, err
}
defer resp.Body.Close()
defer func() {
err = resp.Body.Close()
}()
response := newResponse(resp)
c.Rate = response.Rate
@ -235,9 +237,15 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
if v != nil {
if w, ok := v.(io.Writer); ok {
io.Copy(w, resp.Body)
_, err := io.Copy(w, resp.Body)
if err != nil {
return nil, err
}
} else {
json.NewDecoder(resp.Body).Decode(v)
err := json.NewDecoder(resp.Body).Decode(v)
if err != nil {
return nil, err
}
}
}
@ -259,7 +267,10 @@ func CheckResponse(r *http.Response) error {
errorResponse := &ErrorResponse{Response: r}
data, err := ioutil.ReadAll(r.Body)
if err == nil && len(data) > 0 {
json.Unmarshal(data, errorResponse)
err := json.Unmarshal(data, errorResponse)
if err != nil {
return err
}
}
return errorResponse
@ -297,6 +308,6 @@ func Bool(v bool) *bool {
// StreamToString converts a reader to a string
func StreamToString(stream io.Reader) string {
buf := new(bytes.Buffer)
buf.ReadFrom(stream)
_, _ = buf.ReadFrom(stream)
return buf.String()
}

View File

@ -48,7 +48,11 @@ func testFormValues(t *testing.T, r *http.Request, values values) {
expected.Add(k, v)
}
r.ParseForm()
err := r.ParseForm()
if err != nil {
t.Fatalf("parseForm(): %v", err)
}
if !reflect.DeepEqual(expected, r.Form) {
t.Errorf("Request parameters = %v, expected %v", r.Form, expected)
}
@ -141,7 +145,10 @@ func TestDo(t *testing.T) {
req, _ := client.NewRequest("GET", "/", nil)
body := new(foo)
client.Do(req, body)
_, err := client.Do(req, body)
if err != nil {
t.Fatalf("Do(): %v", err)
}
expected := &foo{"a"}
if !reflect.DeepEqual(body, expected) {
@ -261,7 +268,10 @@ func TestDo_rateLimit(t *testing.T) {
}
req, _ := client.NewRequest("GET", "/", nil)
client.Do(req, nil)
_, err := client.Do(req, nil)
if err != nil {
t.Fatalf("Do(): %v", err)
}
if expected = 60; client.Rate.Limit != expected {
t.Errorf("Client rate limit = %v, expected %v", client.Rate.Limit, expected)
@ -283,13 +293,13 @@ func TestDo_rateLimit_errorResponse(t *testing.T) {
w.Header().Add(headerRateLimit, "60")
w.Header().Add(headerRateRemaining, "59")
w.Header().Add(headerRateReset, "1372700873")
http.Error(w, "Bad Request", 400)
http.Error(w, `{"message":"bad request"}`, 400)
})
var expected int
req, _ := client.NewRequest("GET", "/", nil)
client.Do(req, nil)
_, _ = client.Do(req, nil)
if expected = 60; client.Rate.Limit != expected {
t.Errorf("Client rate limit = %v, expected %v", client.Rate.Limit, expected)

View File

@ -22,7 +22,10 @@ func TestImageActions_Transfer(t *testing.T) {
mux.HandleFunc("/v2/images/12345/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, transferRequest) {

View File

@ -131,7 +131,10 @@ func TestKeys_Create(t *testing.T) {
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
v := new(KeyCreateRequest)
json.NewDecoder(r.Body).Decode(v)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, createRequest) {

View File

@ -20,7 +20,7 @@ func Stringify(message interface{}) string {
// stringifyValue was graciously cargoculted from the goprotubuf library
func stringifyValue(w io.Writer, val reflect.Value) {
if val.Kind() == reflect.Ptr && val.IsNil() {
w.Write([]byte("<nil>"))
_, _ = w.Write([]byte("<nil>"))
return
}
@ -30,20 +30,20 @@ func stringifyValue(w io.Writer, val reflect.Value) {
case reflect.String:
fmt.Fprintf(w, `"%s"`, v)
case reflect.Slice:
w.Write([]byte{'['})
_, _ = w.Write([]byte{'['})
for i := 0; i < v.Len(); i++ {
if i > 0 {
w.Write([]byte{' '})
_, _ = w.Write([]byte{' '})
}
stringifyValue(w, v.Index(i))
}
w.Write([]byte{']'})
_, _ = w.Write([]byte{']'})
return
case reflect.Struct:
if v.Type().Name() != "" {
w.Write([]byte(v.Type().String()))
_, _ = w.Write([]byte(v.Type().String()))
}
// special handling of Timestamp values
@ -52,7 +52,7 @@ func stringifyValue(w io.Writer, val reflect.Value) {
return
}
w.Write([]byte{'{'})
_, _ = w.Write([]byte{'{'})
var sep bool
for i := 0; i < v.NumField(); i++ {
@ -65,17 +65,17 @@ func stringifyValue(w io.Writer, val reflect.Value) {
}
if sep {
w.Write([]byte(", "))
_, _ = w.Write([]byte(", "))
} else {
sep = true
}
w.Write([]byte(v.Type().Field(i).Name))
w.Write([]byte{':'})
_, _ = w.Write([]byte(v.Type().Field(i).Name))
_, _ = w.Write([]byte{':'})
stringifyValue(w, fv)
}
w.Write([]byte{'}'})
_, _ = w.Write([]byte{'}'})
default:
if v.CanInterface() {
fmt.Fprint(w, v.Interface())