mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 08:14:55 +08:00
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
package backendrpc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type testRequest struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
ID json.RawMessage `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params json.RawMessage `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
type testEnvelope struct {
|
||||
OK bool `json:"ok"`
|
||||
Status string `json:"status"`
|
||||
Data any `json:"data,omitempty"`
|
||||
Error any `json:"error,omitempty"`
|
||||
RequestID string `json:"request_id"`
|
||||
}
|
||||
|
||||
type testResponse struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
ID json.RawMessage `json:"id"`
|
||||
Result any `json:"result,omitempty"`
|
||||
Error *JSONRPCError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func newTestClient(t *testing.T, handler func(t *testing.T, req testRequest) testResponse) *Client {
|
||||
t.Helper()
|
||||
client := New("bat.sock")
|
||||
client.DialContext = func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
clientConn, serverConn := net.Pipe()
|
||||
go func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
line, err := bufio.NewReader(conn).ReadBytes('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var req testRequest
|
||||
if err := json.Unmarshal(line, &req); err != nil {
|
||||
return
|
||||
}
|
||||
resp := handler(t, req)
|
||||
if len(resp.ID) == 0 {
|
||||
resp.ID = req.ID
|
||||
}
|
||||
if resp.JSONRPC == "" {
|
||||
resp.JSONRPC = jsonRPCVersion
|
||||
}
|
||||
_ = json.NewEncoder(conn).Encode(resp)
|
||||
}(serverConn)
|
||||
return clientConn, nil
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func TestResourceRepairQueuesTask(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
if req.Method != "resource.repair" {
|
||||
t.Fatalf("method = %s", req.Method)
|
||||
}
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: true,
|
||||
Status: "accepted",
|
||||
RequestID: "req-test-1",
|
||||
Data: map[string]any{
|
||||
"task_id": "task-1",
|
||||
"kind": "resource.repair",
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
task, err := client.ResourceRepair(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("ResourceRepair error: %v", err)
|
||||
}
|
||||
if task.TaskID != "task-1" || task.Kind != "resource.repair" {
|
||||
t.Fatalf("unexpected task: %#v", task)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceListSendsPagination(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
if req.Method != "resource.list" {
|
||||
t.Fatalf("method = %s", req.Method)
|
||||
}
|
||||
var params pageParam
|
||||
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
||||
t.Fatalf("decode params: %v", err)
|
||||
}
|
||||
if params.Offset != 2 || params.Limit != 1 {
|
||||
t.Fatalf("params = %#v", params)
|
||||
}
|
||||
bytes := uint64(42)
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: true,
|
||||
Status: "ok",
|
||||
RequestID: "req-test-2",
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"resource_root": "/tmp/resources/current",
|
||||
"manifest_version": 1,
|
||||
"total_entries": 3,
|
||||
"offset": 2,
|
||||
"limit": 1,
|
||||
"entries": []map[string]any{
|
||||
{
|
||||
"url": "https://example.invalid/a.zip",
|
||||
"destination": "a.zip",
|
||||
"bytes": bytes,
|
||||
"blake3": "abc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
page, err := client.ResourceList(context.Background(), 2, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("ResourceList error: %v", err)
|
||||
}
|
||||
if !page.Available || page.TotalEntries != 3 || len(page.Entries) != 1 {
|
||||
t.Fatalf("unexpected page: %#v", page)
|
||||
}
|
||||
if page.Entries[0].Bytes == nil || *page.Entries[0].Bytes != 42 {
|
||||
t.Fatalf("unexpected entry bytes: %#v", page.Entries[0].Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplicationErrorReturnsAPIError(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
if req.Method != "task.status" {
|
||||
t.Fatalf("method = %s", req.Method)
|
||||
}
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: false,
|
||||
Status: "error",
|
||||
Error: APIError{
|
||||
Code: "BAT-ERR-700004",
|
||||
Kind: "task_not_found",
|
||||
Domain: "rpc",
|
||||
Location: "task.status",
|
||||
Message: "任务不存在:missing",
|
||||
Retryable: false,
|
||||
},
|
||||
RequestID: "req-test-3",
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
_, err := client.TaskStatus(context.Background(), "missing")
|
||||
var apiErr *APIError
|
||||
if !errors.As(err, &apiErr) {
|
||||
t.Fatalf("expected APIError, got %T %v", err, err)
|
||||
}
|
||||
if apiErr.Code != "BAT-ERR-700004" {
|
||||
t.Fatalf("code = %s", apiErr.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransportErrorReturnsJSONRPCError(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
return testResponse{
|
||||
Error: &JSONRPCError{
|
||||
Code: -32700,
|
||||
Message: "parse error",
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
_, err := client.DaemonStatus(context.Background())
|
||||
var rpcErr *JSONRPCError
|
||||
if !errors.As(err, &rpcErr) {
|
||||
t.Fatalf("expected JSONRPCError, got %T %v", err, err)
|
||||
}
|
||||
if rpcErr.Code != -32700 {
|
||||
t.Fatalf("code = %d", rpcErr.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextDeadlineIsApplied(t *testing.T) {
|
||||
client := New("bat.sock")
|
||||
client.Timeout = time.Millisecond
|
||||
client.DialContext = func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
<-ctx.Done()
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
_, err := client.DaemonStatus(ctx)
|
||||
if err == nil {
|
||||
t.Fatal("expected dial error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user