github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/session/pingpong/hermes_status_checker_test.go (about) 1 /* 2 * Copyright (C) 2021 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package pingpong 19 20 import ( 21 "sync" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 var hid = common.HexToAddress("0x8129243802538e426A023FedB0Da20689aee797A") 30 var rid = common.HexToAddress("0x7129243802538e426A023FedB0Da20689aee797A") 31 var chainID int64 = 5 32 33 func Test_HermesActivityChecker(t *testing.T) { 34 t.Run("uses cached value if present and valid", func(t *testing.T) { 35 mbc := &mockBc{} 36 checker := NewHermesStatusChecker(mbc, nil, time.Minute) 37 checker.cachedValues[checker.formKey(chainID, hid)] = HermesStatus{ 38 IsActive: true, 39 ValidUntil: time.Now().Add(time.Minute), 40 } 41 status, err := checker.GetHermesStatus(chainID, rid, hid) 42 assert.NoError(t, err) 43 assert.True(t, status.IsActive) 44 45 assert.Equal(t, 0, mbc.getTimesCalled()) 46 }) 47 48 t.Run("updates value if present and not valid", func(t *testing.T) { 49 startTime := time.Now() 50 51 mbc := &mockBc{ 52 isActiveResult: true, 53 isRegisteredResult: true, 54 feeResult: 1, 55 } 56 checker := NewHermesStatusChecker(mbc, nil, time.Minute) 57 checker.cachedValues[checker.formKey(chainID, hid)] = HermesStatus{ 58 IsActive: false, 59 ValidUntil: time.Now().Add(-time.Minute), 60 } 61 status, err := checker.GetHermesStatus(chainID, rid, hid) 62 assert.NoError(t, err) 63 assert.True(t, status.IsActive) 64 65 assert.Equal(t, uint16(1), status.Fee) 66 67 assert.Equal(t, 3, mbc.getTimesCalled()) 68 69 v, _ := checker.cachedValues[checker.formKey(chainID, hid)] 70 assert.True(t, v.isValid()) 71 72 // check if extended by somewhere around a minute 73 assert.True(t, v.ValidUntil.After(startTime.Add(time.Minute))) 74 assert.False(t, v.ValidUntil.After(startTime.Add(time.Minute).Add(time.Second*2))) 75 }) 76 77 t.Run("updates and sets cache if not present initially", func(t *testing.T) { 78 startTime := time.Now() 79 80 mbc := &mockBc{ 81 isActiveResult: true, 82 isRegisteredResult: true, 83 feeResult: 1, 84 } 85 86 checker := NewHermesStatusChecker(mbc, nil, time.Minute) 87 status, err := checker.GetHermesStatus(chainID, rid, hid) 88 assert.NoError(t, err) 89 assert.True(t, status.IsActive) 90 91 assert.Equal(t, uint16(1), status.Fee) 92 93 assert.Equal(t, 3, mbc.getTimesCalled()) 94 95 v, _ := checker.cachedValues[checker.formKey(chainID, hid)] 96 assert.True(t, v.isValid()) 97 98 // check if extended by somewhere around a minute 99 assert.True(t, v.ValidUntil.After(startTime.Add(time.Minute))) 100 assert.False(t, v.ValidUntil.After(startTime.Add(time.Minute).Add(time.Second*2))) 101 }) 102 103 t.Run("successive runs do not fetch from source if already cached and valid", func(t *testing.T) { 104 mbc := &mockBc{ 105 isActiveResult: true, 106 isRegisteredResult: true, 107 feeResult: 1, 108 } 109 110 checker := NewHermesStatusChecker(mbc, nil, time.Minute) 111 status, err := checker.GetHermesStatus(chainID, rid, hid) 112 assert.NoError(t, err) 113 assert.True(t, status.IsActive) 114 115 assert.Equal(t, 3, mbc.getTimesCalled()) 116 117 status, err = checker.GetHermesStatus(chainID, rid, hid) 118 assert.NoError(t, err) 119 assert.True(t, status.IsActive) 120 assert.Equal(t, 3, mbc.getTimesCalled()) 121 }) 122 123 t.Run("successive fetch from source if cache invalid", func(t *testing.T) { 124 mbc := &mockBc{ 125 isActiveResult: true, 126 isRegisteredResult: true, 127 feeResult: 1, 128 } 129 130 checker := NewHermesStatusChecker(mbc, nil, time.Minute) 131 status, err := checker.GetHermesStatus(chainID, rid, hid) 132 assert.NoError(t, err) 133 assert.True(t, status.IsActive) 134 assert.Equal(t, 3, mbc.getTimesCalled()) 135 136 checker.cachedValues[checker.formKey(chainID, hid)] = HermesStatus{ 137 IsActive: true, 138 ValidUntil: time.Now().Add(-time.Minute), 139 } 140 141 status, err = checker.GetHermesStatus(chainID, rid, hid) 142 assert.NoError(t, err) 143 assert.True(t, status.IsActive) 144 assert.Equal(t, 6, mbc.getTimesCalled()) 145 }) 146 } 147 148 type mockBc struct { 149 isActiveResult bool 150 isActiveErr error 151 152 isRegisteredResult bool 153 isRegisteredErr error 154 155 feeResult uint16 156 feeErr error 157 158 timesCalled int 159 lock sync.Mutex 160 } 161 162 func (mbc *mockBc) incTimesCalled() { 163 mbc.lock.Lock() 164 defer mbc.lock.Unlock() 165 mbc.timesCalled++ 166 } 167 168 func (mbc *mockBc) getTimesCalled() int { 169 mbc.lock.Lock() 170 defer mbc.lock.Unlock() 171 return mbc.timesCalled 172 } 173 174 func (mbc *mockBc) IsHermesActive(chainID int64, hermesID common.Address) (bool, error) { 175 defer mbc.incTimesCalled() 176 return mbc.isActiveResult, mbc.isActiveErr 177 } 178 179 func (mbc *mockBc) IsHermesRegistered(chainID int64, registryAddress, hermesID common.Address) (bool, error) { 180 defer mbc.incTimesCalled() 181 return mbc.isRegisteredResult, mbc.isRegisteredErr 182 } 183 184 func (mbc *mockBc) GetHermesFee(chainID int64, hermesID common.Address) (uint16, error) { 185 defer mbc.incTimesCalled() 186 return mbc.feeResult, mbc.feeErr 187 }