Files
trail-mate/apps/linux_lvgl/tests/linux_local_identity_atomic_test.cpp
T
Trail Mate Dev 6e613e382e Add CM0 Linux support and share device services across platforms
Compose the CM0 fullscreen application and standard Debian package, align the
Cardputer Zero shell, and share protocol, configuration, audio and storage
services with embedded targets through existing platform seams.

Add the paginated on-device TMAP creator using Center's published producer,
private workspace recovery and direct keyboard shortcuts. Preserve unfinished
management work behind its existing opt-in capability.

Include native, ARM and shared-core regression fixtures, integration records,
packaging helpers and dependency/license updates. Keep local build trees,
device credentials, produced packages and validation logs outside version control.

Validation before integration: ESP stack hygiene, Reticulum scope guard, staged
whitespace checks and GitNexus scope audit. Prior device/build evidence and
remaining hardware/package boundaries are recorded in the acceptance documents.
2026-10-29 10:29:29 +08:00

129 lines
4.9 KiB
C++

#include "platform/linux/mesh/linux_sqlite_mesh_identity_store.h"
#include "platform/linux/runtime_paths.h"
#include <algorithm>
#include <cassert>
#include <cstring>
#include <filesystem>
#include <sqlite3.h>
#include <string>
#include <sys/wait.h>
#include <unistd.h>
struct sqlite3_api_routines;
namespace native = platform::linux_runtime;
using Store = native::mesh::LinuxSqliteLocalIdentityStore;
using Failure = mesh::StoreFailure;
mesh::LocalIdentity identity(uint8_t revision)
{
mesh::LocalIdentity value;
value.valid = true;
std::fill_n(value.public_key, 32, revision);
std::fill_n(value.private_key, 32, uint8_t(revision + 0x80));
return value;
}
bool equal(const mesh::LocalIdentity& a, const mesh::LocalIdentity& b)
{
return a.valid == b.valid && !std::memcmp(a.public_key, b.public_key, 32) && !std::memcmp(a.private_key, b.private_key, 32);
}
void sql(const char* text)
{
sqlite3* db = nullptr;
assert(sqlite3_open(native::sqlite_database_path().c_str(), &db) == SQLITE_OK);
assert(sqlite3_exec(db, text, nullptr, nullptr, nullptr) == SQLITE_OK);
sqlite3_close(db);
}
struct Interleave
{
int go = -1, done = -1;
bool fired = false;
};
Interleave* interleave = nullptr;
int trace(unsigned, void* context, void* statement, void*)
{
auto& state = *static_cast<Interleave*>(context);
auto* query = static_cast<sqlite3_stmt*>(statement);
if (state.fired || !sqlite3_stmt_readonly(query)) return 0;
char* text = sqlite3_expanded_sql(query);
const bool public_read = text && std::strstr(text, "'atomic_identity'") && std::strstr(text, "'pub'");
sqlite3_free(text);
if (!public_read) return 0;
state.fired = true;
assert(write(state.go, "1", 1) == 1);
char byte;
assert(read(state.done, &byte, 1) == 1);
return 0;
}
extern "C" int attach_trace(sqlite3* db, char**, const sqlite3_api_routines*)
{
return sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, trace, interleave);
}
void snapshot(Store& store, const mesh::LocalIdentity& original, const mesh::LocalIdentity& next)
{
int go[2], done[2];
assert(pipe(go) == 0 && pipe(done) == 0);
const auto child = fork();
assert(child >= 0);
if (!child)
{
close(go[1]);
close(done[0]);
char byte;
if (read(go[0], &byte, 1) != 1 || !store.save(next).ok || write(done[1], "1", 1) != 1) _exit(2);
_exit(0);
}
close(go[0]);
close(done[1]);
Interleave state{go[1], done[0]};
interleave = &state;
assert(sqlite3_auto_extension(reinterpret_cast<void (*)()>(attach_trace)) == SQLITE_OK);
mesh::LocalIdentity loaded;
assert(store.load(loaded).ok);
sqlite3_reset_auto_extension();
interleave = nullptr;
close(go[1]);
close(done[0]);
int status = 0;
assert(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 0);
assert(state.fired && equal(loaded, original));
assert(store.load(loaded).ok && equal(loaded, next));
}
int main(int argc, char** argv)
{
assert(argc == 2);
char directory[] = "/tmp/trailmate-local-identity-XXXXXX";
assert(mkdtemp(directory));
setenv("TRAIL_MATE_SETTINGS_ROOT", directory, 1);
Store store({"atomic_identity", "pub", "priv"});
const auto original = identity(0x11), next = identity(0x22);
mesh::LocalIdentity loaded;
assert(store.load(loaded).failure == Failure::NotFound && !loaded.valid);
assert(store.save(original).ok);
const std::string mode(argv[1]);
if (mode == "save")
{
sql("CREATE TRIGGER fail_private BEFORE INSERT ON settings WHEN NEW.namespace='atomic_identity' AND NEW.key='priv' BEGIN SELECT RAISE(ABORT,'injected'); END;");
assert(store.save(next).failure == Failure::IoError);
assert(store.load(loaded).ok && equal(loaded, original));
sql("DROP TRIGGER fail_private;");
assert(store.save(next).ok && store.load(loaded).ok && equal(loaded, next));
}
else if (mode == "clear")
{
sql("CREATE TRIGGER fail_private BEFORE DELETE ON settings WHEN OLD.namespace='atomic_identity' AND OLD.key='priv' BEGIN SELECT RAISE(ABORT,'injected'); END;");
assert(store.clear().failure == Failure::IoError);
assert(store.load(loaded).ok && equal(loaded, original));
sql("DROP TRIGGER fail_private;");
assert(store.clear().ok && store.load(loaded).failure == Failure::NotFound);
}
else if (mode == "read")
{
sql("ALTER TABLE settings RENAME TO saved_settings; CREATE VIEW settings AS SELECT namespace,key,kind,unavailable_function(payload) AS payload,updated_at FROM saved_settings;");
assert(store.load(loaded).failure == Failure::IoError && !loaded.valid);
assert(std::all_of(std::begin(loaded.private_key), std::end(loaded.private_key), [](uint8_t byte)
{ return byte == 0; }));
}
else if (mode == "snapshot") snapshot(store, original, next);
else std::abort();
std::filesystem::remove_all(directory);
}