github.com/ethersphere/bee/v2@v2.2.0/pkg/api/peer_test.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package api_test
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"net/http"
    11  	"testing"
    12  
    13  	"github.com/ethereum/go-ethereum/common"
    14  	"github.com/ethersphere/bee/v2/pkg/api"
    15  	"github.com/ethersphere/bee/v2/pkg/bzz"
    16  	"github.com/ethersphere/bee/v2/pkg/crypto"
    17  	"github.com/ethersphere/bee/v2/pkg/jsonhttp"
    18  	"github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest"
    19  	"github.com/ethersphere/bee/v2/pkg/p2p"
    20  	"github.com/ethersphere/bee/v2/pkg/p2p/mock"
    21  	"github.com/ethersphere/bee/v2/pkg/swarm"
    22  	ma "github.com/multiformats/go-multiaddr"
    23  )
    24  
    25  func TestConnect(t *testing.T) {
    26  	t.Parallel()
    27  
    28  	underlay := "/ip4/127.0.0.1/tcp/1634/p2p/16Uiu2HAkx8ULY8cTXhdVAcMmLcH9AsTKz6uBQ7DPLKRjMLgBVYkS"
    29  	errorUnderlay := "/ip4/127.0.0.1/tcp/1634/p2p/16Uiu2HAkw88cjH2orYrB6fDui4eUNdmgkwnDM8W681UbfsPgM9QY"
    30  	testErr := errors.New("test error")
    31  
    32  	privateKey, err := crypto.GenerateSecp256k1Key()
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  
    37  	block := common.HexToHash("0x1").Bytes()
    38  
    39  	overlay, err := crypto.NewOverlayAddress(privateKey.PublicKey, 0, block)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	underlama, err := ma.NewMultiaddr(underlay)
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  
    48  	bzzAddress, err := bzz.NewAddress(crypto.NewDefaultSigner(privateKey), underlama, overlay, 0, nil)
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	testServer, _, _, _ := newTestServer(t, testServerOptions{
    54  		P2P: mock.New(mock.WithConnectFunc(func(ctx context.Context, addr ma.Multiaddr) (*bzz.Address, error) {
    55  			if addr.String() == errorUnderlay {
    56  				return nil, testErr
    57  			}
    58  			return bzzAddress, nil
    59  		})),
    60  	})
    61  
    62  	t.Run("ok", func(t *testing.T) {
    63  		t.Parallel()
    64  		jsonhttptest.Request(t, testServer, http.MethodPost, "/connect"+underlay, http.StatusOK,
    65  			jsonhttptest.WithExpectedJSONResponse(api.PeerConnectResponse{
    66  				Address: overlay.String(),
    67  			}),
    68  		)
    69  	})
    70  
    71  	t.Run("error", func(t *testing.T) {
    72  		t.Parallel()
    73  		jsonhttptest.Request(t, testServer, http.MethodPost, "/connect"+errorUnderlay, http.StatusInternalServerError,
    74  			jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
    75  				Code:    http.StatusInternalServerError,
    76  				Message: testErr.Error(),
    77  			}),
    78  		)
    79  	})
    80  
    81  	t.Run("error - add peer", func(t *testing.T) {
    82  		t.Parallel()
    83  		testServer, _, _, _ := newTestServer(t, testServerOptions{
    84  			P2P: mock.New(mock.WithConnectFunc(func(ctx context.Context, addr ma.Multiaddr) (*bzz.Address, error) {
    85  				if addr.String() == errorUnderlay {
    86  					return nil, testErr
    87  				}
    88  				return bzzAddress, nil
    89  			})),
    90  		})
    91  
    92  		jsonhttptest.Request(t, testServer, http.MethodPost, "/connect"+errorUnderlay, http.StatusInternalServerError,
    93  			jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
    94  				Code:    http.StatusInternalServerError,
    95  				Message: testErr.Error(),
    96  			}),
    97  		)
    98  	})
    99  }
   100  
   101  func TestDisconnect(t *testing.T) {
   102  	t.Parallel()
   103  
   104  	address := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c")
   105  	unknownAddress := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59e")
   106  	errorAddress := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59a")
   107  	testErr := errors.New("test error")
   108  
   109  	testServer, _, _, _ := newTestServer(t, testServerOptions{
   110  		P2P: mock.New(mock.WithDisconnectFunc(func(addr swarm.Address, reason string) error {
   111  			if reason != "user requested disconnect" {
   112  				return testErr
   113  			}
   114  
   115  			if addr.Equal(address) {
   116  				return nil
   117  			}
   118  
   119  			if addr.Equal(errorAddress) {
   120  				return testErr
   121  			}
   122  
   123  			return p2p.ErrPeerNotFound
   124  		})),
   125  	})
   126  
   127  	t.Run("ok", func(t *testing.T) {
   128  		t.Parallel()
   129  
   130  		jsonhttptest.Request(t, testServer, http.MethodDelete, "/peers/"+address.String(), http.StatusOK,
   131  			jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
   132  				Code:    http.StatusOK,
   133  				Message: http.StatusText(http.StatusOK),
   134  			}),
   135  		)
   136  	})
   137  
   138  	t.Run("unknown", func(t *testing.T) {
   139  		t.Parallel()
   140  
   141  		jsonhttptest.Request(t, testServer, http.MethodDelete, "/peers/"+unknownAddress.String(), http.StatusNotFound,
   142  			jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
   143  				Code:    http.StatusNotFound,
   144  				Message: "peer not found",
   145  			}),
   146  		)
   147  	})
   148  
   149  	t.Run("error", func(t *testing.T) {
   150  		t.Parallel()
   151  
   152  		jsonhttptest.Request(t, testServer, http.MethodDelete, "/peers/"+errorAddress.String(), http.StatusInternalServerError,
   153  			jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
   154  				Code:    http.StatusInternalServerError,
   155  				Message: testErr.Error(),
   156  			}),
   157  		)
   158  	})
   159  }
   160  
   161  func TestPeer(t *testing.T) {
   162  	t.Parallel()
   163  
   164  	overlay := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c")
   165  	testServer, _, _, _ := newTestServer(t, testServerOptions{
   166  		P2P: mock.New(mock.WithPeersFunc(func() []p2p.Peer {
   167  			return []p2p.Peer{{Address: overlay}}
   168  		})),
   169  	})
   170  
   171  	t.Run("ok", func(t *testing.T) {
   172  		t.Parallel()
   173  
   174  		jsonhttptest.Request(t, testServer, http.MethodGet, "/peers", http.StatusOK,
   175  			jsonhttptest.WithExpectedJSONResponse(api.PeersResponse{
   176  				Peers: []api.Peer{{Address: overlay}},
   177  			}),
   178  		)
   179  	})
   180  }
   181  
   182  func TestBlocklistedPeers(t *testing.T) {
   183  	t.Parallel()
   184  
   185  	overlay := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c")
   186  	testServer, _, _, _ := newTestServer(t, testServerOptions{
   187  		P2P: mock.New(mock.WithBlocklistedPeersFunc(func() ([]p2p.BlockListedPeer, error) {
   188  			return []p2p.BlockListedPeer{{Peer: p2p.Peer{Address: overlay}}}, nil
   189  		})),
   190  	})
   191  
   192  	jsonhttptest.Request(t, testServer, http.MethodGet, "/blocklist", http.StatusOK,
   193  		jsonhttptest.WithExpectedJSONResponse(api.BlockedListedPeersResponse{
   194  			Peers: []api.BlockListedPeer{{Peer: api.Peer{Address: overlay}, Duration: 0}},
   195  		}),
   196  	)
   197  }
   198  
   199  func TestBlocklistedPeersErr(t *testing.T) {
   200  	t.Parallel()
   201  
   202  	overlay := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c")
   203  	testServer, _, _, _ := newTestServer(t, testServerOptions{
   204  		P2P: mock.New(mock.WithBlocklistedPeersFunc(func() ([]p2p.BlockListedPeer, error) {
   205  			return []p2p.BlockListedPeer{{Peer: p2p.Peer{Address: overlay}}}, errors.New("some error")
   206  		})),
   207  	})
   208  
   209  	jsonhttptest.Request(t, testServer, http.MethodGet, "/blocklist", http.StatusInternalServerError,
   210  		jsonhttptest.WithExpectedJSONResponse(
   211  			jsonhttp.StatusResponse{
   212  				Code:    http.StatusInternalServerError,
   213  				Message: "get blocklisted peers failed",
   214  			}),
   215  	)
   216  }
   217  
   218  func Test_peerConnectHandler_invalidInputs(t *testing.T) {
   219  	t.Parallel()
   220  
   221  	client, _, _, _ := newTestServer(t, testServerOptions{})
   222  
   223  	tests := []struct {
   224  		name         string
   225  		multiAddress string
   226  		want         jsonhttp.StatusResponse
   227  	}{{
   228  		name:         "multi-address - invalid value",
   229  		multiAddress: "ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59a",
   230  		want: jsonhttp.StatusResponse{
   231  			Code:    http.StatusBadRequest,
   232  			Message: "invalid path params",
   233  			Reasons: []jsonhttp.Reason{
   234  				{
   235  					Field: "multi-address",
   236  					Error: "failed to parse multiaddr \"/ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59a\": unknown protocol ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59a",
   237  				},
   238  			},
   239  		},
   240  	}}
   241  
   242  	for _, tc := range tests {
   243  		tc := tc
   244  		t.Run(tc.name, func(t *testing.T) {
   245  			t.Parallel()
   246  
   247  			jsonhttptest.Request(t, client, http.MethodPost, "/connect/"+tc.multiAddress, tc.want.Code,
   248  				jsonhttptest.WithExpectedJSONResponse(tc.want),
   249  			)
   250  		})
   251  	}
   252  }
   253  
   254  func Test_peerDisconnectHandler_invalidInputs(t *testing.T) {
   255  	t.Parallel()
   256  
   257  	client, _, _, _ := newTestServer(t, testServerOptions{})
   258  
   259  	tests := []struct {
   260  		name    string
   261  		address string
   262  		want    jsonhttp.StatusResponse
   263  	}{{
   264  		name:    "address - odd hex string",
   265  		address: "123",
   266  		want: jsonhttp.StatusResponse{
   267  			Code:    http.StatusBadRequest,
   268  			Message: "invalid path params",
   269  			Reasons: []jsonhttp.Reason{
   270  				{
   271  					Field: "address",
   272  					Error: api.ErrHexLength.Error(),
   273  				},
   274  			},
   275  		},
   276  	}, {
   277  		name:    "address - invalid hex character",
   278  		address: "123G",
   279  		want: jsonhttp.StatusResponse{
   280  			Code:    http.StatusBadRequest,
   281  			Message: "invalid path params",
   282  			Reasons: []jsonhttp.Reason{
   283  				{
   284  					Field: "address",
   285  					Error: api.HexInvalidByteError('G').Error(),
   286  				},
   287  			},
   288  		},
   289  	}}
   290  
   291  	for _, tc := range tests {
   292  		tc := tc
   293  		t.Run(tc.name, func(t *testing.T) {
   294  			t.Parallel()
   295  
   296  			jsonhttptest.Request(t, client, http.MethodDelete, "/peers/"+tc.address, tc.want.Code,
   297  				jsonhttptest.WithExpectedJSONResponse(tc.want),
   298  			)
   299  		})
   300  	}
   301  }