mirror of
https://github.com/logos-co/logos-protocol.git
synced 2026-08-27 20:11:07 +00:00
* 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.
140 lines
4.3 KiB
C++
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;
|
|
}
|