mirror of
https://github.com/logos-co/logos-cpp-sdk.git
synced 2026-08-31 01:31:10 +00:00
feat: allow long module names
This commit is contained in:
+57
-1
@@ -1,6 +1,7 @@
|
||||
#ifndef LOGOS_INSTANCE_H
|
||||
#define LOGOS_INSTANCE_H
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QUuid>
|
||||
@@ -15,6 +16,34 @@
|
||||
* ID. Used by both provider and consumer to build matching registry URLs.
|
||||
*/
|
||||
namespace LogosInstance {
|
||||
inline QString shortSha1Hex(const QString& value, int length)
|
||||
{
|
||||
return QString::fromLatin1(
|
||||
QCryptographicHash::hash(value.toUtf8(), QCryptographicHash::Sha1)
|
||||
.toHex()
|
||||
.left(length));
|
||||
}
|
||||
|
||||
inline QString leftUtf8Bytes(const QString& value, int maxBytes)
|
||||
{
|
||||
if (maxBytes <= 0)
|
||||
return QString();
|
||||
|
||||
const QByteArray utf8 = value.toUtf8();
|
||||
if (utf8.size() <= maxBytes)
|
||||
return value;
|
||||
|
||||
QByteArray truncated = utf8.left(maxBytes);
|
||||
while (!truncated.isEmpty()) {
|
||||
const QString decoded =
|
||||
QString::fromUtf8(truncated.constData(), truncated.size());
|
||||
if (decoded.toUtf8().size() == truncated.size())
|
||||
return decoded;
|
||||
truncated.chop(1);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
inline const QString id() {
|
||||
const QByteArray inherited = qgetenv("LOGOS_INSTANCE_ID");
|
||||
if (!inherited.isEmpty())
|
||||
@@ -25,7 +54,34 @@ namespace LogosInstance {
|
||||
}
|
||||
|
||||
inline QString id(const QString& moduleName) {
|
||||
return QString("local:logos_%1_%2").arg(moduleName).arg(id());
|
||||
constexpr int kMaxSocketFilenameBytes = 40;
|
||||
constexpr int kModuleHashHexLen = 16;
|
||||
constexpr int kMaxInstanceIdBytes = 12;
|
||||
|
||||
const QString instanceId = id();
|
||||
const QString baseName =
|
||||
QStringLiteral("logos_%1_%2").arg(moduleName, instanceId);
|
||||
|
||||
if (baseName.toUtf8().size() <= kMaxSocketFilenameBytes)
|
||||
return QStringLiteral("local:") + baseName;
|
||||
|
||||
const QString instanceIdForSocket =
|
||||
(instanceId.toUtf8().size() <= kMaxInstanceIdBytes)
|
||||
? instanceId
|
||||
: shortSha1Hex(instanceId, kMaxInstanceIdBytes);
|
||||
const QString moduleHash = shortSha1Hex(moduleName, kModuleHashHexLen);
|
||||
|
||||
// Reserve bytes for "logos_" + "_" + moduleHash + "_" + instance ID.
|
||||
const int fixedBytes =
|
||||
8 + kModuleHashHexLen + instanceIdForSocket.toUtf8().size();
|
||||
const int modulePrefixBytes =
|
||||
qMax(0, kMaxSocketFilenameBytes - fixedBytes);
|
||||
const QString modulePrefix = leftUtf8Bytes(moduleName, modulePrefixBytes);
|
||||
|
||||
const QString socketName =
|
||||
QStringLiteral("logos_%1_%2_%3")
|
||||
.arg(modulePrefix, moduleHash, instanceIdForSocket);
|
||||
return QStringLiteral("local:") + socketName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,3 +53,65 @@ TEST_F(LogosInstanceTest, RegistryUrlFormat)
|
||||
QString url = LogosInstance::id("my_module");
|
||||
EXPECT_EQ(url, "local:logos_my_module_abc123def456");
|
||||
}
|
||||
|
||||
TEST_F(LogosInstanceTest, RegistryUrlTruncatesLongModuleNames)
|
||||
{
|
||||
qputenv("LOGOS_INSTANCE_ID", "abc123def456");
|
||||
const QString longName =
|
||||
"liblogos_execution_zone_wallet_module_with_extra_suffix";
|
||||
QString url = LogosInstance::id(longName);
|
||||
|
||||
ASSERT_TRUE(url.startsWith("local:"));
|
||||
const QString socketName = url.mid(QString("local:").size());
|
||||
|
||||
EXPECT_LE(socketName.toUtf8().size(), 40);
|
||||
EXPECT_EQ(url, LogosInstance::id(longName));
|
||||
|
||||
EXPECT_NE(url, LogosInstance::id(longName + "_different"));
|
||||
}
|
||||
|
||||
// Golden test: pin the exact derived name so refactors don't silently change
|
||||
// the socket naming scheme.
|
||||
TEST_F(LogosInstanceTest, RegistryUrlGoldenLongName)
|
||||
{
|
||||
qputenv("LOGOS_INSTANCE_ID", "abc123def456");
|
||||
const QString longName =
|
||||
"liblogos_execution_zone_wallet_module_with_extra_suffix";
|
||||
EXPECT_EQ(LogosInstance::id(longName),
|
||||
QStringLiteral("local:logos_libl_dc0d0a2280b70b17_abc123def456"));
|
||||
}
|
||||
|
||||
TEST_F(LogosInstanceTest, RegistryUrlTruncatesLongInstanceId)
|
||||
{
|
||||
const QByteArray longInstanceId =
|
||||
"instance_id_with_extra_suffix_that_is_deliberately_long_for_socket_names";
|
||||
const QString longName =
|
||||
"liblogos_execution_zone_wallet_module_with_extra_suffix";
|
||||
|
||||
qputenv("LOGOS_INSTANCE_ID", longInstanceId);
|
||||
const QString url = LogosInstance::id(longName);
|
||||
|
||||
ASSERT_TRUE(url.startsWith("local:"));
|
||||
const QString socketName = url.mid(QString("local:").size());
|
||||
EXPECT_LE(socketName.toUtf8().size(), 40);
|
||||
EXPECT_EQ(url, LogosInstance::id(longName));
|
||||
|
||||
qputenv(
|
||||
"LOGOS_INSTANCE_ID",
|
||||
"instance_id_with_extra_suffix_that_is_deliberately_long_for_socket_names_changed");
|
||||
EXPECT_NE(url, LogosInstance::id(longName));
|
||||
}
|
||||
|
||||
TEST_F(LogosInstanceTest, RegistryUrlTruncatesByUtf8Bytes)
|
||||
{
|
||||
qputenv("LOGOS_INSTANCE_ID", "abc123def456");
|
||||
const QString unicodeLongName = QString::fromUtf8(
|
||||
"模块_пример_モジュール_الوحدة_가나다라마바사아자차카타파하");
|
||||
|
||||
const QString url = LogosInstance::id(unicodeLongName);
|
||||
ASSERT_TRUE(url.startsWith("local:"));
|
||||
const QString socketName = url.mid(QString("local:").size());
|
||||
|
||||
EXPECT_LE(socketName.toUtf8().size(), 40);
|
||||
EXPECT_EQ(url, LogosInstance::id(unicodeLongName));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user