diff options
Diffstat (limited to 'tests/multi_net')
-rw-r--r-- | tests/multi_net/tcp_accept_recv.py | 73 | ||||
-rw-r--r-- | tests/multi_net/tcp_recv_peek.py | 46 | ||||
-rw-r--r-- | tests/multi_net/udp_data_multi.py | 69 | ||||
-rw-r--r-- | tests/multi_net/udp_data_multi.py.exp | 15 | ||||
-rw-r--r-- | tests/multi_net/udp_recv_dontwait.py | 59 | ||||
-rw-r--r-- | tests/multi_net/udp_recv_dontwait.py.exp | 7 | ||||
-rw-r--r-- | tests/multi_net/udp_recv_peek.py | 36 |
7 files changed, 290 insertions, 15 deletions
diff --git a/tests/multi_net/tcp_accept_recv.py b/tests/multi_net/tcp_accept_recv.py index dee14e3b97..4108a6f8a3 100644 --- a/tests/multi_net/tcp_accept_recv.py +++ b/tests/multi_net/tcp_accept_recv.py @@ -1,30 +1,73 @@ -# Test recv on socket that just accepted a connection +# Test recv on listening socket after accept(), with various listen() arguments import socket PORT = 8000 +# Test cases for listen() function +LISTEN_ARGS = [None, 0, 1, 2] # None means no argument + # Server def instance0(): multitest.globals(IP=multitest.get_network_ip()) - s = socket.socket() - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1]) - s.listen(1) multitest.next() - s.accept() - try: - print("recv", s.recv(10)) # should raise Errno 107 ENOTCONN - except OSError as er: - print(er.errno in (107, 128)) - s.close() + + test_num = 0 + for blocking_mode in [True, False]: + for listen_arg in LISTEN_ARGS: + test_num += 1 + s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1]) + + # Call listen with or without argument based on test case + if listen_arg is None: + print(f"Test case {test_num}/8: listen() blocking={blocking_mode}") + s.listen() + else: + print(f"Test case {test_num}/8: listen({listen_arg}) blocking={blocking_mode}") + s.listen(listen_arg) + + # Signal client that server is ready + multitest.broadcast(f"server_ready_{test_num}") + + # Wait for client connection + c, _ = s.accept() + + # Set blocking mode after accept + s.setblocking(blocking_mode) + + try: + print("recv", s.recv(10)) # should raise Errno 107 ENOTCONN + except OSError as er: + # Verify the error code is either 107 (ENOTCONN) or 128 (ENOTCONN on Windows) + print(er.errno in (107, 128)) + + # Cleanup + c.close() + s.close() + + # Signal client we're done with this test case + multitest.broadcast(f"server_done_{test_num}") # Client def instance1(): multitest.next() - s = socket.socket() - s.connect(socket.getaddrinfo(IP, PORT)[0][-1]) - s.send(b"GET / HTTP/1.0\r\n\r\n") - s.close() + + test_num = 0 + for blocking_mode in [True, False]: + for _ in LISTEN_ARGS: + test_num += 1 + # Wait for server to be ready + multitest.wait(f"server_ready_{test_num}") + + # Connect to server + s = socket.socket() + s.connect(socket.getaddrinfo(IP, PORT)[0][-1]) + s.send(b"GET / HTTP/1.0\r\n\r\n") + s.close() + + # Wait for server to finish this test case + multitest.wait(f"server_done_{test_num}") diff --git a/tests/multi_net/tcp_recv_peek.py b/tests/multi_net/tcp_recv_peek.py new file mode 100644 index 0000000000..ff540dd3c3 --- /dev/null +++ b/tests/multi_net/tcp_recv_peek.py @@ -0,0 +1,46 @@ +# Test TCP recv with MSG_PEEK +# +# Note that bare metal LWIP only returns at most one packet's worth of TCP data +# in any recv() call - including when peeking - so can't be too clever with +# different recv() combinations +import socket +import random + + +# Server +def instance0(): + PORT = random.randrange(10000, 50000) + multitest.globals(IP=multitest.get_network_ip(), PORT=PORT) + s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1]) + s.listen() + multitest.next() + s2, _ = s.accept() + print(s2.recv(8, socket.MSG_PEEK)) + print(s2.recv(8)) + s2.send(b"1234567890") + multitest.broadcast("0-sent") + multitest.wait("1-sent") + print(s2.recv(5, socket.MSG_PEEK)) + print(s2.recv(5, socket.MSG_PEEK)) + multitest.broadcast("0-recved") + multitest.wait("1-recved") # sync here necessary as MP sends RST if closing TCP early + s2.close() + s.close() + + +# Client +def instance1(): + multitest.next() + s = socket.socket() + s.connect(socket.getaddrinfo(IP, PORT)[0][-1]) + s.send(b"abcdefgh") + multitest.broadcast("1-sent") + multitest.wait("0-sent") + s.send(b"klmnopqr") + print(s.recv(5, socket.MSG_PEEK)) + print(s.recv(10)) + multitest.broadcast("1-recved") + multitest.wait("0-recved") + s.close() diff --git a/tests/multi_net/udp_data_multi.py b/tests/multi_net/udp_data_multi.py new file mode 100644 index 0000000000..5d7b13e518 --- /dev/null +++ b/tests/multi_net/udp_data_multi.py @@ -0,0 +1,69 @@ +# Test UDP reception when there are multiple incoming UDP packets that need to be +# queued internally in the TCP/IP stack. + +import socket + +NUM_NEW_SOCKETS = 4 +NUM_PACKET_BURSTS = 6 +NUM_PACKET_GROUPS = 5 +TOTAL_PACKET_BURSTS = NUM_NEW_SOCKETS * NUM_PACKET_BURSTS +# The tast passes if more than 75% of packets are received in each group. +PACKET_RECV_THRESH = 0.75 * TOTAL_PACKET_BURSTS +PORT = 8000 + + +# Server +def instance0(): + recv_count = {i: 0 for i in range(NUM_PACKET_GROUPS)} + multitest.globals(IP=multitest.get_network_ip()) + multitest.next() + for i in range(NUM_NEW_SOCKETS): + print("test socket", i) + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(socket.getaddrinfo("0.0.0.0", PORT + i)[0][-1]) + s.settimeout(0.250) + multitest.broadcast("server ready") + for burst in range(NUM_PACKET_BURSTS): + # Wait for all packets to be sent, without receiving any yet. + multitest.wait("data sent burst={}".format(burst)) + # Try to receive all packets (they should be waiting in the queue). + for group in range(NUM_PACKET_GROUPS): + try: + data, addr = s.recvfrom(1000) + except: + continue + recv_burst, recv_group = data.split(b":") + recv_burst = int(recv_burst) + recv_group = int(recv_group) + if recv_burst == burst: + recv_count[recv_group] += 1 + # Inform the client that all data was received. + multitest.broadcast("data received burst={}".format(burst)) + s.close() + + # Check how many packets were received. + for group, count in recv_count.items(): + if count >= PACKET_RECV_THRESH: + print("pass group={}".format(group)) + else: + print("fail group={} received={}%".format(group, 100 * count // TOTAL_PACKET_BURSTS)) + + +# Client +def instance1(): + multitest.next() + for i in range(NUM_NEW_SOCKETS): + print("test socket", i) + ai = socket.getaddrinfo(IP, PORT + i)[0][-1] + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + multitest.wait("server ready") + for burst in range(NUM_PACKET_BURSTS): + # Send a bunch of packets all in a row. + for group in range(NUM_PACKET_GROUPS): + s.sendto(b"%d:%d" % (burst, group), ai) + # Inform the server that the data has been sent. + multitest.broadcast("data sent burst={}".format(burst)) + # Wait for the server to finish receiving. + multitest.wait("data received burst={}".format(burst)) + s.close() diff --git a/tests/multi_net/udp_data_multi.py.exp b/tests/multi_net/udp_data_multi.py.exp new file mode 100644 index 0000000000..bc67c6ab0c --- /dev/null +++ b/tests/multi_net/udp_data_multi.py.exp @@ -0,0 +1,15 @@ +--- instance0 --- +test socket 0 +test socket 1 +test socket 2 +test socket 3 +pass group=0 +pass group=1 +pass group=2 +pass group=3 +pass group=4 +--- instance1 --- +test socket 0 +test socket 1 +test socket 2 +test socket 3 diff --git a/tests/multi_net/udp_recv_dontwait.py b/tests/multi_net/udp_recv_dontwait.py new file mode 100644 index 0000000000..640f3f060e --- /dev/null +++ b/tests/multi_net/udp_recv_dontwait.py @@ -0,0 +1,59 @@ +# Test UDP recv and recvfrom with MSG_DONTWAIT +import random +import socket + +try: + import errno, time +except ImportError: + print("SKIP") + raise SystemExit + + +# Server +def instance0(): + PORT = random.randrange(10000, 50000) + multitest.globals(IP=multitest.get_network_ip(), PORT=PORT) + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1]) + multitest.next() + begin = time.ticks_ms() + + # do some recvs before instance1 starts, when we know no packet is waiting + try: + print(s.recvfrom(8, socket.MSG_DONTWAIT)) + except OSError as e: + print(e.errno == errno.EAGAIN) + try: + print(s.recv(8, socket.MSG_DONTWAIT)) + except OSError as e: + print(e.errno == errno.EAGAIN) + + # the above steps should not have taken any substantial time + elapsed = time.ticks_diff(time.ticks_ms(), begin) + print(True if elapsed < 50 else elapsed) + + # Now instance1 will send us a UDP packet + multitest.broadcast("0-ready") + multitest.wait("1-sent") + + for _ in range(10): # retry if necessary, to allow for network delay + time.sleep_ms(100) + try: + print(s.recv(8, socket.MSG_DONTWAIT)) + break + except OSError as er: + if er.errno != errno.EAGAIN: + raise er + s.close() + + +# Client +def instance1(): + multitest.next() + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(socket.getaddrinfo(IP, PORT)[0][-1]) + multitest.wait("0-ready") + print(s.send(b"abcdefgh")) + multitest.broadcast("1-sent") + s.close() diff --git a/tests/multi_net/udp_recv_dontwait.py.exp b/tests/multi_net/udp_recv_dontwait.py.exp new file mode 100644 index 0000000000..f61fd4bbe2 --- /dev/null +++ b/tests/multi_net/udp_recv_dontwait.py.exp @@ -0,0 +1,7 @@ +--- instance0 --- +True +True +True +b'abcdefgh' +--- instance1 --- +8 diff --git a/tests/multi_net/udp_recv_peek.py b/tests/multi_net/udp_recv_peek.py new file mode 100644 index 0000000000..47897ce553 --- /dev/null +++ b/tests/multi_net/udp_recv_peek.py @@ -0,0 +1,36 @@ +# Test UDP recv and recvfrom with MSG_PEEK +import random +import socket +import time + + +# Server +def instance0(): + PORT = random.randrange(10000, 50000) + multitest.globals(IP=multitest.get_network_ip(), PORT=PORT) + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1]) + multitest.next() + peek_bytes, peek_addr = s.recvfrom(8, socket.MSG_PEEK) + print(peek_bytes) + real_bytes, real_addr = s.recvfrom(8) + print(real_bytes) + print(peek_addr == real_addr) # source addr should be the same for each + res = s.sendto(b"1234567890", peek_addr) + print(res) + print(s.recv(5, socket.MSG_PEEK)) + print(s.recv(5, socket.MSG_PEEK)) + s.close() + + +# Client +def instance1(): + multitest.next() + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(socket.getaddrinfo(IP, PORT)[0][-1]) + s.send(b"abcdefgh") + s.send(b"klmnopqr") + print(s.recv(5, socket.MSG_PEEK)) + print(s.recv(10)) + s.close() |