micropython: add micropython component
This commit is contained in:
5
components/language/micropython/tests/net_inet/README
Normal file
5
components/language/micropython/tests/net_inet/README
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory contains network tests which require Internet connection.
|
||||
Note that these tests are not run as part of the main testsuite and need
|
||||
to be run seperately (from the main test/ directory):
|
||||
|
||||
./run-tests.py net_inet/*.py
|
@@ -0,0 +1,52 @@
|
||||
try:
|
||||
import usocket as socket, sys
|
||||
except:
|
||||
import socket, sys
|
||||
|
||||
|
||||
def test_non_existent():
|
||||
try:
|
||||
res = socket.getaddrinfo("nonexistent.example.com", 80)
|
||||
print("getaddrinfo returned", res)
|
||||
except OSError as e:
|
||||
print("getaddrinfo raised")
|
||||
|
||||
|
||||
def test_bogus():
|
||||
try:
|
||||
res = socket.getaddrinfo("hey.!!$$", 80)
|
||||
print("getaddrinfo returned", res)
|
||||
except OSError as e:
|
||||
print("getaddrinfo raised")
|
||||
except Exception as e:
|
||||
print("getaddrinfo raised") # CPython raises UnicodeError!?
|
||||
|
||||
|
||||
def test_ip_addr():
|
||||
try:
|
||||
res = socket.getaddrinfo("10.10.10.10", 80)
|
||||
print("getaddrinfo returned resolutions")
|
||||
except Exception as e:
|
||||
print("getaddrinfo raised", e)
|
||||
|
||||
|
||||
def test_0_0_0_0():
|
||||
try:
|
||||
res = socket.getaddrinfo("0.0.0.0", 80)
|
||||
print("getaddrinfo returned resolutions")
|
||||
except Exception as e:
|
||||
print("getaddrinfo raised", e)
|
||||
|
||||
|
||||
def test_valid():
|
||||
try:
|
||||
res = socket.getaddrinfo("micropython.org", 80)
|
||||
print("getaddrinfo returned resolutions")
|
||||
except Exception as e:
|
||||
print("getaddrinfo raised", e)
|
||||
|
||||
|
||||
test_funs = [n for n in dir() if n.startswith("test_")]
|
||||
for f in sorted(test_funs):
|
||||
print("--", f, end=": ")
|
||||
eval(f + "()")
|
51
components/language/micropython/tests/net_inet/ssl_errors.py
Normal file
51
components/language/micropython/tests/net_inet/ssl_errors.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# test that socket.connect() on a non-blocking socket raises EINPROGRESS
|
||||
# and that an immediate write/send/read/recv does the right thing
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
import uerrno as errno, usocket as socket, ussl as ssl
|
||||
except:
|
||||
import errno, socket, ssl
|
||||
|
||||
|
||||
def test(addr, hostname, block=True):
|
||||
print("---", hostname or addr)
|
||||
s = socket.socket()
|
||||
s.setblocking(block)
|
||||
try:
|
||||
s.connect(addr)
|
||||
print("connected")
|
||||
except OSError as e:
|
||||
if e.errno != errno.EINPROGRESS:
|
||||
raise
|
||||
print("EINPROGRESS")
|
||||
|
||||
try:
|
||||
if sys.implementation.name == "micropython":
|
||||
s = ssl.wrap_socket(s, do_handshake=block)
|
||||
else:
|
||||
s = ssl.wrap_socket(s, do_handshake_on_connect=block)
|
||||
print("wrap: True")
|
||||
except OSError:
|
||||
print("wrap: error")
|
||||
|
||||
if not block:
|
||||
try:
|
||||
while s.write(b"0") is None:
|
||||
pass
|
||||
except (ValueError, OSError): # CPython raises ValueError, MicroPython raises OSError
|
||||
print("write: error")
|
||||
s.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# connect to plain HTTP port, oops!
|
||||
addr = socket.getaddrinfo("micropython.org", 80)[0][-1]
|
||||
test(addr, None)
|
||||
# connect to plain HTTP port, oops!
|
||||
addr = socket.getaddrinfo("micropython.org", 80)[0][-1]
|
||||
test(addr, None, False)
|
||||
# connect to server with self-signed cert, oops!
|
||||
addr = socket.getaddrinfo("test.mosquitto.org", 8883)[0][-1]
|
||||
test(addr, "test.mosquitto.org")
|
@@ -0,0 +1,115 @@
|
||||
try:
|
||||
import usocket as socket, ussl as ssl, uerrno as errno, sys
|
||||
except:
|
||||
import socket, ssl, errno, sys, time, select
|
||||
|
||||
|
||||
def test_one(site, opts):
|
||||
ai = socket.getaddrinfo(site, 443)
|
||||
addr = ai[0][-1]
|
||||
print(addr)
|
||||
|
||||
# Connect the raw socket
|
||||
s = socket.socket()
|
||||
s.setblocking(False)
|
||||
try:
|
||||
s.connect(addr)
|
||||
raise OSError(-1, "connect blocks")
|
||||
except OSError as e:
|
||||
if e.errno != errno.EINPROGRESS:
|
||||
raise
|
||||
|
||||
if sys.implementation.name != "micropython":
|
||||
# in CPython we have to wait, otherwise wrap_socket is not happy
|
||||
select.select([], [s], [])
|
||||
|
||||
try:
|
||||
# Wrap with SSL
|
||||
try:
|
||||
if sys.implementation.name == "micropython":
|
||||
s = ssl.wrap_socket(s, do_handshake=False)
|
||||
else:
|
||||
s = ssl.wrap_socket(s, do_handshake_on_connect=False)
|
||||
except OSError as e:
|
||||
if e.errno != errno.EINPROGRESS:
|
||||
raise
|
||||
print("wrapped")
|
||||
|
||||
# CPython needs to be told to do the handshake
|
||||
if sys.implementation.name != "micropython":
|
||||
while True:
|
||||
try:
|
||||
s.do_handshake()
|
||||
break
|
||||
except ssl.SSLError as err:
|
||||
if err.args[0] == ssl.SSL_ERROR_WANT_READ:
|
||||
select.select([s], [], [])
|
||||
elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
|
||||
select.select([], [s], [])
|
||||
else:
|
||||
raise
|
||||
time.sleep(0.1)
|
||||
# print("shook hands")
|
||||
|
||||
# Write HTTP request
|
||||
out = b"GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % bytes(site, "latin")
|
||||
while len(out) > 0:
|
||||
n = s.write(out)
|
||||
if n is None:
|
||||
continue
|
||||
if n > 0:
|
||||
out = out[n:]
|
||||
elif n == 0:
|
||||
raise OSError(-1, "unexpected EOF in write")
|
||||
print("wrote")
|
||||
|
||||
# Read response
|
||||
resp = b""
|
||||
while True:
|
||||
try:
|
||||
b = s.read(128)
|
||||
except OSError as err:
|
||||
if err.errno == 2: # 2=ssl.SSL_ERROR_WANT_READ:
|
||||
continue
|
||||
raise
|
||||
if b is None:
|
||||
continue
|
||||
if len(b) > 0:
|
||||
if len(resp) < 1024:
|
||||
resp += b
|
||||
elif len(b) == 0:
|
||||
break
|
||||
print("read")
|
||||
|
||||
if resp[:7] != b"HTTP/1.":
|
||||
raise ValueError("response doesn't start with HTTP/1.")
|
||||
# print(resp)
|
||||
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
SITES = [
|
||||
"google.com",
|
||||
{"host": "www.google.com"},
|
||||
"micropython.org",
|
||||
"pypi.org",
|
||||
{"host": "api.pushbullet.com", "sni": True},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
for site in SITES:
|
||||
opts = {}
|
||||
if isinstance(site, dict):
|
||||
opts = site
|
||||
site = opts["host"]
|
||||
try:
|
||||
test_one(site, opts)
|
||||
print(site, "ok")
|
||||
except Exception as e:
|
||||
print(site, "error")
|
||||
print("DONE")
|
||||
|
||||
|
||||
main()
|
@@ -0,0 +1,61 @@
|
||||
try:
|
||||
import usocket as _socket
|
||||
except:
|
||||
import _socket
|
||||
try:
|
||||
import ussl as ssl
|
||||
except:
|
||||
import ssl
|
||||
|
||||
# CPython only supports server_hostname with SSLContext
|
||||
ssl = ssl.SSLContext()
|
||||
|
||||
|
||||
def test_one(site, opts):
|
||||
ai = _socket.getaddrinfo(site, 443)
|
||||
addr = ai[0][-1]
|
||||
|
||||
s = _socket.socket()
|
||||
|
||||
try:
|
||||
s.connect(addr)
|
||||
|
||||
if "sni" in opts:
|
||||
s = ssl.wrap_socket(s, server_hostname=opts["host"])
|
||||
else:
|
||||
s = ssl.wrap_socket(s)
|
||||
|
||||
s.write(b"GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % bytes(site, "latin"))
|
||||
resp = s.read(4096)
|
||||
if resp[:7] != b"HTTP/1.":
|
||||
raise ValueError("response doesn't start with HTTP/1.")
|
||||
# print(resp)
|
||||
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
SITES = [
|
||||
"google.com",
|
||||
"www.google.com",
|
||||
"micropython.org",
|
||||
"pypi.org",
|
||||
{"host": "api.pushbullet.com", "sni": True},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
for site in SITES:
|
||||
opts = {}
|
||||
if isinstance(site, dict):
|
||||
opts = site
|
||||
site = opts["host"]
|
||||
|
||||
try:
|
||||
test_one(site, opts)
|
||||
print(site, "ok")
|
||||
except Exception as e:
|
||||
print(site, e)
|
||||
|
||||
|
||||
main()
|
@@ -0,0 +1,5 @@
|
||||
google.com ok
|
||||
www.google.com ok
|
||||
micropython.org ok
|
||||
pypi.org ok
|
||||
api.pushbullet.com ok
|
@@ -0,0 +1,44 @@
|
||||
# test that modtls produces a numerical error message when out of heap
|
||||
|
||||
try:
|
||||
import usocket as socket, ussl as ssl, sys
|
||||
except:
|
||||
import socket, ssl, sys
|
||||
try:
|
||||
from micropython import alloc_emergency_exception_buf, heap_lock, heap_unlock
|
||||
except:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
# test with heap locked to see it switch to number-only error message
|
||||
def test(addr):
|
||||
alloc_emergency_exception_buf(256)
|
||||
s = socket.socket()
|
||||
s.connect(addr)
|
||||
try:
|
||||
s.setblocking(False)
|
||||
s = ssl.wrap_socket(s, do_handshake=False)
|
||||
heap_lock()
|
||||
print("heap is locked")
|
||||
while True:
|
||||
ret = s.write("foo")
|
||||
if ret:
|
||||
break
|
||||
heap_unlock()
|
||||
print("wrap: no exception")
|
||||
except OSError as e:
|
||||
heap_unlock()
|
||||
# mbedtls produces "-29184"
|
||||
# axtls produces "RECORD_OVERFLOW"
|
||||
ok = "-29184" in str(e) or "RECORD_OVERFLOW" in str(e)
|
||||
print("wrap:", ok)
|
||||
if not ok:
|
||||
print("got exception:", e)
|
||||
s.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# connect to plain HTTP port, oops!
|
||||
addr = socket.getaddrinfo("micropython.org", 80)[0][-1]
|
||||
test(addr)
|
@@ -0,0 +1,2 @@
|
||||
heap is locked
|
||||
wrap: True
|
@@ -0,0 +1,33 @@
|
||||
# test that modtls produces a text error message
|
||||
|
||||
try:
|
||||
import usocket as socket, ussl as ssl, sys
|
||||
except:
|
||||
import socket, ssl, sys
|
||||
|
||||
|
||||
def test(addr):
|
||||
s = socket.socket()
|
||||
s.connect(addr)
|
||||
try:
|
||||
s = ssl.wrap_socket(s)
|
||||
print("wrap: no exception")
|
||||
except OSError as e:
|
||||
# mbedtls produces "mbedtls -0x7200: SSL - An invalid SSL record was received"
|
||||
# axtls produces "RECORD_OVERFLOW" but also prints "TLS buffer overflow,..."
|
||||
# CPython produces "[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)"
|
||||
ok = (
|
||||
"SSL_INVALID_RECORD" in str(e)
|
||||
or "RECORD_OVERFLOW" in str(e)
|
||||
or "wrong version" in str(e)
|
||||
)
|
||||
print("wrap:", ok)
|
||||
if not ok:
|
||||
print("got exception:", e)
|
||||
s.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# connect to plain HTTP port, oops!
|
||||
addr = socket.getaddrinfo("micropython.org", 80)[0][-1]
|
||||
test(addr)
|
@@ -0,0 +1,35 @@
|
||||
# Test cancelling a task waiting on stream IO
|
||||
|
||||
try:
|
||||
import uasyncio as asyncio
|
||||
except ImportError:
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def get(reader):
|
||||
print("start")
|
||||
try:
|
||||
await reader.read(10)
|
||||
print("fail")
|
||||
except asyncio.CancelledError:
|
||||
print("cancelled")
|
||||
|
||||
|
||||
async def main(url):
|
||||
reader, writer = await asyncio.open_connection(url, 80)
|
||||
task = asyncio.create_task(get(reader))
|
||||
await asyncio.sleep(0)
|
||||
print("cancelling")
|
||||
task.cancel()
|
||||
print("waiting")
|
||||
await task
|
||||
print("done")
|
||||
writer.close()
|
||||
await writer.wait_closed()
|
||||
|
||||
|
||||
asyncio.run(main("micropython.org"))
|
@@ -0,0 +1,5 @@
|
||||
start
|
||||
cancelling
|
||||
waiting
|
||||
cancelled
|
||||
done
|
@@ -0,0 +1,30 @@
|
||||
# Test simple HTTP request with uasyncio.open_connection()
|
||||
|
||||
try:
|
||||
import uasyncio as asyncio
|
||||
except ImportError:
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def http_get(url):
|
||||
reader, writer = await asyncio.open_connection(url, 80)
|
||||
|
||||
print("write GET")
|
||||
writer.write(b"GET / HTTP/1.0\r\n\r\n")
|
||||
await writer.drain()
|
||||
|
||||
print("read response")
|
||||
data = await reader.read(100)
|
||||
print("read:", data.split(b"\r\n")[0])
|
||||
|
||||
print("close")
|
||||
writer.close()
|
||||
await writer.wait_closed()
|
||||
print("done")
|
||||
|
||||
|
||||
asyncio.run(http_get("micropython.org"))
|
@@ -0,0 +1,5 @@
|
||||
write GET
|
||||
read response
|
||||
read: b'HTTP/1.1 200 OK'
|
||||
close
|
||||
done
|
@@ -0,0 +1,38 @@
|
||||
# Test uasyncio.open_connection() and stream readline()
|
||||
|
||||
try:
|
||||
import uasyncio as asyncio
|
||||
except ImportError:
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def http_get_headers(url):
|
||||
reader, writer = await asyncio.open_connection(url, 80)
|
||||
|
||||
print("write GET")
|
||||
writer.write(b"GET / HTTP/1.0\r\n\r\n")
|
||||
await writer.drain()
|
||||
|
||||
while True:
|
||||
line = await reader.readline()
|
||||
line = line.strip()
|
||||
if not line:
|
||||
break
|
||||
if (
|
||||
line.find(b"Date") == -1
|
||||
and line.find(b"Modified") == -1
|
||||
and line.find(b"Server") == -1
|
||||
):
|
||||
print(line)
|
||||
|
||||
print("close")
|
||||
writer.close()
|
||||
await writer.wait_closed()
|
||||
print("done")
|
||||
|
||||
|
||||
asyncio.run(http_get_headers("micropython.org"))
|
@@ -0,0 +1,11 @@
|
||||
write GET
|
||||
b'HTTP/1.1 200 OK'
|
||||
b'Content-Type: text/html'
|
||||
b'Content-Length: 54'
|
||||
b'Connection: close'
|
||||
b'Vary: Accept-Encoding'
|
||||
b'ETag: "54306c85-36"'
|
||||
b'Strict-Transport-Security: max-age=15768000'
|
||||
b'Accept-Ranges: bytes'
|
||||
close
|
||||
done
|
Reference in New Issue
Block a user