Реализация, фаза 1: добавление данных в qbittorrent
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newTestStore(t *testing.T) *Store {
|
||||
t.Helper()
|
||||
st, err := Open(t.TempDir() + "/test.db")
|
||||
if err != nil {
|
||||
t.Fatalf("open store: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { _ = st.Close() })
|
||||
return st
|
||||
}
|
||||
|
||||
func newDownloading(infohash string) *Download {
|
||||
return &Download{
|
||||
SourceType: SourceMagnet,
|
||||
SourceRef: "magnet:?xt=urn:btih:" + infohash,
|
||||
Context: "ctx",
|
||||
Infohash: NullString(infohash),
|
||||
IdempotencyKey: NullString(infohash),
|
||||
State: StateDownloading,
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAndGetDownload(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
id, err := st.CreateDownload(ctx, newDownloading("aabbccddeeff00112233445566778899aabbccdd"))
|
||||
if err != nil {
|
||||
t.Fatalf("create: %v", err)
|
||||
}
|
||||
|
||||
got, err := st.GetDownload(ctx, id)
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
if got.State != StateDownloading {
|
||||
t.Errorf("state = %q, want downloading", got.State)
|
||||
}
|
||||
if got.Context != "ctx" {
|
||||
t.Errorf("context = %q", got.Context)
|
||||
}
|
||||
if got.CreatedAt == "" {
|
||||
t.Error("created_at пуст")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindActiveByInfohash(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
const ih = "1111111111111111111111111111111111111111"
|
||||
|
||||
if d, err := st.FindActiveByInfohash(ctx, ih); err != nil || d != nil {
|
||||
t.Fatalf("ожидался (nil,nil), получили (%v,%v)", d, err)
|
||||
}
|
||||
|
||||
id, err := st.CreateDownload(ctx, newDownloading(ih))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d, err := st.FindActiveByInfohash(ctx, ih)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if d == nil || d.ID != id {
|
||||
t.Fatalf("активная задача не найдена: %v", d)
|
||||
}
|
||||
}
|
||||
|
||||
// Терминальное состояние снимает ключ идемпотентности и позволяет завести
|
||||
// тот же infohash заново (повторная закачка спустя время).
|
||||
func TestTerminalReleasesInfohash(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
const ih = "2222222222222222222222222222222222222222"
|
||||
|
||||
id, err := st.CreateDownload(ctx, newDownloading(ih))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := st.SetDownloadState(ctx, id, StateFailed, "qbit_add", "boom"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// После терминального состояния активной задачи нет.
|
||||
if d, err := st.FindActiveByInfohash(ctx, ih); err != nil || d != nil {
|
||||
t.Fatalf("после failed активная задача не должна находиться: (%v,%v)", d, err)
|
||||
}
|
||||
// Ключ идемпотентности снят.
|
||||
got, err := st.GetDownload(ctx, id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.IdempotencyKey.Valid {
|
||||
t.Errorf("idempotency_key должен быть NULL, получили %q", got.IdempotencyKey.String)
|
||||
}
|
||||
if got.ErrorCode.String != "qbit_add" {
|
||||
t.Errorf("error_code = %q", got.ErrorCode.String)
|
||||
}
|
||||
|
||||
// Тот же infohash заводится заново — unique index не мешает.
|
||||
id2, err := st.CreateDownload(ctx, newDownloading(ih))
|
||||
if err != nil {
|
||||
t.Fatalf("повторное добавление после терминального должно проходить: %v", err)
|
||||
}
|
||||
if id2 == id {
|
||||
t.Error("ожидалась новая задача")
|
||||
}
|
||||
}
|
||||
|
||||
// Две активные задачи с одним ключом идемпотентности недопустимы.
|
||||
func TestActiveDuplicateRejected(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
const ih = "3333333333333333333333333333333333333333"
|
||||
|
||||
if _, err := st.CreateDownload(ctx, newDownloading(ih)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := st.CreateDownload(ctx, newDownloading(ih)); err == nil {
|
||||
t.Error("ожидалось нарушение уникальности idempotency_key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListAndByState(t *testing.T) {
|
||||
st := newTestStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
id1, _ := st.CreateDownload(ctx, newDownloading("4444444444444444444444444444444444444444"))
|
||||
id2, _ := st.CreateDownload(ctx, newDownloading("5555555555555555555555555555555555555555"))
|
||||
if err := st.SetDownloadState(ctx, id2, StateCompleted, "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
all, err := st.ListDownloads(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(all) != 2 {
|
||||
t.Fatalf("ListDownloads = %d, want 2", len(all))
|
||||
}
|
||||
|
||||
dl, err := st.ListDownloadsByState(ctx, StateDownloading)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(dl) != 1 || dl[0].ID != id1 {
|
||||
t.Fatalf("ListDownloadsByState(downloading) = %v", dl)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user