From 23586dbcd0fad8af9dc518aa625bae7b5e296b80 Mon Sep 17 00:00:00 2001 From: nmalhotra Date: Sat, 2 Mar 2019 14:10:17 -0500 Subject: [PATCH] Added enhancement for #57 and UT coverage for #13 - Added query filter for attack status - Added more UT coverage --- internal/dispatcher/dispatcher.go | 6 +- internal/dispatcher/dispatcher_test.go | 8 +- internal/dispatcher/mocks/IDispatcher.go | 10 +- internal/dispatcher/mocks/ITask.go | 161 ++++++++++ internal/dispatcher/mocks/ITaskActions.go | 73 +++++ internal/dispatcher/mocks/ITaskGetter.go | 99 ++++++ internal/endpoints/attack.go | 8 +- internal/endpoints/attack_test.go | 32 +- internal/reporter/reporter.go | 2 +- models/attack.go | 24 ++ models/db.go | 26 +- models/db_test.go | 356 ++++++++++++++++++++++ models/mocks/IAttackStore.go | 10 +- 13 files changed, 793 insertions(+), 22 deletions(-) create mode 100644 internal/dispatcher/mocks/ITask.go create mode 100644 internal/dispatcher/mocks/ITaskActions.go create mode 100644 internal/dispatcher/mocks/ITaskGetter.go create mode 100644 models/db_test.go diff --git a/internal/dispatcher/dispatcher.go b/internal/dispatcher/dispatcher.go index 289d3e0..2017349 100644 --- a/internal/dispatcher/dispatcher.go +++ b/internal/dispatcher/dispatcher.go @@ -27,7 +27,7 @@ type IDispatcher interface { // Get the attack status, params and ID for a single attack Get(string) (*models.AttackResponse, error) // List the attack status, params and ID for all submitted attacks. - List() []*models.AttackResponse + List(models.FilterParams) []*models.AttackResponse } type dispatcher struct { @@ -181,12 +181,12 @@ func (d *dispatcher) Get(id string) (*models.AttackResponse, error) { } // List all submitted attacks -func (d *dispatcher) List() []*models.AttackResponse { +func (d *dispatcher) List(filters models.FilterParams) []*models.AttackResponse { d.log(nil).Debug("getting attack list") responses := make([]*models.AttackResponse, 0) - for _, attackDetails := range d.db.GetAll() { + for _, attackDetails := range d.db.GetAll(filters) { resp := models.AttackResponse(attackDetails.AttackInfo) responses = append(responses, &resp) } diff --git a/internal/dispatcher/dispatcher_test.go b/internal/dispatcher/dispatcher_test.go index 9500f16..e22208f 100644 --- a/internal/dispatcher/dispatcher_test.go +++ b/internal/dispatcher/dispatcher_test.go @@ -314,11 +314,11 @@ func Test_dispatcher_Get_Error_GetByID(t *testing.T) { func Test_dispatcher_List(t *testing.T) { mockStore := &smocks.IAttackStore{} - mockStore.On("GetAll").Return([]models.AttackDetails{{}}) + mockStore.On("GetAll", make(models.FilterParams)).Return([]models.AttackDetails{{}}) d := setupDispatcher(mockStore) - got := d.List() + got := d.List(make(models.FilterParams)) if len(got) == 0 { t.Fail() } @@ -327,11 +327,11 @@ func Test_dispatcher_List(t *testing.T) { func Test_dispatcher_List_Empty(t *testing.T) { mockStore := &smocks.IAttackStore{} - mockStore.On("GetAll").Return([]models.AttackDetails{}) + mockStore.On("GetAll", make(models.FilterParams)).Return([]models.AttackDetails{}) d := setupDispatcher(mockStore) - got := d.List() + got := d.List(make(models.FilterParams)) if len(got) != 0 { t.Fail() } diff --git a/internal/dispatcher/mocks/IDispatcher.go b/internal/dispatcher/mocks/IDispatcher.go index d3ad825..fe238bd 100644 --- a/internal/dispatcher/mocks/IDispatcher.go +++ b/internal/dispatcher/mocks/IDispatcher.go @@ -70,13 +70,13 @@ func (_m *IDispatcher) Get(_a0 string) (*models.AttackResponse, error) { return r0, r1 } -// List provides a mock function with given fields: -func (_m *IDispatcher) List() []*models.AttackResponse { - ret := _m.Called() +// List provides a mock function with given fields: _a0 +func (_m *IDispatcher) List(_a0 models.FilterParams) []*models.AttackResponse { + ret := _m.Called(_a0) var r0 []*models.AttackResponse - if rf, ok := ret.Get(0).(func() []*models.AttackResponse); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(models.FilterParams) []*models.AttackResponse); ok { + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*models.AttackResponse) diff --git a/internal/dispatcher/mocks/ITask.go b/internal/dispatcher/mocks/ITask.go new file mode 100644 index 0000000..c8e4fd8 --- /dev/null +++ b/internal/dispatcher/mocks/ITask.go @@ -0,0 +1,161 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import dispatcher "vegeta-server/internal/dispatcher" +import io "io" +import mock "github.com/stretchr/testify/mock" +import models "vegeta-server/models" +import time "time" + +// ITask is an autogenerated mock type for the ITask type +type ITask struct { + mock.Mock +} + +// Cancel provides a mock function with given fields: +func (_m *ITask) Cancel() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Complete provides a mock function with given fields: _a0 +func (_m *ITask) Complete(_a0 io.Reader) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(io.Reader) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CreatedAt provides a mock function with given fields: +func (_m *ITask) CreatedAt() time.Time { + ret := _m.Called() + + var r0 time.Time + if rf, ok := ret.Get(0).(func() time.Time); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Time) + } + + return r0 +} + +// Fail provides a mock function with given fields: +func (_m *ITask) Fail() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ID provides a mock function with given fields: +func (_m *ITask) ID() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// Params provides a mock function with given fields: +func (_m *ITask) Params() models.AttackParams { + ret := _m.Called() + + var r0 models.AttackParams + if rf, ok := ret.Get(0).(func() models.AttackParams); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(models.AttackParams) + } + + return r0 +} + +// Result provides a mock function with given fields: +func (_m *ITask) Result() io.Reader { + ret := _m.Called() + + var r0 io.Reader + if rf, ok := ret.Get(0).(func() io.Reader); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(io.Reader) + } + } + + return r0 +} + +// Run provides a mock function with given fields: _a0 +func (_m *ITask) Run(_a0 dispatcher.AttackFunc) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(dispatcher.AttackFunc) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SendUpdate provides a mock function with given fields: +func (_m *ITask) SendUpdate() { + _m.Called() +} + +// Status provides a mock function with given fields: +func (_m *ITask) Status() models.AttackStatus { + ret := _m.Called() + + var r0 models.AttackStatus + if rf, ok := ret.Get(0).(func() models.AttackStatus); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(models.AttackStatus) + } + + return r0 +} + +// UpdatedAt provides a mock function with given fields: +func (_m *ITask) UpdatedAt() time.Time { + ret := _m.Called() + + var r0 time.Time + if rf, ok := ret.Get(0).(func() time.Time); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Time) + } + + return r0 +} diff --git a/internal/dispatcher/mocks/ITaskActions.go b/internal/dispatcher/mocks/ITaskActions.go new file mode 100644 index 0000000..f36d909 --- /dev/null +++ b/internal/dispatcher/mocks/ITaskActions.go @@ -0,0 +1,73 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import dispatcher "vegeta-server/internal/dispatcher" +import io "io" +import mock "github.com/stretchr/testify/mock" + +// ITaskActions is an autogenerated mock type for the ITaskActions type +type ITaskActions struct { + mock.Mock +} + +// Cancel provides a mock function with given fields: +func (_m *ITaskActions) Cancel() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Complete provides a mock function with given fields: _a0 +func (_m *ITaskActions) Complete(_a0 io.Reader) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(io.Reader) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Fail provides a mock function with given fields: +func (_m *ITaskActions) Fail() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Run provides a mock function with given fields: _a0 +func (_m *ITaskActions) Run(_a0 dispatcher.AttackFunc) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(dispatcher.AttackFunc) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SendUpdate provides a mock function with given fields: +func (_m *ITaskActions) SendUpdate() { + _m.Called() +} diff --git a/internal/dispatcher/mocks/ITaskGetter.go b/internal/dispatcher/mocks/ITaskGetter.go new file mode 100644 index 0000000..70c50ca --- /dev/null +++ b/internal/dispatcher/mocks/ITaskGetter.go @@ -0,0 +1,99 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import io "io" +import mock "github.com/stretchr/testify/mock" +import models "vegeta-server/models" +import time "time" + +// ITaskGetter is an autogenerated mock type for the ITaskGetter type +type ITaskGetter struct { + mock.Mock +} + +// CreatedAt provides a mock function with given fields: +func (_m *ITaskGetter) CreatedAt() time.Time { + ret := _m.Called() + + var r0 time.Time + if rf, ok := ret.Get(0).(func() time.Time); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Time) + } + + return r0 +} + +// ID provides a mock function with given fields: +func (_m *ITaskGetter) ID() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// Params provides a mock function with given fields: +func (_m *ITaskGetter) Params() models.AttackParams { + ret := _m.Called() + + var r0 models.AttackParams + if rf, ok := ret.Get(0).(func() models.AttackParams); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(models.AttackParams) + } + + return r0 +} + +// Result provides a mock function with given fields: +func (_m *ITaskGetter) Result() io.Reader { + ret := _m.Called() + + var r0 io.Reader + if rf, ok := ret.Get(0).(func() io.Reader); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(io.Reader) + } + } + + return r0 +} + +// Status provides a mock function with given fields: +func (_m *ITaskGetter) Status() models.AttackStatus { + ret := _m.Called() + + var r0 models.AttackStatus + if rf, ok := ret.Get(0).(func() models.AttackStatus); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(models.AttackStatus) + } + + return r0 +} + +// UpdatedAt provides a mock function with given fields: +func (_m *ITaskGetter) UpdatedAt() time.Time { + ret := _m.Called() + + var r0 time.Time + if rf, ok := ret.Get(0).(func() time.Time); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Time) + } + + return r0 +} diff --git a/internal/endpoints/attack.go b/internal/endpoints/attack.go index a722c55..f1a2c43 100644 --- a/internal/endpoints/attack.go +++ b/internal/endpoints/attack.go @@ -39,7 +39,13 @@ func (e *Endpoints) GetAttackByIDEndpoint(c *gin.Context) { // GetAttackEndpoint implements a handler for the GET /api/v1/attack endpoint func (e *Endpoints) GetAttackEndpoint(c *gin.Context) { - resp := e.dispatcher.List() + filterMap := make(models.FilterParams) + status := c.DefaultQuery("status", "") + filterMap["status"] = status + resp := e.dispatcher.List( + //models.StatusFilter(status), + filterMap, + ) c.JSON(http.StatusOK, resp) } diff --git a/internal/endpoints/attack_test.go b/internal/endpoints/attack_test.go index adef7ec..33e0e1d 100644 --- a/internal/endpoints/attack_test.go +++ b/internal/endpoints/attack_test.go @@ -72,6 +72,34 @@ func TestEndpoints_PostAttackEndpoint(t *testing.T) { http.StatusBadRequest, }, }, + { + name: "Internal Server Error - Dispatcher error", + params: params{ + func() (dispatcher.IDispatcher, *http.Request) { + attackParams := models.AttackParams{ + Rate: 1, + Target: models.Target{ + Method: "GET", + URL: "localhost:80/api/v1/", + Scheme: "http", + }, + Duration: "1s", + } + d := new(dmocks.IDispatcher) + + d. + On("Dispatch", attackParams). + Return(nil, fmt.Errorf("dispatcher error")) + bAttackParamsBody, _ := json.Marshal(attackParams) + attackParamsBody := string(bAttackParamsBody) + + req, _ := http.NewRequest("POST", "/api/v1/attack", strings.NewReader(attackParamsBody)) + + return d, req + }, + http.StatusInternalServerError, + }, + }, { name: "OK", params: params{ @@ -187,7 +215,9 @@ func TestEndpoints_GetAttackEndpoint(t *testing.T) { setup: func() (iDispatcher dispatcher.IDispatcher, request *http.Request) { d := &dmocks.IDispatcher{} d. - On("List"). + On("List", models.FilterParams{ + "status": "", + }). Return([]*models.AttackResponse{}) // Setup router diff --git a/internal/reporter/reporter.go b/internal/reporter/reporter.go index 3c9f908..413a832 100644 --- a/internal/reporter/reporter.go +++ b/internal/reporter/reporter.go @@ -49,7 +49,7 @@ func (r *reporter) Get(id string) ([]byte, error) { // GetAll returns a list of attack reports in byte array format // The default format, JSON is returned. func (r *reporter) GetAll() [][]byte { - attacks := r.db.GetAll() + attacks := r.db.GetAll(make(models.FilterParams)) reports := make([][]byte, 0) for _, attack := range attacks { // Canceled attacks will have a nil result field diff --git a/models/attack.go b/models/attack.go index 405eeb5..2c40b06 100644 --- a/models/attack.go +++ b/models/attack.go @@ -19,3 +19,27 @@ type AttackDetails struct { AttackInfo Result []byte `json:"result,omitempty"` } + +// FilterParams defines a map structure for the filter parameters received via +// query params in the request URL +type FilterParams map[string]interface{} + +// Filter defines a type that must be implemented by +// an attack filter +type Filter func(AttackDetails) bool + +// StatusFilter implements a attack status filter +// in the Filter function format +func StatusFilter(status string) Filter { + return func(a AttackDetails) bool { + if status == "" { + return true + } + + if a.Status == AttackStatus(status) { + return true + } + + return false + } +} diff --git a/models/db.go b/models/db.go index 5f46e71..25d0041 100644 --- a/models/db.go +++ b/models/db.go @@ -11,7 +11,7 @@ type IAttackStore interface { Add(AttackDetails) error // GetAll items - GetAll() []AttackDetails + GetAll(filters FilterParams) []AttackDetails // GetByID gets an item by its ID GetByID(string) (AttackDetails, error) @@ -45,13 +45,20 @@ func (tm TaskMap) Add(attack AttackDetails) error { } // GetAll attacks and details from store -func (tm TaskMap) GetAll() []AttackDetails { +func (tm TaskMap) GetAll(filterParams FilterParams) []AttackDetails { mu.RLock() defer mu.RUnlock() + filters := createFilterChain(filterParams) attacks := make([]AttackDetails, 0) for _, attack := range tm { + for _, filter := range filters { + if !filter(attack) { + goto skip + } + } attacks = append(attacks, attack) + skip: } return attacks @@ -72,6 +79,10 @@ func (tm TaskMap) GetByID(id string) (AttackDetails, error) { // Update an attack detail in the store func (tm TaskMap) Update(id string, attack AttackDetails) error { + if attack.ID != id { + return fmt.Errorf("update ID %s and attack ID %s do not match", id, attack.ID) + } + mu.RLock() _, ok := tm[id] mu.RUnlock() @@ -102,3 +113,14 @@ func (tm TaskMap) Delete(id string) error { return nil } + +func createFilterChain(params FilterParams) []Filter { + filters := make([]Filter, 0) + if status, ok := params["status"]; ok { + filters = append( + filters, + StatusFilter(status.(string)), + ) + } + return filters +} diff --git a/models/db_test.go b/models/db_test.go new file mode 100644 index 0000000..1bc3b6a --- /dev/null +++ b/models/db_test.go @@ -0,0 +1,356 @@ +package models + +import ( + "reflect" + "testing" +) + +func TestTaskMap_Add(t *testing.T) { + type args struct { + attack AttackDetails + } + tests := []struct { + name string + tm TaskMap + args args + wantErr bool + }{ + { + name: "OK", + tm: make(TaskMap), + args: args{ + attack: AttackDetails{ + AttackInfo: AttackInfo{ + ID: "123", + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.tm.Add(tt.args.attack); (err != nil) != tt.wantErr { + t.Errorf("TaskMap.Add() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestTaskMap_GetAll(t *testing.T) { + type args struct { + filterParams FilterParams + } + tests := []struct { + name string + tm TaskMap + args args + want []AttackDetails + }{ + { + name: "OK", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + }, + }, + }, + args: args{ + filterParams: make(FilterParams), + }, + want: []AttackDetails{ + { + AttackInfo: AttackInfo{ + ID: "1", + }, + }, + }, + }, + { + name: "OK - With Status filter match", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusCompleted, + }, + }, + }, + args: args{ + filterParams: FilterParams{ + "status": "completed", + }, + }, + want: []AttackDetails{ + { + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusCompleted, + }, + }, + }, + }, + { + name: "OK - With Status filter mismatch", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusCompleted, + }, + }, + }, + args: args{ + filterParams: FilterParams{ + "status": "failed", + }, + }, + want: []AttackDetails{}, + }, + { + name: "OK - With Status filter empty", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusCompleted, + }, + }, + }, + args: args{ + filterParams: FilterParams{ + "status": "", + }, + }, + want: []AttackDetails{ + { + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusCompleted, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.tm.GetAll(tt.args.filterParams); !reflect.DeepEqual(got, tt.want) { + t.Errorf("TaskMap.GetAll() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTaskMap_GetByID(t *testing.T) { + type args struct { + id string + } + tests := []struct { + name string + tm TaskMap + args args + want AttackDetails + wantErr bool + }{ + { + name: "OK", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + }, + }, + }, + args: args{ + id: "1", + }, + want: AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + }, + }, + wantErr: false, + }, + { + name: "OK", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + }, + }, + }, + args: args{ + id: "2", + }, + want: AttackDetails{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.tm.GetByID(tt.args.id) + if (err != nil) != tt.wantErr { + t.Errorf("TaskMap.GetByID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("TaskMap.GetByID() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTaskMap_Update(t *testing.T) { + type args struct { + id string + attack AttackDetails + } + tests := []struct { + name string + tm TaskMap + args args + wantErr bool + }{ + { + name: "OK", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusRunning, + }, + }, + }, + args: args{ + id: "1", + attack: AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusCompleted, + }, + }, + }, + wantErr: false, + }, + { + name: "Error : args id mismatch", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusRunning, + }, + }, + }, + args: args{ + id: "1", + attack: AttackDetails{ + AttackInfo: AttackInfo{ + ID: "2", + Status: AttackResponseStatusCompleted, + }, + }, + }, + wantErr: true, + }, + { + name: "Error : ID not found", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusRunning, + }, + }, + }, + args: args{ + id: "2", + attack: AttackDetails{ + AttackInfo: AttackInfo{ + ID: "2", + Status: AttackResponseStatusCompleted, + }, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.tm.Update(tt.args.id, tt.args.attack); (err != nil) != tt.wantErr { + t.Errorf("TaskMap.Update() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestTaskMap_Delete(t *testing.T) { + type args struct { + id string + } + tests := []struct { + name string + tm TaskMap + args args + wantErr bool + }{ + { + name: "OK", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusRunning, + }, + }, + }, + args: args{ + id: "1", + }, + wantErr: false, + }, + { + name: "OK", + tm: TaskMap{ + "1": AttackDetails{ + AttackInfo: AttackInfo{ + ID: "1", + Status: AttackResponseStatusRunning, + }, + }, + }, + args: args{ + id: "2", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.tm.Delete(tt.args.id); (err != nil) != tt.wantErr { + t.Errorf("TaskMap.Delete() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestNewTaskMap(t *testing.T) { + tests := []struct { + name string + want TaskMap + }{ + { + name: "OK", + want: make(TaskMap), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewTaskMap(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewTaskMap() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/models/mocks/IAttackStore.go b/models/mocks/IAttackStore.go index 232a480..71f734b 100644 --- a/models/mocks/IAttackStore.go +++ b/models/mocks/IAttackStore.go @@ -38,13 +38,13 @@ func (_m *IAttackStore) Delete(_a0 string) error { return r0 } -// GetAll provides a mock function with given fields: -func (_m *IAttackStore) GetAll() []models.AttackDetails { - ret := _m.Called() +// GetAll provides a mock function with given fields: filters +func (_m *IAttackStore) GetAll(filters models.FilterParams) []models.AttackDetails { + ret := _m.Called(filters) var r0 []models.AttackDetails - if rf, ok := ret.Get(0).(func() []models.AttackDetails); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(models.FilterParams) []models.AttackDetails); ok { + r0 = rf(filters) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]models.AttackDetails)