github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/builder/libp2pscaler_test.go (about) 1 package p2pbuilder 2 3 import ( 4 "testing" 5 6 "github.com/libp2p/go-libp2p" 7 rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" 8 "github.com/pbnjay/memory" 9 "github.com/stretchr/testify/require" 10 11 "github.com/onflow/flow-go/config" 12 p2pconfig "github.com/onflow/flow-go/network/p2p/config" 13 "github.com/onflow/flow-go/utils/unittest" 14 ) 15 16 func TestAllowedMemoryScale(t *testing.T) { 17 m := memory.TotalMemory() 18 require.True(t, m > 0) 19 20 // scaling with factor of 1 should return the total memory. 21 s, err := allowedMemory(1) 22 require.NoError(t, err) 23 require.Equal(t, int64(m), s) 24 25 // scaling with factor of 0 should return an error. 26 _, err = allowedMemory(0) 27 require.Error(t, err) 28 29 // scaling with factor of -1 should return an error. 30 _, err = allowedMemory(-1) 31 require.Error(t, err) 32 33 // scaling with factor of 2 should return an error. 34 _, err = allowedMemory(2) 35 require.Error(t, err) 36 37 // scaling with factor of 0.5 should return half the total memory. 38 s, err = allowedMemory(0.5) 39 require.NoError(t, err) 40 require.Equal(t, int64(m/2), s) 41 42 // scaling with factor of 0.1 should return 10% of the total memory. 43 s, err = allowedMemory(0.1) 44 require.NoError(t, err) 45 require.Equal(t, int64(m/10), s) 46 47 // scaling with factor of 0.01 should return 1% of the total memory. 48 s, err = allowedMemory(0.01) 49 require.NoError(t, err) 50 require.Equal(t, int64(m/100), s) 51 52 // scaling with factor of 0.001 should return 0.1% of the total memory. 53 s, err = allowedMemory(0.001) 54 require.NoError(t, err) 55 require.Equal(t, int64(m/1000), s) 56 57 // scaling with factor of 0.0001 should return 0.01% of the total memory. 58 s, err = allowedMemory(0.0001) 59 require.NoError(t, err) 60 require.Equal(t, int64(m/10000), s) 61 } 62 63 func TestAllowedFileDescriptorsScale(t *testing.T) { 64 // getting actual file descriptor limit. 65 fd, err := getNumFDs() 66 require.NoError(t, err) 67 require.True(t, fd > 0) 68 69 // scaling with factor of 1 should return the total file descriptors. 70 s, err := allowedFileDescriptors(1) 71 require.NoError(t, err) 72 require.Equal(t, fd, s) 73 74 // scaling with factor of 0 should return an error. 75 _, err = allowedFileDescriptors(0) 76 require.Error(t, err) 77 78 // scaling with factor of -1 should return an error. 79 _, err = allowedFileDescriptors(-1) 80 require.Error(t, err) 81 82 // scaling with factor of 2 should return an error. 83 _, err = allowedFileDescriptors(2) 84 require.Error(t, err) 85 86 // scaling with factor of 0.5 should return half the total file descriptors. 87 s, err = allowedFileDescriptors(0.5) 88 require.NoError(t, err) 89 require.Equal(t, fd/2, s) 90 91 // scaling with factor of 0.1 should return 10% of the total file descriptors. 92 s, err = allowedFileDescriptors(0.1) 93 require.NoError(t, err) 94 require.Equal(t, fd/10, s) 95 96 // scaling with factor of 0.01 should return 1% of the total file descriptors. 97 s, err = allowedFileDescriptors(0.01) 98 require.NoError(t, err) 99 require.Equal(t, fd/100, s) 100 101 // scaling with factor of 0.001 should return 0.1% of the total file descriptors. 102 s, err = allowedFileDescriptors(0.001) 103 require.NoError(t, err) 104 require.Equal(t, fd/1000, s) 105 106 // scaling with factor of 0.0001 should return 0.01% of the total file descriptors. 107 s, err = allowedFileDescriptors(0.0001) 108 require.NoError(t, err) 109 require.Equal(t, fd/10000, s) 110 } 111 112 // TestApplyResourceLimitOverride tests the ApplyResourceLimitOverride function. It tests the following cases: 113 // 1. The override limit is not set (i.e., left at zero), the original limit should be used. 114 // 2. The override limit is set, the override limit should be used. 115 func TestApplyResourceLimitOverride(t *testing.T) { 116 cfg, err := config.DefaultConfig() 117 require.NoError(t, err) 118 119 mem, err := allowedMemory(cfg.NetworkConfig.ResourceManager.MemoryLimitRatio) 120 require.NoError(t, err) 121 122 fd, err := allowedFileDescriptors(cfg.NetworkConfig.ResourceManager.FileDescriptorsRatio) 123 require.NoError(t, err) 124 limits := rcmgr.DefaultLimits 125 libp2p.SetDefaultServiceLimits(&limits) 126 scaled := limits.Scale(mem, fd) 127 128 systemOverride := p2pconfig.ResourceManagerOverrideLimit{ 129 StreamsInbound: 0, // should not be overridden. 130 StreamsOutbound: 456, 131 ConnectionsInbound: 789, 132 ConnectionsOutbound: 0, // should not be overridden. 133 FD: 4560, 134 Memory: 7890, 135 } 136 137 peerOverride := p2pconfig.ResourceManagerOverrideLimit{ 138 StreamsInbound: 321, 139 StreamsOutbound: 0, // should not be overridden. 140 ConnectionsInbound: 987, 141 ConnectionsOutbound: 3210, 142 FD: 0, // should not be overridden. 143 Memory: 9870, 144 } 145 146 partial := rcmgr.PartialLimitConfig{} 147 partial.System = ApplyResourceLimitOverride(unittest.Logger(), p2pconfig.ResourceScopeSystem, scaled.ToPartialLimitConfig().System, systemOverride) 148 partial.PeerDefault = ApplyResourceLimitOverride(unittest.Logger(), p2pconfig.ResourceScopePeer, scaled.ToPartialLimitConfig().PeerDefault, peerOverride) 149 150 final := partial.Build(scaled).ToPartialLimitConfig() 151 require.Equal(t, 456, int(final.System.StreamsOutbound)) // should be overridden. 152 require.Equal(t, 789, int(final.System.ConnsInbound)) // should be overridden. 153 require.Equal(t, 4560, int(final.System.FD)) // should be overridden. 154 require.Equal(t, 7890, int(final.System.Memory)) // should be overridden. 155 require.Equal(t, scaled.ToPartialLimitConfig().System.StreamsInbound, final.System.StreamsInbound) // should NOT be overridden. 156 require.Equal(t, scaled.ToPartialLimitConfig().System.ConnsOutbound, final.System.ConnsOutbound) // should NOT be overridden. 157 } 158 159 // TestBuildLibp2pResourceManagerLimits tests the BuildLibp2pResourceManagerLimits function. 160 // It creates a default configuration and an overridden configuration, and tests overriding the default configuration. 161 func TestBuildLibp2pResourceManagerLimits(t *testing.T) { 162 cfg, err := config.DefaultConfig() 163 require.NoError(t, err) 164 165 // the default concrete limits is built from the default configuration. 166 defaultConcreteLimits, err := BuildLibp2pResourceManagerLimits(unittest.Logger(), &cfg.NetworkConfig.ResourceManager) 167 require.NoError(t, err) 168 169 // now the test creates random override configs for each scope, and re-build the concrete limits. 170 cfg.NetworkConfig.ResourceManager.Override.System = unittest.LibP2PResourceLimitOverrideFixture() 171 cfg.NetworkConfig.ResourceManager.Override.Transient = unittest.LibP2PResourceLimitOverrideFixture() 172 cfg.NetworkConfig.ResourceManager.Override.Protocol = unittest.LibP2PResourceLimitOverrideFixture() 173 cfg.NetworkConfig.ResourceManager.Override.Peer = unittest.LibP2PResourceLimitOverrideFixture() 174 cfg.NetworkConfig.ResourceManager.Override.PeerProtocol = unittest.LibP2PResourceLimitOverrideFixture() 175 overriddenConcreteLimits, err := BuildLibp2pResourceManagerLimits(unittest.Logger(), &cfg.NetworkConfig.ResourceManager) 176 require.NoError(t, err) 177 178 // this function will evaluate that the limits are override correctly on each scope using the override config. 179 requireEqual := func(t *testing.T, override p2pconfig.ResourceManagerOverrideLimit, actual rcmgr.ResourceLimits) { 180 require.Equal(t, override.StreamsInbound, int(actual.StreamsInbound)) 181 require.Equal(t, override.StreamsOutbound, int(actual.StreamsOutbound)) 182 require.Equal(t, override.ConnectionsInbound, int(actual.ConnsInbound)) 183 require.Equal(t, override.ConnectionsOutbound, int(actual.ConnsOutbound)) 184 require.Equal(t, override.FD, int(actual.FD)) 185 require.Equal(t, override.Memory, int(actual.Memory)) 186 } 187 188 op := overriddenConcreteLimits.ToPartialLimitConfig() 189 requireEqual(t, cfg.NetworkConfig.ResourceManager.Override.System, op.System) 190 requireEqual(t, cfg.NetworkConfig.ResourceManager.Override.Transient, op.Transient) 191 requireEqual(t, cfg.NetworkConfig.ResourceManager.Override.Protocol, op.ProtocolDefault) 192 requireEqual(t, cfg.NetworkConfig.ResourceManager.Override.Peer, op.PeerDefault) 193 requireEqual(t, cfg.NetworkConfig.ResourceManager.Override.PeerProtocol, op.ProtocolPeerDefault) 194 195 // this function will evaluate that the default limits (before overriding) are not equal to the overridden limits. 196 requireNotEqual := func(t *testing.T, a rcmgr.ResourceLimits, b rcmgr.ResourceLimits) { 197 require.NotEqual(t, a.StreamsInbound, b.StreamsInbound) 198 require.NotEqual(t, a.StreamsOutbound, b.StreamsOutbound) 199 require.NotEqual(t, a.ConnsInbound, b.ConnsInbound) 200 require.NotEqual(t, a.ConnsOutbound, b.ConnsOutbound) 201 require.NotEqual(t, a.FD, b.FD) 202 require.NotEqual(t, a.Memory, b.Memory) 203 } 204 dp := defaultConcreteLimits.ToPartialLimitConfig() 205 requireNotEqual(t, dp.System, op.System) 206 requireNotEqual(t, dp.Transient, op.Transient) 207 requireNotEqual(t, dp.ProtocolDefault, op.ProtocolDefault) 208 requireNotEqual(t, dp.PeerDefault, op.PeerDefault) 209 requireNotEqual(t, dp.ProtocolPeerDefault, op.ProtocolPeerDefault) 210 }