@@ -27,6 +27,7 @@ use libp2p_core::{
27
27
network:: { ConnectionLimits , DialError , NetworkConfig , NetworkEvent } ,
28
28
PeerId ,
29
29
} ;
30
+ use quickcheck:: * ;
30
31
use rand:: Rng ;
31
32
use std:: task:: Poll ;
32
33
use util:: { test_network, TestHandler } ;
@@ -88,89 +89,121 @@ fn max_outgoing() {
88
89
89
90
#[ test]
90
91
fn max_established_incoming ( ) {
91
- let limit = rand:: thread_rng ( ) . gen_range ( 1 , 10 ) ;
92
+ #[ derive( Debug , Clone ) ]
93
+ struct Limit ( u32 ) ;
94
+
95
+ impl Arbitrary for Limit {
96
+ fn arbitrary < G : Gen > ( g : & mut G ) -> Self {
97
+ Self ( g. gen_range ( 1 , 10 ) )
98
+ }
99
+ }
92
100
93
101
fn config ( limit : u32 ) -> NetworkConfig {
94
102
let limits = ConnectionLimits :: default ( ) . with_max_established_incoming ( Some ( limit) ) ;
95
103
NetworkConfig :: default ( ) . with_connection_limits ( limits)
96
104
}
97
105
98
- let mut network1 = test_network ( config ( limit) ) ;
99
- let mut network2 = test_network ( config ( limit) ) ;
100
-
101
- let listen_addr = multiaddr ! [ Memory ( 0u64 ) ] ;
102
- let _ = network1. listen_on ( listen_addr. clone ( ) ) . unwrap ( ) ;
103
- let ( addr_sender, addr_receiver) = futures:: channel:: oneshot:: channel ( ) ;
104
- let mut addr_sender = Some ( addr_sender) ;
105
-
106
- // Spawn the listener.
107
- let listener = async_std:: task:: spawn ( poll_fn ( move |cx| loop {
108
- match ready ! ( network1. poll( cx) ) {
109
- NetworkEvent :: NewListenerAddress { listen_addr, .. } => {
110
- addr_sender. take ( ) . unwrap ( ) . send ( listen_addr) . unwrap ( ) ;
111
- }
112
- NetworkEvent :: IncomingConnection { connection, .. } => {
113
- network1. accept ( connection, TestHandler ( ) ) . unwrap ( ) ;
114
- }
115
- NetworkEvent :: ConnectionEstablished { .. } => { }
116
- NetworkEvent :: IncomingConnectionError {
117
- error : PendingConnectionError :: ConnectionLimit ( err) ,
118
- ..
119
- } => {
120
- assert_eq ! ( err. limit, limit) ;
121
- assert_eq ! ( err. limit, err. current) ;
122
- let info = network1. info ( ) ;
123
- let counters = info. connection_counters ( ) ;
124
- assert_eq ! ( counters. num_established_incoming( ) , limit) ;
125
- assert_eq ! ( counters. num_established( ) , limit) ;
126
- return Poll :: Ready ( ( ) ) ;
127
- }
128
- e => panic ! ( "Unexpected network event: {:?}" , e) ,
129
- }
130
- } ) ) ;
131
-
132
- // Spawn and block on the dialer.
133
- async_std:: task:: block_on ( async move {
134
- let addr = addr_receiver. await . unwrap ( ) ;
135
- let mut n = 0 ;
136
- let _ = network2. dial ( & addr, TestHandler ( ) ) . unwrap ( ) ;
137
- let mut expected_closed = None ;
138
- poll_fn ( |cx| {
139
- loop {
140
- match ready ! ( network2. poll( cx) ) {
141
- NetworkEvent :: ConnectionEstablished { connection, .. } => {
142
- n += 1 ;
106
+ fn prop ( limit : Limit ) {
107
+ let limit = limit. 0 ;
108
+
109
+ let mut network1 = test_network ( config ( limit) ) ;
110
+ let mut network2 = test_network ( config ( limit) ) ;
111
+
112
+ let _ = network1. listen_on ( multiaddr ! [ Memory ( 0u64 ) ] ) . unwrap ( ) ;
113
+ let listen_addr =
114
+ async_std:: task:: block_on ( poll_fn ( |cx| match ready ! ( network1. poll( cx) ) {
115
+ NetworkEvent :: NewListenerAddress { listen_addr, .. } => Poll :: Ready ( listen_addr) ,
116
+ e => panic ! ( "Unexpected network event: {:?}" , e) ,
117
+ } ) ) ;
118
+
119
+ // Spawn and block on the dialer.
120
+ async_std:: task:: block_on ( {
121
+ let mut n = 0 ;
122
+ let _ = network2. dial ( & listen_addr, TestHandler ( ) ) . unwrap ( ) ;
123
+
124
+ let mut expected_closed = false ;
125
+ let mut network_1_established = false ;
126
+ let mut network_2_established = false ;
127
+ let mut network_1_limit_reached = false ;
128
+ let mut network_2_limit_reached = false ;
129
+ poll_fn ( move |cx| {
130
+ loop {
131
+ let mut network_1_pending = false ;
132
+ let mut network_2_pending = false ;
133
+
134
+ match network1. poll ( cx) {
135
+ Poll :: Ready ( NetworkEvent :: IncomingConnection { connection, .. } ) => {
136
+ network1. accept ( connection, TestHandler ( ) ) . unwrap ( ) ;
137
+ }
138
+ Poll :: Ready ( NetworkEvent :: ConnectionEstablished { .. } ) => {
139
+ network_1_established = true ;
140
+ }
141
+ Poll :: Ready ( NetworkEvent :: IncomingConnectionError {
142
+ error : PendingConnectionError :: ConnectionLimit ( err) ,
143
+ ..
144
+ } ) => {
145
+ assert_eq ! ( err. limit, limit) ;
146
+ assert_eq ! ( err. limit, err. current) ;
147
+ let info = network1. info ( ) ;
148
+ let counters = info. connection_counters ( ) ;
149
+ assert_eq ! ( counters. num_established_incoming( ) , limit) ;
150
+ assert_eq ! ( counters. num_established( ) , limit) ;
151
+ network_1_limit_reached = true ;
152
+ }
153
+ Poll :: Pending => {
154
+ network_1_pending = true ;
155
+ }
156
+ e => panic ! ( "Unexpected network event: {:?}" , e) ,
157
+ }
158
+
159
+ match network2. poll ( cx) {
160
+ Poll :: Ready ( NetworkEvent :: ConnectionEstablished { .. } ) => {
161
+ network_2_established = true ;
162
+ }
163
+ Poll :: Ready ( NetworkEvent :: ConnectionClosed { .. } ) => {
164
+ assert ! ( expected_closed) ;
165
+ let info = network2. info ( ) ;
166
+ let counters = info. connection_counters ( ) ;
167
+ assert_eq ! ( counters. num_established_outgoing( ) , limit) ;
168
+ assert_eq ! ( counters. num_established( ) , limit) ;
169
+ network_2_limit_reached = true ;
170
+ }
171
+ Poll :: Pending => {
172
+ network_2_pending = true ;
173
+ }
174
+ e => panic ! ( "Unexpected network event: {:?}" , e) ,
175
+ }
176
+
177
+ if network_1_pending && network_2_pending {
178
+ return Poll :: Pending ;
179
+ }
180
+
181
+ if network_1_established && network_2_established {
182
+ network_1_established = false ;
183
+ network_2_established = false ;
184
+
143
185
if n <= limit {
144
186
// Dial again until the limit is exceeded.
145
- let id = network2. dial ( & addr, TestHandler ( ) ) . unwrap ( ) ;
187
+ n += 1 ;
188
+ network2. dial ( & listen_addr, TestHandler ( ) ) . unwrap ( ) ;
189
+
146
190
if n == limit {
147
191
// The the next dialing attempt exceeds the limit, this
148
192
// is the connection we expected to get closed.
149
- expected_closed = Some ( id ) ;
193
+ expected_closed = true ;
150
194
}
151
195
} else {
152
- // This connection exceeds the limit for the listener and
153
- // is expected to close shortly. For the dialer, these connections
154
- // will first appear established before the listener closes them as
155
- // a result of the limit violation.
156
- assert_eq ! ( Some ( connection. id( ) ) , expected_closed) ;
196
+ panic ! ( "Expect networks not to establish connections beyond the limit." )
157
197
}
158
198
}
159
- NetworkEvent :: ConnectionClosed { id, .. } => {
160
- assert_eq ! ( Some ( id) , expected_closed) ;
161
- let info = network2. info ( ) ;
162
- let counters = info. connection_counters ( ) ;
163
- assert_eq ! ( counters. num_established_outgoing( ) , limit) ;
164
- assert_eq ! ( counters. num_established( ) , limit) ;
199
+
200
+ if network_1_limit_reached && network_2_limit_reached {
165
201
return Poll :: Ready ( ( ) ) ;
166
202
}
167
- e => panic ! ( "Unexpected network event: {:?}" , e) ,
168
203
}
169
- }
170
- } )
171
- . await
172
- } ) ;
204
+ } )
205
+ } ) ;
206
+ }
173
207
174
- // Wait for the listener to complete.
175
- async_std:: task:: block_on ( listener) ;
208
+ quickcheck ( prop as fn ( _) ) ;
176
209
}
0 commit comments