github.com/status-im/status-go@v1.1.0/mailserver/cleaner_test.go (about)

     1  package mailserver
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  	"github.com/syndtr/goleveldb/leveldb"
    10  	"github.com/syndtr/goleveldb/leveldb/storage"
    11  
    12  	"github.com/ethereum/go-ethereum/rlp"
    13  
    14  	"github.com/status-im/status-go/eth-node/types"
    15  	waku "github.com/status-im/status-go/waku/common"
    16  )
    17  
    18  func TestCleaner(t *testing.T) {
    19  	now := time.Now()
    20  	server := setupTestServer(t)
    21  	defer server.Close()
    22  	cleaner := newDBCleaner(server.ms.db, time.Hour)
    23  
    24  	archiveEnvelope(t, now.Add(-10*time.Second), server)
    25  	archiveEnvelope(t, now.Add(-3*time.Second), server)
    26  	archiveEnvelope(t, now.Add(-1*time.Second), server)
    27  
    28  	testMessagesCount(t, 3, server)
    29  
    30  	testPrune(t, now.Add(-5*time.Second), 1, cleaner)
    31  	testPrune(t, now.Add(-2*time.Second), 1, cleaner)
    32  	testPrune(t, now, 1, cleaner)
    33  
    34  	testMessagesCount(t, 0, server)
    35  }
    36  
    37  func TestCleanerSchedule(t *testing.T) {
    38  	now := time.Now()
    39  	server := setupTestServer(t)
    40  	defer server.Close()
    41  
    42  	cleaner := newDBCleaner(server.ms.db, time.Hour)
    43  	cleaner.period = time.Millisecond * 10
    44  	cleaner.Start()
    45  	defer cleaner.Stop()
    46  
    47  	archiveEnvelope(t, now.Add(-3*time.Hour), server)
    48  	archiveEnvelope(t, now.Add(-2*time.Hour), server)
    49  	archiveEnvelope(t, now.Add(-1*time.Minute), server)
    50  
    51  	time.Sleep(time.Millisecond * 50)
    52  
    53  	testMessagesCount(t, 1, server)
    54  }
    55  
    56  func benchmarkCleanerPrune(b *testing.B, messages int, batchSize int) {
    57  	t := &testing.T{}
    58  	now := time.Now()
    59  	sentTime := now.Add(-10 * time.Second)
    60  	server := setupTestServer(t)
    61  	defer server.Close()
    62  
    63  	cleaner := newDBCleaner(server.ms.db, time.Hour)
    64  	cleaner.batchSize = batchSize
    65  
    66  	for i := 0; i < messages; i++ {
    67  		archiveEnvelope(t, sentTime, server)
    68  	}
    69  
    70  	for i := 0; i < b.N; i++ {
    71  		testPrune(t, now, 0, cleaner)
    72  	}
    73  }
    74  
    75  func BenchmarkCleanerPruneM100_000_B100_000(b *testing.B) {
    76  	benchmarkCleanerPrune(b, 100000, 100000)
    77  }
    78  
    79  func BenchmarkCleanerPruneM100_000_B10_000(b *testing.B) {
    80  	benchmarkCleanerPrune(b, 100000, 10000)
    81  }
    82  
    83  func BenchmarkCleanerPruneM100_000_B1000(b *testing.B) {
    84  	benchmarkCleanerPrune(b, 100000, 1000)
    85  }
    86  
    87  func BenchmarkCleanerPruneM100_000_B100(b *testing.B) {
    88  	benchmarkCleanerPrune(b, 100000, 100)
    89  }
    90  
    91  func setupTestServer(t *testing.T) *WakuMailServer {
    92  	var s WakuMailServer
    93  	db, _ := leveldb.Open(storage.NewMemStorage(), nil)
    94  
    95  	s.ms = &mailServer{
    96  		db: &LevelDB{
    97  			ldb:  db,
    98  			done: make(chan struct{}),
    99  		},
   100  		adapter: &wakuAdapter{},
   101  	}
   102  	s.minRequestPoW = powRequirement
   103  	return &s
   104  }
   105  
   106  func archiveEnvelope(t *testing.T, sentTime time.Time, server *WakuMailServer) *waku.Envelope {
   107  	env, err := generateEnvelope(sentTime)
   108  	require.NoError(t, err)
   109  	server.Archive(env)
   110  
   111  	return env
   112  }
   113  
   114  func testPrune(t *testing.T, u time.Time, expected int, c *dbCleaner) {
   115  	n, err := c.PruneEntriesOlderThan(u)
   116  	require.NoError(t, err)
   117  	require.Equal(t, expected, n)
   118  }
   119  
   120  func testMessagesCount(t *testing.T, expected int, s *WakuMailServer) {
   121  	count := countMessages(t, s.ms.db)
   122  	require.Equal(t, expected, count, fmt.Sprintf("expected %d message, got: %d", expected, count))
   123  }
   124  
   125  func countMessages(t *testing.T, db DB) int {
   126  	var (
   127  		count      int
   128  		zero       types.Hash
   129  		emptyTopic types.TopicType
   130  	)
   131  
   132  	now := time.Now()
   133  	kl := NewDBKey(uint32(0), emptyTopic, zero)
   134  	ku := NewDBKey(uint32(now.Unix()), emptyTopic, zero)
   135  
   136  	query := CursorQuery{
   137  		start: kl.raw,
   138  		end:   ku.raw,
   139  	}
   140  
   141  	i, _ := db.BuildIterator(query)
   142  	defer func() { _ = i.Release() }()
   143  
   144  	for i.Next() {
   145  		var env waku.Envelope
   146  		value, err := i.GetEnvelopeByBloomFilter(query.bloom)
   147  		if err != nil {
   148  			t.Fatal(err)
   149  		}
   150  
   151  		err = rlp.DecodeBytes(value, &env)
   152  		if err != nil {
   153  			t.Fatal(err)
   154  		}
   155  
   156  		count++
   157  	}
   158  
   159  	return count
   160  }