Scout/pkg/client/client_test.go

150 lines
4.1 KiB
Go

package client
import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"time"
"scout/internal/httpapi"
"scout/internal/registry"
)
func TestClientUploadQueryCheckAndDownload(t *testing.T) {
store, err := registry.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
server := httptest.NewServer((&httpapi.Server{Registry: store, DeveloperToken: "测试令牌"}).Handler())
defer server.Close()
api, err := New(server.URL, WithDeveloperToken("测试令牌"))
if err != nil {
t.Fatal(err)
}
ctx := context.Background()
uploaded, err := api.Upload(ctx, UploadRequest{
Name: "client-demo",
Version: "1.0.0",
Platform: "any",
Architecture: "universal",
FileName: "demo.pkg",
File: bytes.NewBufferString("client package"),
})
if err != nil {
t.Fatal(err)
}
if uploaded.SHA256 == "" {
t.Fatal("上传结果缺少 SHA-256")
}
packages, err := api.ListPackages(ctx)
if err != nil || len(packages) != 1 {
t.Fatalf("包列表错误: %v, %d", err, len(packages))
}
latest, available, err := api.CheckUpdate(ctx, "client-demo", "0.9.0")
if err != nil || !available || latest.Version != "1.0.0" {
t.Fatalf("更新检查错误: %+v, %t, %v", latest, available, err)
}
versions, err := api.ListVersions(ctx, "client-demo")
if err != nil || len(versions) != 1 {
t.Fatalf("版本列表错误: %v, %d", err, len(versions))
}
output := filepath.Join(t.TempDir(), "download.pkg")
downloaded, err := api.Download(ctx, "client-demo", "", output)
if err != nil {
t.Fatal(err)
}
if downloaded.SHA256 != uploaded.SHA256 {
t.Fatalf("下载校验值不一致: %s != %s", downloaded.SHA256, uploaded.SHA256)
}
content, err := os.ReadFile(output)
if err != nil || string(content) != "client package" {
t.Fatalf("下载内容错误: %q, %v", content, err)
}
}
func TestClientWatchUpdates(t *testing.T) {
store, err := registry.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
server := httptest.NewServer((&httpapi.Server{Registry: store, DeveloperToken: "测试令牌"}).Handler())
defer server.Close()
api, err := New(server.URL, WithDeveloperToken("测试令牌"))
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
updates, err := api.WatchUpdates(ctx, "client-demo")
if err != nil {
t.Fatal(err)
}
go func() {
_, _ = api.Upload(context.Background(), UploadRequest{
Name: "client-demo",
Version: "2.0.0",
Platform: "any",
Architecture: "universal",
FileName: "demo.pkg",
File: bytes.NewBufferString("new package"),
})
}()
select {
case update := <-updates:
if update.Package.Name != "client-demo" || update.Package.Version != "2.0.0" {
t.Fatalf("通知内容错误: %+v", update)
}
case <-time.After(2 * time.Second):
t.Fatal("等待更新通知超时")
}
}
func TestCompareVersions(t *testing.T) {
cases := []struct {
left string
right string
want int
}{
{left: "1.10.0", right: "1.9.0", want: 1},
{left: "v1.0.0", right: "1.0.0", want: 0},
{left: "1.0.0", right: "2.0.0", want: -1},
}
for _, item := range cases {
if got := CompareVersions(item.left, item.right); got != item.want {
t.Fatalf("CompareVersions(%q, %q) = %d, want %d", item.left, item.right, got, item.want)
}
}
}
func TestDownloadKeepsDestinationWhenChecksumFails(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.Header().Set("Content-Length", "7")
writer.Header().Set("X-Scout-SHA256", "invalid")
_, _ = writer.Write([]byte("payload"))
}))
defer server.Close()
api, err := New(server.URL)
if err != nil {
t.Fatal(err)
}
destination := filepath.Join(t.TempDir(), "package.pkg")
if err := os.WriteFile(destination, []byte("original"), 0o600); err != nil {
t.Fatal(err)
}
if _, err := api.Download(context.Background(), "demo", "1.0.0", destination); err == nil {
t.Fatal("错误校验值应该导致下载失败")
}
data, err := os.ReadFile(destination)
if err != nil {
t.Fatal(err)
}
if string(data) != "original" {
t.Fatalf("校验失败不应覆盖原文件:%q", data)
}
}