1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

device tests: some of them can be run on host (#6912)

* device tests: mock scripts + rename some tests to enable mock-testing them

* move symbol
This commit is contained in:
david gauchard
2019-12-16 19:20:07 +01:00
committed by GitHub
parent d1237fd016
commit d40dbb4584
16 changed files with 41 additions and 6 deletions

View File

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC3zCCAccCCQCUajf39FoF9jANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtj
YS50bHMudGVzdDAeFw0xNjA2MTUwMjQ2MzFaFw0xNzA2MTUwMjQ2MzFaME0xCzAJ
BgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZ2hhaTESMBAGA1UECgwJRXNwcmVzc2lm
MRcwFQYDVQQDDA4xOTIuMTY4Ljc3LjIwODCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMIchkjtd/6MxtKy+hcQ2msWIDMj1St4SIUx3yjiv3kWRUQxQIWL
nc/TW5L1DCBdUk6BA/RQYTGya5D8wlN3Cwtc4J0y7HqDktxSgvMVXyVcLFg/GIzL
8kFFf1KPUwB0EgOEnzgeFiY0QTF9hgqFiyucFc8V/lxneQ56jBOJ/whviJdbfJgf
gAngNRSsFT04tcBrw87gqLMEhF9ydPCQfaz+XYse7fhXs4K+j5L1HJwHLuLrQMOn
+nNC6B5NEp8lyYNY03Sq5SfHSMlkEdHL2sWxftOIb6Q3qcf+tgj/mkbNc3At+3hE
NwVX+KYSV28Ll20+2tQlH10NHFpyYPJnX3ECAwEAATANBgkqhkiG9w0BAQsFAAOC
AQEAMzNNwXnhp1OyNinGk700jRfe6zwdkpo1ZkclUD7fVEfnWxBj6j2lXReC6WT1
isWXe/M9k+HS0fK7rTqDumeZYgp/Ui5LKgD2JTvLX91toG7apATWqLM1XPtLEGub
webPO2CW/7aRfkPlXvP4Ss/QbqawxkmUKW3kJ4Lw1mmklu9ULGfiHPPUKvY5Qbe9
9aDC/aTrjiaDmNoToZfAWuFBnxz95bKqFdbij35ZYzyVSNpezePtdOaDBR2mOMYd
P54ENzFbOjVRm3K+7I9S+xa/lUPWnfjVJ026JDw/3/HVWvnwkZI8xNWVOk5CbdPH
7d5Md13cmF1VQ0VNDqvqI3TZ5g==
-----END CERTIFICATE-----

View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICgjCCAWoCAQAwPTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
MRgwFgYDVQQDDA9zZXJ2ZXIudGxzLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDCHIZI7Xf+jMbSsvoXENprFiAzI9UreEiFMd8o4r95FkVEMUCF
i53P01uS9QwgXVJOgQP0UGExsmuQ/MJTdwsLXOCdMux6g5LcUoLzFV8lXCxYPxiM
y/JBRX9Sj1MAdBIDhJ84HhYmNEExfYYKhYsrnBXPFf5cZ3kOeowTif8Ib4iXW3yY
H4AJ4DUUrBU9OLXAa8PO4KizBIRfcnTwkH2s/l2LHu34V7OCvo+S9RycBy7i60DD
p/pzQugeTRKfJcmDWNN0quUnx0jJZBHRy9rFsX7TiG+kN6nH/rYI/5pGzXNwLft4
RDcFV/imEldvC5dtPtrUJR9dDRxacmDyZ19xAgMBAAGgADANBgkqhkiG9w0BAQsF
AAOCAQEAE2xZjAkmVr7/p7LkV3UV3Y0wzeVP7kDBN7VnhNmEMw8xTKwXKsc6z5pY
fa4/lmMMCIJ04dUPIgPC2qiYXJ1AXevLm0A7Blpay6HJilw51NMjhF6SLUkShl6e
k3zyj9LnA5TxijsTrFy/km7qIoo6l7sR7+DwTOIlO/Sj/SDNJn+GAVL153zjxYCy
eBYdEz07kxkeONLUjAW2bV+TkliqTdM6meRpf9GQGQksQrkHrudl7JyyKZTf2m6Z
U33AnUp2SRIXESJmst824LKwkjLMYiXgxRK8ZSSP7iiNBj71DK1vQOZQwEZ2cCjW
/pQxKJnHnRvZ3rityuShtHTUF+C39w==
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwhyGSO13/ozG0rL6FxDaaxYgMyPVK3hIhTHfKOK/eRZFRDFA
hYudz9NbkvUMIF1SToED9FBhMbJrkPzCU3cLC1zgnTLseoOS3FKC8xVfJVwsWD8Y
jMvyQUV/Uo9TAHQSA4SfOB4WJjRBMX2GCoWLK5wVzxX+XGd5DnqME4n/CG+Il1t8
mB+ACeA1FKwVPTi1wGvDzuCoswSEX3J08JB9rP5dix7t+Fezgr6PkvUcnAcu4utA
w6f6c0LoHk0SnyXJg1jTdKrlJ8dIyWQR0cvaxbF+04hvpDepx/62CP+aRs1zcC37
eEQ3BVf4phJXbwuXbT7a1CUfXQ0cWnJg8mdfcQIDAQABAoIBAQCKfl2VFNEjbf/B
fu8Om/iqpOuucSd7z2M2nSGSg02HsEsVX2qgnb+n8y4ICQxw3wSFfGl83Aiss5cp
qB1h/bKEleywXA/7TXrv9XL2ys3K0xvUjpgOhMjApzwzhIz86tObbPlIybaV5XyK
Ofvz79oe8EtjKFcGSNFHckoU+sValzH/gyaeIFuPFlJdsW9MOgN5lcyLDtddg2lr
Z9k+OEEob9BC1dDmc5hxtnClfyiXW1ugjZovOBv79Mq2N8G/V8JZaTHxzEFdOGy3
lUQ1B/s2xPDejQYGddc3N5+wF4ZuGHAYOmcv8IRaMvLdBMPmVnKdgDJeY4HheJY0
z0t4BEYtAoGBAPL1exWZputT8GitBxTJcJB1crMzxvlSplS5mGxM36GgZxf2ql72
8Ufa1hCAQLP7keKPWWl26Bt6Bm4uv/jsB/F8ezMloPvwwQ3nQrN8QY4ihtLLFcvK
OMaErweMEVvQ6GdQHPGow5RqAkYj/X6jJjoAI88uV1yOx+TucmDneEnbAoGBAMyH
04ZR3VNvzHSjDx2wo48FP7Cs/uCynOEd/bRb1I8n+fazIXIlWdWX2drFr2YRM+Uy
UzAadgqFOu3Bvuk64UKwAlxX9jCIm1Ed5O1MUGPj+6OnW1oq/eYIbJ9RlFDyIEBv
Ic+jV/zxojgpP38jpTzn2oC5jWWS+CjHpZNThtujAoGBAOquRB4xNRLLGcWCnPxv
N9PSHuEKeoAKXbApNhomhz1P+0Uidp8UWSvXLj7yI422ysvVO8Crorgnvl5fuf9v
vpx8aWSWTFIP0+riH4PP2mK45xJmKL+Yrg7Ty1225m2R9WsV719ebMzHOTsXOJ1C
aoJL8EsHsEsvf9aanNENxRtRAoGAVIP34zQm2diDytqqX2FjZLENjWse8yi7bMag
1ItxvSoOv2Nr+af3hCx4aE9x2CJZqGbwOxtkFZrSK/b4dZXQCWeDwjbS02FPlOhe
dbQoL+7AR/La69qCCjEG+ZqTSBOVQirp9MwRisMqfjyFMXtAR3ejMbf69rMReoBt
KgDE5DMCgYAkcBd7XyPjR6t09BXAcz8n5J8QCsoY4taNVeCmCCkl8rUt9y8tjQah
5NtBk6i834p5/GbGhI4en/sisVUWzpOgc9G80lUAFQSR3weR6lOL1T+/cy691GqO
wKAWbpOH01fJYmnbUjC7TC2idx033ZA9vJq/s9sNfG2CS2w3egcxag==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,252 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureAxTLS.h>
#include <BSTest.h>
#include <pgmspace.h>
BS_ENV_DECLARE();
void setup()
{
Serial.begin(115200);
Serial.setDebugOutput(true);
BS_RUN(Serial);
}
bool pretest()
{
WiFi.persistent(false);
WiFi.begin(getenv("STA_SSID"), getenv("STA_PASS"));
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
return true;
}
const char* fp = "44 40 9E 34 92 2D E4 61 A4 89 A8 D5 7F 71 B7 62 B3 FD DD E1";
TEST_CASE("HTTP GET & POST requests", "[HTTPClient]")
{
{
// small request
WiFiClient client;
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/");
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "hello!!!");
}
{
// request which returns 8000 bytes
WiFiClient client;
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/data?size=8000");
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
auto len = payload.length();
REQUIRE(len == 8000);
for (size_t i = 0; i < len; ++i) {
if (payload[i] != 'a') {
REQUIRE(false);
}
}
}
{
// can do two POST requests with one HTTPClient object (#1902)
WiFiClient client;
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/");
http.addHeader("Content-Type", "text/plain");
auto httpCode = http.POST("foo");
Serial.println(httpCode);
REQUIRE(httpCode == HTTP_CODE_OK);
http.end();
httpCode = http.POST("bar");
// its not expected to work but should not crash
REQUIRE(httpCode == HTTPC_ERROR_CONNECTION_REFUSED);
http.end();
}
{
// 301 redirect with follow enabled
WiFiClient client;
HTTPClient http;
http.setFollowRedirects(true);
String uri = String("/redirect301?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "redirect success");
}
{
// 301 redirect with follow disabled
WiFiClient client;
HTTPClient http;
String uri = String("/redirect301?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == 301);
}
{
// 302 redirect with follow enabled
WiFiClient client;
HTTPClient http;
http.setFollowRedirects(true);
String uri = String("/redirect302?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "redirect success");
}
{
// 302 redirect with follow disabled
WiFiClient client;
HTTPClient http;
String uri = String("/redirect302?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == 302);
}
{
// 307 redirect with follow enabled
WiFiClient client;
HTTPClient http;
http.setFollowRedirects(true);
String uri = String("/redirect307?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "redirect success");
}
{
// 307 redirect with follow disabled
WiFiClient client;
HTTPClient http;
String uri = String("/redirect307?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == 307);
}
{
// 301 exceeding redirect limit
WiFiClient client;
HTTPClient http;
http.setFollowRedirects(true);
http.setRedirectLimit(0);
String uri = String("/redirect301?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == 301);
}
{
// POST 303 redirect with follow enabled
WiFiClient client;
HTTPClient http;
http.setFollowRedirects(true);
http.begin(client, getenv("SERVER_IP"), 8088, "/redirect303");
auto httpCode = http.POST(getenv("SERVER_IP"));
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "redirect success");
}
{
// POST 303 redirect with follow disabled
WiFiClient client;
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/redirect303");
auto httpCode = http.POST(getenv("SERVER_IP"));
REQUIRE(httpCode == 303);
}
{
// 302 redirect with follow disabled
WiFiClient client;
HTTPClient http;
String uri = String("/redirect302?host=")+getenv("SERVER_IP");
http.begin(client, getenv("SERVER_IP"), 8088, uri.c_str());
auto httpCode = http.GET();
REQUIRE(httpCode == 302);
}
}
TEST_CASE("HTTPS GET request", "[HTTPClient]")
{
//
// Tests with BearSSL
//
{
// small request
BearSSL::WiFiClientSecure client;
client.setFingerprint(fp);
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/", fp);
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "hello!!!");
}
{
// request which returns 4000 bytes
BearSSL::WiFiClientSecure client;
client.setFingerprint(fp);
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/data?size=4000", fp);
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
auto len = payload.length();
REQUIRE(len == 4000);
for (size_t i = 0; i < len; ++i) {
if (payload[i] != 'a') {
REQUIRE(false);
}
}
}
//
// Same tests with axTLS
//
#if !CORE_MOCK
{
// small request
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
axTLS::WiFiClientSecure client;
#pragma GCC diagnostic pop
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/", fp);
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
REQUIRE(payload == "hello!!!");
}
{
// request which returns 4000 bytes
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
axTLS::WiFiClientSecure client;
#pragma GCC diagnostic pop
HTTPClient http;
http.begin(client, getenv("SERVER_IP"), 8088, "/data?size=4000", fp);
auto httpCode = http.GET();
REQUIRE(httpCode == HTTP_CODE_OK);
String payload = http.getString();
auto len = payload.length();
REQUIRE(len == 4000);
for (size_t i = 0; i < len; ++i) {
if (payload[i] != 'a') {
REQUIRE(false);
}
}
}
#endif
}
void loop()
{
}

View File

@ -0,0 +1,91 @@
from mock_decorators import setup, teardown
from flask import Flask, request, redirect
from threading import Thread
import urllib
import os
import ssl
import time
@setup('HTTP GET & POST requests')
def setup_http_get(e):
app = Flask(__name__)
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
@app.route('/shutdown')
def shutdown():
shutdown_server()
return 'Server shutting down...'
@app.route("/", methods = ['GET', 'POST'])
def root():
print('Got data: ' + request.data.decode());
return 'hello!!!'
@app.route("/data")
def get_data():
size = int(request.args['size'])
return 'a'*size
@app.route("/target")
def target():
return "redirect success"
@app.route("/redirect301")
def redirect301():
return redirect("http://{}:8088/target".format(request.args['host']), code=301)
@app.route("/redirect302")
def redirect302():
return redirect("http://{}:8088/target".format(request.args['host']), code=302)
@app.route("/redirect303", methods = ['POST'])
def redirect303():
return redirect("http://{}:8088/target".format(request.data.decode()), code=303)
@app.route("/redirect307")
def redirect307():
return redirect("http://{}:8088/target".format(request.args['host']), code=307)
def flaskThread():
app.run(host='0.0.0.0', port=8088)
th = Thread(target=flaskThread)
th.start()
@teardown('HTTP GET & POST requests')
def teardown_http_get(e):
response = urllib.request.urlopen('http://localhost:8088/shutdown')
html = response.read()
time.sleep(1) # avoid address in use error on macOS
@setup('HTTPS GET request')
def setup_http_get(e):
app = Flask(__name__)
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
@app.route('/shutdown')
def shutdown():
shutdown_server()
return 'Server shutting down...'
@app.route("/")
def root():
return 'hello!!!'
@app.route("/data")
def get_data():
size = int(request.args['size'])
return 'a'*size
def flaskThread():
p = os.path.dirname(os.path.abspath(__file__))
context = (p + '/server.crt', p + '/server.key')
print(context)
app.run(host='0.0.0.0', port=8088, ssl_context=context)
th = Thread(target=flaskThread)
th.start()
@teardown('HTTPS GET request')
def teardown_http_get(e):
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
p = os.path.dirname(os.path.abspath(__file__))
response = urllib.request.urlopen('https://localhost:8088/shutdown', context=ctx)
html = response.read()