Add a saved override to keep USB packet logging continuous
This commit is contained in:
1 parent
1f2fcfc449
commit
05679aa741
18 files changed
+382
-39
No files matched your search
@@ -59,9 +59,9 @@ class TestFS : public MemoryFS {
|
||||
@CONSTANTS@
|
||||
namespace mesh {
|
||||
struct RadioProfiles { static constexpr unsigned MaxPreamble = 65535; };
|
||||
static bool usb_logging = true, usb_debug = false;
|
||||
static bool usb_logging = true, usb_debug = false, usb_always = false;
|
||||
static bool prohibit_stale_debug = false;
|
||||
static unsigned usb_updates = 0, debug_updates = 0;
|
||||
static unsigned usb_updates = 0, debug_updates = 0, always_updates = 0;
|
||||
void setUsbLoggingEnabled(bool enabled) {
|
||||
if (enabled && prohibit_stale_debug) assert(!usb_debug);
|
||||
usb_logging = enabled; ++usb_updates;
|
||||
@@ -69,6 +69,8 @@ void setUsbLoggingEnabled(bool enabled) {
|
||||
void setUsbDebugEnabled(bool enabled) { usb_debug = enabled; ++debug_updates; }
|
||||
bool isUsbLoggingEnabled() { return usb_logging; }
|
||||
void resumeUsbPacketLogging() {}
|
||||
void setUsbPacketLoggingAlways(bool enabled) { usb_always = enabled; ++always_updates; }
|
||||
bool isUsbPacketLoggingAlways() { return usb_always; }
|
||||
bool isUsbDebugEnabled() { return usb_debug; }
|
||||
bool isUsbDebugLoggingEnabled() { return usb_logging && usb_debug; }
|
||||
}
|
||||
@@ -182,6 +184,7 @@ int main() {
|
||||
assert(baseline[gps_offset] == 0 && baseline[gps_offset + 1] == 0);
|
||||
assert(baseline[trace_offset] == 0);
|
||||
assert(baseline[873] == 0); // OTA channel follows the established tail.
|
||||
assert(baseline[123] == 0); // Reserved legacy byte keeps continuous logging OFF.
|
||||
Capture capture;
|
||||
assert(writeCommonPrefsImage(capture, &cli.prefs));
|
||||
assert(capture.bytes == baseline); // Checked and ordinary writers agree.
|
||||
@@ -295,6 +298,100 @@ int main() {
|
||||
cli.prefs.usb_debug_enabled = 1;
|
||||
cli.loadPrefsInt(&cli.fs, "/missing");
|
||||
assert(cli.prefs.usb_debug_enabled == 0);
|
||||
|
||||
// Continuous capture has its own saved policy; changing it must not alter
|
||||
// the master/debug gates, any established offset, or the optional tail.
|
||||
CommonCLI policy;
|
||||
mesh::setUsbDebugEnabled(false);
|
||||
mesh::setUsbLoggingEnabled(true);
|
||||
mesh::setUsbPacketLoggingAlways(false);
|
||||
assert(policy.prefs.usb_logging_always == 0);
|
||||
policy.savePrefs(&policy.fs, PrefsSaveRouting::Scope::Common);
|
||||
const auto policy_off = policy.fs.files["/com_prefs"];
|
||||
assert(policy_off == baseline);
|
||||
policy.get("usb.logging.always", reply);
|
||||
assert(strcmp(reply, "> off") == 0);
|
||||
policy.set("usb.logging.always on", reply);
|
||||
assert(strcmp(reply, "OK - USB logging always on (saved)") == 0);
|
||||
assert(policy.prefs.usb_logging_always == 1 && mesh::isUsbPacketLoggingAlways());
|
||||
assert(mesh::isUsbLoggingEnabled() && !mesh::isUsbDebugEnabled());
|
||||
auto policy_on = policy.fs.files["/com_prefs"];
|
||||
auto expected_on = policy_off;
|
||||
expected_on[123] = 0xA1;
|
||||
assert(policy_on == expected_on && policy_on.size() == baseline.size());
|
||||
capture.bytes.clear();
|
||||
assert(writeCommonPrefsImage(capture, &policy.prefs) && capture.bytes == policy_on);
|
||||
policy.get("usb.logging.always", reply);
|
||||
assert(strcmp(reply, "> on") == 0);
|
||||
for (const char* command : {"usb.logging.always", "usb.logging.always true",
|
||||
"usb.logging.always 1", "usb.logging.always ON", "usb.logging.always off junk",
|
||||
"usb.logging.always off ", "usb.logging.always on reboot", "usb.logging.always off reboot"}) {
|
||||
const unsigned updates = mesh::always_updates;
|
||||
policy.set(command, reply);
|
||||
assert(strcmp(reply, "Error: usage set usb.logging.always on|off") == 0);
|
||||
assert(policy.prefs.usb_logging_always == 1 && mesh::isUsbPacketLoggingAlways());
|
||||
assert(mesh::always_updates == updates && policy.fs.files["/com_prefs"] == policy_on);
|
||||
}
|
||||
policy.set("usb.logging.alwaysfake off", reply);
|
||||
assert(strcmp(reply, "unknown") == 0);
|
||||
policy.get("usb.logging.alwaysfake", reply);
|
||||
assert(strcmp(reply, "unknown") == 0);
|
||||
policy.set("usb.logging.always\t \toff", reply);
|
||||
assert(strcmp(reply, "OK - USB logging always off (saved)") == 0);
|
||||
assert(!policy.prefs.usb_logging_always && !mesh::isUsbPacketLoggingAlways());
|
||||
assert(policy.fs.files["/com_prefs"] == policy_off);
|
||||
for (int fault : {0, 1, 2, 3}) {
|
||||
if (fault == 0) policy.fs.fail_write = true;
|
||||
if (fault == 1) policy.fs.fail_write_after = 123;
|
||||
if (fault == 2) policy.fs.fail_read_open = true;
|
||||
if (fault == 3) policy.fs.fail_rename = 1;
|
||||
const unsigned updates = mesh::always_updates;
|
||||
policy.set("usb.logging.always on", reply);
|
||||
assert(strcmp(reply, "Error: save unconfirmed; reboot may differ") == 0);
|
||||
assert(policy.prefs.usb_logging_always == 0 && !mesh::isUsbPacketLoggingAlways());
|
||||
assert(mesh::always_updates == updates && policy.fs.files["/com_prefs"] == policy_off);
|
||||
policy.fs.fail_write = false; policy.fs.fail_write_after = -1;
|
||||
policy.fs.fail_read_open = false; policy.fs.fail_rename = 0;
|
||||
}
|
||||
BridgePrefs policy_schema(&policy.prefs);
|
||||
assert(policy_schema.import("usb_always", 1));
|
||||
assert(*policy_schema.bytes.at("usb_always") == 1); // Export ordinary 0/1, not the wire marker.
|
||||
assert(!mesh::isUsbPacketLoggingAlways());
|
||||
const unsigned before_import = mesh::always_updates;
|
||||
policy.savePrefs(&policy.fs, PrefsSaveRouting::Scope::Observer);
|
||||
assert(!mesh::isUsbPacketLoggingAlways() && mesh::always_updates == before_import);
|
||||
assert(policy.fs.files["/com_prefs"] == policy_off);
|
||||
policy.fs.fail_write = true;
|
||||
policy.savePrefs(&policy.fs, PrefsSaveRouting::Scope::Common);
|
||||
assert(!policy._common_save_succeeded && !mesh::isUsbPacketLoggingAlways());
|
||||
policy.fs.fail_write = false;
|
||||
policy.savePrefs(&policy.fs, PrefsSaveRouting::Scope::Common);
|
||||
assert(policy._common_save_succeeded && mesh::isUsbPacketLoggingAlways());
|
||||
assert(policy.fs.files["/com_prefs"] == policy_on);
|
||||
for (uint8_t invalid : {2, 161, 255}) {
|
||||
assert(policy_schema.import("usb_always", invalid));
|
||||
policy.savePrefs(&policy.fs, PrefsSaveRouting::Scope::Common);
|
||||
assert(policy._common_save_succeeded && !mesh::isUsbPacketLoggingAlways());
|
||||
assert(policy.prefs.usb_logging_always == 0 && policy.fs.files["/com_prefs"] == policy_off);
|
||||
}
|
||||
// Old padding (including1/FF) cannot opt in, and neither a missing file nor
|
||||
// a truncated core may retain an ON policy from a previous image.
|
||||
for (uint8_t stored : {0, 1, 0xA0, 0xA1, 0xA2, 255}) {
|
||||
auto image = policy_off; image[123] = stored;
|
||||
policy.fs.files["/com_prefs"] = image;
|
||||
policy.prefs.usb_logging_always = 1;
|
||||
policy.loadPrefsInt(&policy.fs, "/com_prefs");
|
||||
assert(policy.prefs.usb_logging_always == (stored == 0xA1 ? 1 : 0));
|
||||
}
|
||||
for (size_t size : {size_t(0), size_t(123), size_t(124), size_t(289), size_t(290)}) {
|
||||
policy.fs.files["/com_prefs"] = {policy_off.begin(), policy_off.begin() + size};
|
||||
policy.prefs.usb_logging_always = 1;
|
||||
policy.loadPrefsInt(&policy.fs, "/com_prefs");
|
||||
assert(policy.prefs.usb_logging_always == 0);
|
||||
}
|
||||
policy.prefs.usb_logging_always = 1;
|
||||
policy.loadPrefsInt(&policy.fs, "/missing");
|
||||
assert(policy.prefs.usb_logging_always == 0);
|
||||
}
|
||||
'''
|
||||
|
||||
@@ -325,7 +422,8 @@ class CommonUsbDebugTest(unittest.TestCase):
|
||||
'void CommonCLI::savePrefs(FILESYSTEM*',
|
||||
'void CommonCLI::savePrefs(PrefsSaveRouting::Scope scope)',
|
||||
'bool CommonCLI::trySavePrefs(', 'void CommonCLI::loadPrefsInt('))
|
||||
code = HARNESS
|
||||
code = HARNESS.replace('@SET_DEBUG@', '@SET_ALWAYS@\n @SET_DEBUG@').replace(
|
||||
'@GET_DEBUG@', '@GET_ALWAYS@\n @GET_DEBUG@')
|
||||
for key, value in {
|
||||
'FIELDS': fields, 'CONSTANTS': constants, 'HELPERS': helpers,
|
||||
'LEGACY': extract_braced(header, 'struct LegacyObserverTail') + ';',
|
||||
@@ -334,6 +432,8 @@ class CommonUsbDebugTest(unittest.TestCase):
|
||||
'STORE': extract_braced(source, 'class CommonPrefsFileStore'),
|
||||
'METHODS': ("\n#include <stddef.h>\ntemplate<typename Writer>\n" + extract_braced(source, "static void writeCommonRetryPrefs(") + "\n" + methods),
|
||||
'DYNAMIC': extract_braced(header, 'class BridgePrefs :'),
|
||||
'SET_ALWAYS': extract_braced(source, 'if (strncmp(config, "usb.logging.always", 18)'),
|
||||
'GET_ALWAYS': extract_braced(source, 'if (strcmp(config, "usb.logging.always") == 0)'),
|
||||
'SET_DEBUG': extract_braced(source, 'if (strncmp(config, "usb.debug", 9)'),
|
||||
'SET_MASTER': extract_braced(source, 'if (strncmp(config, "usb.logging", 11)'),
|
||||
'GET_DEBUG': extract_braced(source, 'if (strcmp(config, "usb.debug") == 0)'),
|
||||
@@ -371,8 +471,10 @@ class CommonUsbDebugTest(unittest.TestCase):
|
||||
source = (ROOT / 'src/helpers/CommonCLI.cpp').read_text(encoding='utf-8')
|
||||
load = extract_braced(source, 'void CommonCLI::loadPrefs(FILESYSTEM*')
|
||||
self.assertIn('_prefs->usb_debug_enabled = 0;', load)
|
||||
self.assertIn('_prefs->usb_logging_always = 0;', load)
|
||||
self.assertIn('mesh::setUsbLoggingEnabled(_prefs->usb_logging_enabled != 0);', load)
|
||||
self.assertIn('mesh::setUsbDebugEnabled(_prefs->usb_debug_enabled != 0);', load)
|
||||
self.assertIn('mesh::setUsbPacketLoggingAlways(_prefs->usb_logging_always != 0);', load)
|
||||
self.assertLess(load.index('mesh::setUsbDebugEnabled('),
|
||||
load.index('mesh::setUsbLoggingEnabled('))
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ bool isUsbLoggingEnabled(){return logging;}
|
||||
bool isUsbDebugLoggingEnabled(){return false;}
|
||||
void setPlatformDebugOutputEnabled(bool){}
|
||||
void setUsbDebugEnabled(bool){}
|
||||
void setUsbPacketLoggingAlways(bool){}
|
||||
void setUsbLoggingEnabled(bool enabled){logging=enabled;usb_logging_preference_known=true;}
|
||||
bool saveUsbLoggingBootPreference(bool){return true;}
|
||||
unsigned packet_logging_resumes=0;
|
||||
@@ -190,7 +191,7 @@ class CompanionPacketStreamTests(unittest.TestCase):
|
||||
start = mesh.index(' if (strcmp(command, "get usb.logging") == 0)')
|
||||
end = mesh.index('\n#endif', start)
|
||||
boot_start = mesh.index(' const bool usb_logging_enabled = _prefs.usb_logging_enabled != 0;')
|
||||
boot_end = mesh.index('\n#endif', boot_start)
|
||||
boot_end = mesh.index(' if (!mesh::saveUsbLoggingBootPreference(', boot_start)
|
||||
normalize = next(line for line in mesh.splitlines()
|
||||
if '_prefs.usb_logging_enabled = constrain(' in line)
|
||||
code = MODE_HARNESS.replace('@USB_FUNCTIONS@', functions)
|
||||
|
||||
@@ -14,7 +14,7 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||
# and the class's in-memory member order or padding. None represents reserved
|
||||
# padding; compact Wio Companion claims the single byte at wire offset 79.
|
||||
WIRE_FIELDS = (
|
||||
('airtime_factor', 4), ('node_name', 32), (None, 4),
|
||||
('airtime_factor', 4), ('node_name', 32), ('usb_logging_always', 4),
|
||||
('@lat', 8), ('@lon', 8), ('freq', 4), ('sf', 1), ('cr', 1),
|
||||
('client_repeat', 1), ('manual_add_contacts', 1), ('bw', 4),
|
||||
('tx_power_dbm', 1), ('telemetry_mode_base', 1), ('telemetry_mode_loc', 1),
|
||||
@@ -62,6 +62,7 @@ static void seed(CompanionNodePrefs& prefs, uint32_t& random) {
|
||||
}
|
||||
};
|
||||
@SEED@
|
||||
prefs.usb_logging_always = random & 1;
|
||||
prefs.tx_media = random % 5;
|
||||
prefs.tx_ssh = (random >> 8) % 5;
|
||||
#if defined(RAK_4631)
|
||||
@@ -148,22 +149,21 @@ int main() {
|
||||
#endif
|
||||
DataStore reference;
|
||||
assert(reference.savePrefsLegacy(prefs, 47.125, -122.25));
|
||||
#if defined(WIO_E5_MINI_HEADLESS_COMPANION_UI)
|
||||
// The compact target claims exactly the former reserved byte. Its frozen
|
||||
// predecessor still emits zero there; every other byte stays identical.
|
||||
// The predecessor emitted zero at the newly claimed reserved bytes.
|
||||
auto historical = store.fs.files.at("/new_prefs");
|
||||
assert(historical[36] == (prefs.usb_logging_always == 1 ? 0xa1 : 0));
|
||||
historical[36] = 0;
|
||||
#if defined(WIO_E5_MINI_HEADLESS_COMPANION_UI)
|
||||
assert(historical[79] == prefs.leds_quiet);
|
||||
historical[79] = 0;
|
||||
assert(reference.fs.files.at("/new_prefs") == historical);
|
||||
#else
|
||||
assert(reference.fs.files.at("/new_prefs") == store.fs.files.at("/new_prefs"));
|
||||
#endif
|
||||
assert(reference.fs.files.at("/new_prefs") == historical);
|
||||
++comparisons;
|
||||
}
|
||||
|
||||
CompanionNodePrefs original;
|
||||
assert(original.buzzer_quiet == 1 && original.vibe_quiet == 0);
|
||||
assert(original.lost_reply == 0);
|
||||
assert(original.lost_reply == 0 && original.usb_logging_always == 0);
|
||||
assert(original.tx_media == mesh::RADIO_TX_AUTO && original.tx_ssh == mesh::RADIO_TX_AUTO);
|
||||
strcpy(original.node_name, "durable image");
|
||||
original.freq = 915.25f; original.ble_pin = 123456;
|
||||
@@ -324,6 +324,7 @@ int main() {
|
||||
changed.freq = 910.5f; changed.usb_debug_enabled = 0;
|
||||
changed.gps_sync_interval_hours = 24;
|
||||
changed.lost_reply = 1;
|
||||
changed.usb_logging_always = 1;
|
||||
#if defined(WIO_E5_MINI_HEADLESS_COMPANION_UI)
|
||||
changed.leds_quiet = 0;
|
||||
#endif
|
||||
@@ -465,6 +466,7 @@ int main() {
|
||||
assert(loaded.gps_sync_interval_hours == 24 && loaded.usb_debug_enabled == 0);
|
||||
assert(loaded.lost_reply == 1);
|
||||
assert(loaded.tx_media == original.tx_media && loaded.tx_ssh == original.tx_ssh);
|
||||
assert(loaded.usb_logging_always == 1);
|
||||
assert(lat == 42.25 && lon == -121.125);
|
||||
|
||||
#if defined(STM32_PLATFORM)
|
||||
@@ -531,6 +533,12 @@ def field_code(rows, seed=False):
|
||||
if not seed:
|
||||
result.append('#else\nbytes.push_back(0);')
|
||||
result.append('#endif')
|
||||
elif name == 'usb_logging_always':
|
||||
if seed:
|
||||
result.append('fill(&prefs.usb_logging_always, sizeof(prefs.usb_logging_always));')
|
||||
else:
|
||||
result.append('bytes.push_back(prefs.usb_logging_always == 1 ? 0xa1 : 0);')
|
||||
result.append('bytes.insert(bytes.end(), 3, uint8_t(0));')
|
||||
elif name == 'tz_offset':
|
||||
if seed:
|
||||
result.append('prefs.tz_offset = float(int(random % 27) - 12);')
|
||||
|
||||
@@ -30,8 +30,10 @@ struct ConfigText : Stream {
|
||||
}
|
||||
};
|
||||
namespace mesh {
|
||||
bool logging_enabled=true, debug_enabled=false;
|
||||
unsigned debug_applies=0;
|
||||
bool logging_enabled=true, debug_enabled=false, always_enabled=false;
|
||||
unsigned debug_applies=0, always_applies=0;
|
||||
bool isUsbPacketLoggingAlways(){return always_enabled;}
|
||||
void setUsbPacketLoggingAlways(bool enabled){always_enabled=enabled;++always_applies;}
|
||||
bool isUsbLoggingEnabled(){return logging_enabled;}
|
||||
bool isUsbDebugEnabled(){return debug_enabled;}
|
||||
void setUsbDebugEnabled(bool enabled){debug_enabled=enabled;++debug_applies;}
|
||||
@@ -177,6 +179,61 @@ int main(){
|
||||
// Bounded replies do not write beyond their supplied capacity.
|
||||
char small[9];memset(small,'X',sizeof(small));
|
||||
assert(node.command("get usb.debug",small,8));assert(small[7]==0&&small[8]=='X');
|
||||
// The always-log policy uses only reserved byte 36, preserving all image sizes.
|
||||
assert(node._prefs.usb_logging_always==0&&!mesh::always_enabled);
|
||||
mesh::logging_enabled=false;
|
||||
assert(node.command("set usb.logging.always on",reply,sizeof(reply)));
|
||||
assert(node._prefs.usb_logging_always==1&&mesh::always_enabled&&!mesh::logging_enabled);
|
||||
const auto always_disk=node.store.fs.files["/new_prefs"];
|
||||
assert(always_disk[36]==0xa1&&always_disk[37]==0&&always_disk[38]==0
|
||||
&&always_disk[39]==0&&always_disk[79]==0);
|
||||
assert(node.command("get usb.logging.always",reply,sizeof(reply)));
|
||||
assert(!strcmp(reply,"usb.logging.always on"));
|
||||
for(const char* invalid : {"", "ON", "true", "1", "on extra", "on ", "off reboot"}) {
|
||||
std::string command=std::string("set usb.logging.always ")+invalid;
|
||||
const unsigned applied=mesh::always_applies;
|
||||
assert(node.command(command.c_str(),reply,sizeof(reply))&&strstr(reply,"Error:"));
|
||||
assert(node._prefs.usb_logging_always==1&&mesh::always_enabled);
|
||||
assert(mesh::always_applies==applied&&node.store.fs.files["/new_prefs"]==always_disk);
|
||||
}
|
||||
for(int fail_after : {17,36,int(always_disk.size()-1)}) {
|
||||
node.store.fs.fail_write_after=fail_after;
|
||||
const unsigned applied=mesh::always_applies;
|
||||
assert(node.command("set usb.logging.always off",reply,sizeof(reply)));
|
||||
assert(strstr(reply,"could not be saved")&&node._prefs.usb_logging_always==1);
|
||||
assert(mesh::always_enabled&&mesh::always_applies==applied);
|
||||
assert(node.store.fs.files["/new_prefs"]==always_disk);
|
||||
}
|
||||
node.store.fs.fail_write_after=-1;
|
||||
assert(node.command("set usb.logging.always off",reply,sizeof(reply)));
|
||||
assert(!node._prefs.usb_logging_always&&!mesh::always_enabled&&!mesh::logging_enabled);
|
||||
const auto quiet_disk=node.store.fs.files["/new_prefs"];
|
||||
assert(quiet_disk.size()==always_disk.size());
|
||||
for(size_t i=0;i<quiet_disk.size();++i)
|
||||
assert(quiet_disk[i]==(i==36?0:always_disk[i]));
|
||||
// Only the marker opts in. Historic zero padding and arbitrary padding stay off.
|
||||
for(uint8_t marker : {0,1,2,0xa0,0xa1,0xff}) {
|
||||
DataStore reload;reload.fs.files["/new_prefs"]=always_disk;
|
||||
reload.fs.files["/new_prefs"][36]=marker;
|
||||
CompanionNodePrefs loaded;loaded.usb_logging_always=1;
|
||||
double lat=0,lon=0;assert(reload.loadPrefs(loaded,lat,lon));
|
||||
assert(loaded.usb_logging_always==(marker==0xa1));
|
||||
assert(loaded.ble_pin==876543&&loaded.freq==910.525f);
|
||||
}
|
||||
assert(node._prefs.getCustom()->setByKey("usb_log_always","1"));
|
||||
assert(!node._prefs.getRadioPrefs()->setByKey("usb_log_always","2"));
|
||||
assert(node.savePrefs()&&mesh::always_enabled);
|
||||
assert(node._prefs.getCustom()->getByKey("usb_log_always",dynamic,sizeof(dynamic)));
|
||||
assert(!strcmp(dynamic,"1"));
|
||||
ConfigText policy_import;policy_import.text="{usb_log_always:0}";
|
||||
assert(serializer->loadSerial(policy_import)&&node._prefs.usb_logging_always==0);
|
||||
assert(node.savePrefs()&&!mesh::always_enabled);
|
||||
ConfigText policy_export;assert(node._prefs.getRadioPrefs()->saveSerial(policy_export));
|
||||
assert(policy_export.text.find("usb_log_always:0")!=std::string::npos);
|
||||
node._prefs.usb_logging_always=255;assert(node.savePrefs());
|
||||
assert(node._prefs.usb_logging_always==0&&!mesh::always_enabled);
|
||||
node._prefs.usb_logging_always=255;node.store.fs.fail_write=true;
|
||||
assert(!node.savePrefs()&&node._prefs.usb_logging_always==255&&!mesh::always_enabled);
|
||||
}
|
||||
'''
|
||||
|
||||
@@ -357,7 +414,10 @@ inline char* utoa(unsigned int value,char* output,int base){
|
||||
prefix = STORE_HARNESS.split('int main(')[0].replace('@METHODS@', store_methods)
|
||||
start = source.index(' if (strcmp(command, "get usb.debug") == 0)')
|
||||
end = source.index(' if (strcmp(command, "get usb.logging") == 0)', start)
|
||||
harness = PREFERENCE_HARNESS.replace('@DEBUG_COMMANDS@', source[start:end])
|
||||
always = '#if !defined(MESH_DUAL_CDC_LOGGING)\n' + '\n'.join(method(source, signature)
|
||||
for signature in ('if (strcmp(command, "get usb.logging.always") == 0)',
|
||||
'if (strncmp(command, "set usb.logging.always", 22) == 0')) + '\n#endif\n'
|
||||
harness = PREFERENCE_HARNESS.replace('@DEBUG_COMMANDS@', always + source[start:end])
|
||||
harness = harness.replace('@SAVE_PREFS@', method(header, ' bool savePrefs()'))
|
||||
harness = harness.replace('@SAVE_PREFERENCE@', method(
|
||||
header, 'template <typename T> bool savePreference('))
|
||||
|
||||
@@ -33,6 +33,7 @@ struct MyMesh {
|
||||
static void timerCases() {
|
||||
mesh::setUsbLoggingEnabled(true);mesh::resumeUsbPacketLogging();
|
||||
mesh::configureUsbLoggingPacketStream(false);g_mock_millis=0;
|
||||
assert(!mesh::isUsbPacketLoggingAlways());
|
||||
for(const char* ignored:std::initializer_list<const char*>{nullptr,""," \t\r\n","stats-core"," \tstats-radio\t ","stats-packets",
|
||||
"\x01" "get name","get\x7f","\xff" "get name","get name\n","stats-core\r","get\rname"}) {
|
||||
mesh::noteUsbConsoleCommand(ignored);assert(mesh::isUsbPacketLoggingAllowed());
|
||||
@@ -71,6 +72,20 @@ static void timerCases() {
|
||||
mesh::setUsbLoggingEnabled(true);mesh::configureUsbLoggingPacketStream(true);
|
||||
mesh::noteUsbConsoleCommand("get name");assert(mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::configureUsbLoggingPacketStream(false);assert(mesh::isUsbPacketLoggingAllowed());
|
||||
// Always-on capture clears an existing quiet period without enabling USB.
|
||||
mesh::noteUsbConsoleCommand("get name");assert(!mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::setUsbPacketLoggingAlways(true);
|
||||
assert(mesh::isUsbPacketLoggingAlways()&&mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::noteUsbConsoleCommand("get name");mesh::noteUsbConsoleCommand("get radio");
|
||||
assert(mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::setUsbLoggingEnabled(false);
|
||||
assert(mesh::isUsbPacketLoggingAlways()&&!mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::setUsbLoggingEnabled(true);
|
||||
assert(mesh::isUsbPacketLoggingAlways()&&mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::setUsbPacketLoggingAlways(false);
|
||||
assert(!mesh::isUsbPacketLoggingAlways()&&mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::noteUsbConsoleCommand("get name");assert(!mesh::isUsbPacketLoggingAllowed());
|
||||
mesh::setUsbLoggingEnabled(true);assert(!mesh::isUsbPacketLoggingAllowed());
|
||||
std::puts("PASS: packet quiet timers, reset, wrap, polls, stream and saved master");
|
||||
}
|
||||
static void outputCases() {
|
||||
@@ -109,6 +124,15 @@ static void outputCases() {
|
||||
#else
|
||||
assert(host=="stamp RAW: 00ABFF\r\n");
|
||||
#endif
|
||||
host.clear();mesh::setUsbPacketLoggingAlways(true);mesh::noteUsbConsoleCommand("get name");
|
||||
node.logRxRaw(2.5f,-92,raw,sizeof(raw));drain();
|
||||
#if MESH_PACKET_LOGGING_COMPACT
|
||||
assert(host=="R00ABFF\n");
|
||||
#else
|
||||
assert(host=="stamp RAW: 00ABFF\r\n");
|
||||
#endif
|
||||
host.clear();mesh::setUsbPacketLoggingAlways(false);mesh::noteUsbConsoleCommand("get name");
|
||||
node.logRxRaw(2.5f,-92,raw,sizeof(raw));drain();assert(host.empty());
|
||||
std::puts("PASS: quiet RAW records preserve replies and complete in-progress records");
|
||||
}
|
||||
int main(int argc,char**) {if(argc==1)timerCases();else outputCases();}
|
||||
@@ -122,6 +146,7 @@ CORE_CASE = r'''
|
||||
namespace mesh {
|
||||
static std::atomic<bool> usb_logging_enabled{true};
|
||||
static std::atomic<uint32_t> usb_packet_logging_quiet_until{0};
|
||||
static std::atomic<bool> usb_packet_logging_always{false};
|
||||
bool dedicated=false,stream=false;
|
||||
bool hasDedicatedUsbLoggingPort(){return dedicated;}
|
||||
bool isUsbLoggingPacketStream(){return stream;}
|
||||
@@ -175,7 +200,8 @@ class UsbPacketLoggingQuietTests(unittest.TestCase):
|
||||
source = (ROOT / "src/helpers/UsbLogging.cpp").read_text()
|
||||
methods = "\n".join(method(source, signature) for signature in (
|
||||
"bool isUsbLoggingEnabled(", "void noteUsbConsoleCommand(",
|
||||
"void resumeUsbPacketLogging(", "bool isUsbPacketLoggingAllowed("))
|
||||
"void resumeUsbPacketLogging(", "void setUsbPacketLoggingAlways(",
|
||||
"bool isUsbPacketLoggingAlways(", "bool isUsbPacketLoggingAllowed("))
|
||||
with tempfile.TemporaryDirectory(prefix="meshcore-packet-dedicated-") as directory:
|
||||
binary = self.compile(Path(directory), "dedicated", CORE_CASE.replace("@METHODS@", methods), ["-DMESH_DEBUG=1"])
|
||||
ran = subprocess.run([str(binary)], capture_output=True, text=True, timeout=20)
|
||||
@@ -199,6 +225,7 @@ int main(){
|
||||
assert(mesh::hasDedicatedUsbLoggingPort()==!stream);
|
||||
mesh::noteUsbConsoleCommand(nullptr);mesh::noteUsbConsoleCommand("get name");
|
||||
assert(mesh::isUsbPacketLoggingAllowed()==enabled);
|
||||
mesh::setUsbPacketLoggingAlways(true);assert(!mesh::isUsbPacketLoggingAlways());
|
||||
mesh::resumeUsbPacketLogging();
|
||||
assert(mesh::isUsbPacketLoggingAllowed()==enabled);
|
||||
}
|
||||
@@ -219,6 +246,7 @@ int main(){
|
||||
int main(){
|
||||
static_assert(!MESH_USB_LOGGING_AVAILABLE,"disabled test profile");
|
||||
mesh::noteUsbConsoleCommand("get name");mesh::resumeUsbPacketLogging();
|
||||
mesh::setUsbPacketLoggingAlways(true);assert(!mesh::isUsbPacketLoggingAlways());
|
||||
assert(!mesh::isUsbPacketLoggingAllowed());
|
||||
}
|
||||
''', flags)
|
||||
|
||||
Reference in new issue
Block a user