@@ -48,6 +48,11 @@ func (m *mockContentRouter) FindPeers(ctx context.Context, pid peer.ID, limit in
4848 return args .Get (0 ).(iter.ResultIter [* types.PeerRecord ]), args .Error (1 )
4949}
5050
51+ func (m * mockContentRouter ) GetClosestPeers (ctx context.Context , key cid.Cid ) (iter.ResultIter [* types.PeerRecord ], error ) {
52+ args := m .Called (ctx , key )
53+ return args .Get (0 ).(iter.ResultIter [* types.PeerRecord ]), args .Error (1 )
54+ }
55+
5156func (m * mockContentRouter ) GetIPNS (ctx context.Context , name ipns.Name ) (* ipns.Record , error ) {
5257 args := m .Called (ctx , name )
5358 rec , _ := args .Get (0 ).(* ipns.Record )
@@ -836,6 +841,132 @@ func TestClient_EmptyResponses(t *testing.T) {
836841 }
837842}
838843
844+ func TestClient_GetClosestPeers (t * testing.T ) {
845+ bitswapPeerRecord := makePeerRecord ([]string {"transport-bitswap" })
846+ httpPeerRecord := makePeerRecord ([]string {"transport-ipfs-gateway-http" })
847+
848+ peerRecords := []iter.Result [* types.PeerRecord ]{
849+ {Val : & bitswapPeerRecord },
850+ {Val : & httpPeerRecord },
851+ }
852+
853+ key := peer .ToCid (* bitswapPeerRecord .ID )
854+
855+ cases := []struct {
856+ name string
857+ httpStatusCode int
858+ stopServer bool
859+ routerResult []iter.Result [* types.PeerRecord ]
860+ routerErr error
861+ clientRequiresStreaming bool
862+ serverStreamingDisabled bool
863+
864+ expErrContains osErrContains
865+ expResult []iter.Result [* types.PeerRecord ]
866+ expStreamingResponse bool
867+ expJSONResponse bool
868+ }{
869+ {
870+ name : "happy case" ,
871+ routerResult : peerRecords ,
872+ expResult : peerRecords ,
873+ expStreamingResponse : true ,
874+ },
875+ {
876+ name : "server doesn't support streaming" ,
877+ routerResult : peerRecords ,
878+ expResult : peerRecords ,
879+ serverStreamingDisabled : true ,
880+ expJSONResponse : true ,
881+ },
882+ {
883+ name : "client requires streaming but server doesn't support it" ,
884+ serverStreamingDisabled : true ,
885+ clientRequiresStreaming : true ,
886+ expErrContains : osErrContains {expContains : "HTTP error with StatusCode=400: no supported content types" },
887+ },
888+ {
889+ name : "returns an error if there's a non-200 response" ,
890+ httpStatusCode : 500 ,
891+ expErrContains : osErrContains {expContains : "HTTP error with StatusCode=500" },
892+ },
893+ {
894+ name : "returns an error if the HTTP client returns a non-HTTP error" ,
895+ stopServer : true ,
896+ expErrContains : osErrContains {
897+ expContains : "connect: connection refused" ,
898+ expContainsWin : "connectex: No connection could be made because the target machine actively refused it." ,
899+ },
900+ },
901+ {
902+ name : "returns no providers if the HTTP server returns a 404 response" ,
903+ httpStatusCode : 404 ,
904+ expResult : nil ,
905+ },
906+ }
907+ for _ , c := range cases {
908+ t .Run (c .name , func (t * testing.T ) {
909+ var clientOpts []Option
910+ var serverOpts []server.Option
911+ var onRespReceived []func (* http.Response )
912+ var onReqReceived []func (* http.Request )
913+
914+ if c .serverStreamingDisabled {
915+ serverOpts = append (serverOpts , server .WithStreamingResultsDisabled ())
916+ }
917+
918+ if c .clientRequiresStreaming {
919+ clientOpts = append (clientOpts , WithStreamResultsRequired ())
920+ onReqReceived = append (onReqReceived , func (r * http.Request ) {
921+ assert .Equal (t , mediaTypeNDJSON , r .Header .Get ("Accept" ))
922+ })
923+ }
924+
925+ if c .expStreamingResponse {
926+ onRespReceived = append (onRespReceived , func (r * http.Response ) {
927+ assert .Equal (t , mediaTypeNDJSON , r .Header .Get ("Content-Type" ))
928+ })
929+ }
930+
931+ if c .expJSONResponse {
932+ onRespReceived = append (onRespReceived , func (r * http.Response ) {
933+ assert .Equal (t , mediaTypeJSON , r .Header .Get ("Content-Type" ))
934+ })
935+ }
936+
937+ deps := makeTestDeps (t , clientOpts , serverOpts )
938+
939+ deps .recordingHTTPClient .f = append (deps .recordingHTTPClient .f , onRespReceived ... )
940+ deps .recordingHandler .f = append (deps .recordingHandler .f , onReqReceived ... )
941+
942+ client := deps .client
943+ router := deps .router
944+
945+ ctx , cancel := context .WithCancel (context .Background ())
946+ t .Cleanup (cancel )
947+
948+ if c .httpStatusCode != 0 {
949+ deps .server .Config .Handler = http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
950+ w .WriteHeader (c .httpStatusCode )
951+ })
952+ }
953+
954+ if c .stopServer {
955+ deps .server .Close ()
956+ }
957+
958+ routerResultIter := iter .FromSlice (c .routerResult )
959+ router .On ("GetClosestPeers" , mock .Anything , key ).Return (routerResultIter , c .routerErr )
960+
961+ resultIter , err := client .GetClosestPeers (ctx , key )
962+ c .expErrContains .errContains (t , err )
963+
964+ results := iter .ReadAll (resultIter )
965+ assert .Equal (t , c .expResult , results )
966+ })
967+ }
968+ }
969+
839970func TestNormalizeBaseURL (t * testing.T ) {
840971 cases := []struct {
841972 name string
0 commit comments