Skip to content

Commit

Permalink
test: port content routing over HTTP sharness test
Browse files Browse the repository at this point in the history
This sharness test is flaky, so porting to Go.
  • Loading branch information
guseggert committed Mar 30, 2023
1 parent ebdca5c commit c3763f6
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 61 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ require (
github.com/rs/cors v1.7.0 // indirect
github.com/samber/lo v1.36.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
Expand Down
115 changes: 115 additions & 0 deletions test/cli/content_routing_http_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package cli

import (
"context"
"errors"
"net"
"net/http"
"os/exec"
"testing"
"time"

"github.com/ipfs/boxo/routing/http/server"
"github.com/ipfs/boxo/routing/http/types"
"github.com/ipfs/go-cid"
"github.com/ipfs/kubo/test/cli/harness"
"github.com/ipfs/kubo/test/cli/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

type mockHTTPContentRouter struct{ mock.Mock }

func (r *mockHTTPContentRouter) FindProviders(ctx context.Context, key cid.Cid) ([]types.ProviderResponse, error) {
args := r.Called(ctx, key)
return args.Get(0).([]types.ProviderResponse), args.Error(1)
}

func (r *mockHTTPContentRouter) ProvideBitswap(ctx context.Context, req *server.BitswapWriteProvideRequest) (time.Duration, error) {
args := r.Called(ctx, req)
return args.Get(0).(time.Duration), args.Error(1)
}
func (r *mockHTTPContentRouter) Provide(ctx context.Context, req *server.WriteProvideRequest) (types.ProviderResponse, error) {
args := r.Called(ctx, req)
return args.Get(0).(types.ProviderResponse), args.Error(1)
}

// userAgentRecorder records the user agent of every HTTP request
type userAgentRecorder struct {
delegate http.Handler
userAgents []string
}

func (r *userAgentRecorder) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.userAgents = append(r.userAgents, req.UserAgent())
r.delegate.ServeHTTP(w, req)
}

func TestContentRoutingHTTP(t *testing.T) {
cr := &mockHTTPContentRouter{}
cr.Test(t)

// run the content routing HTTP server
listener, err := net.Listen("tcp", "127.0.0.1:")
require.NoError(t, err)
t.Cleanup(func() { listener.Close() })
userAgentRecorder := &userAgentRecorder{delegate: server.Handler(cr)}
go func() {
err := http.Serve(listener, userAgentRecorder)
if err != nil && !errors.Is(err, http.ErrServerClosed) && !errors.Is(err, net.ErrClosed) {
t.Logf("HTTP server closed with error: %s", err)
}
}()

// setup the node
node := harness.NewT(t).NewNode().Init()
node.Runner.Env["IPFS_HTTP_ROUTERS"] = "http://" + listener.Addr().String()
node.StartDaemon()

// compute a random CID
randStr := string(testutils.RandomBytes(100))
res := node.PipeStrToIPFS(randStr, "add", "-qn")
wantCIDStr := res.Stdout.Trimmed()
wantCID, err := cid.Decode(wantCIDStr)
require.NoError(t, err)

cr.On("FindProviders", mock.Anything, wantCID).Return([]types.ProviderResponse{}, nil)

t.Run("fetching an uncached block results in an HTTP lookup", func(t *testing.T) {
statRes := node.Runner.Run(harness.RunRequest{
Path: node.IPFSBin,
Args: []string{"block", "stat", wantCIDStr},
RunFunc: (*exec.Cmd).Start,
})
defer func() {
if err := statRes.Cmd.Process.Kill(); err != nil {
t.Logf("error killing 'block stat' cmd: %s", err)
}
}()

// verify the content router was called
assert.Eventually(t, func() bool {
return len(cr.Calls) > 0
}, 10*time.Second, 10*time.Millisecond)

assert.NotEmpty(t, userAgentRecorder.userAgents)
version := node.IPFS("id", "-f", "<aver>").Stdout.Trimmed()
for _, userAgent := range userAgentRecorder.userAgents {
assert.Equal(t, version, userAgent)
}
})

// cid.contact supports GET-only: https://github.com/ipfs/kubo/issues/9504
// which means no announcements over HTTP should be made.
t.Run("adding a new CID does not result in an HTTP provide", func(t *testing.T) {
cr.Calls = nil
cr.ExpectedCalls = nil

randStr := string(testutils.RandomBytes(100))
node.IPFSAddStr(randStr)

assert.Zero(t, cr.Calls, "expected no HTTP router calls")
})

}
61 changes: 0 additions & 61 deletions test/sharness/t0172-content-routing-over-http.sh

This file was deleted.

0 comments on commit c3763f6

Please sign in to comment.