github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/peer/mrunoncemap_test.go (about)

     1  // Copyright (c) 2015 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package peer
     7  
     8  import (
     9  	"fmt"
    10  	"testing"
    11  )
    12  
    13  // TestMruNonceMap ensures the mruNonceMap behaves as expected including
    14  // limiting, eviction of least-recently used entries, specific entry removal,
    15  // and existence tests.
    16  func TestMruNonceMap(t *testing.T) {
    17  	// Create a bunch of fake nonces to use in testing the mru nonce code.
    18  	numNonces := 10
    19  	nonces := make([]uint64, 0, numNonces)
    20  	for i := 0; i < numNonces; i++ {
    21  		nonces = append(nonces, uint64(i))
    22  	}
    23  
    24  	tests := []struct {
    25  		name  string
    26  		limit int
    27  	}{
    28  		{name: "limit 0", limit: 0},
    29  		{name: "limit 1", limit: 1},
    30  		{name: "limit 5", limit: 5},
    31  		{name: "limit 7", limit: 7},
    32  		{name: "limit one less than available", limit: numNonces - 1},
    33  		{name: "limit all available", limit: numNonces},
    34  	}
    35  
    36  testLoop:
    37  	for i, test := range tests {
    38  		// Create a new mru nonce map limited by the specified test
    39  		// limit and add all of the test nonces.  This will cause
    40  		// evicition since there are more test nonces than the limits.
    41  		mruNonceMap := newMruNonceMap(uint(test.limit))
    42  		for j := 0; j < numNonces; j++ {
    43  			mruNonceMap.Add(nonces[j])
    44  		}
    45  
    46  		// Ensure the limited number of most recent entries in the list
    47  		// exist.
    48  		for j := numNonces - test.limit; j < numNonces; j++ {
    49  			if !mruNonceMap.Exists(nonces[j]) {
    50  				t.Errorf("Exists #%d (%s) entry %d does not "+
    51  					"exist", i, test.name, nonces[j])
    52  				continue testLoop
    53  			}
    54  		}
    55  
    56  		// Ensure the entries before the limited number of most recent
    57  		// entries in the list do not exist.
    58  		for j := 0; j < numNonces-test.limit; j++ {
    59  			if mruNonceMap.Exists(nonces[j]) {
    60  				t.Errorf("Exists #%d (%s) entry %d exists", i,
    61  					test.name, nonces[j])
    62  				continue testLoop
    63  			}
    64  		}
    65  
    66  		// Readd the entry that should currently be the least-recently
    67  		// used entry so it becomes the most-recently used entry, then
    68  		// force an eviction by adding an entry that doesn't exist and
    69  		// ensure the evicted entry is the new least-recently used
    70  		// entry.
    71  		//
    72  		// This check needs at least 2 entries.
    73  		if test.limit > 1 {
    74  			origLruIndex := numNonces - test.limit
    75  			mruNonceMap.Add(nonces[origLruIndex])
    76  
    77  			mruNonceMap.Add(uint64(numNonces) + 1)
    78  
    79  			// Ensure the original lru entry still exists since it
    80  			// was updated and should've have become the mru entry.
    81  			if !mruNonceMap.Exists(nonces[origLruIndex]) {
    82  				t.Errorf("MRU #%d (%s) entry %d does not exist",
    83  					i, test.name, nonces[origLruIndex])
    84  				continue testLoop
    85  			}
    86  
    87  			// Ensure the entry that should've become the new lru
    88  			// entry was evicted.
    89  			newLruIndex := origLruIndex + 1
    90  			if mruNonceMap.Exists(nonces[newLruIndex]) {
    91  				t.Errorf("MRU #%d (%s) entry %d exists", i,
    92  					test.name, nonces[newLruIndex])
    93  				continue testLoop
    94  			}
    95  		}
    96  
    97  		// Delete all of the entries in the list, including those that
    98  		// don't exist in the map, and ensure they no longer exist.
    99  		for j := 0; j < numNonces; j++ {
   100  			mruNonceMap.Delete(nonces[j])
   101  			if mruNonceMap.Exists(nonces[j]) {
   102  				t.Errorf("Delete #%d (%s) entry %d exists", i,
   103  					test.name, nonces[j])
   104  				continue testLoop
   105  			}
   106  		}
   107  	}
   108  }
   109  
   110  // TestMruNonceMapStringer tests the stringized output for the mruNonceMap type.
   111  func TestMruNonceMapStringer(t *testing.T) {
   112  	// Create a couple of fake nonces to use in testing the mru nonce
   113  	// stringer code.
   114  	nonce1 := uint64(10)
   115  	nonce2 := uint64(20)
   116  
   117  	// Create new mru nonce map and add the nonces.
   118  	mruNonceMap := newMruNonceMap(uint(2))
   119  	mruNonceMap.Add(nonce1)
   120  	mruNonceMap.Add(nonce2)
   121  
   122  	// Ensure the stringer gives the expected result.  Since map iteration
   123  	// is not ordered, either entry could be first, so account for both
   124  	// cases.
   125  	wantStr1 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce1, nonce2)
   126  	wantStr2 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce2, nonce1)
   127  	gotStr := mruNonceMap.String()
   128  	if gotStr != wantStr1 && gotStr != wantStr2 {
   129  		t.Fatalf("unexpected string representation - got %q, want %q "+
   130  			"or %q", gotStr, wantStr1, wantStr2)
   131  	}
   132  }
   133  
   134  // BenchmarkMruNonceList performs basic benchmarks on the most recently used
   135  // nonce handling.
   136  func BenchmarkMruNonceList(b *testing.B) {
   137  	// Create a bunch of fake nonces to use in benchmarking the mru nonce
   138  	// code.
   139  	b.StopTimer()
   140  	numNonces := 100000
   141  	nonces := make([]uint64, 0, numNonces)
   142  	for i := 0; i < numNonces; i++ {
   143  		nonces = append(nonces, uint64(i))
   144  	}
   145  	b.StartTimer()
   146  
   147  	// Benchmark the add plus evicition code.
   148  	limit := 20000
   149  	mruNonceMap := newMruNonceMap(uint(limit))
   150  	for i := 0; i < b.N; i++ {
   151  		mruNonceMap.Add(nonces[i%numNonces])
   152  	}
   153  }