fix(actions): reject if client is disabled (#1626)

* fix(actions): error on disabled client

* fix(actions): sql scan args

* refactor: download client cache for actions

* fix: tests client store

* fix: tests client store and int conversion

* fix: tests revert findbyid ctx timeout

* fix: tests row.err

* feat: add logging to download client cache
This commit is contained in:
ze0s 2024-08-27 19:45:06 +02:00 committed by GitHub
parent 77e1c2c305
commit 861f30c144
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 928 additions and 680 deletions

View file

@ -30,7 +30,266 @@ func NewActionRepo(log logger.Logger, db *DB, clientRepo domain.DownloadClientRe
}
}
func (r *ActionRepo) FindByFilterID(ctx context.Context, filterID int, active *bool) ([]*domain.Action, error) {
func (r *ActionRepo) FindByFilterID(ctx context.Context, filterID int, active *bool, withClient bool) ([]*domain.Action, error) {
if withClient {
return r.findByFilterIDWithClient(ctx, filterID, active)
}
return r.findByFilterID(ctx, filterID, active)
}
func (r *ActionRepo) findByFilterID(ctx context.Context, filterID int, active *bool) ([]*domain.Action, error) {
queryBuilder := r.db.squirrel.
Select(
"a.id",
"a.name",
"a.type",
"a.enabled",
"a.exec_cmd",
"a.exec_args",
"a.watch_folder",
"a.category",
"a.tags",
"a.label",
"a.save_path",
"a.paused",
"a.ignore_rules",
"a.first_last_piece_prio",
"a.skip_hash_check",
"a.content_layout",
"a.priority",
"a.limit_download_speed",
"a.limit_upload_speed",
"a.limit_ratio",
"a.limit_seed_time",
"a.reannounce_skip",
"a.reannounce_delete",
"a.reannounce_interval",
"a.reannounce_max_attempts",
"a.webhook_host",
"a.webhook_type",
"a.webhook_method",
"a.webhook_data",
"a.external_client_id",
"a.external_client",
"a.client_id",
).
From("action a").
Where(sq.Eq{"a.filter_id": filterID})
if active != nil {
queryBuilder = queryBuilder.Where(sq.Eq{"enabled": *active})
}
query, args, err := queryBuilder.ToSql()
if err != nil {
return nil, errors.Wrap(err, "error building query")
}
rows, err := r.db.handler.QueryContext(ctx, query, args...)
if err != nil {
return nil, errors.Wrap(err, "error executing query")
}
defer rows.Close()
actions := make([]*domain.Action, 0)
for rows.Next() {
var a domain.Action
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData, externalClient sql.NullString
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var externalClientID, clientID sql.NullInt32
var paused, ignoreRules sql.NullBool
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.FirstLastPiecePrio, &a.SkipHashCheck, &contentLayout, &priorityLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &externalClient, &clientID); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
a.ExecCmd = execCmd.String
a.ExecArgs = execArgs.String
a.WatchFolder = watchFolder.String
a.Category = category.String
a.Tags = tags.String
a.Label = label.String
a.SavePath = savePath.String
a.Paused = paused.Bool
a.IgnoreRules = ignoreRules.Bool
a.ContentLayout = domain.ActionContentLayout(contentLayout.String)
a.PriorityLayout = domain.PriorityLayout(priorityLayout.String)
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
a.LimitRatio = limitRatio.Float64
a.LimitSeedTime = limitSeedTime.Int64
a.WebhookHost = webhookHost.String
a.WebhookType = webhookType.String
a.WebhookMethod = webhookMethod.String
a.WebhookData = webhookData.String
a.ExternalDownloadClientID = externalClientID.Int32
a.ExternalDownloadClient = externalClient.String
a.ClientID = clientID.Int32
actions = append(actions, &a)
}
if err := rows.Err(); err != nil {
return nil, errors.Wrap(err, "row error")
}
return actions, nil
}
func (r *ActionRepo) findByFilterIDWithClient(ctx context.Context, filterID int, active *bool) ([]*domain.Action, error) {
queryBuilder := r.db.squirrel.
Select(
"a.id",
"a.name",
"a.type",
"a.enabled",
"a.exec_cmd",
"a.exec_args",
"a.watch_folder",
"a.category",
"a.tags",
"a.label",
"a.save_path",
"a.paused",
"a.ignore_rules",
"a.first_last_piece_prio",
"a.skip_hash_check",
"a.content_layout",
"a.priority",
"a.limit_download_speed",
"a.limit_upload_speed",
"a.limit_ratio",
"a.limit_seed_time",
"a.reannounce_skip",
"a.reannounce_delete",
"a.reannounce_interval",
"a.reannounce_max_attempts",
"a.webhook_host",
"a.webhook_type",
"a.webhook_method",
"a.webhook_data",
"a.external_client_id",
"a.external_client",
"a.client_id",
"c.id",
"c.name",
"c.type",
"c.enabled",
"c.host",
"c.port",
"c.tls",
"c.tls_skip_verify",
"c.username",
"c.password",
"c.settings",
).
From("action a").
Join("client c ON a.client_id = c.id").
Where(sq.Eq{"a.filter_id": filterID})
if active != nil {
queryBuilder = queryBuilder.Where(sq.Eq{"enabled": *active})
}
query, args, err := queryBuilder.ToSql()
if err != nil {
return nil, errors.Wrap(err, "error building query")
}
rows, err := r.db.handler.QueryContext(ctx, query, args...)
if err != nil {
return nil, errors.Wrap(err, "error executing query")
}
defer rows.Close()
actions := make([]*domain.Action, 0)
for rows.Next() {
var a domain.Action
var c domain.DownloadClient
var execCmd, execArgs, watchFolder, category, tags, label, savePath, contentLayout, priorityLayout, webhookHost, webhookType, webhookMethod, webhookData, externalClient sql.NullString
var limitUl, limitDl, limitSeedTime sql.NullInt64
var limitRatio sql.NullFloat64
var externalClientID, clientID sql.NullInt32
var paused, ignoreRules sql.NullBool
var clientClientId, clientPort sql.Null[int32]
var clientName, clientType, clientHost, clientUsername, clientPassword, clientSettings sql.Null[string]
var clientEnabled, clientTLS, clientTLSSkip sql.Null[bool]
if err := rows.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &a.FirstLastPiecePrio, &a.SkipHashCheck, &contentLayout, &priorityLayout, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &externalClientID, &externalClient, &clientID, &clientClientId, &clientName, &clientType, &clientEnabled, &clientHost, &clientPort, &clientTLS, &clientTLSSkip, &clientUsername, &clientPassword, &clientSettings); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
a.ExecCmd = execCmd.String
a.ExecArgs = execArgs.String
a.WatchFolder = watchFolder.String
a.Category = category.String
a.Tags = tags.String
a.Label = label.String
a.SavePath = savePath.String
a.Paused = paused.Bool
a.IgnoreRules = ignoreRules.Bool
a.ContentLayout = domain.ActionContentLayout(contentLayout.String)
a.PriorityLayout = domain.PriorityLayout(priorityLayout.String)
a.LimitDownloadSpeed = limitDl.Int64
a.LimitUploadSpeed = limitUl.Int64
a.LimitRatio = limitRatio.Float64
a.LimitSeedTime = limitSeedTime.Int64
a.WebhookHost = webhookHost.String
a.WebhookType = webhookType.String
a.WebhookMethod = webhookMethod.String
a.WebhookData = webhookData.String
a.ExternalDownloadClientID = externalClientID.Int32
a.ExternalDownloadClient = externalClient.String
a.ClientID = clientID.Int32
c.ID = clientClientId.V
c.Name = clientName.V
c.Type = domain.DownloadClientType(clientType.V)
c.Enabled = clientEnabled.V
c.Host = clientHost.V
c.Port = int(clientPort.V)
c.TLS = clientTLS.V
c.TLSSkipVerify = clientTLSSkip.V
c.Username = clientUsername.V
c.Password = clientPassword.V
//c.Settings = clientSettings.String
if a.ClientID > 0 {
if clientSettings.Valid {
if err := json.Unmarshal([]byte(clientSettings.V), &c.Settings); err != nil {
return nil, errors.Wrap(err, "could not unmarshal download client settings: %v", clientSettings.V)
}
}
a.Client = &c
}
actions = append(actions, &a)
}
if err := rows.Err(); err != nil {
return nil, errors.Wrap(err, "row error")
}
return actions, nil
}
func (r *ActionRepo) FindByFilterIDTx(ctx context.Context, filterID int, active *bool) ([]*domain.Action, error) {
tx, err := r.db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadCommitted})
if err != nil {
return nil, err
@ -38,7 +297,7 @@ func (r *ActionRepo) FindByFilterID(ctx context.Context, filterID int, active *b
defer tx.Rollback()
actions, err := r.findByFilterID(ctx, tx, filterID, active)
actions, err := r.findByFilterIDTx(ctx, tx, filterID, active)
if err != nil {
return nil, err
}
@ -59,7 +318,7 @@ func (r *ActionRepo) FindByFilterID(ctx context.Context, filterID int, active *b
return actions, nil
}
func (r *ActionRepo) findByFilterID(ctx context.Context, tx *Tx, filterID int, active *bool) ([]*domain.Action, error) {
func (r *ActionRepo) findByFilterIDTx(ctx context.Context, tx *Tx, filterID int, active *bool) ([]*domain.Action, error) {
queryBuilder := r.db.squirrel.
Select(
"id",

View file

@ -62,9 +62,10 @@ func TestActionRepo_Store(t *testing.T) {
t.Run(fmt.Sprintf("Store_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -73,7 +74,7 @@ func TestActionRepo_Store(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
// Actual test for Store
@ -84,7 +85,7 @@ func TestActionRepo_Store(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("Store_Succeeds_With_Missing_or_empty_fields [%s]", dbType), func(t *testing.T) {
@ -125,9 +126,10 @@ func TestActionRepo_StoreFilterActions(t *testing.T) {
t.Run(fmt.Sprintf("StoreFilterActions_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -136,7 +138,7 @@ func TestActionRepo_StoreFilterActions(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
// Actual test for StoreFilterActions
@ -148,7 +150,7 @@ func TestActionRepo_StoreFilterActions(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("StoreFilterActions_Fails_Invalid_FilterID [%s]", dbType), func(t *testing.T) {
@ -203,9 +205,10 @@ func TestActionRepo_FindByFilterID(t *testing.T) {
t.Run(fmt.Sprintf("FindByFilterID_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -214,13 +217,13 @@ func TestActionRepo_FindByFilterID(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
createdActions, err := repo.StoreFilterActions(context.Background(), int64(createdFilters[0].ID), []*domain.Action{&mockData})
assert.NoError(t, err)
// Actual test for FindByFilterID
actions, err := repo.FindByFilterID(context.Background(), createdFilters[0].ID, nil)
actions, err := repo.FindByFilterID(context.Background(), createdFilters[0].ID, nil, false)
assert.NoError(t, err)
assert.NotNil(t, actions)
assert.Equal(t, 1, len(actions))
@ -228,7 +231,7 @@ func TestActionRepo_FindByFilterID(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("FindByFilterID_Fails_No_Actions [%s]", dbType), func(t *testing.T) {
@ -241,7 +244,7 @@ func TestActionRepo_FindByFilterID(t *testing.T) {
assert.NotNil(t, createdFilters)
// Actual test for FindByFilterID
actions, err := repo.FindByFilterID(context.Background(), createdFilters[0].ID, nil)
actions, err := repo.FindByFilterID(context.Background(), createdFilters[0].ID, nil, false)
assert.NoError(t, err)
assert.Equal(t, 0, len(actions))
@ -250,7 +253,7 @@ func TestActionRepo_FindByFilterID(t *testing.T) {
})
t.Run(fmt.Sprintf("FindByFilterID_Succeeds_With_Invalid_FilterID [%s]", dbType), func(t *testing.T) {
actions, err := repo.FindByFilterID(context.Background(), 9999, nil) // 9999 is an invalid filter ID
actions, err := repo.FindByFilterID(context.Background(), 9999, nil, false) // 9999 is an invalid filter ID
assert.NoError(t, err)
assert.NotNil(t, actions)
assert.Equal(t, 0, len(actions))
@ -260,7 +263,7 @@ func TestActionRepo_FindByFilterID(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
defer cancel()
actions, err := repo.FindByFilterID(ctx, 1, nil)
actions, err := repo.FindByFilterID(ctx, 1, nil, false)
assert.Error(t, err)
assert.Nil(t, actions)
})
@ -277,9 +280,10 @@ func TestActionRepo_List(t *testing.T) {
t.Run(fmt.Sprintf("List_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -288,7 +292,7 @@ func TestActionRepo_List(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
createdActions, err := repo.StoreFilterActions(context.Background(), int64(createdFilters[0].ID), []*domain.Action{&mockData})
assert.NoError(t, err)
@ -302,7 +306,7 @@ func TestActionRepo_List(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("List_Fails_Context_Timeout [%s]", dbType), func(t *testing.T) {
@ -326,9 +330,10 @@ func TestActionRepo_Get(t *testing.T) {
t.Run(fmt.Sprintf("Get_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -337,7 +342,7 @@ func TestActionRepo_Get(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
createdActions, err := repo.StoreFilterActions(context.Background(), int64(createdFilters[0].ID), []*domain.Action{&mockData})
assert.NoError(t, err)
@ -351,7 +356,7 @@ func TestActionRepo_Get(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("Get_Fails_No_Record [%s]", dbType), func(t *testing.T) {
@ -382,9 +387,10 @@ func TestActionRepo_Delete(t *testing.T) {
t.Run(fmt.Sprintf("Delete_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -393,7 +399,7 @@ func TestActionRepo_Delete(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
createdActions, err := repo.StoreFilterActions(context.Background(), int64(createdFilters[0].ID), []*domain.Action{&mockData})
assert.NoError(t, err)
@ -411,7 +417,7 @@ func TestActionRepo_Delete(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("Delete_Fails_Context_Timeout [%s]", dbType), func(t *testing.T) {
@ -435,9 +441,10 @@ func TestActionRepo_DeleteByFilterID(t *testing.T) {
t.Run(fmt.Sprintf("DeleteByFilterID_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -446,7 +453,7 @@ func TestActionRepo_DeleteByFilterID(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
createdActions, err := repo.StoreFilterActions(context.Background(), int64(createdFilters[0].ID), []*domain.Action{&mockData})
assert.NoError(t, err)
@ -463,7 +470,7 @@ func TestActionRepo_DeleteByFilterID(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("DeleteByFilterID_Fails_Context_Timeout [%s]", dbType), func(t *testing.T) {
@ -486,9 +493,10 @@ func TestActionRepo_ToggleEnabled(t *testing.T) {
t.Run(fmt.Sprintf("ToggleEnabled_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -497,7 +505,7 @@ func TestActionRepo_ToggleEnabled(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, createdFilters)
mockData.ClientID = int32(createdClient.ID)
mockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
mockData.Enabled = false
createdActions, err := repo.StoreFilterActions(context.Background(), int64(createdFilters[0].ID), []*domain.Action{&mockData})
@ -515,7 +523,7 @@ func TestActionRepo_ToggleEnabled(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdActions[0].ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("ToggleEnabled_Fails_No_Record [%s]", dbType), func(t *testing.T) {

View file

@ -7,7 +7,6 @@ import (
"context"
"database/sql"
"encoding/json"
"sync"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/internal/logger"
@ -18,55 +17,18 @@ import (
)
type DownloadClientRepo struct {
log zerolog.Logger
db *DB
cache *clientCache
}
type clientCache struct {
mu sync.RWMutex
clients map[int]*domain.DownloadClient
}
func NewClientCache() *clientCache {
return &clientCache{
clients: make(map[int]*domain.DownloadClient, 0),
}
}
func (c *clientCache) Set(id int, client *domain.DownloadClient) {
c.mu.Lock()
c.clients[id] = client
c.mu.Unlock()
}
func (c *clientCache) Get(id int) *domain.DownloadClient {
c.mu.RLock()
defer c.mu.RUnlock()
v, ok := c.clients[id]
if ok {
return v
}
return nil
}
func (c *clientCache) Pop(id int) {
c.mu.Lock()
delete(c.clients, id)
c.mu.Unlock()
log zerolog.Logger
db *DB
}
func NewDownloadClientRepo(log logger.Logger, db *DB) domain.DownloadClientRepo {
return &DownloadClientRepo{
log: log.With().Str("repo", "action").Logger(),
db: db,
cache: NewClientCache(),
log: log.With().Str("repo", "action").Logger(),
db: db,
}
}
func (r *DownloadClientRepo) List(ctx context.Context) ([]domain.DownloadClient, error) {
clients := make([]domain.DownloadClient, 0)
queryBuilder := r.db.squirrel.
Select(
"id",
@ -100,6 +62,8 @@ func (r *DownloadClientRepo) List(ctx context.Context) ([]domain.DownloadClient,
}
}(rows)
clients := make([]domain.DownloadClient, 0)
for rows.Next() {
var f domain.DownloadClient
var settingsJsonStr string
@ -124,12 +88,6 @@ func (r *DownloadClientRepo) List(ctx context.Context) ([]domain.DownloadClient,
}
func (r *DownloadClientRepo) FindByID(ctx context.Context, id int32) (*domain.DownloadClient, error) {
// get client from cache
c := r.cache.Get(int(id))
if c != nil {
return c, nil
}
queryBuilder := r.db.squirrel.
Select(
"id",
@ -153,7 +111,7 @@ func (r *DownloadClientRepo) FindByID(ctx context.Context, id int32) (*domain.Do
}
row := r.db.handler.QueryRowContext(ctx, query, args...)
if err != nil {
if err := row.Err(); err != nil {
return nil, errors.Wrap(err, "error executing query")
}
@ -177,9 +135,7 @@ func (r *DownloadClientRepo) FindByID(ctx context.Context, id int32) (*domain.Do
return &client, nil
}
func (r *DownloadClientRepo) Store(ctx context.Context, client domain.DownloadClient) (*domain.DownloadClient, error) {
var err error
func (r *DownloadClientRepo) Store(ctx context.Context, client *domain.DownloadClient) error {
settings := domain.DownloadClientSettings{
APIKey: client.Settings.APIKey,
Basic: client.Settings.Basic,
@ -190,7 +146,7 @@ func (r *DownloadClientRepo) Store(ctx context.Context, client domain.DownloadCl
settingsJson, err := json.Marshal(&settings)
if err != nil {
return nil, errors.Wrap(err, "error marshal download client settings %+v", settings)
return errors.Wrap(err, "error marshal download client settings %+v", settings)
}
queryBuilder := r.db.squirrel.
@ -204,22 +160,17 @@ func (r *DownloadClientRepo) Store(ctx context.Context, client domain.DownloadCl
err = queryBuilder.QueryRowContext(ctx).Scan(&retID)
if err != nil {
return nil, errors.Wrap(err, "error executing query")
return errors.Wrap(err, "error executing query")
}
client.ID = retID
client.ID = int32(retID)
r.log.Debug().Msgf("download_client.store: %d", client.ID)
// save to cache
r.cache.Set(client.ID, &client)
return &client, nil
return nil
}
func (r *DownloadClientRepo) Update(ctx context.Context, client domain.DownloadClient) (*domain.DownloadClient, error) {
var err error
func (r *DownloadClientRepo) Update(ctx context.Context, client *domain.DownloadClient) error {
settings := domain.DownloadClientSettings{
APIKey: client.Settings.APIKey,
Basic: client.Settings.Basic,
@ -230,7 +181,7 @@ func (r *DownloadClientRepo) Update(ctx context.Context, client domain.DownloadC
settingsJson, err := json.Marshal(&settings)
if err != nil {
return nil, errors.Wrap(err, "error marshal download client settings %+v", settings)
return errors.Wrap(err, "error marshal download client settings %+v", settings)
}
queryBuilder := r.db.squirrel.
@ -249,32 +200,29 @@ func (r *DownloadClientRepo) Update(ctx context.Context, client domain.DownloadC
query, args, err := queryBuilder.ToSql()
if err != nil {
return nil, errors.Wrap(err, "error building query")
return errors.Wrap(err, "error building query")
}
result, err := r.db.handler.ExecContext(ctx, query, args...)
if err != nil {
return nil, errors.Wrap(err, "error executing query")
return errors.Wrap(err, "error executing query")
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return nil, errors.Wrap(err, "error getting rows affected")
return errors.Wrap(err, "error getting rows affected")
}
if rowsAffected == 0 {
return nil, errors.New("no rows updated")
return errors.New("no rows updated")
}
r.log.Debug().Msgf("download_client.update: %d", client.ID)
// save to cache
r.cache.Set(client.ID, &client)
return &client, nil
return nil
}
func (r *DownloadClientRepo) Delete(ctx context.Context, clientID int) error {
func (r *DownloadClientRepo) Delete(ctx context.Context, clientID int32) error {
tx, err := r.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return err
@ -311,10 +259,11 @@ func (r *DownloadClientRepo) Delete(ctx context.Context, clientID int) error {
}
r.log.Debug().Msgf("delete download client: %d", clientID)
return nil
}
func (r *DownloadClientRepo) delete(ctx context.Context, tx *Tx, clientID int) error {
func (r *DownloadClientRepo) delete(ctx context.Context, tx *Tx, clientID int32) error {
queryBuilder := r.db.squirrel.
Delete("client").
Where(sq.Eq{"id": clientID})
@ -329,9 +278,6 @@ func (r *DownloadClientRepo) delete(ctx context.Context, tx *Tx, clientID int) e
return errors.Wrap(err, "error executing query")
}
// remove from cache
r.cache.Pop(clientID)
rows, _ := res.RowsAffected()
if rows == 0 {
return errors.New("no rows affected")
@ -342,9 +288,7 @@ func (r *DownloadClientRepo) delete(ctx context.Context, tx *Tx, clientID int) e
return nil
}
func (r *DownloadClientRepo) deleteClientFromAction(ctx context.Context, tx *Tx, clientID int) error {
var err error
func (r *DownloadClientRepo) deleteClientFromAction(ctx context.Context, tx *Tx, clientID int32) error {
queryBuilder := r.db.squirrel.
Update("action").
Set("enabled", false).
@ -355,12 +299,14 @@ func (r *DownloadClientRepo) deleteClientFromAction(ctx context.Context, tx *Tx,
// return values
var filterID int
if err = queryBuilder.QueryRowContext(ctx).Scan(&filterID); err != nil {
err := queryBuilder.QueryRowContext(ctx).Scan(&filterID)
if err != nil {
// this will throw when the client is not connected to any actions
// it is not an error in this case
if errors.Is(err, sql.ErrNoRows) {
return nil
}
return errors.Wrap(err, "error executing query")
}

View file

@ -8,10 +8,12 @@ package database
import (
"context"
"fmt"
"github.com/autobrr/autobrr/internal/domain"
"github.com/stretchr/testify/assert"
"testing"
"time"
"github.com/autobrr/autobrr/internal/domain"
"github.com/stretchr/testify/assert"
)
func getMockDownloadClient() domain.DownloadClient {
@ -54,13 +56,14 @@ func TestDownloadClientRepo_List(t *testing.T) {
t.Run(fmt.Sprintf("List_Succeeds_With_No_Filters [%s]", dbType), func(t *testing.T) {
// Insert mock data
createdClient, err := repo.Store(context.Background(), mockData)
mock := &mockData
err := repo.Store(context.Background(), mock)
clients, err := repo.List(context.Background())
assert.NoError(t, err)
assert.NotEmpty(t, clients)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("List_Succeeds_With_Empty_Database [%s]", dbType), func(t *testing.T) {
@ -77,32 +80,34 @@ func TestDownloadClientRepo_List(t *testing.T) {
})
t.Run(fmt.Sprintf("List_Succeeds_With_Data_Integrity [%s]", dbType), func(t *testing.T) {
createdClient, err := repo.Store(context.Background(), mockData)
mock := &mockData
err := repo.Store(context.Background(), mock)
clients, err := repo.List(context.Background())
assert.NoError(t, err)
assert.Equal(t, 1, len(clients))
assert.Equal(t, createdClient.Name, clients[0].Name)
assert.Equal(t, mock.Name, clients[0].Name)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("List_Succeeds_With_Boundary_Value_For_Port [%s]", dbType), func(t *testing.T) {
mockData.Port = 65535
createdClient, err := repo.Store(context.Background(), mockData)
mock := &mockData
mock.Port = 65535
err := repo.Store(context.Background(), mock)
clients, err := repo.List(context.Background())
assert.NoError(t, err)
assert.Equal(t, 65535, clients[0].Port)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("List_Succeeds_With_Boolean_Flags_Set_To_False [%s]", dbType), func(t *testing.T) {
mockData.Enabled = false
mockData.TLS = false
mockData.TLSSkipVerify = false
createdClient, err := repo.Store(context.Background(), mockData)
err := repo.Store(context.Background(), &mockData)
clients, err := repo.List(context.Background())
assert.NoError(t, err)
assert.Equal(t, false, clients[0].Enabled)
@ -110,18 +115,18 @@ func TestDownloadClientRepo_List(t *testing.T) {
assert.Equal(t, false, clients[0].TLSSkipVerify)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mockData.ID)
})
t.Run(fmt.Sprintf("List_Succeeds_With_Special_Characters_In_Name [%s]", dbType), func(t *testing.T) {
mockData.Name = "Special$Name"
createdClient, err := repo.Store(context.Background(), mockData)
err := repo.Store(context.Background(), &mockData)
clients, err := repo.List(context.Background())
assert.NoError(t, err)
assert.Equal(t, "Special$Name", clients[0].Name)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mockData.ID)
})
}
}
@ -133,13 +138,14 @@ func TestDownloadClientRepo_FindByID(t *testing.T) {
mockData := getMockDownloadClient()
t.Run(fmt.Sprintf("FindByID_Succeeds [%s]", dbType), func(t *testing.T) {
createdClient, _ := repo.Store(context.Background(), mockData)
foundClient, err := repo.FindByID(context.Background(), int32(createdClient.ID))
mock := &mockData
_ = repo.Store(context.Background(), mock)
foundClient, err := repo.FindByID(context.Background(), mock.ID)
assert.NoError(t, err)
assert.NotNil(t, foundClient)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("FindByID_Fails_With_Nonexistent_ID [%s]", dbType), func(t *testing.T) {
@ -156,40 +162,44 @@ func TestDownloadClientRepo_FindByID(t *testing.T) {
t.Run(fmt.Sprintf("FindByID_Fails_With_Context_Timeout [%s]", dbType), func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
defer cancel()
_, err := repo.FindByID(ctx, 1)
assert.Error(t, err)
})
t.Run(fmt.Sprintf("FindByID_Fails_After_Client_Deleted [%s]", dbType), func(t *testing.T) {
createdClient, _ := repo.Store(context.Background(), mockData)
_ = repo.Delete(context.Background(), createdClient.ID)
_, err := repo.FindByID(context.Background(), int32(createdClient.ID))
mock := &mockData
_ = repo.Store(context.Background(), mock)
_ = repo.Delete(context.Background(), mock.ID)
_, err := repo.FindByID(context.Background(), mock.ID)
assert.Error(t, err)
assert.Equal(t, "no client configured", err.Error())
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("FindByID_Succeeds_With_Data_Integrity [%s]", dbType), func(t *testing.T) {
createdClient, _ := repo.Store(context.Background(), mockData)
foundClient, err := repo.FindByID(context.Background(), int32(createdClient.ID))
mock := &mockData
_ = repo.Store(context.Background(), mock)
foundClient, err := repo.FindByID(context.Background(), mock.ID)
assert.NoError(t, err)
assert.Equal(t, createdClient.Name, foundClient.Name)
assert.Equal(t, mock.Name, foundClient.Name)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
t.Run(fmt.Sprintf("FindByID_Succeeds_From_Cache [%s]", dbType), func(t *testing.T) {
createdClient, _ := repo.Store(context.Background(), mockData)
foundClient1, _ := repo.FindByID(context.Background(), int32(createdClient.ID))
foundClient2, err := repo.FindByID(context.Background(), int32(createdClient.ID))
mock := &mockData
_ = repo.Store(context.Background(), mock)
foundClient1, _ := repo.FindByID(context.Background(), mock.ID)
foundClient2, err := repo.FindByID(context.Background(), mock.ID)
assert.NoError(t, err)
assert.Equal(t, foundClient1, foundClient2)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mock.ID)
})
}
}
@ -201,17 +211,17 @@ func TestDownloadClientRepo_Store(t *testing.T) {
t.Run(fmt.Sprintf("Store_Succeeds [%s]", dbType), func(t *testing.T) {
mockData := getMockDownloadClient()
createdClient, err := repo.Store(context.Background(), mockData)
err := repo.Store(context.Background(), &mockData)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mockData)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mockData.ID)
})
//TODO: Is this okay? Should we be able to store a client with no name (empty string)?
t.Run(fmt.Sprintf("Store_Succeeds?_With_Missing_Required_Fields [%s]", dbType), func(t *testing.T) {
badMockData := domain.DownloadClient{
badMockData := &domain.DownloadClient{
Type: "",
Enabled: false,
Host: "",
@ -222,30 +232,30 @@ func TestDownloadClientRepo_Store(t *testing.T) {
Password: "",
Settings: domain.DownloadClientSettings{},
}
createdClient, err := repo.Store(context.Background(), badMockData)
err := repo.Store(context.Background(), badMockData)
assert.NoError(t, err)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), badMockData.ID)
})
t.Run(fmt.Sprintf("Store_Fails_With_Context_Timeout [%s]", dbType), func(t *testing.T) {
mockData := getMockDownloadClient()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
defer cancel()
_, err := repo.Store(ctx, mockData)
err := repo.Store(ctx, &mockData)
assert.Error(t, err)
})
t.Run(fmt.Sprintf("Store_Succeeds_And_Caches [%s]", dbType), func(t *testing.T) {
mockData := getMockDownloadClient()
createdClient, _ := repo.Store(context.Background(), mockData)
_ = repo.Store(context.Background(), &mockData)
cachedClient, _ := repo.FindByID(context.Background(), int32(createdClient.ID))
assert.Equal(t, createdClient, cachedClient)
cachedClient, _ := repo.FindByID(context.Background(), mockData.ID)
assert.Equal(t, &mockData, cachedClient)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mockData.ID)
})
}
}
@ -258,22 +268,22 @@ func TestDownloadClientRepo_Update(t *testing.T) {
t.Run(fmt.Sprintf("Update_Successfully_Updates_Record [%s]", dbType), func(t *testing.T) {
mockClient := getMockDownloadClient()
createdClient, _ := repo.Store(context.Background(), mockClient)
createdClient.Name = "updatedName"
updatedClient, err := repo.Update(context.Background(), *createdClient)
_ = repo.Store(context.Background(), &mockClient)
mockClient.Name = "updatedName"
err := repo.Update(context.Background(), &mockClient)
assert.NoError(t, err)
assert.Equal(t, "updatedName", updatedClient.Name)
assert.Equal(t, "updatedName", mockClient.Name)
// Cleanup
_ = repo.Delete(context.Background(), updatedClient.ID)
_ = repo.Delete(context.Background(), mockClient.ID)
})
t.Run(fmt.Sprintf("Update_Fails_With_Missing_ID [%s]", dbType), func(t *testing.T) {
badMockData := getMockDownloadClient()
badMockData.ID = 0
_, err := repo.Update(context.Background(), badMockData)
err := repo.Update(context.Background(), &badMockData)
assert.Error(t, err)
@ -283,7 +293,7 @@ func TestDownloadClientRepo_Update(t *testing.T) {
badMockData := getMockDownloadClient()
badMockData.ID = 9999
_, err := repo.Update(context.Background(), badMockData)
err := repo.Update(context.Background(), &badMockData)
assert.Error(t, err)
})
@ -291,7 +301,7 @@ func TestDownloadClientRepo_Update(t *testing.T) {
t.Run(fmt.Sprintf("Update_Fails_With_Missing_Required_Fields [%s]", dbType), func(t *testing.T) {
badMockData := domain.DownloadClient{}
_, err := repo.Update(context.Background(), badMockData)
err := repo.Update(context.Background(), &badMockData)
assert.Error(t, err)
})
@ -305,13 +315,13 @@ func TestDownloadClientRepo_Delete(t *testing.T) {
t.Run(fmt.Sprintf("Delete_Successfully_Deletes_Client [%s]", dbType), func(t *testing.T) {
mockClient := getMockDownloadClient()
createdClient, _ := repo.Store(context.Background(), mockClient)
_ = repo.Store(context.Background(), &mockClient)
err := repo.Delete(context.Background(), createdClient.ID)
err := repo.Delete(context.Background(), mockClient.ID)
assert.NoError(t, err)
// Verify client was deleted
_, err = repo.FindByID(context.Background(), int32(createdClient.ID))
_, err = repo.FindByID(context.Background(), mockClient.ID)
assert.Error(t, err)
})
@ -322,16 +332,16 @@ func TestDownloadClientRepo_Delete(t *testing.T) {
t.Run(fmt.Sprintf("Delete_Fails_With_Context_Timeout [%s]", dbType), func(t *testing.T) {
mockClient := getMockDownloadClient()
createdClient, _ := repo.Store(context.Background(), mockClient)
_ = repo.Store(context.Background(), &mockClient)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
defer cancel()
err := repo.Delete(ctx, createdClient.ID)
err := repo.Delete(ctx, mockClient.ID)
assert.Error(t, err)
// Cleanup
_ = repo.Delete(context.Background(), createdClient.ID)
_ = repo.Delete(context.Background(), mockClient.ID)
})
}
}

View file

@ -255,13 +255,12 @@ func (r *FilterRepo) FindByID(ctx context.Context, filterID int) (*domain.Filter
}
row := r.db.handler.QueryRowContext(ctx, query, args...)
if row.Err() != nil {
if errors.Is(row.Err(), sql.ErrNoRows) {
if err := row.Err(); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, domain.ErrRecordNotFound
}
return nil, errors.Wrap(row.Err(), "error row")
return nil, errors.Wrap(err, "error row")
}
var f domain.Filter

View file

@ -791,12 +791,14 @@ func TestFilterRepo_GetDownloadsByFilterId(t *testing.T) {
err := repo.Store(context.Background(), mockData)
assert.NoError(t, err)
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mockClient := getMockDownloadClient()
err = downloadClientRepo.Store(context.Background(), &mockClient)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mockClient)
mockAction.FilterID = mockData.ID
mockAction.ClientID = int32(createdClient.ID)
mockAction.ClientID = mockClient.ID
action, err := actionRepo.Store(context.Background(), mockAction)
@ -827,7 +829,7 @@ func TestFilterRepo_GetDownloadsByFilterId(t *testing.T) {
// Cleanup
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: action.ID})
_ = repo.Delete(context.Background(), mockData.ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mockClient.ID)
_ = releaseRepo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
})

View file

@ -89,9 +89,10 @@ func TestReleaseRepo_Store(t *testing.T) {
t.Run(fmt.Sprintf("StoreReleaseActionStatus_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -101,7 +102,7 @@ func TestReleaseRepo_Store(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
// Execute
@ -124,7 +125,7 @@ func TestReleaseRepo_Store(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -144,9 +145,10 @@ func TestReleaseRepo_StoreReleaseActionStatus(t *testing.T) {
t.Run(fmt.Sprintf("StoreReleaseActionStatus_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -156,7 +158,7 @@ func TestReleaseRepo_StoreReleaseActionStatus(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
// Execute
@ -179,7 +181,7 @@ func TestReleaseRepo_StoreReleaseActionStatus(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -199,9 +201,10 @@ func TestReleaseRepo_Find(t *testing.T) {
t.Run(fmt.Sprintf("FindReleases_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -211,7 +214,7 @@ func TestReleaseRepo_Find(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
// Execute
@ -238,7 +241,7 @@ func TestReleaseRepo_Find(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -258,9 +261,10 @@ func TestReleaseRepo_FindRecent(t *testing.T) {
t.Run(fmt.Sprintf("FindRecent_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -270,7 +274,7 @@ func TestReleaseRepo_FindRecent(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
// Execute
@ -286,7 +290,7 @@ func TestReleaseRepo_FindRecent(t *testing.T) {
// Cleanup
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -306,9 +310,10 @@ func TestReleaseRepo_GetIndexerOptions(t *testing.T) {
t.Run(fmt.Sprintf("GetIndexerOptions_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -318,7 +323,7 @@ func TestReleaseRepo_GetIndexerOptions(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
err = repo.Store(context.Background(), mockData)
@ -344,7 +349,7 @@ func TestReleaseRepo_GetIndexerOptions(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -364,9 +369,10 @@ func TestReleaseRepo_GetActionStatusByReleaseID(t *testing.T) {
t.Run(fmt.Sprintf("GetActionStatusByReleaseID_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -376,7 +382,7 @@ func TestReleaseRepo_GetActionStatusByReleaseID(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
err = repo.Store(context.Background(), mockData)
@ -403,7 +409,7 @@ func TestReleaseRepo_GetActionStatusByReleaseID(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -423,9 +429,10 @@ func TestReleaseRepo_Get(t *testing.T) {
t.Run(fmt.Sprintf("Get_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -435,7 +442,7 @@ func TestReleaseRepo_Get(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
err = repo.Store(context.Background(), mockData)
@ -462,7 +469,7 @@ func TestReleaseRepo_Get(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -482,9 +489,10 @@ func TestReleaseRepo_Stats(t *testing.T) {
t.Run(fmt.Sprintf("Stats_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -494,7 +502,7 @@ func TestReleaseRepo_Stats(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
err = repo.Store(context.Background(), mockData)
@ -521,7 +529,7 @@ func TestReleaseRepo_Stats(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -541,9 +549,10 @@ func TestReleaseRepo_Delete(t *testing.T) {
t.Run(fmt.Sprintf("Delete_Succeeds [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -553,7 +562,7 @@ func TestReleaseRepo_Delete(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
err = repo.Store(context.Background(), mockData)
@ -577,7 +586,7 @@ func TestReleaseRepo_Delete(t *testing.T) {
// Cleanup
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}
@ -597,9 +606,10 @@ func TestReleaseRepo_CheckSmartEpisodeCanDownloadShow(t *testing.T) {
t.Run(fmt.Sprintf("Check_Smart_Episode_Can_Download [%s]", dbType), func(t *testing.T) {
// Setup
createdClient, err := downloadClientRepo.Store(context.Background(), getMockDownloadClient())
mock := getMockDownloadClient()
err := downloadClientRepo.Store(context.Background(), &mock)
assert.NoError(t, err)
assert.NotNil(t, createdClient)
assert.NotNil(t, mock)
err = filterRepo.Store(context.Background(), getMockFilter())
assert.NoError(t, err)
@ -609,7 +619,7 @@ func TestReleaseRepo_CheckSmartEpisodeCanDownloadShow(t *testing.T) {
assert.NotNil(t, createdFilters)
actionMockData.FilterID = createdFilters[0].ID
actionMockData.ClientID = int32(createdClient.ID)
actionMockData.ClientID = mock.ID
mockData.FilterID = createdFilters[0].ID
err = repo.Store(context.Background(), mockData)
@ -644,7 +654,7 @@ func TestReleaseRepo_CheckSmartEpisodeCanDownloadShow(t *testing.T) {
_ = repo.Delete(context.Background(), &domain.DeleteReleaseRequest{OlderThan: 0})
_ = actionRepo.Delete(context.Background(), &domain.DeleteActionRequest{ActionId: createdAction.ID})
_ = filterRepo.Delete(context.Background(), createdFilters[0].ID)
_ = downloadClientRepo.Delete(context.Background(), createdClient.ID)
_ = downloadClientRepo.Delete(context.Background(), mock.ID)
})
}
}