github.com/decred/politeia@v1.4.0/politeiad/backendv2/tstorebe/plugins/pi/statusescache_test.go (about) 1 // Copyright (c) 2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package pi 6 7 import ( 8 "container/list" 9 "testing" 10 11 backend "github.com/decred/politeia/politeiad/backendv2" 12 "github.com/decred/politeia/politeiad/plugins/pi" 13 "github.com/decred/politeia/politeiad/plugins/ticketvote" 14 ) 15 16 func TestGet(t *testing.T) { 17 // Create a new cache 18 statuses := proposalStatuses{ 19 data: make(map[string]*statusEntry, statusesCacheLimit), 20 entries: list.New(), 21 } 22 23 // Setup a cache entry 24 token := "key" 25 entry := statusEntry{ 26 propStatus: pi.PropStatusCompleted, 27 } 28 29 // Ensure nil is returned when no cache entry associated with 30 // the token exists in cache. 31 ce := statuses.get(token) 32 if ce != nil { 33 t.Errorf("unexpected cache entry; want nil, got '%v'", ce) 34 } 35 36 // Store entry in cache. 37 statuses.set(token, entry) 38 39 // Get entry from cache and verify value 40 ce = statuses.get(token) 41 if entry.propStatus != ce.propStatus { 42 t.Errorf("want proposal status %v, got '%v'", entry.propStatus, 43 ce.propStatus) 44 } 45 } 46 47 func TestSet(t *testing.T) { 48 // Temporarily set global cache capacity limit to two in order to test 49 // adding a new entry to a full cache. 50 defaultCacheLimit := statusesCacheLimit 51 statusesCacheLimit = 2 52 defer func() { 53 statusesCacheLimit = defaultCacheLimit 54 }() 55 56 // Create cache 57 statuses := proposalStatuses{ 58 data: make(map[string]*statusEntry, statusesCacheLimit), 59 entries: list.New(), 60 } 61 62 // Setup test tokens and cache entries 63 tokens := []string{"45154fb45664714a", "45154fb45664714b"} 64 entries := []statusEntry{ 65 { 66 propStatus: pi.PropStatusActive, 67 recordState: backend.StateUnvetted, 68 recordStatus: backend.StatusPublic, 69 voteStatus: ticketvote.VoteStatusRejected, 70 }, 71 { 72 propStatus: pi.PropStatusActive, 73 recordState: backend.StateUnvetted, 74 recordStatus: backend.StatusPublic, 75 voteStatus: ticketvote.VoteStatusApproved, 76 }, 77 } 78 79 // Store entries in cache 80 for i, token := range tokens { 81 statuses.set(token, entries[i]) 82 } 83 84 // Store a third entry, it should replace the oldest entry as the cache 85 // is a FIFO data structure. 86 tokenThird := "45154fb45664714c" 87 entryThird := statusEntry{ 88 propStatus: pi.PropStatusClosed, 89 recordState: backend.StateUnvetted, 90 recordStatus: backend.StatusPublic, 91 voteStatus: ticketvote.VoteStatusApproved, 92 } 93 statuses.set(tokenThird, entryThird) 94 95 // Ensure that the oldest entry was removed, and that the other two entries 96 // exist is cache. 97 var e *statusEntry 98 if e = statuses.get(tokenThird); e == nil { 99 t.Errorf("entry not found in cache, token: %v", tokenThird) 100 } 101 if e = statuses.get(tokens[1]); e == nil { 102 t.Errorf("entry not found in cache, token: %v", tokens[1]) 103 } 104 if e = statuses.get(tokens[0]); e != nil { 105 t.Errorf("unexpected entry found in cache, token: %v", tokenThird) 106 } 107 108 // Ensure that the cache's tokens list is a FIFO data structure where 109 // the oldest element is at the back of the list and the newest is the 110 // at the front. 111 listTokenLast := statuses.entries.Back().Value.(string) 112 if listTokenLast != tokens[1] { 113 t.Errorf("unexpected entry is at the back of the entries list; "+ 114 "expected %v, got %v", tokens[1], listTokenLast) 115 } 116 listTokenFirst := statuses.entries.Front().Value.(string) 117 if listTokenFirst != tokenThird { 118 t.Errorf("unexpected entry is at the front of the entries list; "+ 119 "expected %v, got %v", tokenThird, listTokenFirst) 120 } 121 122 // Overwrite existing cache entry. 123 entryThird.propStatus = pi.PropStatusActive 124 statuses.set(tokenThird, entryThird) 125 126 // Ensure that the new entry was stored in cache successfully 127 e = statuses.data[tokenThird] 128 if e.propStatus != pi.PropStatusActive { 129 t.Errorf("unexpected proposal status: want %v, got %v", 130 pi.PropStatusActive, e.propStatus) 131 } 132 133 // Verify that the list order has not changed on entry overwrites 134 listTokenLast = statuses.entries.Back().Value.(string) 135 if listTokenLast != tokens[1] { 136 t.Errorf("unexpected entry is at the back of the entries list; "+ 137 "expected %v, got %v", tokens[1], listTokenLast) 138 } 139 listTokenFirst = statuses.entries.Front().Value.(string) 140 if listTokenFirst != tokenThird { 141 t.Errorf("unexpected entry is at the front of the entries list; "+ 142 "expected %v, got %v", tokenThird, listTokenFirst) 143 } 144 }