github.com/ethersphere/bee/v2@v2.2.0/pkg/status/status_test.go (about)

     1  // Copyright 2023 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 status_test
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"testing"
    11  
    12  	"github.com/ethersphere/bee/v2/pkg/api"
    13  	"github.com/ethersphere/bee/v2/pkg/log"
    14  	"github.com/ethersphere/bee/v2/pkg/p2p/protobuf"
    15  	"github.com/ethersphere/bee/v2/pkg/p2p/streamtest"
    16  	"github.com/ethersphere/bee/v2/pkg/postage"
    17  	"github.com/ethersphere/bee/v2/pkg/status"
    18  	"github.com/ethersphere/bee/v2/pkg/status/internal/pb"
    19  	"github.com/ethersphere/bee/v2/pkg/swarm"
    20  	"github.com/ethersphere/bee/v2/pkg/topology"
    21  	"github.com/google/go-cmp/cmp"
    22  )
    23  
    24  func TestStatus(t *testing.T) {
    25  	t.Parallel()
    26  
    27  	want := &pb.Snapshot{
    28  		BeeMode:          api.FullMode.String(),
    29  		ReserveSize:      128,
    30  		PullsyncRate:     64,
    31  		StorageRadius:    8,
    32  		BatchCommitment:  1024,
    33  		NeighborhoodSize: 1,
    34  		IsReachable:      true,
    35  		LastSyncedBlock:  6092500,
    36  	}
    37  
    38  	sssMock := &statusSnapshotMock{want}
    39  
    40  	peersIterMock := new(topologyPeersIterNoopMock)
    41  
    42  	peer1 := status.NewService(
    43  		log.Noop,
    44  		nil,
    45  		peersIterMock,
    46  		want.BeeMode,
    47  		sssMock,
    48  		sssMock,
    49  	)
    50  
    51  	peer1.SetSync(sssMock)
    52  
    53  	recorder := streamtest.New(streamtest.WithProtocols(peer1.Protocol()))
    54  
    55  	peer2 := status.NewService(log.Noop, recorder, peersIterMock, "", nil, nil)
    56  
    57  	address := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c")
    58  
    59  	if _, err := peer2.PeerSnapshot(context.Background(), address); err != nil {
    60  		t.Fatalf("send msg get: unexpected error: %v", err)
    61  	}
    62  
    63  	records, err := recorder.Records(address, status.ProtocolName, status.ProtocolVersion, status.StreamName)
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	if have, want := len(records), 1; want != have {
    68  		t.Fatalf("have %v records, want %v", have, want)
    69  	}
    70  
    71  	messages, err := protobuf.ReadMessages(
    72  		bytes.NewReader(records[0].In()),
    73  		func() protobuf.Message { return new(pb.Get) },
    74  	)
    75  	if err != nil {
    76  		t.Fatalf("read messages: unexpected error: %v", err)
    77  	}
    78  	if have, want := len(messages), 1; want != have {
    79  		t.Fatalf("have %v messages, want %v", have, want)
    80  	}
    81  
    82  	messages, err = protobuf.ReadMessages(
    83  		bytes.NewReader(records[0].Out()),
    84  		func() protobuf.Message { return new(pb.Snapshot) },
    85  	)
    86  	if err != nil {
    87  		t.Fatalf("read messages: unexpected error: %v", err)
    88  	}
    89  	have := messages[0].(*pb.Snapshot)
    90  
    91  	if diff := cmp.Diff(want, have); diff != "" {
    92  		t.Fatalf("unexpected snapshot (-want +have):\n%s", diff)
    93  	}
    94  }
    95  
    96  // TestStatusLightNode tests that the status service returns the correct
    97  // information for a light node.
    98  func TestStatusLightNode(t *testing.T) {
    99  	t.Parallel()
   100  
   101  	want := &pb.Snapshot{
   102  		BeeMode:          api.LightMode.String(),
   103  		ReserveSize:      0,
   104  		PullsyncRate:     0,
   105  		StorageRadius:    0,
   106  		BatchCommitment:  1024,
   107  		IsReachable:      true,
   108  		NeighborhoodSize: 1,
   109  		LastSyncedBlock:  6092500,
   110  	}
   111  
   112  	sssMock := &statusSnapshotMock{&pb.Snapshot{
   113  		ReserveSize:     100, // should be ignored
   114  		PullsyncRate:    100, // should be ignored
   115  		StorageRadius:   100, // should be ignored
   116  		BatchCommitment: 1024,
   117  		LastSyncedBlock: 6092500,
   118  	}}
   119  
   120  	peersIterMock := new(topologyPeersIterNoopMock)
   121  
   122  	peer1 := status.NewService(
   123  		log.Noop,
   124  		nil,
   125  		peersIterMock,
   126  		want.BeeMode,
   127  		sssMock,
   128  		nil,
   129  	)
   130  
   131  	recorder := streamtest.New(streamtest.WithProtocols(peer1.Protocol()))
   132  
   133  	peer2 := status.NewService(log.Noop, recorder, peersIterMock, "", nil, nil)
   134  
   135  	address := swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c")
   136  
   137  	if _, err := peer2.PeerSnapshot(context.Background(), address); err != nil {
   138  		t.Fatalf("send msg get: unexpected error: %v", err)
   139  	}
   140  
   141  	records, err := recorder.Records(address, status.ProtocolName, status.ProtocolVersion, status.StreamName)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	if have, want := len(records), 1; want != have {
   146  		t.Fatalf("have %v records, want %v", have, want)
   147  	}
   148  
   149  	messages, err := protobuf.ReadMessages(
   150  		bytes.NewReader(records[0].In()),
   151  		func() protobuf.Message { return new(pb.Get) },
   152  	)
   153  	if err != nil {
   154  		t.Fatalf("read messages: unexpected error: %v", err)
   155  	}
   156  	if have, want := len(messages), 1; want != have {
   157  		t.Fatalf("have %v messages, want %v", have, want)
   158  	}
   159  
   160  	messages, err = protobuf.ReadMessages(
   161  		bytes.NewReader(records[0].Out()),
   162  		func() protobuf.Message { return new(pb.Snapshot) },
   163  	)
   164  	if err != nil {
   165  		t.Fatalf("read messages: unexpected error: %v", err)
   166  	}
   167  	have := messages[0].(*pb.Snapshot)
   168  
   169  	if diff := cmp.Diff(want, have); diff != "" {
   170  		t.Fatalf("unexpected snapshot (-want +have):\n%s", diff)
   171  	}
   172  }
   173  
   174  // topologyPeersIterNoopMock is noop topology.PeerIterator.
   175  type topologyPeersIterNoopMock struct{}
   176  
   177  func (m *topologyPeersIterNoopMock) EachConnectedPeer(_ topology.EachPeerFunc, _ topology.Select) error {
   178  	return nil
   179  }
   180  
   181  func (m *topologyPeersIterNoopMock) EachConnectedPeerRev(_ topology.EachPeerFunc, _ topology.Select) error {
   182  	return nil
   183  }
   184  
   185  func (m *topologyPeersIterNoopMock) IsReachable() bool {
   186  	return true
   187  }
   188  
   189  // statusSnapshotMock satisfies the following interfaces:
   190  //   - Reserve
   191  //   - SyncReporter
   192  type statusSnapshotMock struct {
   193  	*pb.Snapshot
   194  }
   195  
   196  func (m *statusSnapshotMock) SyncRate() float64           { return m.Snapshot.PullsyncRate }
   197  func (m *statusSnapshotMock) ReserveSize() int            { return int(m.Snapshot.ReserveSize) }
   198  func (m *statusSnapshotMock) StorageRadius() uint8        { return uint8(m.Snapshot.StorageRadius) }
   199  func (m *statusSnapshotMock) Commitment() (uint64, error) { return m.Snapshot.BatchCommitment, nil }
   200  func (m *statusSnapshotMock) GetChainState() *postage.ChainState {
   201  	return &postage.ChainState{Block: m.Snapshot.LastSyncedBlock}
   202  }
   203  func (m *statusSnapshotMock) ReserveSizeWithinRadius() uint64 {
   204  	return m.Snapshot.ReserveSizeWithinRadius
   205  }