Files

177 lines
5.5 KiB
C++
Raw Permalink Normal View History

2026-03-24 10:14:17 -04:00
#include <gtest/gtest.h>
#include <QtTest/QSignalSpy>
#include <QJsonObject>
#include "logos_mock.h"
#include "logos_api.h"
#include "logos_provider_object.h"
#include "module_proxy.h"
// Minimal provider for proxy testing
class ProxyTestProvider : public LogosProviderBase {
public:
QString providerName() const override { return "proxy_test"; }
QString providerVersion() const override { return "1.0.0"; }
QVariant callMethod(const QString& methodName, const QVariantList& args) override
{
lastMethodCalled = methodName;
lastArgs = args;
return returnValue;
}
// getMethods() returns the whole interface: methods AND events, each tagged
// with a "type". The proxy slices it into getPluginMethods/Events/Interface.
2026-03-24 10:14:17 -04:00
QJsonArray getMethods() override
{
QJsonArray arr;
{
QJsonObject m;
m["type"] = "method";
m["name"] = "testMethod";
arr.append(m);
}
{
QJsonObject e;
e["type"] = "event";
e["name"] = "testEvent";
arr.append(e);
}
2026-03-24 10:14:17 -04:00
return arr;
}
// Expose protected emitEvent for testing
void testEmitEvent(const QString& name, const QVariantList& data) { emitEvent(name, data); }
QString lastMethodCalled;
QVariantList lastArgs;
QVariant returnValue = QVariant(99);
};
class ModuleProxyTest : public ::testing::Test {
protected:
void SetUp() override
{
m_mock = new LogosMockSetup();
m_provider = new ProxyTestProvider();
}
void TearDown() override
{
delete m_provider;
delete m_mock;
}
LogosMockSetup* m_mock = nullptr;
ProxyTestProvider* m_provider = nullptr;
};
TEST_F(ModuleProxyTest, CallRemoteMethodDispatchesToProvider)
{
ModuleProxy proxy(m_provider);
2026-06-05 10:38:55 -04:00
proxy.saveToken("caller", "token"); // authorize the caller's token
2026-03-24 10:14:17 -04:00
QVariant r = proxy.callRemoteMethod("token", "myMethod", {QVariant(1)});
EXPECT_EQ(r.toInt(), 99);
EXPECT_EQ(m_provider->lastMethodCalled, "myMethod");
EXPECT_EQ(m_provider->lastArgs.size(), 1);
}
TEST_F(ModuleProxyTest, GetPluginMethodsDispatchesToProvider)
{
ModuleProxy proxy(m_provider);
// getPluginMethods() returns the method-typed entries only — the event the
// provider also reports through getMethods() is filtered out.
2026-03-24 10:14:17 -04:00
QJsonArray methods = proxy.getPluginMethods();
ASSERT_EQ(methods.size(), 1);
EXPECT_EQ(methods[0].toObject()["name"].toString(), "testMethod");
}
TEST_F(ModuleProxyTest, GetPluginEventsReturnsOnlyEvents)
{
ModuleProxy proxy(m_provider);
QJsonArray events = proxy.getPluginEvents();
ASSERT_EQ(events.size(), 1);
EXPECT_EQ(events[0].toObject()["name"].toString(), "testEvent");
}
TEST_F(ModuleProxyTest, GetPluginInterfaceReturnsMethodsAndEvents)
{
ModuleProxy proxy(m_provider);
// The whole interface — both the method and the event — in one array.
EXPECT_EQ(proxy.getPluginInterface().size(), 2);
2026-03-24 10:14:17 -04:00
}
TEST_F(ModuleProxyTest, GetPluginMethodsSpecialCaseInCallRemoteMethod)
{
ModuleProxy proxy(m_provider);
QVariant r = proxy.callRemoteMethod("token", "getPluginMethods");
// Should return the methods array as QVariant, not dispatch to provider's callMethod
EXPECT_TRUE(r.toJsonArray().size() > 0);
// Provider's callMethod should NOT have been called for "getPluginMethods"
EXPECT_TRUE(m_provider->lastMethodCalled.isEmpty());
}
TEST_F(ModuleProxyTest, GetPluginEventsAndInterfaceSpecialCaseInCallRemoteMethod)
{
ModuleProxy proxy(m_provider);
QVariant ev = proxy.callRemoteMethod("token", "getPluginEvents");
EXPECT_EQ(ev.toJsonArray().size(), 1);
QVariant iface = proxy.callRemoteMethod("token", "getPluginInterface");
EXPECT_EQ(iface.toJsonArray().size(), 2);
// Both are intercepted by the proxy, never dispatched to the provider.
EXPECT_TRUE(m_provider->lastMethodCalled.isEmpty());
}
2026-03-24 10:14:17 -04:00
TEST_F(ModuleProxyTest, NullProviderHandling)
{
ModuleProxy proxy(nullptr);
QVariant r = proxy.callRemoteMethod("token", "fn");
EXPECT_FALSE(r.isValid());
EXPECT_EQ(proxy.getPluginMethods().size(), 0);
}
TEST_F(ModuleProxyTest, EmptyMethodNameHandling)
{
ModuleProxy proxy(m_provider);
QVariant r = proxy.callRemoteMethod("token", "");
EXPECT_FALSE(r.isValid());
EXPECT_TRUE(m_provider->lastMethodCalled.isEmpty());
}
TEST_F(ModuleProxyTest, SaveTokenValidation)
{
ModuleProxy proxy(m_provider);
EXPECT_TRUE(proxy.saveToken("mod", "tok"));
EXPECT_FALSE(proxy.saveToken("", "tok")); // empty module name
EXPECT_FALSE(proxy.saveToken("mod", "")); // empty token
}
TEST_F(ModuleProxyTest, EventForwarding)
{
ModuleProxy proxy(m_provider);
QSignalSpy spy(&proxy, &ModuleProxy::eventResponse);
// The proxy sets up event listener on construction.
// When provider emits event, proxy should emit signal.
m_provider->testEmitEvent("my_event", {QVariant("data")});
EXPECT_EQ(spy.count(), 1);
EXPECT_EQ(spy.at(0).at(0).toString(), "my_event");
QVariantList data = spy.at(0).at(1).value<QVariantList>();
ASSERT_EQ(data.size(), 1);
EXPECT_EQ(data[0].toString(), "data");
}
TEST_F(ModuleProxyTest, InformModuleTokenDelegatesToProvider)
{
LogosAPI api("origin");
m_provider->init(&api);
ModuleProxy proxy(m_provider);
bool result = proxy.informModuleToken("auth", "target_mod", "tok123");
EXPECT_TRUE(result);
// Provider's informModuleToken saves via TokenManager
EXPECT_EQ(TokenManager::instance().getToken("target_mod"), "tok123");
}