@fairfox/polly 0.15.6 → 0.15.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -371,6 +371,8 @@ class TLAGenerator {
|
|
|
371
371
|
temporalProperties = [];
|
|
372
372
|
symmetrySets = [];
|
|
373
373
|
resolvedActionNames = new Map;
|
|
374
|
+
tabSymmetryEnabled = false;
|
|
375
|
+
tabCount = 0;
|
|
374
376
|
constructor(options) {
|
|
375
377
|
this.options = options;
|
|
376
378
|
}
|
|
@@ -531,6 +533,7 @@ class TLAGenerator {
|
|
|
531
533
|
this.addExtends();
|
|
532
534
|
this.addConstants(config);
|
|
533
535
|
this.addMessageTypes(config, analysis);
|
|
536
|
+
this.addTabSymmetry(config);
|
|
534
537
|
this.addStateType(config, analysis);
|
|
535
538
|
this.addVariables();
|
|
536
539
|
if (this.temporalProperties.length > 0) {
|
|
@@ -596,7 +599,11 @@ class TLAGenerator {
|
|
|
596
599
|
lines.push(` MaxClients = ${messages.maxClients}`);
|
|
597
600
|
hasProjectConstant = true;
|
|
598
601
|
}
|
|
599
|
-
if (
|
|
602
|
+
if (this.tabSymmetryEnabled) {
|
|
603
|
+
for (let i = 0;i < this.tabCount; i++) {
|
|
604
|
+
lines.push(` Tab${i} = Tab${i}`);
|
|
605
|
+
}
|
|
606
|
+
} else if ("maxTabs" in messages && messages.maxTabs !== undefined) {
|
|
600
607
|
lines.push(` MaxTabId = ${messages.maxTabs}`);
|
|
601
608
|
} else if (hasProjectConstant) {
|
|
602
609
|
lines.push(" MaxTabId = 0");
|
|
@@ -930,6 +937,39 @@ class TLAGenerator {
|
|
|
930
937
|
this.symmetrySets = ["Symmetry"];
|
|
931
938
|
this.line("");
|
|
932
939
|
}
|
|
940
|
+
addTabSymmetry(config) {
|
|
941
|
+
if (!config.messages.tabSymmetry) {
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
const maxTabs = config.messages.maxTabs ?? 1;
|
|
945
|
+
this.tabCount = maxTabs + 1;
|
|
946
|
+
this.tabSymmetryEnabled = true;
|
|
947
|
+
this.line("\\* Tab symmetry constants for state space reduction (Tier 1 optimization)");
|
|
948
|
+
this.line("CONSTANTS");
|
|
949
|
+
this.indent++;
|
|
950
|
+
const tabConstants = [];
|
|
951
|
+
for (let i = 0;i <= maxTabs; i++) {
|
|
952
|
+
tabConstants.push(`Tab${i}`);
|
|
953
|
+
}
|
|
954
|
+
this.line(tabConstants.join(", "));
|
|
955
|
+
this.indent--;
|
|
956
|
+
this.line("");
|
|
957
|
+
this.line(`Tabs == {${tabConstants.join(", ")}}`);
|
|
958
|
+
this.line("");
|
|
959
|
+
this.line("TabSymmetry == Permutations(Tabs)");
|
|
960
|
+
this.line("");
|
|
961
|
+
const hasMessageSymmetry = this.symmetrySets.length > 0 && this.symmetrySets[0] === "Symmetry";
|
|
962
|
+
if (hasMessageSymmetry) {
|
|
963
|
+
this.line("\\* Combined symmetry: message types and tabs");
|
|
964
|
+
this.line("AllSymmetry == Symmetry \\cup TabSymmetry");
|
|
965
|
+
this.line("");
|
|
966
|
+
this.symmetrySets = ["AllSymmetry"];
|
|
967
|
+
console.log(`[INFO] [TLAGenerator] Combined symmetry: message symmetry + ${this.tabCount} tabs as model values`);
|
|
968
|
+
} else {
|
|
969
|
+
this.symmetrySets = ["TabSymmetry"];
|
|
970
|
+
console.log(`[INFO] [TLAGenerator] Tab symmetry enabled: ${this.tabCount} tabs as model values`);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
933
973
|
addVariables() {
|
|
934
974
|
this.line("\\* Application state per context");
|
|
935
975
|
this.line("VARIABLE contextStates");
|
|
@@ -1684,7 +1724,8 @@ class TLAGenerator {
|
|
|
1684
1724
|
if (hasValidHandlers) {
|
|
1685
1725
|
this.line("\\/ \\E c \\in Contexts : ConnectPort(c) /\\ UNCHANGED <<contextStates, payload>>");
|
|
1686
1726
|
this.line("\\/ \\E c \\in Contexts : DisconnectPort(c) /\\ UNCHANGED <<contextStates, payload>>");
|
|
1687
|
-
|
|
1727
|
+
const tabSet = this.tabSymmetryEnabled ? "Tabs" : "0..MaxTabId";
|
|
1728
|
+
this.line(`\\/ \\E src \\in Contexts : \\E targetSet \\in (SUBSET Contexts \\ {{}}) : \\E tab \\in ${tabSet} : \\E msgType \\in UserMessageTypes :`);
|
|
1688
1729
|
this.indent++;
|
|
1689
1730
|
this.line("SendMessage(src, targetSet, tab, msgType) /\\ UNCHANGED <<contextStates, payload>>");
|
|
1690
1731
|
this.indent--;
|
|
@@ -2111,9 +2152,12 @@ class DockerRunner {
|
|
|
2111
2152
|
"tlc",
|
|
2112
2153
|
"-workers",
|
|
2113
2154
|
`${options?.workers || 1}`,
|
|
2114
|
-
"-cleanup"
|
|
2115
|
-
`${specName}.tla`
|
|
2155
|
+
"-cleanup"
|
|
2116
2156
|
];
|
|
2157
|
+
if (options?.maxDepth !== undefined && options.maxDepth > 0) {
|
|
2158
|
+
args.push("-depth", `${options.maxDepth}`);
|
|
2159
|
+
}
|
|
2160
|
+
args.push(`${specName}.tla`);
|
|
2117
2161
|
const result = await this.runCommand("docker", args, {
|
|
2118
2162
|
timeout: options?.timeout
|
|
2119
2163
|
});
|
|
@@ -3037,6 +3081,26 @@ class ConfigValidator {
|
|
|
3037
3081
|
}
|
|
3038
3082
|
}
|
|
3039
3083
|
}
|
|
3084
|
+
if (messages.tabSymmetry !== undefined) {
|
|
3085
|
+
if (typeof messages.tabSymmetry !== "boolean") {
|
|
3086
|
+
this.issues.push({
|
|
3087
|
+
type: "invalid_value",
|
|
3088
|
+
severity: "error",
|
|
3089
|
+
field: "messages.tabSymmetry",
|
|
3090
|
+
message: "tabSymmetry must be a boolean",
|
|
3091
|
+
suggestion: "Use true or false"
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
if (messages.tabSymmetry && (messages.maxTabs === undefined || messages.maxTabs === null)) {
|
|
3095
|
+
this.issues.push({
|
|
3096
|
+
type: "invalid_value",
|
|
3097
|
+
severity: "warning",
|
|
3098
|
+
field: "messages.tabSymmetry",
|
|
3099
|
+
message: "tabSymmetry enabled but maxTabs not set",
|
|
3100
|
+
suggestion: "Set maxTabs to define the number of tabs for symmetry reduction"
|
|
3101
|
+
});
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3040
3104
|
}
|
|
3041
3105
|
validateVerificationOptions(verification) {
|
|
3042
3106
|
if (verification.timeout !== undefined) {
|
|
@@ -5920,6 +5984,12 @@ function getTimeout(config) {
|
|
|
5920
5984
|
function getWorkers(config) {
|
|
5921
5985
|
return config.verification?.workers ?? 1;
|
|
5922
5986
|
}
|
|
5987
|
+
function getMaxDepth(config) {
|
|
5988
|
+
if ("tier2" in config && config.tier2?.boundedExploration?.maxDepth) {
|
|
5989
|
+
return config.tier2.boundedExploration.maxDepth;
|
|
5990
|
+
}
|
|
5991
|
+
return;
|
|
5992
|
+
}
|
|
5923
5993
|
async function runFullVerification(configPath) {
|
|
5924
5994
|
const config = await loadVerificationConfig(configPath);
|
|
5925
5995
|
const analysis = await runCodebaseAnalysis();
|
|
@@ -5931,6 +6001,7 @@ async function runFullVerification(configPath) {
|
|
|
5931
6001
|
const docker = await setupDocker();
|
|
5932
6002
|
const timeoutSeconds = getTimeout(config);
|
|
5933
6003
|
const workers = getWorkers(config);
|
|
6004
|
+
const maxDepth = getMaxDepth(config);
|
|
5934
6005
|
console.log(color("⚙️ Running TLC model checker...", COLORS.blue));
|
|
5935
6006
|
if (timeoutSeconds === 0) {
|
|
5936
6007
|
console.log(color(" No timeout set - will run until completion", COLORS.gray));
|
|
@@ -5939,10 +6010,14 @@ async function runFullVerification(configPath) {
|
|
|
5939
6010
|
const timeoutLabel = timeoutMinutes > 0 ? `${timeoutMinutes} minute${timeoutMinutes > 1 ? "s" : ""}` : `${timeoutSeconds} seconds`;
|
|
5940
6011
|
console.log(color(` Timeout: ${timeoutLabel}`, COLORS.gray));
|
|
5941
6012
|
}
|
|
6013
|
+
if (maxDepth !== undefined) {
|
|
6014
|
+
console.log(color(` Max depth: ${maxDepth}`, COLORS.gray));
|
|
6015
|
+
}
|
|
5942
6016
|
console.log();
|
|
5943
6017
|
const result = await docker.runTLC(specPath, {
|
|
5944
6018
|
workers,
|
|
5945
|
-
timeout: timeoutSeconds > 0 ? timeoutSeconds * 1000 : undefined
|
|
6019
|
+
timeout: timeoutSeconds > 0 ? timeoutSeconds * 1000 : undefined,
|
|
6020
|
+
maxDepth
|
|
5946
6021
|
});
|
|
5947
6022
|
displayVerificationResults(result, specDir);
|
|
5948
6023
|
}
|
|
@@ -6159,4 +6234,4 @@ main().catch((error) => {
|
|
|
6159
6234
|
process.exit(1);
|
|
6160
6235
|
});
|
|
6161
6236
|
|
|
6162
|
-
//# debugId=
|
|
6237
|
+
//# debugId=A9938BA1A7CCD3B464756E2164756E21
|