Return write evidence from Gitea operations
This commit is contained in:
@@ -245,3 +245,171 @@ func TestBackendPreflightPreservesCancellation(t *testing.T) {
|
||||
t.Fatalf("Preflight() error = %v, want unavailable and context cancellation", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendCreateReleaseSendsRequestedFieldsAndAcceptsProtocolAcknowledgment(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost || r.URL.Path != "/api/v1/repos/owner/project/releases" {
|
||||
t.Errorf("request = %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
if got, want := r.Header.Get("Authorization"), "token fixture-secret-token"; got != want {
|
||||
t.Errorf("authorization = %q, want %q", got, want)
|
||||
}
|
||||
var request createReleaseRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
t.Errorf("decode request: %v", err)
|
||||
}
|
||||
if request.TagName != "v1.2.3" || request.TargetCommitish != strings.Repeat("a", 40) || request.Name != "Release title" || request.Body != "# Release title\n\nComplete notes." || !request.Draft || !request.Prerelease {
|
||||
t.Errorf("release request = %#v", request)
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(releaseResponse{ID: 12, TagName: "server tag", Name: "server title", Body: "server body", Draft: true, Prerelease: true})
|
||||
}))
|
||||
defer server.Close()
|
||||
backend := NewBackend(testDestination(server.URL), server.Client())
|
||||
|
||||
release, evidence, err := backend.CreateRelease(context.Background(), forge.CreateReleaseRequest{
|
||||
Tag: "v1.2.3", Commit: strings.Repeat("a", 40), Title: "Release title",
|
||||
Body: "# Release title\n\nComplete notes.", Draft: true, Prerelease: true,
|
||||
})
|
||||
if err != nil || evidence != (forge.WriteEvidence{Attempted: true, Disposition: forge.WriteAccepted}) {
|
||||
t.Fatalf("CreateRelease() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
if release.Handle == nil || release.Tag != "server tag" || release.Title != "server title" || release.Body != "server body" || !release.Draft || !release.Prerelease {
|
||||
t.Fatalf("CreateRelease() release = %#v", release)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendCreateReleaseMarksInvalidAcknowledgmentUncertain(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_ = json.NewEncoder(w).Encode(releaseResponse{TagName: "v1.2.3"})
|
||||
}))
|
||||
defer server.Close()
|
||||
backend := NewBackend(testDestination(server.URL), server.Client())
|
||||
|
||||
_, evidence, err := backend.CreateRelease(context.Background(), validCreateReleaseRequest())
|
||||
var failure *forge.Failure
|
||||
if !errors.As(err, &failure) || failure.Kind != forge.FailureMalformed || evidence != (forge.WriteEvidence{Attempted: true, Disposition: forge.WriteUncertain}) {
|
||||
t.Fatalf("CreateRelease() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendCreateReleaseClassifiesConflictAndServerFailure(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
status int
|
||||
disposition forge.WriteDisposition
|
||||
}{
|
||||
{status: http.StatusBadRequest, disposition: forge.WriteRejected},
|
||||
{status: http.StatusConflict, disposition: forge.WriteConflict},
|
||||
{status: http.StatusServiceUnavailable, disposition: forge.WriteUncertain},
|
||||
} {
|
||||
t.Run(http.StatusText(test.status), func(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(test.status) }))
|
||||
defer server.Close()
|
||||
backend := NewBackend(testDestination(server.URL), server.Client())
|
||||
|
||||
_, evidence, err := backend.CreateRelease(context.Background(), validCreateReleaseRequest())
|
||||
if err == nil || evidence != (forge.WriteEvidence{Attempted: true, Disposition: test.disposition}) {
|
||||
t.Fatalf("CreateRelease() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendUploadAssetBorrowsReaderAndValidatesAcknowledgment(t *testing.T) {
|
||||
var uploaded string
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost || r.URL.Path != "/api/v1/repos/owner/project/releases/12/assets" || r.URL.Query().Get("name") != "app.bin" {
|
||||
t.Errorf("request = %s %s?%s", r.Method, r.URL.Path, r.URL.RawQuery)
|
||||
}
|
||||
if got, want := r.Header.Get("Authorization"), "token fixture-secret-token"; got != want {
|
||||
t.Errorf("authorization = %q, want %q", got, want)
|
||||
}
|
||||
file, header, err := r.FormFile("attachment")
|
||||
if err != nil {
|
||||
t.Errorf("attachment: %v", err)
|
||||
} else {
|
||||
defer file.Close()
|
||||
content, readErr := io.ReadAll(file)
|
||||
if readErr != nil {
|
||||
t.Errorf("read attachment: %v", readErr)
|
||||
}
|
||||
if header.Filename != "app.bin" {
|
||||
t.Errorf("multipart filename = %q", header.Filename)
|
||||
}
|
||||
uploaded = string(content)
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(assetResponse{ID: 50, Name: "app.bin"})
|
||||
}))
|
||||
defer server.Close()
|
||||
backend := NewBackend(testDestination(server.URL), server.Client())
|
||||
reader := &trackedReader{Reader: strings.NewReader("streamed bytes")}
|
||||
|
||||
evidence, err := backend.UploadAsset(context.Background(), releaseHandle{id: 12}, "app.bin", reader)
|
||||
if err != nil || evidence != (forge.WriteEvidence{Attempted: true, Disposition: forge.WriteAccepted}) {
|
||||
t.Fatalf("UploadAsset() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
if uploaded != "streamed bytes" || reader.closed {
|
||||
t.Fatalf("uploaded = %q, caller reader closed = %v", uploaded, reader.closed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendUploadAssetMarksBadAcknowledgmentUncertain(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_ = json.NewEncoder(w).Encode(assetResponse{ID: 50, Name: "different.bin"})
|
||||
}))
|
||||
defer server.Close()
|
||||
backend := NewBackend(testDestination(server.URL), server.Client())
|
||||
|
||||
evidence, err := backend.UploadAsset(context.Background(), releaseHandle{id: 12}, "app.bin", strings.NewReader("data"))
|
||||
var failure *forge.Failure
|
||||
if !errors.As(err, &failure) || failure.Kind != forge.FailureMalformed || evidence != (forge.WriteEvidence{Attempted: true, Disposition: forge.WriteUncertain}) {
|
||||
t.Fatalf("UploadAsset() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendUploadAssetClassifiesKnownRejectionAndConflict(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
status int
|
||||
disposition forge.WriteDisposition
|
||||
}{
|
||||
{status: http.StatusBadRequest, disposition: forge.WriteRejected},
|
||||
{status: http.StatusConflict, disposition: forge.WriteConflict},
|
||||
{status: http.StatusInternalServerError, disposition: forge.WriteUncertain},
|
||||
} {
|
||||
t.Run(http.StatusText(test.status), func(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(test.status) }))
|
||||
defer server.Close()
|
||||
backend := NewBackend(testDestination(server.URL), server.Client())
|
||||
|
||||
evidence, err := backend.UploadAsset(context.Background(), releaseHandle{id: 12}, "app.bin", strings.NewReader("data"))
|
||||
if err == nil || evidence != (forge.WriteEvidence{Attempted: true, Disposition: test.disposition}) {
|
||||
t.Fatalf("UploadAsset() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendUploadAssetPreservesCancellationAsUncertain(t *testing.T) {
|
||||
server := httptest.NewServer(http.NotFoundHandler())
|
||||
defer server.Close()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
evidence, err := NewBackend(testDestination(server.URL), server.Client()).UploadAsset(ctx, releaseHandle{id: 12}, "app.bin", strings.NewReader("data"))
|
||||
if evidence != (forge.WriteEvidence{Attempted: true, Disposition: forge.WriteUncertain}) || !errors.Is(err, context.Canceled) {
|
||||
t.Fatalf("UploadAsset() evidence = %#v, error = %v", evidence, err)
|
||||
}
|
||||
}
|
||||
|
||||
func validCreateReleaseRequest() forge.CreateReleaseRequest {
|
||||
return forge.CreateReleaseRequest{Tag: "v1.2.3", Commit: strings.Repeat("a", 40), Title: "Release", Body: "# Release"}
|
||||
}
|
||||
|
||||
type trackedReader struct {
|
||||
io.Reader
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (reader *trackedReader) Close() error {
|
||||
reader.closed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user