github.com/ethersphere/bee/v2@v2.2.0/pkg/blocker/blocker_test.go (about)

     1  // Copyright 2021 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 blocker_test
     6  
     7  import (
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"go.uber.org/goleak"
    13  
    14  	"github.com/ethersphere/bee/v2/pkg/blocker"
    15  	"github.com/ethersphere/bee/v2/pkg/log"
    16  	"github.com/ethersphere/bee/v2/pkg/p2p"
    17  	"github.com/ethersphere/bee/v2/pkg/swarm"
    18  	"github.com/ethersphere/bee/v2/pkg/util/testutil"
    19  )
    20  
    21  const (
    22  	sequencerResolution = time.Millisecond
    23  	flagTime            = sequencerResolution * 25
    24  	blockTime           = time.Second
    25  )
    26  
    27  func TestMain(m *testing.M) {
    28  	defer func(resolution time.Duration) {
    29  		*blocker.SequencerResolution = resolution
    30  	}(*blocker.SequencerResolution)
    31  	*blocker.SequencerResolution = sequencerResolution
    32  
    33  	os.Exit(m.Run())
    34  
    35  	goleak.VerifyTestMain(m)
    36  }
    37  
    38  func TestBlocksAfterFlagTimeout(t *testing.T) {
    39  	t.Parallel()
    40  
    41  	addr := swarm.RandAddress(t)
    42  	blockedC := make(chan swarm.Address, 10)
    43  
    44  	mock := mockBlockLister(func(a swarm.Address, d time.Duration, r string) error {
    45  		blockedC <- a
    46  
    47  		if d != blockTime {
    48  			t.Fatalf("block time: want %v, got %v", blockTime, d)
    49  		}
    50  
    51  		return nil
    52  	})
    53  
    54  	b := blocker.New(mock, flagTime, blockTime, time.Millisecond, nil, log.Noop)
    55  	testutil.CleanupCloser(t, b)
    56  
    57  	// Flagging address shouldn't block it immediately
    58  	b.Flag(addr)
    59  	if len(blockedC) != 0 {
    60  		t.Fatal("blocker did not wait flag duration")
    61  	}
    62  
    63  	time.Sleep(flagTime / 2)
    64  	b.Flag(addr) // check that this flag call does not override previous call
    65  	if len(blockedC) != 0 {
    66  		t.Fatal("blocker did not wait flag duration")
    67  	}
    68  
    69  	// Suspending current goroutine and expect that in this interval
    70  	// block listener was called to block flagged address
    71  	time.Sleep(flagTime * 3)
    72  
    73  	if a := <-blockedC; !a.Equal(addr) {
    74  		t.Fatalf("expecting flagged address to be blocked")
    75  	}
    76  	if len(blockedC) != 0 {
    77  		t.Fatalf("address should only be blocked once")
    78  	}
    79  }
    80  
    81  func TestUnflagBeforeBlock(t *testing.T) {
    82  	t.Parallel()
    83  
    84  	addr := swarm.RandAddress(t)
    85  	mock := mockBlockLister(func(a swarm.Address, d time.Duration, r string) error {
    86  		t.Fatalf("address should not be blocked")
    87  
    88  		return nil
    89  	})
    90  
    91  	b := blocker.New(mock, flagTime, blockTime, time.Millisecond, nil, log.Noop)
    92  	testutil.CleanupCloser(t, b)
    93  
    94  	// Flagging address shouldn't block it imidietly
    95  	b.Flag(addr)
    96  
    97  	time.Sleep(flagTime / 2)
    98  	b.Flag(addr) // check that this flag call does not override previous call
    99  
   100  	b.Unflag(addr)
   101  
   102  	// Suspending current goroutine and expect that in this interval
   103  	// block listener was not called to block flagged address
   104  	time.Sleep(flagTime * 3)
   105  }
   106  
   107  func TestPruneBeforeBlock(t *testing.T) {
   108  	t.Parallel()
   109  
   110  	addr := swarm.RandAddress(t)
   111  	mock := mockBlockLister(func(a swarm.Address, d time.Duration, r string) error {
   112  		t.Fatalf("address should not be blocked")
   113  
   114  		return nil
   115  	})
   116  
   117  	b := blocker.New(mock, flagTime, blockTime, time.Millisecond, nil, log.Noop)
   118  	testutil.CleanupCloser(t, b)
   119  
   120  	// Flagging address shouldn't block it imidietly
   121  	b.Flag(addr)
   122  
   123  	time.Sleep(flagTime / 2)
   124  
   125  	// communicate that we have seen no peers, resulting in the peer being removed
   126  	b.PruneUnseen([]swarm.Address{})
   127  
   128  	// Suspending current goroutine expect that in this interval
   129  	// block listener was not called to block flagged address
   130  	time.Sleep(flagTime * 3)
   131  }
   132  
   133  type blocklister struct {
   134  	blocklistFunc func(swarm.Address, time.Duration, string) error
   135  }
   136  
   137  func mockBlockLister(f func(swarm.Address, time.Duration, string) error) *blocklister {
   138  	return &blocklister{
   139  		blocklistFunc: f,
   140  	}
   141  }
   142  
   143  func (b *blocklister) Blocklist(addr swarm.Address, t time.Duration, r string) error {
   144  	return b.blocklistFunc(addr, t, r)
   145  }
   146  
   147  // NetworkStatus implements p2p.NetworkStatuser interface.
   148  // It always returns p2p.NetworkStatusAvailable.
   149  func (b *blocklister) NetworkStatus() p2p.NetworkStatus {
   150  	return p2p.NetworkStatusAvailable
   151  }