test: traces réelles du moteur jugées contre le contrat (refoptimizer)
Les 16 lignes de testTracesReplayWithZeroDivergence : chaque requête, et chaque réponse de l'optimiseur rejugée sur sa requête (--trace --semantic). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fc41c4ff40
commit
308444f39d
@ -43,29 +43,16 @@ struct Verdict {
|
|||||||
* Juge une session (un message JSON-RPC par élément, dans l'ordre) contre \p schema.
|
* Juge une session (un message JSON-RPC par élément, dans l'ordre) contre \p schema.
|
||||||
* \p arguments : options en plus (`--requests-only`, `--semantic`).
|
* \p arguments : options en plus (`--requests-only`, `--semantic`).
|
||||||
*/
|
*/
|
||||||
inline Verdict juger(const QList<QJsonObject> &messages, const QString &schema, const QStringList &arguments = {})
|
/*! Lance le validateur avec \p arguments (après `--schema`). */
|
||||||
|
inline Verdict lancer(const QString &schema, const QStringList &arguments)
|
||||||
{
|
{
|
||||||
Verdict v;
|
Verdict v;
|
||||||
QTemporaryDir dir;
|
|
||||||
if (!dir.isValid()) {
|
|
||||||
v.sortie = QStringLiteral("répertoire temporaire impossible");
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
QFile f(dir.filePath(QStringLiteral("session.ndjson")));
|
|
||||||
if (!f.open(QIODevice::WriteOnly)) {
|
|
||||||
v.sortie = QStringLiteral("écriture de la session impossible");
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
for (const QJsonObject &m : messages)
|
|
||||||
f.write(QJsonDocument(m).toJson(QJsonDocument::Compact) + '\n');
|
|
||||||
f.close();
|
|
||||||
QProcess p;
|
QProcess p;
|
||||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
p.start(QStringLiteral("python3"),
|
p.start(QStringLiteral("python3"),
|
||||||
QStringList{QStringLiteral("-I"), QStringLiteral("-B"),
|
QStringList{QStringLiteral("-I"), QStringLiteral("-B"),
|
||||||
racineSources() + QStringLiteral("/tools/etm-powersync-schema-check"),
|
racineSources() + QStringLiteral("/tools/etm-powersync-schema-check"),
|
||||||
QStringLiteral("--schema"), schema, QStringLiteral("--ndjson"), f.fileName()}
|
QStringLiteral("--schema"), schema} + arguments);
|
||||||
+ arguments);
|
|
||||||
if (!p.waitForFinished(60000)) {
|
if (!p.waitForFinished(60000)) {
|
||||||
p.kill();
|
p.kill();
|
||||||
v.sortie = QStringLiteral("validateur sans réponse en 60 s");
|
v.sortie = QStringLiteral("validateur sans réponse en 60 s");
|
||||||
@ -79,6 +66,31 @@ inline Verdict juger(const QList<QJsonObject> &messages, const QString &schema,
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Juge une session (un message JSON-RPC par élément, dans l'ordre) contre \p schema.
|
||||||
|
* \p arguments : options en plus (`--requests-only`, `--semantic`).
|
||||||
|
*/
|
||||||
|
inline Verdict juger(const QList<QJsonObject> &messages, const QString &schema, const QStringList &arguments = {})
|
||||||
|
{
|
||||||
|
QTemporaryDir dir;
|
||||||
|
QFile f(dir.filePath(QStringLiteral("session.ndjson")));
|
||||||
|
if (!dir.isValid() || !f.open(QIODevice::WriteOnly)) {
|
||||||
|
Verdict v;
|
||||||
|
v.sortie = QStringLiteral("écriture de la session impossible");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
for (const QJsonObject &m : messages)
|
||||||
|
f.write(QJsonDocument(m).toJson(QJsonDocument::Compact) + '\n');
|
||||||
|
f.close();
|
||||||
|
return lancer(schema, QStringList{QStringLiteral("--ndjson"), f.fileName()} + arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Juge un fichier de traces de décision (annexe D) contre \p schema. */
|
||||||
|
inline Verdict jugerTraces(const QString &trace, const QString &schema, const QStringList &arguments = {})
|
||||||
|
{
|
||||||
|
return lancer(schema, QStringList{QStringLiteral("--trace"), trace} + arguments);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Écrit \p octets dans \p dir et rend le chemin : le contrat EMBARQUÉ, passé au validateur. */
|
/*! Écrit \p octets dans \p dir et rend le chemin : le contrat EMBARQUÉ, passé au validateur. */
|
||||||
inline QString ecrireSchema(const QTemporaryDir &dir, const QByteArray &octets)
|
inline QString ecrireSchema(const QTemporaryDir &dir, const QByteArray &octets)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -836,6 +836,16 @@ void TestRefOptimizer::testTracesReplayWithZeroDivergence()
|
|||||||
const QStringList fichiers = QDir(d).entryList({"etm-powersync-optimizer-trace-*.ndjson"}, QDir::Files);
|
const QStringList fichiers = QDir(d).entryList({"etm-powersync-optimizer-trace-*.ndjson"}, QDir::Files);
|
||||||
QCOMPARE(fichiers.count(), 1);
|
QCOMPARE(fichiers.count(), 1);
|
||||||
const QString trace = QDir(d).filePath(fichiers.first());
|
const QString trace = QDir(d).filePath(fichiers.first());
|
||||||
|
// Lot contrat OpenRPC : les traces RÉELLES du moteur — requêtes des 16 cycles, réponses de
|
||||||
|
// l'optimiseur rejugées sur leur requête — sont conformes au contrat embarqué.
|
||||||
|
{
|
||||||
|
QTemporaryDir dir;
|
||||||
|
const Contrat::Verdict v = Contrat::jugerTraces(trace, Contrat::ecrireSchema(dir, OptimizerProtocol::schemaDocumentBytes()),
|
||||||
|
{QStringLiteral("--semantic")});
|
||||||
|
QVERIFY2(v.code == 0, qUtf8Printable(v.sortie.right(4000)));
|
||||||
|
QCOMPARE(v.compte("GetPlan.params"), lignes.count());
|
||||||
|
QCOMPARE(v.compte("GetPlan.result"), surplus.count()); // les lignes à latencyMs : celles de l'optimiseur
|
||||||
|
}
|
||||||
|
|
||||||
RefOptimizer neuf;
|
RefOptimizer neuf;
|
||||||
QString erreur;
|
QString erreur;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user