From 097ed659b21b740de1b71515bf6fc95d5bf4f86a Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 10 Jul 2021 16:57:13 +0200 Subject: [PATCH] rest: test that zero-length replies over HTTP2 work correctly The first test function ensures that the workaround works as expected. And the second test function is intended to fail as soon as the issue has been fixed in golang to allow us to eventually remove the workaround. --- internal/backend/rest/rest_int_go114_test.go | 94 ++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 internal/backend/rest/rest_int_go114_test.go diff --git a/internal/backend/rest/rest_int_go114_test.go b/internal/backend/rest/rest_int_go114_test.go new file mode 100644 index 000000000..036a136e1 --- /dev/null +++ b/internal/backend/rest/rest_int_go114_test.go @@ -0,0 +1,94 @@ +// +build go1.14 + +package rest_test + +import ( + "context" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/restic/restic/internal/backend/rest" + "github.com/restic/restic/internal/restic" +) + +func TestZeroLengthRead(t *testing.T) { + // Test workaround for https://github.com/golang/go/issues/46071. Can be removed once this is fixed in Go + // and the minimum golang version supported by restic includes the fix. + numRequests := 0 + srv := httptest.NewUnstartedServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + numRequests++ + t.Logf("req %v %v", req.Method, req.URL.Path) + if req.Method == "GET" { + res.Header().Set("Content-Length", "42") + // Now the handler fails for some reason and is unable to send data + return + } + + t.Errorf("unhandled request %v %v", req.Method, req.URL.Path) + })) + srv.EnableHTTP2 = true + srv.StartTLS() + defer srv.Close() + + srvURL, err := url.Parse(srv.URL) + if err != nil { + t.Fatal(err) + } + + cfg := rest.Config{ + Connections: 5, + URL: srvURL, + } + be, err := rest.Open(cfg, srv.Client().Transport) + if err != nil { + t.Fatal(err) + } + defer func() { + err = be.Close() + if err != nil { + t.Fatal(err) + } + }() + + err = be.Load(context.TODO(), restic.Handle{Type: restic.ConfigFile}, 0, 0, func(rd io.Reader) error { + _, err := ioutil.ReadAll(rd) + if err == nil { + t.Fatal("ReadAll should have returned an 'Unexpected EOF' error") + } + return nil + }) + if err == nil { + t.Fatal("Got no unexpected EOF error") + } +} + +func TestGolangZeroLengthRead(t *testing.T) { + // This test is intended to fail once the underlying issue has been fixed in Go + ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Length", "42") + // Now the handler fails for some reason and is unable to send data + })) + ts.EnableHTTP2 = true + ts.StartTLS() + defer ts.Close() + + res, err := ts.Client().Get(ts.URL) + if err != nil { + t.Fatal(err) + } + _, err = ioutil.ReadAll(res.Body) + defer func() { + err = res.Body.Close() + if err != nil { + t.Fatal(err) + } + }() + if err != nil { + // This should fail with an 'Unexpected EOF' error + t.Fatal(err) + } +}