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 }