github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/node/internal/cache_test.go (about) 1 package internal_test 2 3 import ( 4 "fmt" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/libp2p/go-libp2p/core/peer" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/onflow/flow-go/module/metrics" 14 "github.com/onflow/flow-go/network" 15 "github.com/onflow/flow-go/network/p2p/node/internal" 16 "github.com/onflow/flow-go/utils/unittest" 17 ) 18 19 // TestNewDisallowListCache tests the NewDisallowListCache function. It verifies that the returned disallowListCache 20 // is not nil. 21 func TestNewDisallowListCache(t *testing.T) { 22 disallowListCache := internal.NewDisallowListCache(uint32(100), unittest.Logger(), metrics.NewNoopCollector()) 23 24 // Verify that the new disallowListCache is not nil 25 assert.NotNil(t, disallowListCache) 26 } 27 28 // TestDisallowFor_SinglePeer tests the DisallowFor function for a single peer. It verifies that the peerID is 29 // disallow-listed for the given cause and that the cause is returned when the peerID is disallow-listed again. 30 func TestDisallowFor_SinglePeer(t *testing.T) { 31 disallowListCache := internal.NewDisallowListCache(uint32(100), unittest.Logger(), metrics.NewNoopCollector()) 32 require.NotNil(t, disallowListCache) 33 34 // disallowing a peerID for a cause when the peerID doesn't exist in the cache 35 causes, err := disallowListCache.DisallowFor(peer.ID("peer1"), network.DisallowListedCauseAdmin) 36 require.NoError(t, err) 37 require.Len(t, causes, 1) 38 require.Contains(t, causes, network.DisallowListedCauseAdmin) 39 40 // disallowing a peerID for a cause when the peerID already exists in the cache 41 causes, err = disallowListCache.DisallowFor(peer.ID("peer1"), network.DisallowListedCauseAlsp) 42 require.NoError(t, err) 43 require.Len(t, causes, 2) 44 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 45 46 // disallowing a peerID for a duplicate cause 47 causes, err = disallowListCache.DisallowFor(peer.ID("peer1"), network.DisallowListedCauseAdmin) 48 require.NoError(t, err) 49 require.Len(t, causes, 2) 50 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 51 } 52 53 // TestDisallowFor_MultiplePeers tests the DisallowFor function for multiple peers. It verifies that the peerIDs are 54 // disallow-listed for the given cause and that the cause is returned when the peerIDs are disallow-listed again. 55 func TestDisallowFor_MultiplePeers(t *testing.T) { 56 disallowListCache := internal.NewDisallowListCache(uint32(100), unittest.Logger(), metrics.NewNoopCollector()) 57 require.NotNil(t, disallowListCache) 58 59 for i := 0; i <= 10; i++ { 60 // disallowing a peerID for a cause when the peerID doesn't exist in the cache 61 causes, err := disallowListCache.DisallowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 62 require.NoError(t, err) 63 require.Len(t, causes, 1) 64 require.Contains(t, causes, network.DisallowListedCauseAdmin) 65 } 66 67 for i := 0; i <= 10; i++ { 68 // disallowing a peerID for a cause when the peerID already exists in the cache 69 causes, err := disallowListCache.DisallowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAlsp) 70 require.NoError(t, err) 71 require.Len(t, causes, 2) 72 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 73 } 74 75 for i := 0; i <= 10; i++ { 76 // getting the disallow-listed causes for a peerID 77 causes, disallowListed := disallowListCache.IsDisallowListed(peer.ID(fmt.Sprintf("peer-%d", i))) 78 require.True(t, disallowListed) 79 require.Len(t, causes, 2) 80 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 81 } 82 } 83 84 // TestAllowFor_SinglePeer is a unit test function to verify the behavior of DisallowListCache for a single peer. 85 // The test checks the following functionalities in sequence: 86 // 1. Allowing a peerID for a cause when the peerID already exists in the cache. 87 // 2. Disallowing the peerID for a cause when the peerID doesn't exist in the cache. 88 // 3. Getting the disallow-listed causes for the peerID. 89 // 4. Allowing a peerID for a cause when the peerID already exists in the cache. 90 // 5. Getting the disallow-listed causes for the peerID. 91 // 6. Disallowing the peerID for a cause. 92 // 7. Allowing the peerID for a different cause than it is disallowed when the peerID already exists in the cache. 93 // 8. Disallowing the peerID for another cause. 94 // 9. Allowing the peerID for the first cause. 95 // 10. Allowing the peerID for the second cause. 96 func TestAllowFor_SinglePeer(t *testing.T) { 97 disallowListCache := internal.NewDisallowListCache(uint32(100), unittest.Logger(), metrics.NewNoopCollector()) 98 require.NotNil(t, disallowListCache) 99 peerID := peer.ID("peer1") 100 101 // allowing the peerID for a cause when the peerID already exists in the cache 102 causes := disallowListCache.AllowFor(peerID, network.DisallowListedCauseAdmin) 103 require.Len(t, causes, 0) 104 105 // disallowing the peerID for a cause when the peerID doesn't exist in the cache 106 causes, err := disallowListCache.DisallowFor(peerID, network.DisallowListedCauseAdmin) 107 require.NoError(t, err) 108 require.Len(t, causes, 1) 109 require.Contains(t, causes, network.DisallowListedCauseAdmin) 110 111 // getting the disallow-listed causes for the peerID 112 causes, disallowListed := disallowListCache.IsDisallowListed(peerID) 113 require.True(t, disallowListed) 114 require.Len(t, causes, 1) 115 require.Contains(t, causes, network.DisallowListedCauseAdmin) 116 117 // allowing a peerID for a cause when the peerID already exists in the cache 118 causes = disallowListCache.AllowFor(peerID, network.DisallowListedCauseAdmin) 119 require.NoError(t, err) 120 require.Len(t, causes, 0) 121 122 // getting the disallow-listed causes for the peerID 123 causes, disallowListed = disallowListCache.IsDisallowListed(peerID) 124 require.False(t, disallowListed) 125 require.Len(t, causes, 0) 126 127 // disallowing the peerID for a cause 128 causes, err = disallowListCache.DisallowFor(peerID, network.DisallowListedCauseAdmin) 129 require.NoError(t, err) 130 require.Len(t, causes, 1) 131 132 // allowing the peerID for a different cause than it is disallowed when the peerID already exists in the cache 133 causes = disallowListCache.AllowFor(peerID, network.DisallowListedCauseAlsp) 134 require.NoError(t, err) 135 require.Len(t, causes, 1) 136 require.Contains(t, causes, network.DisallowListedCauseAdmin) // the peerID is still disallow-listed for the previous cause 137 138 // disallowing the peerID for another cause 139 causes, err = disallowListCache.DisallowFor(peerID, network.DisallowListedCauseAlsp) 140 require.NoError(t, err) 141 require.Len(t, causes, 2) 142 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 143 144 // allowing the peerID for the first cause 145 causes = disallowListCache.AllowFor(peerID, network.DisallowListedCauseAdmin) 146 require.NoError(t, err) 147 require.Len(t, causes, 1) 148 require.Contains(t, causes, network.DisallowListedCauseAlsp) // the peerID is still disallow-listed for the previous cause 149 150 // allowing the peerID for the second cause 151 causes = disallowListCache.AllowFor(peerID, network.DisallowListedCauseAlsp) 152 require.NoError(t, err) 153 require.Len(t, causes, 0) 154 } 155 156 // TestAllowFor_MultiplePeers_Sequentially is a unit test function to test the behavior of DisallowListCache with multiple peers. 157 // The test checks the following functionalities in sequence: 158 // 1. Allowing a peerID for a cause when the peerID doesn't exist in the cache. 159 // 2. Disallowing peers for a cause. 160 // 3. Getting the disallow-listed causes for a peerID. 161 // 4. Allowing the peer ids for a cause different than the one they are disallow-listed for. 162 // 5. Disallowing the peer ids for a different cause. 163 // 6. Allowing the peer ids for the first cause. 164 // 7. Allowing the peer ids for the second cause. 165 func TestAllowFor_MultiplePeers_Sequentially(t *testing.T) { 166 disallowListCache := internal.NewDisallowListCache(uint32(100), unittest.Logger(), metrics.NewNoopCollector()) 167 require.NotNil(t, disallowListCache) 168 169 for i := 0; i <= 10; i++ { 170 // allowing a peerID for a cause when the peerID doesn't exist in the cache 171 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 172 require.Len(t, causes, 0) 173 } 174 175 for i := 0; i <= 10; i++ { 176 // disallowing peers for a cause 177 causes, err := disallowListCache.DisallowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAlsp) 178 require.NoError(t, err) 179 require.Len(t, causes, 1) 180 require.Contains(t, causes, network.DisallowListedCauseAlsp) 181 } 182 183 for i := 0; i <= 10; i++ { 184 // getting the disallow-listed causes for a peerID 185 causes, disallowListed := disallowListCache.IsDisallowListed(peer.ID(fmt.Sprintf("peer-%d", i))) 186 require.True(t, disallowListed) 187 require.Len(t, causes, 1) 188 require.Contains(t, causes, network.DisallowListedCauseAlsp) 189 } 190 191 for i := 0; i <= 10; i++ { 192 // allowing the peer ids for a cause different than the one they are disallow-listed for 193 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 194 require.Len(t, causes, 1) 195 require.Contains(t, causes, network.DisallowListedCauseAlsp) 196 } 197 198 for i := 0; i <= 10; i++ { 199 // disallowing the peer ids for a different cause 200 causes, err := disallowListCache.DisallowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 201 require.NoError(t, err) 202 require.Len(t, causes, 2) 203 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 204 } 205 206 for i := 0; i <= 10; i++ { 207 // allowing the peer ids for the first cause 208 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 209 require.Len(t, causes, 1) 210 require.Contains(t, causes, network.DisallowListedCauseAlsp) 211 } 212 213 for i := 0; i <= 10; i++ { 214 // allowing the peer ids for the second cause 215 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAlsp) 216 require.Len(t, causes, 0) 217 } 218 } 219 220 // TestAllowFor_MultiplePeers_Concurrently is a unit test function that verifies the behavior of DisallowListCache 221 // when multiple peerIDs are added and managed concurrently. This test is designed to confirm that DisallowListCache 222 // works as expected under concurrent access, an important aspect for a system dealing with multiple connections. 223 // 224 // The test runs multiple goroutines simultaneously, each handling a different peerID and performs the following 225 // operations in the sequence: 226 // 1. Allowing a peerID for a cause when the peerID doesn't exist in the cache. 227 // 2. Disallowing peers for a cause. 228 // 3. Getting the disallow-listed causes for a peerID. 229 // 4. Allowing the peer ids for a cause different than the one they are disallow-listed for. 230 // 5. Disallowing the peer ids for a different cause. 231 // 6. Allowing the peer ids for the first cause. 232 // 7. Allowing the peer ids for the second cause. 233 // 8. Getting the disallow-listed causes for a peerID. 234 // 9. Allowing a peerID for a cause when the peerID doesn't exist in the cache for a new set of peers. 235 func TestAllowFor_MultiplePeers_Concurrently(t *testing.T) { 236 disallowListCache := internal.NewDisallowListCache(uint32(100), unittest.Logger(), metrics.NewNoopCollector()) 237 require.NotNil(t, disallowListCache) 238 239 var wg sync.WaitGroup 240 for i := 0; i <= 10; i++ { 241 wg.Add(1) 242 go func(i int) { 243 defer wg.Done() 244 245 // allowing a peerID for a cause when the peerID doesn't exist in the cache 246 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 247 require.Len(t, causes, 0) 248 }(i) 249 } 250 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 251 252 for i := 0; i <= 10; i++ { 253 wg.Add(1) 254 go func(i int) { 255 defer wg.Done() 256 257 // disallowing peers for a cause 258 causes, err := disallowListCache.DisallowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAlsp) 259 require.NoError(t, err) 260 require.Len(t, causes, 1) 261 require.Contains(t, causes, network.DisallowListedCauseAlsp) 262 }(i) 263 } 264 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 265 266 for i := 0; i <= 10; i++ { 267 wg.Add(1) 268 go func(i int) { 269 defer wg.Done() 270 271 // getting the disallow-listed causes for a peerID 272 causes, disallowListed := disallowListCache.IsDisallowListed(peer.ID(fmt.Sprintf("peer-%d", i))) 273 require.Len(t, causes, 1) 274 require.True(t, disallowListed) 275 require.Contains(t, causes, network.DisallowListedCauseAlsp) 276 }(i) 277 } 278 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 279 280 for i := 0; i <= 10; i++ { 281 wg.Add(1) 282 go func(i int) { 283 defer wg.Done() 284 285 // allowing the peer ids for a cause different than the one they are disallow-listed for 286 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 287 require.Len(t, causes, 1) 288 require.Contains(t, causes, network.DisallowListedCauseAlsp) 289 }(i) 290 } 291 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 292 293 for i := 0; i <= 10; i++ { 294 wg.Add(1) 295 go func(i int) { 296 defer wg.Done() 297 298 // disallowing the peer ids for a different cause 299 causes, err := disallowListCache.DisallowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 300 require.NoError(t, err) 301 require.Len(t, causes, 2) 302 require.ElementsMatch(t, causes, []network.DisallowListedCause{network.DisallowListedCauseAdmin, network.DisallowListedCauseAlsp}) 303 }(i) 304 } 305 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 306 307 for i := 0; i <= 10; i++ { 308 wg.Add(1) 309 go func(i int) { 310 defer wg.Done() 311 312 // allowing the peer ids for the first cause 313 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 314 require.Len(t, causes, 1) 315 require.Contains(t, causes, network.DisallowListedCauseAlsp) 316 }(i) 317 } 318 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 319 320 for i := 0; i <= 10; i++ { 321 wg.Add(1) 322 go func(i int) { 323 defer wg.Done() 324 325 // allowing the peer ids for the second cause 326 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAlsp) 327 require.Len(t, causes, 0) 328 }(i) 329 } 330 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 331 332 for i := 0; i <= 10; i++ { 333 wg.Add(1) 334 go func(i int) { 335 defer wg.Done() 336 337 // getting the disallow-listed causes for a peerID 338 causes, disallowListed := disallowListCache.IsDisallowListed(peer.ID(fmt.Sprintf("peer-%d", i))) 339 require.False(t, disallowListed) 340 require.Len(t, causes, 0) 341 }(i) 342 } 343 unittest.RequireReturnsBefore(t, wg.Wait, 100*time.Millisecond, "timed out waiting for goroutines to finish") 344 345 for i := 11; i <= 20; i++ { 346 wg.Add(1) 347 go func(i int) { 348 defer wg.Done() 349 350 // allowing a peerID for a cause when the peerID doesn't exist in the cache 351 causes := disallowListCache.AllowFor(peer.ID(fmt.Sprintf("peer-%d", i)), network.DisallowListedCauseAdmin) 352 require.Len(t, causes, 0) 353 }(i) 354 } 355 }