mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-06-02 22:20:41 +08:00
feat(aria2): add Aria2 download command and client integration
This commit is contained in:
322
pkg/aria2/client_test.go
Normal file
322
pkg/aria2/client_test.go
Normal file
@@ -0,0 +1,322 @@
|
||||
package aria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
secret string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid client",
|
||||
url: "http://localhost:6800/jsonrpc",
|
||||
secret: "test-secret",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid client without secret",
|
||||
url: "http://localhost:6800/jsonrpc",
|
||||
secret: "",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid empty url",
|
||||
url: "",
|
||||
secret: "test-secret",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client, err := NewClient(tt.url, tt.secret)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewClient() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !tt.wantErr && client == nil {
|
||||
t.Error("NewClient() returned nil client")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_AddURI(t *testing.T) {
|
||||
// Create a mock server
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
t.Errorf("Expected POST request, got %s", r.Method)
|
||||
}
|
||||
|
||||
var req rpcRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
t.Errorf("Failed to decode request: %v", err)
|
||||
}
|
||||
|
||||
// Verify method
|
||||
if req.Method != "aria2.addUri" {
|
||||
t.Errorf("Expected method aria2.addUri, got %s", req.Method)
|
||||
}
|
||||
|
||||
// Send response
|
||||
resp := rpcResponse{
|
||||
Jsonrpc: "2.0",
|
||||
ID: req.ID,
|
||||
Result: json.RawMessage(`"2089b05ecca3d829"`),
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(server.URL, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
gid, err := client.AddURI(ctx, []string{"http://example.com/file.txt"}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("AddURI() error = %v", err)
|
||||
}
|
||||
|
||||
if gid != "2089b05ecca3d829" {
|
||||
t.Errorf("Expected gid 2089b05ecca3d829, got %s", gid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_TellStatus(t *testing.T) {
|
||||
// Create a mock server
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req rpcRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
t.Errorf("Failed to decode request: %v", err)
|
||||
}
|
||||
|
||||
// Verify method
|
||||
if req.Method != "aria2.tellStatus" {
|
||||
t.Errorf("Expected method aria2.tellStatus, got %s", req.Method)
|
||||
}
|
||||
|
||||
// Send response
|
||||
status := Status{
|
||||
GID: "2089b05ecca3d829",
|
||||
Status: "active",
|
||||
TotalLength: "1024000",
|
||||
CompletedLength: "512000",
|
||||
DownloadSpeed: "102400",
|
||||
Files: []File{},
|
||||
}
|
||||
result, _ := json.Marshal(status)
|
||||
|
||||
resp := rpcResponse{
|
||||
Jsonrpc: "2.0",
|
||||
ID: req.ID,
|
||||
Result: result,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(server.URL, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
status, err := client.TellStatus(ctx, "2089b05ecca3d829")
|
||||
if err != nil {
|
||||
t.Fatalf("TellStatus() error = %v", err)
|
||||
}
|
||||
|
||||
if status.GID != "2089b05ecca3d829" {
|
||||
t.Errorf("Expected gid 2089b05ecca3d829, got %s", status.GID)
|
||||
}
|
||||
|
||||
if status.Status != "active" {
|
||||
t.Errorf("Expected status active, got %s", status.Status)
|
||||
}
|
||||
|
||||
if !status.IsDownloadActive() {
|
||||
t.Error("Expected download to be active")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_WithSecret(t *testing.T) {
|
||||
expectedSecret := "my-secret-token"
|
||||
|
||||
// Create a mock server
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req rpcRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
t.Errorf("Failed to decode request: %v", err)
|
||||
}
|
||||
|
||||
// Verify secret token is included in params
|
||||
if len(req.Params) == 0 {
|
||||
t.Error("Expected params to contain secret token")
|
||||
} else {
|
||||
token, ok := req.Params[0].(string)
|
||||
if !ok || token != "token:"+expectedSecret {
|
||||
t.Errorf("Expected token:%s, got %v", expectedSecret, req.Params[0])
|
||||
}
|
||||
}
|
||||
|
||||
// Send response
|
||||
version := Version{
|
||||
Version: "1.36.0",
|
||||
EnabledFeatures: []string{"Async DNS", "BitTorrent", "HTTP", "HTTPS"},
|
||||
}
|
||||
result, _ := json.Marshal(version)
|
||||
|
||||
resp := rpcResponse{
|
||||
Jsonrpc: "2.0",
|
||||
ID: req.ID,
|
||||
Result: result,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(server.URL, expectedSecret)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
version, err := client.GetVersion(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("GetVersion() error = %v", err)
|
||||
}
|
||||
|
||||
if version.Version != "1.36.0" {
|
||||
t.Errorf("Expected version 1.36.0, got %s", version.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_ContextCancellation(t *testing.T) {
|
||||
// Create a mock server that delays response
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(rpcResponse{
|
||||
Jsonrpc: "2.0",
|
||||
ID: "1",
|
||||
Result: json.RawMessage(`"OK"`),
|
||||
})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(server.URL, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
_, err = client.GetVersion(ctx)
|
||||
if err == nil {
|
||||
t.Error("Expected context cancellation error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_RPCError(t *testing.T) {
|
||||
// Create a mock server that returns an error
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req rpcRequest
|
||||
json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
resp := rpcResponse{
|
||||
Jsonrpc: "2.0",
|
||||
ID: req.ID,
|
||||
Error: &rpcError{
|
||||
Code: 1,
|
||||
Message: "Unauthorized",
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewClient(server.URL, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
_, err = client.GetVersion(ctx)
|
||||
if err == nil {
|
||||
t.Error("Expected RPC error, got nil")
|
||||
}
|
||||
|
||||
var rpcErr *rpcError
|
||||
if !errors.As(err, &rpcErr) {
|
||||
t.Errorf("Expected rpcError, got %T", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatus_DownloadStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
status string
|
||||
check func(*Status) bool
|
||||
}{
|
||||
{
|
||||
name: "active",
|
||||
status: "active",
|
||||
check: (*Status).IsDownloadActive,
|
||||
},
|
||||
{
|
||||
name: "waiting",
|
||||
status: "waiting",
|
||||
check: (*Status).IsDownloadWaiting,
|
||||
},
|
||||
{
|
||||
name: "paused",
|
||||
status: "paused",
|
||||
check: (*Status).IsDownloadPaused,
|
||||
},
|
||||
{
|
||||
name: "error",
|
||||
status: "error",
|
||||
check: (*Status).IsDownloadError,
|
||||
},
|
||||
{
|
||||
name: "complete",
|
||||
status: "complete",
|
||||
check: (*Status).IsDownloadComplete,
|
||||
},
|
||||
{
|
||||
name: "removed",
|
||||
status: "removed",
|
||||
check: (*Status).IsDownloadRemoved,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &Status{Status: tt.status}
|
||||
if !tt.check(s) {
|
||||
t.Errorf("Expected status %s check to return true", tt.status)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user