Files
Dario Lipicar 29afbac532 Extract the Logos protocol layer from logos-cpp-sdk (lp_* C ABI + protocol semver) (#2)
* Extract the Logos protocol layer from logos-cpp-sdk

Transports (plain TCP/TLS, qt_local, qt_remote/QRO, mock), token manager,
consumer core (LogosAPIClient/LogosAPIConsumer incl. the capability
auto-requestModule flow), ModuleProxy, the abstract LogosProviderObject
interface, and the canonical QVariant<->JSON conversion — now behind the
language-neutral lp_* C ABI (logos_protocol.h) carrying the protocol
semver (LOGOS_PROTOCOL_VERSION_*, lp_protocol_version()).

Bytes crossing the ABI use the lossless {"_bytes": base64url} tagging
(NUL-safe), matching the plain wire encoding.

Provider lp_* surface is compiled groundwork; serving lands with module
authoring.

* consumer: typed requestModule for the capability flow

Port of logos-cpp-sdk master f5a127dd ('use updated capability module',
cpp-sdk#85, Iuri Matias) — the touched files (logos_api_client.cpp,
logos_api_consumer.{h,cpp}) moved into this repo in the P1 extraction.
The capability auto-requestModule path now calls a typed std::string
helper on the consumer (which acquires the capability object directly)
instead of a stringly invokeRemoteMethod round-trip. 111/111 tests.
2026-06-12 18:59:01 -03:00

140 lines
4.3 KiB
C++

#include "mock_store.h"
#include <QMutexLocker>
#include <QDebug>
MockStore& MockStore::instance()
{
static MockStore s;
return s;
}
void MockStore::reset()
{
QMutexLocker lock(&m_mutex);
m_expectations.clear();
m_calls.clear();
m_mockObjectReleaseProbe = nullptr;
}
void MockStore::setMockObjectReleaseProbe(std::atomic<int>* counter)
{
QMutexLocker lock(&m_mutex);
m_mockObjectReleaseProbe = counter;
}
void MockStore::incrementMockObjectReleaseProbeIfSet()
{
QMutexLocker lock(&m_mutex);
if (m_mockObjectReleaseProbe)
++(*m_mockObjectReleaseProbe);
}
// ── ExpectationBuilder ───────────────────────────────────────────────────────
MockStore::ExpectationBuilder::ExpectationBuilder(MockStore& store,
const QString& module,
const QString& method)
: m_store(store)
{
QMutexLocker lock(&store.m_mutex);
MockExpectation exp;
exp.module = module;
exp.method = method;
exp.matchAnyArgs = true;
store.m_expectations.append(exp);
m_index = store.m_expectations.size() - 1;
}
MockStore::ExpectationBuilder& MockStore::ExpectationBuilder::withArgs(const QVariantList& args)
{
QMutexLocker lock(&m_store.m_mutex);
m_store.m_expectations[m_index].expectedArgs = args;
m_store.m_expectations[m_index].matchAnyArgs = false;
return *this;
}
MockStore::ExpectationBuilder& MockStore::ExpectationBuilder::thenReturn(const QVariant& value)
{
QMutexLocker lock(&m_store.m_mutex);
m_store.m_expectations[m_index].returnValue = value;
return *this;
}
// ── MockStore ────────────────────────────────────────────────────────────────
MockStore::ExpectationBuilder MockStore::when(const QString& module, const QString& method)
{
return ExpectationBuilder(*this, module, method);
}
QVariant MockStore::recordAndReturn(const QString& module, const QString& method,
const QVariantList& args)
{
QMutexLocker lock(&m_mutex);
MockCallRecord record;
record.module = module;
record.method = method;
record.args = args;
m_calls.append(record);
// Search expectations in reverse (last registered wins)
for (int i = m_expectations.size() - 1; i >= 0; --i) {
const MockExpectation& exp = m_expectations.at(i);
if (exp.module != module || exp.method != method) continue;
if (!exp.matchAnyArgs && exp.expectedArgs != args) continue;
qDebug() << "MockStore: matched expectation for" << module << "::" << method
<< "-> returning" << exp.returnValue;
return exp.returnValue;
}
qWarning() << "MockStore: no expectation registered for" << module << "::" << method
<< "- returning invalid QVariant";
return QVariant();
}
bool MockStore::wasCalled(const QString& module, const QString& method) const
{
QMutexLocker lock(&m_mutex);
for (const MockCallRecord& r : m_calls) {
if (r.module == module && r.method == method) return true;
}
return false;
}
bool MockStore::wasCalledWith(const QString& module, const QString& method,
const QVariantList& args) const
{
QMutexLocker lock(&m_mutex);
for (const MockCallRecord& r : m_calls) {
if (r.module == module && r.method == method && r.args == args) return true;
}
return false;
}
int MockStore::callCount(const QString& module, const QString& method) const
{
QMutexLocker lock(&m_mutex);
int count = 0;
for (const MockCallRecord& r : m_calls) {
if (r.module == module && r.method == method) ++count;
}
return count;
}
QVariantList MockStore::lastArgs(const QString& module, const QString& method) const
{
QMutexLocker lock(&m_mutex);
for (int i = m_calls.size() - 1; i >= 0; --i) {
const MockCallRecord& r = m_calls.at(i);
if (r.module == module && r.method == method) return r.args;
}
return QVariantList();
}
QList<MockCallRecord> MockStore::allCalls() const
{
QMutexLocker lock(&m_mutex);
return m_calls;
}