Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 47 additions & 19 deletions pkg/internal/itest/http_fetch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ func TestHttpFetch(t *testing.T) {
type queryModifier func(url.Values, []testpeer.TestPeer)
type bodyValidator func(*testing.T, unixfs.DirEntry, []byte)
type lassieOptsGen func(*testing.T, *mocknet.MockRetrievalNet) []lassie.LassieOption
type response struct {
StatusCode int
Header http.Header
Body []byte
}
wrapPath := "/want2/want1/want0"

testCases := []struct {
Expand Down Expand Up @@ -1077,9 +1082,9 @@ func TestHttpFetch(t *testing.T) {
}
}

responseChans := make([]chan *http.Response, 0)
responseChans := make([]chan response, 0)
for i := 0; i < len(srcData); i++ {
responseChan := make(chan *http.Response, 1)
responseChan := make(chan response, 1)
responseChans = append(responseChans, responseChan)
go func(i int) {
// Make a request for our CID and read the complete CAR bytes
Expand All @@ -1099,11 +1104,17 @@ func TestHttpFetch(t *testing.T) {
t.Log("Fetching", getReq.URL.String())
resp, err := http.DefaultClient.Do(getReq)
req.NoError(err)
responseChan <- resp
expectBodyReadError := ""
if testCase.expectUncleanEnd {
expectBodyReadError = "http: unexpected EOF reading trailer"
}
body := readAllBody(t, resp.Body, expectBodyReadError)
req.NoError(resp.Body.Close())
responseChan <- response{StatusCode: resp.StatusCode, Header: resp.Header, Body: body}
}(i)
}

responses := make([]*http.Response, 0)
responses := make([]response, 0)
for _, responseChan := range responseChans {
select {
case resp := <-responseChan:
Expand Down Expand Up @@ -1133,9 +1144,7 @@ func TestHttpFetch(t *testing.T) {
req.Equal(http.StatusUnauthorized, resp.StatusCode)
} else {
if resp.StatusCode != http.StatusOK {
body, err := io.ReadAll(resp.Body)
req.NoError(err)
req.Failf("200 response code not received", "got code: %d, body: %s", resp.StatusCode, string(body))
req.Failf("200 response code not received", "got code: %d, body: %s", resp.StatusCode, string(resp.Body))
}
req.Regexp(`^lassie/v\d+\.\d+\.\d+-\w+$`, resp.Header.Get("Server"))
req.Equal(fmt.Sprintf(`attachment; filename="%s.car"`, srcData[i].Root.String()), resp.Header.Get("Content-Disposition"))
Expand All @@ -1154,30 +1163,21 @@ func TestHttpFetch(t *testing.T) {
require.NotEmpty(t, requestId)
_, err := uuid.Parse(requestId)
req.NoError(err)
body, err := io.ReadAll(resp.Body)
if !testCase.expectUncleanEnd {
req.NoError(err)
} else {
req.Error(err)
}
err = resp.Body.Close()
req.NoError(err)

if DEBUG_DATA {
t.Logf("Creating CAR %s in temp dir", fmt.Sprintf("%s_received%d.car", testCase.name, i))
dstf, err := os.CreateTemp("", fmt.Sprintf("%s_received%d.car", testCase.name, i))
req.NoError(err)
t.Logf("Writing received data to CAR @ %s", dstf.Name())
_, err = dstf.Write(body)
_, err = dstf.Write(resp.Body)
req.NoError(err)
carFiles = append(carFiles, dstf)
}

if testCase.validateBodies != nil && testCase.validateBodies[i] != nil {
testCase.validateBodies[i](t, srcData[i], body)
testCase.validateBodies[i](t, srcData[i], resp.Body)
} else {
// gotDir := CarToDirEntry(t, bytes.NewReader(body), srcData[i].Root, true)
gotLsys := CarBytesLinkSystem(t, bytes.NewReader(body))
gotLsys := CarBytesLinkSystem(t, bytes.NewReader(resp.Body))
gotDir := unixfs.ToDirEntry(t, gotLsys, srcData[i].Root, true)
unixfs.CompareDirEntries(t, srcData[i], gotDir)
}
Expand Down Expand Up @@ -1269,3 +1269,31 @@ func debugRemotes(t *testing.T, ctx context.Context, name string, remotes []test
}
return carFiles
}

func readAllBody(t *testing.T, r io.Reader, expectError string) []byte {
if expectError == "" {
body, err := io.ReadAll(r)
require.NoError(t, err)
return body
}
// expect an error, so let's creep up on it and collect as much of the body
// as we can before the error blocks us
// see readLocked() in src/net/http/transfer.go:
// → b.src.Read(p)
// → followed by b.readTrailer() which should error; we want to capture both
var buf bytes.Buffer
var byt [1]byte
var err error
var n int
for {
n, err = r.Read(byt[:])
// record the bytes we read, the error should come after the normal body
// read and then it attempts to read trailers where it should fail
buf.Write(byt[:n])
if err != nil {
require.EqualError(t, err, expectError)
break
}
}
return buf.Bytes()
}