Complete upstream transport integration and regression coverage
This commit is contained in:
1 parent
4d34448602
commit
439dc7da3c
10 files changed
+124
-3
No files matched your search
@@ -82,6 +82,7 @@ jobs:
|
||||
sudo apt-get install -y libssl-dev
|
||||
python3 -B test/test_companion_tx_routing.py -v
|
||||
python3 -B test/test_companion_discovery.py -v
|
||||
python3 -B test/test_pico_ble_queues.py -v
|
||||
python3 -B test/test_companion_preferences_transaction.py -v
|
||||
python3 -B test/test_companion_radio_settings_transaction.py -v
|
||||
python3 -B test/test_companion_prefs_transactions.py -v
|
||||
|
||||
@@ -6841,6 +6841,13 @@ bool MyMesh::applyAndSaveBluetoothMac(const char* value, char* reply,
|
||||
mode = mesh::companion::BLUETOOTH_MAC_CUSTOM;
|
||||
}
|
||||
|
||||
#if defined(RP2040_PLATFORM)
|
||||
if (mode != mesh::companion::BLUETOOTH_MAC_DEFAULT) {
|
||||
snprintf(reply, reply_size, "Error: Bluetooth address overrides are not supported on Pico W");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!saveBluetoothMac(mode, address)) {
|
||||
snprintf(reply, reply_size, "Error: Bluetooth MAC save failed");
|
||||
return false;
|
||||
@@ -6913,6 +6920,13 @@ bool MyMesh::applyAndSaveBluetoothStealth(const char* value, char* reply,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(RP2040_PLATFORM)
|
||||
if (strcmp(value, "on") == 0) {
|
||||
snprintf(reply, reply_size, "Error: Bluetooth stealth is not supported on Pico W");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint8_t previous_mode = _prefs.bluetooth_stealth_mode;
|
||||
const uint8_t previous_type = _prefs.bluetooth_stealth_peer_type;
|
||||
uint8_t previous_peer[mesh::companion::BLUETOOTH_MAC_BYTES];
|
||||
|
||||
@@ -2799,7 +2799,7 @@ void setup() {
|
||||
#endif
|
||||
|
||||
// Load WiFi credentials without starting the radio.
|
||||
#ifdef WIFI_SSID
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
loadCompanionWiFiCredentials();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@ lib_deps = ${arduino_base.lib_deps}
|
||||
ricmoo/QRCode @ 0.0.1
|
||||
build_src_filter = ${arduino_base.build_src_filter}
|
||||
+<helpers/ui/DisplayDriver.cpp>
|
||||
; Shared WiFi transport moved out of esp32/ upstream. Keep it available to
|
||||
; this fork's WiFi/MQTT and synthesized Full profiles as well.
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/esp32/WebConfigServer.cpp>
|
||||
+<helpers/esp32/PortableErrorStrings.cpp>
|
||||
+<helpers/esp32/WiFiOtaSeeder.cpp>
|
||||
|
||||
@@ -172,9 +172,20 @@ bool SerialBLEInterface::isConnected() const {
|
||||
}
|
||||
|
||||
bool SerialBLEInterface::isWriteBusy() const {
|
||||
BluetoothLock lock;
|
||||
return send_queue_len >= (FRAME_QUEUE_SIZE * 2 / 3);
|
||||
}
|
||||
|
||||
bool SerialBLEInterface::isReadBusy() const {
|
||||
BluetoothLock lock;
|
||||
return recv_queue_len > 0;
|
||||
}
|
||||
|
||||
bool SerialBLEInterface::hasPendingIO() const {
|
||||
BluetoothLock lock;
|
||||
return recv_queue_len > 0 || send_queue_len > 0 || _tx_pending;
|
||||
}
|
||||
|
||||
size_t SerialBLEInterface::writeFrame(const uint8_t src[], size_t len) {
|
||||
if (len == 0 || len > MAX_FRAME_SIZE) {
|
||||
BLE_DEBUG_PRINTLN("writeFrame(), frame too big, len=%u", (unsigned)len);
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
/**
|
||||
* init the BLE interface.
|
||||
* @param prefix a prefix for the device name
|
||||
* @param name IN/OUT - a name for the device (combined with prefix). If "@@MAC", is modified and returned
|
||||
* @param name a name for the device (combined with prefix), or "@@MAC"
|
||||
* @param pin_code the BLE security pin
|
||||
*/
|
||||
bool begin(const char* prefix, const char* name, uint32_t pin_code,
|
||||
@@ -70,7 +70,9 @@ public:
|
||||
void disable() override;
|
||||
bool isEnabled() const override { return _isEnabled; }
|
||||
bool isConnected() const override;
|
||||
bool isReadBusy() const override;
|
||||
bool isWriteBusy() const override;
|
||||
bool hasPendingIO() const override;
|
||||
size_t writeFrame(const uint8_t src[], size_t len) override;
|
||||
size_t checkRecvFrame(uint8_t dest[]) override;
|
||||
};
|
||||
|
||||
@@ -41,6 +41,23 @@ class BluetoothMacContractTests(unittest.TestCase):
|
||||
self.nrf_source,
|
||||
)
|
||||
|
||||
def test_pico_rejects_unsupported_identity_policies_before_saving(self):
|
||||
pico = source("src/helpers/rp2040/SerialBLEInterface.cpp")
|
||||
self.assertIn(
|
||||
"if (custom_address || clear_bonds || stealth_pair_once || bonded_only_peer) return false;",
|
||||
pico,
|
||||
)
|
||||
mac = self.mesh[self.mesh.index("bool MyMesh::applyAndSaveBluetoothMac("):
|
||||
self.mesh.index("void MyMesh::formatBluetoothMacStatus(")]
|
||||
self.assertLess(mac.index("#if defined(RP2040_PLATFORM)"),
|
||||
mac.index("saveBluetoothMac(mode, address)"))
|
||||
self.assertIn("mode != mesh::companion::BLUETOOTH_MAC_DEFAULT", mac)
|
||||
stealth = self.mesh[self.mesh.index("bool MyMesh::applyAndSaveBluetoothStealth("):
|
||||
self.mesh.index("void MyMesh::formatBluetoothStealthStatus(")]
|
||||
self.assertLess(stealth.index("#if defined(RP2040_PLATFORM)"),
|
||||
stealth.index("setCompanionBluetoothStealth(_prefs,"))
|
||||
self.assertIn('if (strcmp(value, "on") == 0)', stealth)
|
||||
|
||||
def test_esp32_supports_nimble_and_bluedroid(self):
|
||||
self.assertIn("BLEDevice::setOwnAddr(native_address)", self.esp_source)
|
||||
self.assertIn("BLEDevice::setOwnAddrType(BLE_OWN_ADDR_RANDOM)", self.esp_source)
|
||||
|
||||
@@ -191,7 +191,9 @@ int main() {
|
||||
enum_start = ui.index(" enum HomePage {")
|
||||
enum = ui[enum_start : ui.index("\n };", enum_start)]
|
||||
self.assertIn(
|
||||
"#if UI_WIFI_SETUP_HOME_PAGE == 1\n WIFI_SETUP,\n#endif\n Count",
|
||||
"#if UI_WIFI_SETUP_HOME_PAGE == 1\n WIFI_SETUP,\n#endif\n"
|
||||
"#if !(defined(UI_NO_DISCOVER_SCREEN) && (UI_NO_DISCOVER_SCREEN + 0 != 0))\n"
|
||||
" DISCOVERY,\n#endif\n Count",
|
||||
enum,
|
||||
)
|
||||
self.assertIn("_page == HomePage::WIFI_SETUP", ui)
|
||||
|
||||
@@ -156,6 +156,17 @@ TEST(MQTTPresets, WcmeshIsJwtWithIsrgRootX1) {
|
||||
EXPECT_FALSE(mqttPresetUsesDevicePubkeyUsername(p));
|
||||
}
|
||||
|
||||
TEST(MQTTPresets, BsmeshIsJwtWithIsrgRootX1) {
|
||||
const MQTTPresetDef* p = findMQTTPreset("bsmesh");
|
||||
ASSERT_NE(nullptr, p);
|
||||
EXPECT_EQ(MQTT_AUTH_JWT, p->auth_type);
|
||||
EXPECT_EQ(MQTT_TOPIC_MESHCORE, p->topic_style);
|
||||
EXPECT_STREQ("wss://mqtt.bsmesh.de:8885", p->server_url);
|
||||
EXPECT_STREQ("mqtt.bsmesh.de", p->jwt_audience);
|
||||
EXPECT_EQ(ISRG_ROOT_X1, p->ca_cert);
|
||||
EXPECT_FALSE(mqttPresetNeedsSlotCredentials(p));
|
||||
}
|
||||
|
||||
// ---- slot count constants -------------------------------------------------
|
||||
|
||||
TEST(MQTTPresets, SlotCountsAreSane) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
"""Execute Pico W's production queue predicates used by companion sleep control."""
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from test_radio_receive_contract import method
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
class PicoBleQueueTests(unittest.TestCase):
|
||||
def test_pending_frames_keep_the_transport_awake_below_high_water(self):
|
||||
source = (ROOT / 'src/helpers/rp2040/SerialBLEInterface.cpp').read_text()
|
||||
methods = '\n'.join(method(source, 'bool SerialBLEInterface::' + name + '() const')
|
||||
for name in ('isReadBusy', 'isWriteBusy', 'hasPendingIO'))
|
||||
code = r'''
|
||||
#include <cassert>
|
||||
#define FRAME_QUEUE_SIZE 8
|
||||
static int locks = 0;
|
||||
struct BluetoothLock {
|
||||
BluetoothLock() { ++locks; }
|
||||
~BluetoothLock() { --locks; }
|
||||
};
|
||||
struct SerialBLEInterface {
|
||||
unsigned recv_queue_len = 0, send_queue_len = 0;
|
||||
bool _tx_pending = false;
|
||||
bool isReadBusy() const;
|
||||
bool isWriteBusy() const;
|
||||
bool hasPendingIO() const;
|
||||
};
|
||||
@METHODS@
|
||||
int main() {
|
||||
SerialBLEInterface transport;
|
||||
for (unsigned rx = 0; rx <= FRAME_QUEUE_SIZE; ++rx) {
|
||||
for (unsigned tx = 0; tx <= FRAME_QUEUE_SIZE; ++tx) {
|
||||
for (unsigned pending = 0; pending <= 1; ++pending) {
|
||||
transport.recv_queue_len = rx;
|
||||
transport.send_queue_len = tx;
|
||||
transport._tx_pending = pending;
|
||||
assert(transport.isReadBusy() == (rx != 0));
|
||||
assert(transport.isWriteBusy() == (tx >= 5));
|
||||
assert(transport.hasPendingIO() == (rx || tx || pending));
|
||||
assert(locks == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'''.replace('@METHODS@', methods)
|
||||
for name in ('isReadBusy', 'isWriteBusy', 'hasPendingIO'):
|
||||
self.assertIn('BluetoothLock lock;', method(source, 'bool SerialBLEInterface::' + name))
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory)
|
||||
(path / 'test.cpp').write_text(code)
|
||||
subprocess.run(['g++', '-std=c++17', '-fsanitize=address,undefined',
|
||||
'-fno-pie', '-no-pie', str(path / 'test.cpp'), '-o', str(path / 'test')], check=True)
|
||||
subprocess.run([str(path / 'test')], check=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user