Strengthen in-flight cancellation coverage · Entire

Strengthen in-flight cancellation coverage

Sessions

bce3d316a633View transcript

Changes

3

414 unmodified lines

Current rewrite note:
- Some of these are now covered, including empty source repo, tag force-retarget, duplicate/conflicting mappings, and tag creation when target objects already exist.
- Context cancellation and some harder batch-failure/cutover paths still appear missing.
- Basic context cancellation coverage now exists, but in-flight cancellation and some harder batch-failure/cutover paths still need stronger coverage.

### 22. No benchmark coverage for the expensive paths
3 unmodified lines
package example

import (
    "context"
    "errors"
    "net/http"
    "net/http/httptest"
    "testing"
    "time"

"github.com/go-git/go-git/v5/plumbing/transport"
    transporthttp "github.com/go-git/go-git/v5/plumbing/transport/http"
)

func TestRequestInfoRefsContextCanceled(t *testing.T) {
    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        <-r.Context().Done()
    }))
    defer server.Close()

ep, err := transport.NewEndpoint(server.URL + "/repo.git")
    started := make(chan struct{}, 1)
    ep, err = transport.NewEndpoint("https://example.com/repo.git")
    if err != nil {
        t.Fatalf("parse endpoint: %v", err)
    }
    conn := NewConn(ep, "source", nil, http.DefaultTransport)
    conn := NewConn(ep, "source", nil, roundTripperFunc(func(req *http.Request) (*http.Response, error) {
        started <- struct{}{}
        <-req.Context().Done()
        return nil, req.Context().Err()
    }))

ctx, cancel := context.WithCancel(context.Background())

done := make(chan error, 1)
    go func() {
        _, err := RequestInfoRefs(ctx, conn, "git-upload-pack", "version=2")
        done <- err
    }()

select {
    case <-started:
    case <-time.After(2 * time.Second):
        t.Fatal("request did not reach server before timeout")
    }
cancel()

_, err = RequestInfoRefs(ctx, conn, "git-upload-pack", "version=2")
    select {
    case err = <-done:
    case <-time.After(2 * time.Second):
        t.Fatal("request did not return after cancellation")
    }
    if err == nil {
        t.Fatal("expected cancellation error, got nil")
    }
}

func TestPostRPCStreamContextCanceled(t *testing.T) {
    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        <-r.Context().Done()
    }))
    defer server.Close()

ctx, cancel := context.WithCancel(context.Background())

done := make(chan error, 1)
    go func() {
        _, err := PostRPCStream(ctx, conn, "git-upload-pack", []byte("0000"), true, "upload-pack fetch")
        done <- err
    }()

select {
    case <-started:
    case <-time.After(2 * time.Second):
        t.Fatal("request did not reach server before timeout")
    }
cancel()

_, err = PostRPCStream(ctx, conn, "git-upload-pack", []byte("0000"), true, "upload-pack fetch")
    select {
    case err = <-done:
    case <-time.After(2 * time.Second):
        t.Fatal("request did not return after cancellation")
    }
    if err == nil {
        t.Fatalf("expected context.Canceled, got %v", err)
    }
}

func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
    return f(req)
}
package example

func TestProbe_ContextCanceled(t *testing.T) {
    started := make(chan struct{}, 1)
    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        started <- struct{}{}
        <-r.Context().Done()
    }))
    defer server.Close()

ctx, cancel := context.WithCancel(context.Background())

done := make(chan error, 1)
    go func() {
        _, err := Probe(ctx, Config{
            Source: Endpoint{URL: server.URL + "/repo.git"},
        })
        done <- err
    }()

select {
    case <-started:
    case <-time.After(2 * time.Second):
        t.Fatal("probe request did not reach server before timeout")
    }
cancel()

_, err := Probe(ctx, Config{
        Source: Endpoint{URL: server.URL + "/repo.git"},
    })
    var err error
    select {
    case err = <-done:
    case <-time.After(2 * time.Second):
        t.Fatal("probe did not return after cancellation")
    }
    if err == nil {
        t.Fatal("expected context cancellation error")
    }
}