From d5f8d57bf225ba7ac3ab3fcced12ef4260faa284 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Thu, 12 Oct 2017 20:47:44 -0400 Subject: [PATCH] testing: Add tests for fetching multiple securities --- internal/handlers/errors.go | 1 + internal/handlers/securities.go | 16 ++++- internal/handlers/securities_test.go | 102 +++++++++++++++++++++++++-- 3 files changed, 112 insertions(+), 7 deletions(-) diff --git a/internal/handlers/errors.go b/internal/handlers/errors.go index 1c0928f..17a5c0c 100644 --- a/internal/handlers/errors.go +++ b/internal/handlers/errors.go @@ -34,6 +34,7 @@ var error_codes = map[int]string{ 4: "User Exists", // 5: "Connection Failed", //reserved for client-side error 6: "Import Error", + 7: "In Use Error", 999: "Internal Error", } diff --git a/internal/handlers/securities.go b/internal/handlers/securities.go index fba8363..7333d65 100644 --- a/internal/handlers/securities.go +++ b/internal/handlers/securities.go @@ -183,6 +183,14 @@ func UpdateSecurity(db *DB, s *Security) error { return nil } +type SecurityInUseError struct { + message string +} + +func (e SecurityInUseError) Error() string { + return e.message +} + func DeleteSecurity(db *DB, s *Security) error { transaction, err := db.Begin() if err != nil { @@ -194,7 +202,7 @@ func DeleteSecurity(db *DB, s *Security) error { if accounts != 0 { transaction.Rollback() - return errors.New("One or more accounts still use this security") + return SecurityInUseError{"One or more accounts still use this security"} } user, err := GetUserTx(transaction, s.UserId) @@ -203,7 +211,7 @@ func DeleteSecurity(db *DB, s *Security) error { return err } else if user.DefaultCurrency == s.SecurityId { transaction.Rollback() - return errors.New("Cannot delete security which is user's default currency") + return SecurityInUseError{"Cannot delete security which is user's default currency"} } // Remove all prices involving this security (either of this security, or @@ -401,7 +409,9 @@ func SecurityHandler(w http.ResponseWriter, r *http.Request, db *DB) { } err = DeleteSecurity(db, security) - if err != nil { + if _, ok := err.(SecurityInUseError); ok { + WriteError(w, 7 /*In Use Error*/) + } else if err != nil { WriteError(w, 999 /*Internal Error*/) log.Print(err) return diff --git a/internal/handlers/securities_test.go b/internal/handlers/securities_test.go index f749b61..de9c036 100644 --- a/internal/handlers/securities_test.go +++ b/internal/handlers/securities_test.go @@ -22,6 +22,15 @@ func getSecurity(client *http.Client, securityid int64) (*handlers.Security, err return &s, nil } +func getSecurities(client *http.Client) (*handlers.SecurityList, error) { + var sl handlers.SecurityList + err := read(client, &sl, "/security/", "securities") + if err != nil { + return nil, err + } + return &sl, nil +} + func updateSecurity(client *http.Client, security *handlers.Security) (*handlers.Security, error) { var s handlers.Security err := update(client, security, &s, "/security/"+strconv.FormatInt(security.SecurityId, 10), "security") @@ -41,7 +50,7 @@ func deleteSecurity(client *http.Client, s *handlers.Security) error { func TestCreateSecurity(t *testing.T) { RunWith(t, &data[0], func(t *testing.T, d *TestData) { - for i := 1; i < len(data[0].securities); i++ { + for i := 0; i < len(data[0].securities); i++ { orig := data[0].securities[i] s := d.securities[i] @@ -72,7 +81,7 @@ func TestCreateSecurity(t *testing.T) { func TestGetSecurity(t *testing.T) { RunWith(t, &data[0], func(t *testing.T, d *TestData) { - for i := 1; i < len(data[0].securities); i++ { + for i := 0; i < len(data[0].securities); i++ { orig := data[0].securities[i] curr := d.securities[i] @@ -105,9 +114,59 @@ func TestGetSecurity(t *testing.T) { }) } +func TestGetSecurities(t *testing.T) { + RunWith(t, &data[0], func(t *testing.T, d *TestData) { + sl, err := getSecurities(d.clients[0]) + if err != nil { + t.Fatalf("Error fetching securities: %s\n", err) + } + + numsecurities := 0 + foundIds := make(map[int64]bool) + for i := 0; i < len(data[0].securities); i++ { + orig := data[0].securities[i] + curr := d.securities[i] + + if curr.UserId != d.users[0].UserId { + continue + } + numsecurities += 1 + + found := false + for _, s := range *sl.Securities { + if orig.Name == s.Name && orig.Description == s.Description && orig.Symbol == orig.Symbol && orig.Precision == s.Precision && orig.Type == s.Type && orig.AlternateId == s.AlternateId { + if _, ok := foundIds[s.SecurityId]; ok { + continue + } + foundIds[s.SecurityId] = true + found = true + break + } + } + if !found { + t.Errorf("Unable to find matching security: %+v", curr) + } + } + + if numsecurities+1 == len(*sl.Securities) { + for _, s := range *sl.Securities { + if _, ok := foundIds[s.SecurityId]; !ok { + if s.SecurityId == d.users[0].DefaultCurrency { + t.Fatalf("Extra security wasn't default currency, seems like an extra security was created") + } + break + } + } + } else if numsecurities != len(*sl.Securities) { + t.Errorf("%+v\n", *sl.Securities) + t.Fatalf("Expected %d securities, received %d", numsecurities, len(*sl.Securities)) + } + }) +} + func TestUpdateSecurity(t *testing.T) { RunWith(t, &data[0], func(t *testing.T, d *TestData) { - for i := 1; i < len(data[0].securities); i++ { + for i := 0; i < len(data[0].securities); i++ { orig := data[0].securities[i] curr := d.securities[i] @@ -148,10 +207,17 @@ func TestUpdateSecurity(t *testing.T) { func TestDeleteSecurity(t *testing.T) { RunWith(t, &data[0], func(t *testing.T, d *TestData) { - for i := 1; i < len(data[0].securities); i++ { + Outer: + for i := 0; i < len(data[0].securities); i++ { orig := data[0].securities[i] curr := d.securities[i] + for _, a := range d.accounts { + if a.SecurityId == curr.SecurityId { + continue Outer + } + } + err := deleteSecurity(d.clients[orig.UserId], &curr) if err != nil { t.Fatalf("Error deleting security: %s\n", err) @@ -171,3 +237,31 @@ func TestDeleteSecurity(t *testing.T) { } }) } + +func TestDontDeleteSecurity(t *testing.T) { + RunWith(t, &data[0], func(t *testing.T, d *TestData) { + Outer: + for i := 0; i < len(data[0].securities); i++ { + orig := data[0].securities[i] + curr := d.securities[i] + + for _, a := range d.accounts { + if a.SecurityId != curr.SecurityId { + continue Outer + } + } + + err := deleteSecurity(d.clients[orig.UserId], &curr) + if err == nil { + t.Fatalf("Expected error deleting in-use security") + } + if herr, ok := err.(*handlers.Error); ok { + if herr.ErrorId != 7 { // In Use Error + t.Fatalf("Unexpected API error deleting in-use security: %s", herr) + } + } else { + t.Fatalf("Unexpected error deleting in-use security") + } + } + }) +}