mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
test(ci): quarantine concurrency-sensitive flakes into a serial pass (#6347)
* test(ci): quarantine concurrency-sensitive flakes into a serial pass (tests/unit/serial/) glm-coding-plan-monthly-3580, quota-division-blocks and provider-health-autopilot fail under --test-concurrency>1 CPU contention but pass isolated (v3.8.45 release benchmark: this class cost ~28min re-runs per CI round). They now live in tests/unit/serial/ and run in a dedicated --test-concurrency=1 step appended to every runner (test:unit, :ci, :ci:shard, :fast, :shard:1/2, coverage:runner — sharded variants shard the serial pass too, so concurrent shard jobs never self-collide). Discovery + TIA gates know the new glob; stryker.conf.json path updated. Guard: tests/unit/test-serial-quarantine.test.ts (4 tests). * test(ci): quarantine combo-health-autopilot too (async logger writes after test end under load) Fresh evidence from this PR's own CI: all 3 subtests pass but an async log write lands after the test ends (ENOENT app.log -> uncaughtException) — same concurrency-flake family. Moved to tests/unit/serial/, imports adjusted, stryker path updated, guard test now asserts 4 quarantined files.
This commit is contained in:
committed by
GitHub
parent
5d07bdd76f
commit
c0430342c6
15
package.json
15
package.json
@@ -97,13 +97,13 @@
|
||||
"electron:build:linux": "npm run build && cd electron && npm run build:linux",
|
||||
"electron:smoke:packaged": "node scripts/dev/smoke-electron-packaged.mjs",
|
||||
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-concurrency=20 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-concurrency=20 \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=20 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=20 \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit:ci": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit:ci:shard": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 --test-shard=$TEST_SHARD tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 --test-shard=$TEST_SHARD \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit:fast": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-isolation=none tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-isolation=none \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=20 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=20 \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial",
|
||||
"test:unit:ci": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial",
|
||||
"test:unit:ci:shard": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 --test-shard=$TEST_SHARD tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=4 --test-shard=$TEST_SHARD \"tests/unit/dashboard/**/*.test.ts\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=$TEST_SHARD \"tests/unit/serial/**/*.test.ts\"",
|
||||
"test:unit:fast": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-isolation=none tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-isolation=none \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial",
|
||||
"test:unit:shard": "concurrently --kill-others-on-fail -n s1,s2 \"npm:test:unit:shard:1\" \"npm:test:unit:shard:2\"",
|
||||
"test:unit:shard:1": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit:shard:2": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 \"tests/unit/dashboard/**/*.test.ts\"",
|
||||
"test:unit:shard:1": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 \"tests/unit/dashboard/**/*.test.ts\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=1/2 \"tests/unit/serial/**/*.test.ts\"",
|
||||
"test:unit:shard:2": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 \"tests/unit/dashboard/**/*.test.ts\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 --test-shard=2/2 \"tests/unit/serial/**/*.test.ts\"",
|
||||
"test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test tests/unit/plan3-p0.test.ts",
|
||||
"test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test tests/unit/fixes-p1.test.ts",
|
||||
"test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test tests/unit/security-fase01.test.ts",
|
||||
@@ -212,7 +212,8 @@
|
||||
"build:cli-api": "node --import tsx/esm scripts/cli/generate-api-commands.mjs",
|
||||
"release:contributors": "node scripts/release/gen-contributors.mjs",
|
||||
"release:uncovered": "node scripts/release/list-uncovered-commits.mjs",
|
||||
"test:coverage:runner": "node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=8 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true NODE_OPTIONS=--max-old-space-size=8192 c8 --merge-async --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=8 \"tests/unit/dashboard/**/*.test.ts\""
|
||||
"test:coverage:runner": "node --max-old-space-size=8192 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=8 tests/unit/*.test.ts \"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,db,db-adapters,docs,gamification,guardrails,lib,mcp,memory,runtime,security,services,settings,shared,ui,usage}/**/*.test.ts\" \"tests/unit/**/*.test.mjs\" && cross-env DISABLE_SQLITE_AUTO_BACKUP=true NODE_OPTIONS=--max-old-space-size=8192 c8 --merge-async --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=8 \"tests/unit/dashboard/**/*.test.ts\" && npm run test:unit:serial",
|
||||
"test:unit:serial": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=4096 --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit --test-concurrency=1 \"tests/unit/serial/**/*.test.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.1073.0",
|
||||
|
||||
@@ -67,6 +67,11 @@ export const COLLECTORS = [
|
||||
// 24.18 do CI; no 24.16 local vira um crawl de ~60s/arquivo). O resto da suíte roda
|
||||
// sob tsx/esm (~-50% de bootstrap por processo). Plano mestre testes+CI, QW-b.
|
||||
{ glob: "tests/unit/dashboard/**/*.test.ts", sources: ["package.json"] },
|
||||
// Quarentena de flakes de concorrência (plano melhorias v3.8.46, P0.3): arquivos
|
||||
// sensíveis a contenção de CPU/timing (classe glm-3580 / quota-division /
|
||||
// provider-health-autopilot) rodam num passo dedicado --test-concurrency=1 ao FIM
|
||||
// de cada runner. Fora dos globs paralelos acima por diretório próprio.
|
||||
{ glob: "tests/unit/serial/**/*.test.ts", sources: ["package.json"] },
|
||||
// Órfãos religados (plano mestre QW-c): arquivos .test.mjs (top-level + db/ + feature-triage/) — fora do glob
|
||||
// *.test.ts histórico, nunca rodava em job nenhum (53 casos recuperados).
|
||||
{ glob: "tests/unit/**/*.test.mjs", sources: ["package.json"] },
|
||||
|
||||
@@ -61,6 +61,8 @@ const testFiles = globSync(
|
||||
[
|
||||
"tests/unit/*.test.ts",
|
||||
"tests/unit/{api,auth,authz,build,cli,cli-helper,combo,compression,correctness,cors,dashboard,db,db-adapters,docs,executors,gamification,guardrails,lib,mcp,runtime,security,services,settings,shared,ui}/**/*.test.ts",
|
||||
// Quarentena serial (P0.3): também são node:test — a TIA precisa mapeá-los.
|
||||
"tests/unit/serial/**/*.test.ts",
|
||||
],
|
||||
{ cwd: ROOT, absolute: true }
|
||||
);
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
"tests/unit/combo-config.test.ts",
|
||||
"tests/unit/combo-context-relay.test.ts",
|
||||
"tests/unit/combo-headroom-strategy.test.ts",
|
||||
"tests/unit/combo-health-autopilot.test.ts",
|
||||
"tests/unit/serial/combo-health-autopilot.test.ts",
|
||||
"tests/unit/combo-health-dashboard.test.ts",
|
||||
"tests/unit/combo-health-route.test.ts",
|
||||
"tests/unit/combo-hedging.test.ts",
|
||||
@@ -189,7 +189,7 @@
|
||||
"tests/unit/plugin-sandbox-permissions.test.ts",
|
||||
"tests/unit/plugins-route-error-sanitization.test.ts",
|
||||
"tests/unit/provider-error-rules.test.ts",
|
||||
"tests/unit/provider-health-autopilot.test.ts",
|
||||
"tests/unit/serial/provider-health-autopilot.test.ts",
|
||||
"tests/unit/provider-health-matrix.test.ts",
|
||||
"tests/unit/provider-request-failure-pipeline.test.ts",
|
||||
"tests/unit/public-client-ids-3493.test.ts",
|
||||
|
||||
@@ -4,7 +4,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
import { makeManagementSessionRequest } from "../helpers/managementSession.ts";
|
||||
import { makeManagementSessionRequest } from "../../helpers/managementSession.ts";
|
||||
|
||||
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-combo-autopilot-"));
|
||||
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
|
||||
@@ -13,15 +13,15 @@ const ORIGINAL_JWT_SECRET = process.env.JWT_SECRET;
|
||||
|
||||
process.env.DATA_DIR = TEST_DATA_DIR;
|
||||
|
||||
const core = await import("../../src/lib/db/core.ts");
|
||||
const combosDb = await import("../../src/lib/db/combos.ts");
|
||||
const settingsDb = await import("../../src/lib/db/settings.ts");
|
||||
const quotaSnapshotsDb = await import("../../src/lib/db/quotaSnapshots.ts");
|
||||
const callLogs = await import("../../src/lib/usage/callLogs.ts");
|
||||
const comboMetrics = await import("../../open-sse/services/comboMetrics.ts");
|
||||
const comboAutopilot = await import("../../src/lib/monitoring/comboHealthAutopilot.ts");
|
||||
const route = await import("../../src/app/api/usage/combo-health-autopilot/route.ts");
|
||||
const { normalizeComboStep } = await import("../../src/lib/combos/steps.ts");
|
||||
const core = await import("../../../src/lib/db/core.ts");
|
||||
const combosDb = await import("../../../src/lib/db/combos.ts");
|
||||
const settingsDb = await import("../../../src/lib/db/settings.ts");
|
||||
const quotaSnapshotsDb = await import("../../../src/lib/db/quotaSnapshots.ts");
|
||||
const callLogs = await import("../../../src/lib/usage/callLogs.ts");
|
||||
const comboMetrics = await import("../../../open-sse/services/comboMetrics.ts");
|
||||
const comboAutopilot = await import("../../../src/lib/monitoring/comboHealthAutopilot.ts");
|
||||
const route = await import("../../../src/app/api/usage/combo-health-autopilot/route.ts");
|
||||
const { normalizeComboStep } = await import("../../../src/lib/combos/steps.ts");
|
||||
|
||||
async function resetStorage() {
|
||||
comboMetrics.resetAllComboMetrics();
|
||||
@@ -1,7 +1,7 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { glmMonthlyRemainingPercentage } from "../../open-sse/services/usage.ts";
|
||||
import { glmMonthlyRemainingPercentage } from "../../../open-sse/services/usage.ts";
|
||||
|
||||
// #3580 — z.ai/GLM coding plans have no monthly cap (only 5-hour windows), so the
|
||||
// quota API reports the TIME_LIMIT ("Monthly") entry with total=0. The previous
|
||||
@@ -4,7 +4,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { NextRequest } from "next/server";
|
||||
import { makeManagementSessionRequest } from "../helpers/managementSession.ts";
|
||||
import { makeManagementSessionRequest } from "../../helpers/managementSession.ts";
|
||||
|
||||
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-health-autopilot-"));
|
||||
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
|
||||
@@ -13,14 +13,14 @@ const ORIGINAL_JWT_SECRET = process.env.JWT_SECRET;
|
||||
|
||||
process.env.DATA_DIR = TEST_DATA_DIR;
|
||||
|
||||
const core = await import("../../src/lib/db/core.ts");
|
||||
const settingsDb = await import("../../src/lib/db/settings.ts");
|
||||
const providersDb = await import("../../src/lib/db/providers.ts");
|
||||
const autopilot = await import("../../src/lib/monitoring/providerHealthAutopilot.ts");
|
||||
const actionsRoute = await import("../../src/app/api/providers/health-autopilot/actions/route.ts");
|
||||
const reportRoute = await import("../../src/app/api/providers/health-autopilot/route.ts");
|
||||
const routeGuard = await import("../../src/server/authz/routeGuard.ts");
|
||||
const authzPipeline = await import("../../src/server/authz/pipeline.ts");
|
||||
const core = await import("../../../src/lib/db/core.ts");
|
||||
const settingsDb = await import("../../../src/lib/db/settings.ts");
|
||||
const providersDb = await import("../../../src/lib/db/providers.ts");
|
||||
const autopilot = await import("../../../src/lib/monitoring/providerHealthAutopilot.ts");
|
||||
const actionsRoute = await import("../../../src/app/api/providers/health-autopilot/actions/route.ts");
|
||||
const reportRoute = await import("../../../src/app/api/providers/health-autopilot/route.ts");
|
||||
const routeGuard = await import("../../../src/server/authz/routeGuard.ts");
|
||||
const authzPipeline = await import("../../../src/server/authz/pipeline.ts");
|
||||
const accountFallback = await import("@omniroute/open-sse/services/accountFallback");
|
||||
|
||||
const PROVIDER = "autopilot-test-provider";
|
||||
@@ -42,11 +42,11 @@ const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-division-
|
||||
process.env.DATA_DIR = TEST_DATA_DIR;
|
||||
|
||||
// ── Imports ──────────────────────────────────────────────────────────────────
|
||||
const providerPlans = await import("../../src/lib/db/providerPlans.ts");
|
||||
const quotaPools = await import("../../src/lib/db/quotaPools.ts");
|
||||
const { SqliteQuotaStore } = await import("../../src/lib/quota/sqliteQuotaStore.ts");
|
||||
const { enforceQuotaShare } = await import("../../src/lib/quota/enforce.ts");
|
||||
const core = await import("../../src/lib/db/core.ts");
|
||||
const providerPlans = await import("../../../src/lib/db/providerPlans.ts");
|
||||
const quotaPools = await import("../../../src/lib/db/quotaPools.ts");
|
||||
const { SqliteQuotaStore } = await import("../../../src/lib/quota/sqliteQuotaStore.ts");
|
||||
const { enforceQuotaShare } = await import("../../../src/lib/quota/enforce.ts");
|
||||
const core = await import("../../../src/lib/db/core.ts");
|
||||
|
||||
// ── Suite cleanup ─────────────────────────────────────────────────────────────
|
||||
test.after(() => {
|
||||
72
tests/unit/test-serial-quarantine.test.ts
Normal file
72
tests/unit/test-serial-quarantine.test.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync, readdirSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
|
||||
// Quarentena de flakes de concorrência (plano melhorias v3.8.46, P0.3).
|
||||
// Os arquivos em tests/unit/serial/ falham sob contenção de CPU (--test-concurrency>1
|
||||
// com a suíte inteira) mas passam isolados — classe glm-3580 / quota-division /
|
||||
// provider-health-autopilot, que custava re-runs de ~28min por rodada de CI.
|
||||
// Este guard garante que a quarentena continua ligada em TODOS os runners.
|
||||
|
||||
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const pkg = JSON.parse(readFileSync(path.join(ROOT, "package.json"), "utf8"));
|
||||
const scripts: Record<string, string> = pkg.scripts;
|
||||
|
||||
const SERIAL_GLOB = 'tests/unit/serial/**/*.test.ts';
|
||||
|
||||
test("test:unit:serial existe e roda o diretório de quarentena com concurrency=1", () => {
|
||||
const s = scripts["test:unit:serial"];
|
||||
assert.ok(s, "script test:unit:serial deve existir");
|
||||
assert.ok(s.includes("--test-concurrency=1"), "quarentena deve rodar serial");
|
||||
assert.ok(s.includes(SERIAL_GLOB), "quarentena deve apontar para tests/unit/serial/");
|
||||
});
|
||||
|
||||
test("todos os runners paralelos terminam com o passo serial", () => {
|
||||
for (const key of ["test:unit", "test:unit:ci", "test:unit:fast", "test:coverage:runner"]) {
|
||||
assert.ok(
|
||||
scripts[key].endsWith("&& npm run test:unit:serial"),
|
||||
`${key} deve encadear o passo serial no fim`
|
||||
);
|
||||
}
|
||||
for (const [key, shard] of [
|
||||
["test:unit:ci:shard", "$TEST_SHARD"],
|
||||
["test:unit:shard:1", "1/2"],
|
||||
["test:unit:shard:2", "2/2"],
|
||||
] as const) {
|
||||
const s = scripts[key];
|
||||
const serialPart = s.slice(s.lastIndexOf("&&"));
|
||||
assert.ok(serialPart.includes("--test-concurrency=1"), `${key}: passo serial ausente`);
|
||||
assert.ok(
|
||||
serialPart.includes(`--test-shard=${shard}`),
|
||||
`${key}: o passo serial deve ser SHARDADO (${shard}) — sem isso os dois shards rodam ` +
|
||||
`os mesmos arquivos ao mesmo tempo e recriam a colisão que a quarentena elimina`
|
||||
);
|
||||
assert.ok(serialPart.includes(SERIAL_GLOB), `${key}: glob da quarentena ausente`);
|
||||
}
|
||||
});
|
||||
|
||||
test("os globs paralelos NÃO capturam tests/unit/serial/ (sem dupla execução)", () => {
|
||||
const parallel = scripts["test:unit"].split("&& npm run test:unit:serial")[0];
|
||||
assert.ok(!parallel.includes("serial"), "parte paralela não deve referenciar serial/");
|
||||
// o glob de subdiretórios é uma brace-list explícita — 'serial' não pode entrar nela
|
||||
const braceList = parallel.match(/tests\/unit\/\{([^}]+)\}/)?.[1] ?? "";
|
||||
assert.ok(!braceList.split(",").includes("serial"), "brace-list não deve conter 'serial'");
|
||||
});
|
||||
|
||||
test("a quarentena contém os 3 flakes conhecidos e os gates de discovery/TIA a conhecem", () => {
|
||||
const files = readdirSync(path.join(ROOT, "tests/unit/serial"));
|
||||
for (const f of [
|
||||
"glm-coding-plan-monthly-3580.test.ts",
|
||||
"quota-division-blocks.test.ts",
|
||||
"provider-health-autopilot.test.ts",
|
||||
"combo-health-autopilot.test.ts",
|
||||
]) {
|
||||
assert.ok(files.includes(f), `${f} deve estar na quarentena`);
|
||||
}
|
||||
const discovery = readFileSync(path.join(ROOT, "scripts/check/check-test-discovery.mjs"), "utf8");
|
||||
assert.ok(discovery.includes(SERIAL_GLOB), "check-test-discovery deve listar o glob serial");
|
||||
const tia = readFileSync(path.join(ROOT, "scripts/quality/build-test-impact-map.mjs"), "utf8");
|
||||
assert.ok(tia.includes(SERIAL_GLOB), "build-test-impact-map deve listar o glob serial");
|
||||
});
|
||||
Reference in New Issue
Block a user