mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-10-22 10:32:31 +00:00
134 lines
6.4 KiB
Python
134 lines
6.4 KiB
Python
"""Run canonical GPS sync CLI branches with durable and live state failures."""
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
from test_replay_reset_integration import extract_braced
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
HARNESS = r'''
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <initializer_list>
|
|
#include <helpers/GpsPowerPolicy.h>
|
|
struct Prefs { uint16_t gps_sync_interval_hours = 0; };
|
|
struct Provider {
|
|
uint16_t hours = 0;
|
|
uint16_t getTimeSyncIntervalHours() const { return hours; }
|
|
};
|
|
struct Sensors {
|
|
Provider provider;
|
|
bool present = true;
|
|
unsigned applications = 0;
|
|
Provider* getLocationProvider() { return present ? &provider : nullptr; }
|
|
void applyGpsTimeSyncInterval(uint16_t hours) { provider.hours = hours; ++applications; }
|
|
};
|
|
struct CLI {
|
|
Prefs prefs, persisted;
|
|
Prefs* _prefs = &prefs;
|
|
Sensors sensors;
|
|
Sensors* _sensors = &sensors;
|
|
bool save_ok = true;
|
|
unsigned saves = 0;
|
|
bool trySavePrefs() { ++saves; if (save_ok) persisted = prefs; return save_ok; }
|
|
void set(const char* config, char* reply) { @COMMON_SET@ }
|
|
void get(const char* config, char* reply) { @COMMON_GET@ }
|
|
};
|
|
struct Companion {
|
|
Prefs _prefs, persisted;
|
|
Sensors sensors;
|
|
bool save_ok = true;
|
|
unsigned saves = 0;
|
|
bool savePrefs() { ++saves; if (save_ok) persisted = _prefs; return save_ok; }
|
|
@SAVE_PREFERENCE@
|
|
bool command(const char* command, char* reply, size_t reply_size) {
|
|
@COMPANION_GET@
|
|
const char* gps_sync_value = nullptr;
|
|
@COMPANION_PREFIX@
|
|
@COMPANION_SET@
|
|
return false;
|
|
}
|
|
};
|
|
int main() {
|
|
char reply[160];
|
|
CLI common; Companion companion;
|
|
common.get("gps.sync.interval", reply);
|
|
assert(strstr(reply, "default") && !strstr(reply, "0 hours"));
|
|
assert(companion.command("get gps.sync.interval", reply, sizeof(reply)));
|
|
assert(strstr(reply, "default") && !strstr(reply, "0 hours"));
|
|
for (const char* value : {"1", "24", "336", "337", "4294967296", "999999999999999999999999"}) {
|
|
char command[96];
|
|
uint16_t expected=0; assert(mesh::gps::parseSyncIntervalHours(value,expected));
|
|
snprintf(command,sizeof(command),"gps.sync.interval %s",value);
|
|
common.set(command,reply);
|
|
assert(common.prefs.gps_sync_interval_hours==expected);
|
|
assert(common.persisted.gps_sync_interval_hours==expected && common.sensors.provider.hours==expected);
|
|
char actual[32];snprintf(actual,sizeof(actual),"%u hours",unsigned(expected));
|
|
assert(strstr(reply,actual) && strstr(reply,"saved"));
|
|
snprintf(command,sizeof(command),"set gps.sync.interval %s",value);
|
|
assert(companion.command(command,reply,sizeof(reply)));
|
|
assert(companion._prefs.gps_sync_interval_hours==expected);
|
|
assert(companion.persisted.gps_sync_interval_hours==expected && companion.sensors.provider.hours==expected);
|
|
assert(strstr(reply,actual) && strstr(reply,"saved"));
|
|
}
|
|
for(const char* value : {"", "0", "0000", "-1", "1.5", "5h", "1 2", "337junk"}) {
|
|
char command[64];
|
|
const unsigned common_saves=common.saves, companion_saves=companion.saves;
|
|
snprintf(command,sizeof(command),"gps.sync.interval %s",value);
|
|
common.set(command,reply);assert(strstr(reply,"Error:"));
|
|
snprintf(command,sizeof(command),"set gps.sync.interval %s",value);
|
|
assert(companion.command(command,reply,sizeof(reply)) && strstr(reply,"Error:"));
|
|
assert(common.saves==common_saves && companion.saves==companion_saves);
|
|
}
|
|
common.save_ok=companion.save_ok=false;
|
|
const unsigned common_applied=common.sensors.applications, companion_applied=companion.sensors.applications;
|
|
common.set("gps.sync.interval 7",reply);assert(strstr(reply,"could not be saved"));
|
|
assert(companion.command("set gps.sync.interval 7",reply,sizeof(reply)) && strstr(reply,"could not be saved"));
|
|
assert(common.prefs.gps_sync_interval_hours==336 && common.persisted.gps_sync_interval_hours==336);
|
|
assert(companion._prefs.gps_sync_interval_hours==336 && companion.persisted.gps_sync_interval_hours==336);
|
|
assert(common.sensors.provider.hours==336 && companion.sensors.provider.hours==336);
|
|
assert(common.sensors.applications==common_applied && companion.sensors.applications==companion_applied);
|
|
common.get("gps.sync.interval",reply);assert(!strcmp(reply,"> 336 hours"));
|
|
assert(companion.command("get gps.sync.interval",reply,sizeof(reply)) && !strcmp(reply,"> 336 hours"));
|
|
common.sensors.present=companion.sensors.present=false;
|
|
const unsigned common_saves=common.saves, companion_saves=companion.saves;
|
|
common.set("gps.sync.interval 1",reply);assert(strstr(reply,"unavailable"));
|
|
assert(companion.command("set gps.sync.interval 1",reply,sizeof(reply)) && strstr(reply,"unavailable"));
|
|
common.get("gps.sync.interval",reply);assert(strstr(reply,"unavailable"));
|
|
assert(companion.command("get gps.sync.interval",reply,sizeof(reply)) && strstr(reply,"unavailable"));
|
|
assert(common.saves==common_saves && companion.saves==companion_saves);
|
|
}
|
|
'''
|
|
|
|
|
|
class GpsSyncPreferencesTest(unittest.TestCase):
|
|
def test_canonical_cli_transactions(self):
|
|
common = (ROOT / 'src/helpers/CommonCLI.cpp').read_text()
|
|
companion = (ROOT / 'examples/companion_radio/MyMesh.cpp').read_text()
|
|
header = (ROOT / 'examples/companion_radio/MyMesh.h').read_text()
|
|
replacements = {
|
|
'@COMMON_SET@': extract_braced(common, 'if (strncmp(config, "gps.sync.interval", 17)'),
|
|
'@COMMON_GET@': extract_braced(common, 'if (strcmp(config, "gps.sync.interval") == 0)'),
|
|
'@COMPANION_GET@': extract_braced(companion, 'if (strcmp(command, "get gps.sync.interval") == 0)'),
|
|
'@COMPANION_PREFIX@': extract_braced(companion, 'if (strncmp(command, "set gps.sync.interval", 21)'),
|
|
'@COMPANION_SET@': extract_braced(companion, 'if (gps_sync_value)'),
|
|
'@SAVE_PREFERENCE@': extract_braced(header, 'template <typename T> bool savePreference('),
|
|
}
|
|
code = HARNESS
|
|
for token, value in replacements.items():
|
|
code = code.replace(token, value)
|
|
with tempfile.TemporaryDirectory(prefix='meshcore-gps-sync-prefs-') as directory:
|
|
cpp, exe = Path(directory) / 'test.cpp', Path(directory) / 'test.exe'
|
|
cpp.write_text(code)
|
|
subprocess.run(['g++', '-std=c++17', '-Wall', '-Wextra', '-Werror',
|
|
'-I' + str(ROOT / 'src'), str(cpp), '-o', str(exe)], check=True)
|
|
subprocess.run([str(exe)], check=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|