package httpapi import ( "bytes" "encoding/json" "io" "mime/multipart" "net/http" "net/http/httptest" "net/url" "testing" "scout/internal/registry" ) func TestUploadListLatestAndDownload(t *testing.T) { store, err := registry.New(t.TempDir()) if err != nil { t.Fatal(err) } server := httptest.NewServer((&Server{Registry: store, DeveloperToken: "测试令牌"}).Handler()) defer server.Close() unauthorized, err := http.Post(server.URL+"/api/v1/packages/upload", "application/json", nil) if err != nil { t.Fatal(err) } if unauthorized.StatusCode != http.StatusUnauthorized { t.Fatalf("未授权状态错误: %d", unauthorized.StatusCode) } unauthorized.Body.Close() body := &bytes.Buffer{} writer := multipart.NewWriter(body) _ = writer.WriteField("name", "demo-core") _ = writer.WriteField("version", "1.0.0") fileWriter, err := writer.CreateFormFile("file", "demo.pkg") if err != nil { t.Fatal(err) } _, _ = fileWriter.Write([]byte("demo package")) _ = writer.Close() request, err := http.NewRequest(http.MethodPost, server.URL+"/api/v1/packages/upload", body) if err != nil { t.Fatal(err) } request.Header.Set("Content-Type", writer.FormDataContentType()) request.Header.Set("Authorization", "Bearer 测试令牌") response, err := http.DefaultClient.Do(request) if err != nil { t.Fatal(err) } if response.StatusCode != http.StatusCreated { t.Fatalf("上传状态错误: %d", response.StatusCode) } var uploaded registry.Package if err := json.NewDecoder(response.Body).Decode(&uploaded); err != nil { t.Fatal(err) } response.Body.Close() if uploaded.Name != "demo-core" || uploaded.Version != "1.0.0" { t.Fatalf("上传结果错误: %+v", uploaded) } listResponse, err := http.Get(server.URL + "/api/v1/packages") if err != nil { t.Fatal(err) } var listed struct { Packages []registry.Package `json:"packages"` } if err := json.NewDecoder(listResponse.Body).Decode(&listed); err != nil { t.Fatal(err) } listResponse.Body.Close() if len(listed.Packages) != 1 { t.Fatalf("包列表数量错误: %d", len(listed.Packages)) } downloadResponse, err := http.Get(server.URL + "/api/v1/packages/demo-core/1.0.0/download") if err != nil { t.Fatal(err) } content, err := io.ReadAll(downloadResponse.Body) if err != nil { t.Fatal(err) } downloadResponse.Body.Close() if downloadResponse.StatusCode != http.StatusOK || string(content) != "demo package" { t.Fatalf("下载结果错误: %d %q", downloadResponse.StatusCode, content) } if downloadResponse.Header.Get("X-Scout-SHA256") != uploaded.SHA256 { t.Fatal("下载校验值不一致") } } func TestStreamFiltersPackage(t *testing.T) { store, err := registry.New(t.TempDir()) if err != nil { t.Fatal(err) } server := httptest.NewServer((&Server{Registry: store, DeveloperToken: "测试令牌"}).Handler()) defer server.Close() request, err := http.NewRequest(http.MethodGet, server.URL+"/api/v1/updates/stream?packages=target", nil) if err != nil { t.Fatal(err) } client := &http.Client{} streamResponse, err := client.Do(request) if err != nil { t.Fatal(err) } defer streamResponse.Body.Close() if streamResponse.StatusCode != http.StatusOK { t.Fatalf("通知状态错误: %d", streamResponse.StatusCode) } if streamResponse.Header.Get("Content-Type") != "text/event-stream; charset=utf-8" { t.Fatalf("通知类型错误: %s", streamResponse.Header.Get("Content-Type")) } _ = url.Values{} }