docs: add Dewey row 131 r1 packet (plug-in kind registry and loader)
Candidate packet for #1626: build.patch on 0bdd573ff, candidate manifest,
targeted gate (588/0 over plugins, business, bus, webui, cli) and 42/42
mutants killed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
# Row 131 / #1626: the plug-in layer, kind registry and loader (round 1)
|
||||
|
||||
Builder: Dewey. Brief: `docs/plans/2026-10-14_prd-1.2-build.md`, step 6b.
|
||||
Requirements: REQ-PLUG-1 (the plug-in layer), REQ-LIMIT-4 (the first two kinds,
|
||||
usage-source and limit-check). The `plugins` write goes through step 5's write
|
||||
path (REQ-ROLE-3). Base: see `base.txt`. Source is in a detached worktree; nothing
|
||||
here is pushed, wired into a host process or written to Jason's organization file.
|
||||
|
||||
Governing rulings: lead decision 143 (in-repo modules only until Jason rules on
|
||||
Vikunja #286; no path from config) and sage-0301 (choices 1, 3, 4 and 5 as
|
||||
proposed; choice 2 changed).
|
||||
|
||||
## What ships
|
||||
|
||||
| Path | Change |
|
||||
| --- | --- |
|
||||
| `packages/plugins/package.json` | new package `@mosaic/plugins` |
|
||||
| `packages/plugins/src/kinds.mjs` | kind registry: usage-source and limit-check, interface version 1, each switched on by a list; `checkPlugins` for the organization file's `plugins` key |
|
||||
| `packages/plugins/src/loader.mjs` | `createLoader({log})` → `{load, loaded, modules}` |
|
||||
| `packages/plugins/README.md` | kinds, export contract, adding a module, the key, the loader and its limits |
|
||||
| `packages/plugins/tests/{helpers,kinds.test,loader.test}.mjs` | 19 tests |
|
||||
| `packages/business/src/business.mjs` | `plugins` in TOP_KEYS; checked with `checkPlugins`; returned frozen (`{}` when absent) |
|
||||
| `packages/business/src/plugin-settings.mjs` | the host setter: the only writer of `plugins`, through `organizationWriter` |
|
||||
| `packages/business/tests/plugin-settings.test.mjs` | 3 tests: schema, setter success and log, setter refusals |
|
||||
| `packages/business/README.md` | the `plugins` key and its writer |
|
||||
| `scripts/stack-copy.sh` | whole `packages/plugins` in COPY_PATHS (approved, sage-0301) |
|
||||
| `packages/cli/tests/stack-copy.test.mjs` | the copied-path list includes the plug-in sources |
|
||||
|
||||
No module of either kind ships. No core module imports a plug-in module by
|
||||
name: `business.mjs` and `plugin-settings.mjs` import only `kinds.mjs`, and
|
||||
nothing imports `loader.mjs` outside its tests. `organization.mjs` is untouched.
|
||||
No limit ceiling is in code (Q150).
|
||||
|
||||
## sage-0301 rulings, as built
|
||||
|
||||
1. **One writer.** `pluginSettings({dir, rolesDir}).set(id, {revision, plugins}, actor)`
|
||||
is the only writer. No broker verb, mosaic command, Settings form or
|
||||
chief-of-staff write was added.
|
||||
2. **A refused write throws a code and logs nothing.** `set` checks the request
|
||||
shape (`invalid-request`: anything but `revision` and `plugins`, or a revision
|
||||
that isn't 64 hex) and the value (`invalid-plugins`, from `checkPlugins`)
|
||||
before the writer runs. The writer validates the whole document before its
|
||||
`prepared` entry, so nothing reaches `changes.jsonl`. The test checks the
|
||||
file bytes are unchanged and the log is empty after eleven refusals. A
|
||||
committed write logs actor, transaction and old and new names per kind, the
|
||||
same way a limit change does (`plugins` with old null when the key was
|
||||
absent; `plugins.<kind>` with whole old and new lists after that).
|
||||
Load-time refusals go through the loader's `log` callback.
|
||||
3. **Last good modules per kind.** A loader instance holds, per kind, the
|
||||
modules from its last good load. Any refusal for a kind keeps them. A kind
|
||||
refused on its first load has nothing on. The test loads `["meter","absent"]`
|
||||
so a half-loaded list would show. `load()` and `loaded()` report what each
|
||||
kind actually has on. Every refusal calls `log` once with
|
||||
`{event: "plugin-refused", kind, name, code, message, kept}`; the first-load
|
||||
test checks kind and name. The loader is not wired into any host process.
|
||||
4. **Export contract.** Every module exports `interfaceVersion`; usage-source
|
||||
exports `readTurn`; limit-check exports `mayLaunch` and `mustStop`; both kinds
|
||||
switch on a list. The README carries the contract. These names bind row 124.
|
||||
Argument and return shapes are left to the calling rows.
|
||||
5. **What is checked.** `packages/plugins`, `<kind>`, `<name>` (each an lstat:
|
||||
exists, a directory, not a symlink) and `index.mjs` (exists, a regular file,
|
||||
not a symlink); not the ancestors of `packages/plugins`. Just before
|
||||
`import`, `realpath(index.mjs)` must equal
|
||||
`realpath(packages/plugins)/<kind>/<name>/index.mjs`, and the import uses that
|
||||
expected path.
|
||||
|
||||
## The check-then-import gap
|
||||
|
||||
For Darkwing, in those words: there is a check-then-import gap. The lstat
|
||||
checks and the realpath comparison run, then `import()` opens the file by path.
|
||||
Someone who can write `packages/plugins` as the host's user can swap
|
||||
`index.mjs` (or a directory above it) between the realpath check and the open
|
||||
inside `import()`. Node has no import-from-descriptor, so the loader cannot
|
||||
close the gap. The checks catch mistakes, stale links and a link planted
|
||||
before load; they do not stop a writer racing the host as the same user, and
|
||||
such a writer could edit any core file anyway. The test with the `checked`
|
||||
barrier swaps `index.mjs` for a symlink after the lstat checks and shows the
|
||||
realpath check refusing it; it cannot show the narrower window after realpath.
|
||||
The README states the same limit. Two related limits: a module runs with the
|
||||
host's authority once imported (the loader does not sandbox it), and Node
|
||||
caches modules by URL, so a changed `index.mjs` is not re-read until restart.
|
||||
|
||||
The `packages/plugins` symlink case is only reachable when Node keeps symlinked
|
||||
paths (`--preserve-symlinks`); otherwise `import.meta.url` is already the real
|
||||
path. The test runs that case in a child `node --preserve-symlinks`.
|
||||
|
||||
## Acceptance, mapped
|
||||
|
||||
| Acceptance item | Where |
|
||||
| --- | --- |
|
||||
| a test for each refusal, old setting kept | `loader.test.mjs`: bad name, missing (absent dir, empty dir, dir as index), symlink (name dir, index, kind dir, packages/plugins, realpath swap), load-failed (syntax error, top-level throw), missing export (absent, non-function, half of limit-check, no interfaceVersion), interface version (2, string "1"); each through `refusesKeepingOld`, which checks the kept setting, the one refusal entry and the one log call |
|
||||
| fixture module of each kind switched on from a test organization file, no core file changed | `loader.test.mjs` first test: a business document built with business test helpers, validated by `validateBusinessDocument`, its `plugins` passed to the loader; fixture modules written into a temp copy of the package |
|
||||
| one mutant per check, each failing a test | `MUTANTS.md`, `mutants.py`, `mutants/results.json` |
|
||||
| `plugins` key in the schema, written through step 5's write path and logged like a limit change | `plugin-settings.test.mjs` |
|
||||
|
||||
REQ ids are in each test name.
|
||||
|
||||
## Gate (decision 136, targeted)
|
||||
|
||||
Approved list (sage-0301): plugins, business, bus, webui, cli, each
|
||||
`node --test tests/*.test.mjs` (the command land-work.sh runs), via `gate.sh`.
|
||||
Run 2026-10-15T16:20:28Z to 16:21:48Z in the slot Sage gave in sage-0310, on the
|
||||
candidate as shipped in `build.patch`. Logs: `gate/`, summary `gate-run.log`.
|
||||
|
||||
| Package | Tests | Pass | Fail |
|
||||
| --- | --- | --- | --- |
|
||||
| plugins | 19 | 19 | 0 |
|
||||
| business | 91 | 91 | 0 |
|
||||
| bus | 171 | 171 | 0 |
|
||||
| webui (includes pinned-copy.test.mjs) | 112 | 112 | 0 |
|
||||
| cli (includes stack-copy.test.mjs) | 195 | 195 | 0 |
|
||||
|
||||
Not run: the other packages and the shell suites; Sage's full gate at the
|
||||
landing target covers them (decision 136). BASE..refactor HEAD (ea5e70fa8 at
|
||||
packet time) touches none of the candidate's paths.
|
||||
|
||||
Mutants: 42 of 42 killed (`MUTANTS.md`).
|
||||
|
||||
## Overlap
|
||||
|
||||
Row 123 (Researcher) also edits `packages/business/README.md`. Sage orders the
|
||||
landings; the second row rebases.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Row 131 mutants (round 1)
|
||||
|
||||
One fault per check. `mutants.py` makes each edit to the candidate, runs only the
|
||||
listed test files with `node --test` in its own process group (whole-group kill at
|
||||
300 s), records the result and restores the file. `mutants.py --dry` checks that each
|
||||
mutation site appears exactly once. Per-mutant output is in `mutants/<id>.log`;
|
||||
`mutants/results.json` holds every result. Run: 2026-10-15T16:21:54Z to 16:22:09Z, in
|
||||
the slot Sage gave in sage-0310.
|
||||
|
||||
Result: 42 of 42 KILLED, 0 SURVIVED, 0 TIMEOUT.
|
||||
|
||||
| Mutant | Check | Result | Test files | First failing test |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 01-name-pattern | kinds: names must match ^[a-z][a-z0-9-]*$ | KILLED (exit 1) | plugins/tests/kinds.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates |
|
||||
| 02-list-cardinality | kinds: a list kind refuses a non-list | KILLED (exit 1) | plugins/tests/kinds.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything |
|
||||
| 03-one-cardinality | kinds: a one-module kind refuses a non-string | KILLED (exit 1) | plugins/tests/kinds.test.mjs | REQ-PLUG-1 a kind that switches on one module takes one name, not a list |
|
||||
| 04-no-duplicates | kinds: a name twice refuses | KILLED (exit 1) | plugins/tests/kinds.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates |
|
||||
| 05-known-kind | kinds: an unknown kind refuses | KILLED (exit 1) | plugins/tests/kinds.test.mjs | REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates |
|
||||
| 06-plugins-object | kinds: plugins must be a non-array object | KILLED (exit 1) | plugins/tests/kinds.test.mjs | REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates |
|
||||
| 07-registry-exports | registry: limit-check exports mayLaunch and mustStop | KILLED (exit 1) | plugins/tests/kinds.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list |
|
||||
| 08-registry-version | registry: usage-source is interface version 1 | KILLED (exit 1) | plugins/tests/kinds.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list |
|
||||
| 09-missing-directory | loader: an absent path refuses as missing | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting |
|
||||
| 10-component-type | loader: a component of the wrong type refuses | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting |
|
||||
| 11-symlink-test | loader: a symlinked component refuses | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting |
|
||||
| 12-plugins-dir-checked | loader: packages/plugins is checked | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) |
|
||||
| 13-kind-dir-checked | loader: <kind> is checked | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting |
|
||||
| 14-name-dir-checked | loader: <name> is checked | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting |
|
||||
| 15-index-checked | loader: index.mjs is checked | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting |
|
||||
| 16-realpath-before-import | loader: realpath(index.mjs) equals the expected path just before import | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check |
|
||||
| 17-load-failure | loader: a module that fails to load refuses | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a module that fails to load refuses and keeps the old setting |
|
||||
| 18-export-present | loader: every export is present | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing export refuses and keeps the old setting |
|
||||
| 19-export-function | loader: the kind's exports are functions | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing export refuses and keeps the old setting |
|
||||
| 20-interface-version | loader: interfaceVersion must equal the kind's | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a different interface version refuses and keeps the old setting |
|
||||
| 21-version-strict | loader: the version comparison is strict (string "1" refuses) | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a different interface version refuses and keeps the old setting |
|
||||
| 22-keep-old-setting | loader: a refusal keeps the last good modules | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting |
|
||||
| 23-first-load-nothing-on | loader: a kind refused on first load has nothing on | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name |
|
||||
| 24-refusal-logged | loader: every refusal calls log | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting |
|
||||
| 25-log-names-module | loader: the log names the refused module | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting |
|
||||
| 26-log-kept | loader: the log says what stays on | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting |
|
||||
| 27-whole-setting-object | loader: an array setting refuses every kind | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything |
|
||||
| 28-unknown-kind-logged | loader: an unknown kind refuses and is logged | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything |
|
||||
| 29-absent-key-off | loader: an absent key switches the kind off | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything |
|
||||
| 30-loads-serialized | loader: loads run one at a time | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 loads run one at a time, so the last requested setting wins |
|
||||
| 31-log-required | loader: createLoader needs a log callback | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 the loader needs a log callback |
|
||||
| 32-schema-key | schema: plugins is an allowed top-level key | KILLED (exit 1) | business/tests/plugin-settings.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names |
|
||||
| 33-schema-check | schema: plugins is checked with checkPlugins | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names |
|
||||
| 34-schema-returned | schema: plugins is returned | KILLED (exit 1) | business/tests/plugin-settings.test.mjs, plugins/tests/loader.test.mjs | REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names |
|
||||
| 35-schema-copy | schema: the returned value is a frozen copy, the document stays mutable | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names |
|
||||
| 36-setter-strict-keys | setter: only revision and plugins are accepted | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing |
|
||||
| 37-setter-revision-format | setter: revision must be 64 hex | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing |
|
||||
| 38-setter-checks-names | setter: plugins is checked before the writer runs | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing |
|
||||
| 39-setter-actor-logged | setter: the actor is logged | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names |
|
||||
| 40-setter-writes-plugins | setter: plugins is written | KILLED (exit 1) | business/tests/plugin-settings.test.mjs | REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names |
|
||||
| 41-copy-ships-plugins | stack-copy: packages/plugins ships in the pinned copy | KILLED (exit 1) | cli/tests/stack-copy.test.mjs | shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation |
|
||||
| 42-modules-known-kind | loader: modules() refuses an unknown kind | KILLED (exit 1) | plugins/tests/loader.test.mjs | REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything |
|
||||
|
||||
`42-modules-known-kind` was added after the slot request named 41 mutants, together
|
||||
with its test, before the run. Mutant 17's log shows a SyntaxError: it is the
|
||||
fixture module's deliberate syntax error, which the mutant rethrows instead of refusing.
|
||||
@@ -0,0 +1 @@
|
||||
0bdd573ffff11bd563113f0077e88e9075b5de58
|
||||
@@ -0,0 +1,904 @@
|
||||
diff --git a/packages/business/README.md b/packages/business/README.md
|
||||
index 9a6baad3c..4b091dcc2 100644
|
||||
--- a/packages/business/README.md
|
||||
+++ b/packages/business/README.md
|
||||
@@ -100,6 +100,13 @@ instance whose definition holds `role.launch` within-role; otherwise the
|
||||
file refuses. Only that instance keeps `role.launch`. Every other instance
|
||||
loses it, so for them it's gated.
|
||||
|
||||
+`plugins` (optional) switches on plug-in modules, one key per kind from
|
||||
+`packages/plugins/src/kinds.mjs`, each a list of module names matching
|
||||
+`^[a-z][a-z0-9-]*$` with no name twice. An unknown kind or a bad name
|
||||
+refuses the file. Absent means nothing is switched on. Whether a named
|
||||
+module exists and loads is the plug-in loader's check, at load time; see
|
||||
+`packages/plugins/README.md`.
|
||||
+
|
||||
### Chief-of-staff and assistant instances
|
||||
|
||||
Two roles stand above the PM (PRD 1.2; row 119, #1613).
|
||||
@@ -237,7 +244,10 @@ launches keep using the whole validated file on disk, without consulting receipt
|
||||
confirm that its old writer is gone before clearing it; the host does not
|
||||
race another recovering process by deleting locks automatically. Settings reads never repair evidence themselves.
|
||||
`launch-settings.mjs` restricts human edits to limits, model table and instance
|
||||
-model selections and validates effective selections before publication. Migration
|
||||
+model selections and validates effective selections before publication. `plugin-settings.mjs`
|
||||
+is the only writer of `plugins`: the host calls it, and no broker verb, `mosaic`
|
||||
+command or Settings form reaches it. A refused `plugins` write throws
|
||||
+`invalid-plugins` or `invalid-request` before the writer runs and logs nothing. Migration
|
||||
uses none of this: it only prints a converted document (decision 145).
|
||||
|
||||
For inherited selections, print-only migration reads the existing system config
|
||||
diff --git a/packages/business/src/business.mjs b/packages/business/src/business.mjs
|
||||
index cbe04a59b..49ac1fa45 100644
|
||||
--- a/packages/business/src/business.mjs
|
||||
+++ b/packages/business/src/business.mjs
|
||||
@@ -9,12 +9,13 @@ import { checkModels, checkLimits } from "./launch.mjs";
|
||||
import { checkVars } from "./vars.mjs";
|
||||
import { parseCredentialRef } from "./credentials.mjs";
|
||||
import { loadRole } from "./role.mjs";
|
||||
+import { checkPlugins } from "../../plugins/src/kinds.mjs";
|
||||
import {
|
||||
requireObject, rejectUnknownKeys, requireId, requirePositiveInt, requireString, requireDistinctList, readJsonFile, deepFreeze,
|
||||
} from "./util.mjs";
|
||||
|
||||
const BOT_NAME = /^bot-[a-z0-9][a-z0-9._-]{0,60}$/;
|
||||
-const TOP_KEYS = ["businessVersion", "id", "human", "arbiters", "projects", "vars", "tracker", "roles", "launch"];
|
||||
+const TOP_KEYS = ["businessVersion", "id", "human", "arbiters", "projects", "vars", "tracker", "roles", "launch", "plugins"];
|
||||
|
||||
// The config directory: next to the system config, $MOSAIC_CONFIG or
|
||||
// ~/.config/mosaic-dev/config.json, the same rule mosaic-config.mjs uses.
|
||||
@@ -178,9 +179,13 @@ export function validateBusinessDocument(document, file, { rolesDir }) {
|
||||
}
|
||||
}
|
||||
const launch = document.launch === undefined ? null : checkLaunch(document.launch, roles, definitions, file);
|
||||
+ // REQ-PLUG-1: the module names switched on per kind. The names are checked
|
||||
+ // here; whether each module loads is the loader's check, at load time.
|
||||
+ const plugins = document.plugins === undefined ? {}
|
||||
+ : structuredClone(checkPlugins(document.plugins, `${file} plugins`, { fail: (_code, message) => refuse(message) }));
|
||||
|
||||
return deepFreeze({
|
||||
- businessVersion: 1, id: document.id, file, human, arbiters, projects, vars, tracker, roles, launch, definitions,
|
||||
+ businessVersion: 1, id: document.id, file, human, arbiters, projects, vars, tracker, roles, launch, plugins, definitions,
|
||||
});
|
||||
}
|
||||
|
||||
diff --git a/packages/business/src/plugin-settings.mjs b/packages/business/src/plugin-settings.mjs
|
||||
new file mode 100644
|
||||
index 000000000..7827a7ec9
|
||||
--- /dev/null
|
||||
+++ b/packages/business/src/plugin-settings.mjs
|
||||
@@ -0,0 +1,38 @@
|
||||
+// Host setter for the organization file's `plugins` switch (REQ-PLUG-1,
|
||||
+// REQ-ROLE-3). It is the only writer of that key: no broker verb, mosaic
|
||||
+// command, Settings form or chief-of-staff write reaches it (sage-0301).
|
||||
+// Writes go through the organization writer, which logs old and new names
|
||||
+// like a limit change. A refused write throws a code and logs nothing.
|
||||
+import { organizationWriter, OrganizationError } from "./organization.mjs";
|
||||
+import { isPlainObject } from "./util.mjs";
|
||||
+import { PluginError, checkPlugins } from "../../plugins/src/kinds.mjs";
|
||||
+
|
||||
+export function pluginSettings({ dir, rolesDir }) {
|
||||
+ const writer = organizationWriter({ dir, rolesDir });
|
||||
+
|
||||
+ function read(id) {
|
||||
+ const { document, revision } = writer.read(id);
|
||||
+ return { business: id, revision, plugins: structuredClone(document.plugins ?? {}) };
|
||||
+ }
|
||||
+
|
||||
+ function set(id, args, actor) {
|
||||
+ if (!isPlainObject(args) || Object.keys(args).some(key => key !== "revision" && key !== "plugins")) {
|
||||
+ throw new OrganizationError("invalid-request");
|
||||
+ }
|
||||
+ if (typeof args.revision !== "string" || !/^[a-f0-9]{64}$/.test(args.revision)) {
|
||||
+ throw new OrganizationError("invalid-request");
|
||||
+ }
|
||||
+ try {
|
||||
+ checkPlugins(args.plugins, "plugins");
|
||||
+ } catch (e) {
|
||||
+ if (e instanceof PluginError) throw new OrganizationError("invalid-plugins", e.message);
|
||||
+ throw e;
|
||||
+ }
|
||||
+ const next = structuredClone(writer.read(id).document);
|
||||
+ next.plugins = structuredClone(args.plugins);
|
||||
+ const receipt = writer.write(id, next, { revision: args.revision, actor });
|
||||
+ return { ...read(id), transaction: receipt.transaction };
|
||||
+ }
|
||||
+
|
||||
+ return { writer, read, set };
|
||||
+}
|
||||
diff --git a/packages/business/tests/plugin-settings.test.mjs b/packages/business/tests/plugin-settings.test.mjs
|
||||
new file mode 100644
|
||||
index 000000000..ec3c55cbe
|
||||
--- /dev/null
|
||||
+++ b/packages/business/tests/plugin-settings.test.mjs
|
||||
@@ -0,0 +1,86 @@
|
||||
+// REQ-PLUG-1 / REQ-ROLE-3 (step 5 write path): the `plugins` key in the organization
|
||||
+// file, written only through the host setter and logged like a limit change.
|
||||
+import test, { after } from "node:test";
|
||||
+import assert from "node:assert/strict";
|
||||
+import { existsSync, readFileSync, rmSync } from "node:fs";
|
||||
+import { join } from "node:path";
|
||||
+import { businessDoc, rolesCopy, tmp as makeRoot, writeJson } from "./helpers.mjs";
|
||||
+import { validateBusinessDocument } from "../src/business.mjs";
|
||||
+import { pluginSettings } from "../src/plugin-settings.mjs";
|
||||
+import { OrganizationError } from "../src/organization.mjs";
|
||||
+import { BusinessError } from "../src/errors.mjs";
|
||||
+
|
||||
+const roots = [];
|
||||
+after(() => roots.forEach(root => rmSync(root, { recursive: true, force: true })));
|
||||
+
|
||||
+function fixture() {
|
||||
+ const root = makeRoot();
|
||||
+ roots.push(root);
|
||||
+ const rolesDir = rolesCopy(root);
|
||||
+ const doc = businessDoc(root, "acme");
|
||||
+ const file = writeJson(join(root, "businesses", "acme.json"), doc);
|
||||
+ return { root, rolesDir, doc, file, settings: pluginSettings({ dir: root, rolesDir }) };
|
||||
+}
|
||||
+
|
||||
+const events = f => existsSync(f.settings.writer.logFile("acme"))
|
||||
+ ? readFileSync(f.settings.writer.logFile("acme"), "utf8").trim().split("\n").map(JSON.parse) : [];
|
||||
+
|
||||
+test("REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names", () => {
|
||||
+ const f = fixture();
|
||||
+ const check = d => validateBusinessDocument(d, f.file, { rolesDir: f.rolesDir });
|
||||
+ assert.deepEqual(check(f.doc).plugins, {});
|
||||
+ const on = { ...structuredClone(f.doc), plugins: { "usage-source": ["meter"], "limit-check": [] } };
|
||||
+ const business = check(on);
|
||||
+ assert.deepEqual(business.plugins, on.plugins);
|
||||
+ assert.ok(Object.isFrozen(business.plugins));
|
||||
+ assert.ok(!Object.isFrozen(on.plugins), "the document itself stays mutable");
|
||||
+ for (const plugins of [{ "made-up": [] }, { "usage-source": "meter" }, { "usage-source": ["Meter"] }, { "usage-source": ["a", "a"] }, []]) {
|
||||
+ assert.throws(() => check({ ...structuredClone(f.doc), plugins }), BusinessError, JSON.stringify(plugins));
|
||||
+ }
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names", () => {
|
||||
+ const f = fixture();
|
||||
+ const view = f.settings.read("acme");
|
||||
+ assert.deepEqual(view.plugins, {});
|
||||
+ const done = f.settings.set("acme", { revision: view.revision, plugins: { "usage-source": ["meter"] } }, "jason");
|
||||
+ assert.deepEqual(JSON.parse(readFileSync(f.file, "utf8")).plugins, { "usage-source": ["meter"] });
|
||||
+ assert.deepEqual(done.plugins, { "usage-source": ["meter"] });
|
||||
+ assert.notEqual(done.revision, view.revision);
|
||||
+ let last = events(f).at(-1);
|
||||
+ assert.equal(last.state, "committed");
|
||||
+ assert.equal(last.actor, "jason");
|
||||
+ assert.equal(last.transaction, done.transaction);
|
||||
+ assert.deepEqual(last.changes, [{ path: "plugins", old: null, new: { "usage-source": ["meter"] }, oldPresent: false, newPresent: true }]);
|
||||
+ f.settings.set("acme", { revision: done.revision, plugins: { "usage-source": ["meter", "other"], "limit-check": ["cap"] } }, "jason");
|
||||
+ last = events(f).at(-1);
|
||||
+ assert.deepEqual(last.changes.map(c => [c.path, c.old, c.new]), [
|
||||
+ ["plugins.usage-source", ["meter"], ["meter", "other"]],
|
||||
+ ["plugins.limit-check", null, ["cap"]],
|
||||
+ ]);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing", () => {
|
||||
+ const f = fixture();
|
||||
+ const { revision } = f.settings.read("acme");
|
||||
+ const bytes = readFileSync(f.file, "utf8");
|
||||
+ const refusals = [
|
||||
+ [{ revision, plugins: { "made-up": ["x"] } }, "invalid-plugins"],
|
||||
+ [{ revision, plugins: { "usage-source": ["Bad"] } }, "invalid-plugins"],
|
||||
+ [{ revision, plugins: { "usage-source": "meter" } }, "invalid-plugins"],
|
||||
+ [{ revision, plugins: { "limit-check": ["cap", "cap"] } }, "invalid-plugins"],
|
||||
+ [{ revision }, "invalid-plugins"],
|
||||
+ [{ revision, plugins: [] }, "invalid-plugins"],
|
||||
+ [{ revision, plugins: {}, limits: {} }, "invalid-request"],
|
||||
+ [{ revision: "nope", plugins: {} }, "invalid-request"],
|
||||
+ [{ plugins: {} }, "invalid-request"],
|
||||
+ [null, "invalid-request"],
|
||||
+ [["x"], "invalid-request"],
|
||||
+ ];
|
||||
+ for (const [args, expected] of refusals) {
|
||||
+ assert.throws(() => f.settings.set("acme", args, "jason"),
|
||||
+ e => e instanceof OrganizationError && e.code === expected, JSON.stringify(args));
|
||||
+ }
|
||||
+ assert.equal(readFileSync(f.file, "utf8"), bytes);
|
||||
+ assert.deepEqual(events(f), []);
|
||||
+});
|
||||
diff --git a/packages/cli/tests/stack-copy.test.mjs b/packages/cli/tests/stack-copy.test.mjs
|
||||
index d98e771ac..d44ce5788 100644
|
||||
--- a/packages/cli/tests/stack-copy.test.mjs
|
||||
+++ b/packages/cli/tests/stack-copy.test.mjs
|
||||
@@ -34,7 +34,7 @@ export function setup(t, realPin=false){
|
||||
test('shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation',t=>{
|
||||
const s=setup(t),r=s.run('stack-copy.sh',['copy',s.id,'--copies',s.copies]);assert.equal(r.status,0,r.stderr);
|
||||
const copy=join(s.copies,s.id);assert.equal(statSync(copy).mode&0o777,0o555);
|
||||
- for(const f of ['scripts/mosaic','adapters/pi/adapter.sh','packages/queue/src/cli.mjs','package.json','package-lock.json','packages/tasks/requirements.json'])assert.ok(existsSync(join(copy,f)),f);
|
||||
+ for(const f of ['scripts/mosaic','adapters/pi/adapter.sh','packages/queue/src/cli.mjs','package.json','package-lock.json','packages/tasks/requirements.json','packages/plugins/src/kinds.mjs','packages/plugins/src/loader.mjs'])assert.ok(existsSync(join(copy,f)),f);
|
||||
const npm=join(s.bin,'npm');writeFileSync(npm,'#!/bin/sh\nexit 99\n');chmodSync(npm,0o755);
|
||||
const existing=s.run('webui-service.sh',['copy',s.id,'--copies',s.copies]);assert.equal(existing.status,0);assert.equal(existing.stdout,`exists: ${copy}\n`);unlinkSync(npm);
|
||||
git(s.repo,'update-ref','refs/remotes/origin/refactor',git(s.repo,'hash-object','-w','package.json'));
|
||||
diff --git a/packages/plugins/README.md b/packages/plugins/README.md
|
||||
new file mode 100644
|
||||
index 000000000..2960396c0
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/README.md
|
||||
@@ -0,0 +1,108 @@
|
||||
+# Plug-ins
|
||||
+
|
||||
+The plug-in layer (PRD REQ-PLUG-1, build step 6b, Gitea #1626). Every part
|
||||
+the core calls out to is a plug-in kind. A module of a kind is a directory
|
||||
+in this package, and the organization file says which modules are switched
|
||||
+on. No core module imports a plug-in module by name; calls go through the
|
||||
+loader.
|
||||
+
|
||||
+| Path | What it is |
|
||||
+|---|---|
|
||||
+| `src/kinds.mjs` | the kind registry and the check for the organization file's `plugins` key |
|
||||
+| `src/loader.mjs` | loads the switched-on modules from this tree |
|
||||
+| `<kind>/<name>/index.mjs` | one module of a kind |
|
||||
+
|
||||
+## Kinds
|
||||
+
|
||||
+| Kind | Interface | Switch | Exports |
|
||||
+|---|---|---|---|
|
||||
+| `usage-source` | 1 | list | `interfaceVersion`, `readTurn` |
|
||||
+| `limit-check` | 1 | list | `interfaceVersion`, `mayLaunch`, `mustStop` |
|
||||
+
|
||||
+Every module exports `interfaceVersion`, equal to its kind's interface
|
||||
+version, plus the kind's functions. PRD REQ-LIMIT-4 says what the two kinds
|
||||
+do: a usage source reads what a session used after each turn, and a limit
|
||||
+check answers whether a launch may start (`mayLaunch`) and whether a running
|
||||
+session must stop at the end of its turn (`mustStop`). The arguments and
|
||||
+return values of these functions are set by the rows that call them (row 124
|
||||
+converts the first usage source). No module of either kind ships yet.
|
||||
+
|
||||
+Adding a kind, or changing a kind's exports, interface version or switch,
|
||||
+is a core change: a reviewed edit to `src/kinds.mjs`, with the code that
|
||||
+calls the kind.
|
||||
+
|
||||
+## Adding a module
|
||||
+
|
||||
+1. Pick a name matching `^[a-z][a-z0-9-]*$`.
|
||||
+2. Create `packages/plugins/<kind>/<name>/index.mjs`. A real directory and
|
||||
+ a real file: the loader refuses a symlink anywhere from
|
||||
+ `packages/plugins` down, `index.mjs` included.
|
||||
+3. Export `interfaceVersion` and every function the kind lists.
|
||||
+4. Land it like any other change. A running stack sees it only after a
|
||||
+ re-pin, because `scripts/stack-copy.sh` copies the whole
|
||||
+ `packages/plugins` directory into the pinned copy.
|
||||
+5. Switch it on in the organization file's `plugins` object, under its
|
||||
+ kind. The host setter `packages/business/src/plugin-settings.mjs` is the
|
||||
+ only writer of that key.
|
||||
+
|
||||
+Adding a module changes no core file.
|
||||
+
|
||||
+## The organization file's `plugins` key
|
||||
+
|
||||
+One key per kind. A list kind takes a list of names; a kind that switches
|
||||
+on one module takes one name. An absent key switches the kind off.
|
||||
+
|
||||
+```json
|
||||
+"plugins": { "usage-source": ["meter"], "limit-check": [] }
|
||||
+```
|
||||
+
|
||||
+`validateBusinessDocument` checks the shape: known kinds, the name pattern,
|
||||
+no name twice. It doesn't check that a module exists; the loader does that
|
||||
+when it loads. The setter writes through the organization writer, which
|
||||
+logs actor and old and new names in `changes.jsonl` like a limit change. A
|
||||
+refused write throws `OrganizationError` (`invalid-plugins` or
|
||||
+`invalid-request`) and logs nothing.
|
||||
+
|
||||
+## The loader
|
||||
+
|
||||
+```js
|
||||
+import { createLoader } from "../packages/plugins/src/loader.mjs";
|
||||
+
|
||||
+const loader = createLoader({ log: entry => record(entry) });
|
||||
+const { loaded, refused } = await loader.load(business.plugins);
|
||||
+loader.modules("limit-check"); // the switched-on modules, in order
|
||||
+loader.loaded(); // { kind: [names actually switched on] }
|
||||
+```
|
||||
+
|
||||
+The loader finds this package from its own location and takes no path from
|
||||
+config. Until Jason rules on Vikunja #286 it loads modules from this tree
|
||||
+only (lead decision 143). For each name it checks, in order:
|
||||
+
|
||||
+1. the name matches `^[a-z][a-z0-9-]*$` (`bad-name`);
|
||||
+2. `packages/plugins`, `<kind>`, `<name>` and `index.mjs` exist, are a
|
||||
+ directory or a regular file as expected, and are not symlinks (`missing`,
|
||||
+ `symlink`); ancestors of `packages/plugins` are not checked;
|
||||
+3. just before import, `realpath(index.mjs)` is still the expected path
|
||||
+ (`symlink`);
|
||||
+4. the module imports (`load-failed`);
|
||||
+5. it has every export, and the kind's functions are functions
|
||||
+ (`missing-export`);
|
||||
+6. `interfaceVersion` equals the kind's (`interface-version`).
|
||||
+
|
||||
+A refusal refuses the whole kind for that load: the kind keeps the modules
|
||||
+it had, and the loader calls `log` with `{event: "plugin-refused", kind,
|
||||
+name, code, message, kept}`. A kind refused on its first load has nothing
|
||||
+switched on. An unknown kind refuses only itself; a `plugins` value that
|
||||
+isn't an object refuses every kind. Loads run one at a time.
|
||||
+
|
||||
+Limits of the checks:
|
||||
+
|
||||
+- A module runs with the host's authority once imported. The checks keep
|
||||
+ the loader inside this tree; they don't sandbox the module.
|
||||
+- Someone who can write this tree can swap a file between the realpath
|
||||
+ check and the import. The checks catch mistakes and stale links, not a
|
||||
+ writer racing the host as the same user.
|
||||
+- Node caches a module by URL, so a changed `index.mjs` is not re-read
|
||||
+ until the process restarts.
|
||||
+- The loader is not wired into any host process yet. The rows that call
|
||||
+ the first two kinds (124, 125, 126) wire it.
|
||||
diff --git a/packages/plugins/package.json b/packages/plugins/package.json
|
||||
new file mode 100644
|
||||
index 000000000..2cbd5f028
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/package.json
|
||||
@@ -0,0 +1,11 @@
|
||||
+{
|
||||
+ "name": "@mosaic/plugins",
|
||||
+ "version": "0.1.0",
|
||||
+ "private": true,
|
||||
+ "description": "Plug-in kind registry and in-repo module loader (PRD 1.2 row 131).",
|
||||
+ "license": "UNLICENSED",
|
||||
+ "type": "module",
|
||||
+ "engines": { "node": ">=24" },
|
||||
+ "exports": { "./kinds": "./src/kinds.mjs", "./loader": "./src/loader.mjs" },
|
||||
+ "scripts": { "test": "node --test tests/" }
|
||||
+}
|
||||
diff --git a/packages/plugins/src/kinds.mjs b/packages/plugins/src/kinds.mjs
|
||||
new file mode 100644
|
||||
index 000000000..42b320a51
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/src/kinds.mjs
|
||||
@@ -0,0 +1,66 @@
|
||||
+// The plug-in kind registry (REQ-PLUG-1; the first two kinds are
|
||||
+// REQ-LIMIT-4's). A kind names the exports its modules must provide, the
|
||||
+// interface version they implement, and whether the organization file
|
||||
+// switches on one module or a list. Adding a kind, or changing one, is a
|
||||
+// core change: a reviewed edit to this file.
|
||||
+
|
||||
+export const NAME = /^[a-z][a-z0-9-]*$/;
|
||||
+
|
||||
+export const KINDS = Object.freeze({
|
||||
+ // Reads one turn's usage for the limit checks (row 124 converts the first).
|
||||
+ "usage-source": Object.freeze({
|
||||
+ kind: "usage-source", interfaceVersion: 1, exports: Object.freeze(["readTurn"]), switch: "list",
|
||||
+ }),
|
||||
+ // Decides whether a launch may start and whether a running session must stop.
|
||||
+ "limit-check": Object.freeze({
|
||||
+ kind: "limit-check", interfaceVersion: 1, exports: Object.freeze(["mayLaunch", "mustStop"]), switch: "list",
|
||||
+ }),
|
||||
+});
|
||||
+
|
||||
+export class PluginError extends Error {
|
||||
+ constructor(code, message, name = null) {
|
||||
+ super(message);
|
||||
+ this.code = code;
|
||||
+ this.name = "PluginError";
|
||||
+ this.plugin = name;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+const raise = (code, message, name) => {
|
||||
+ throw new PluginError(code, message, name);
|
||||
+};
|
||||
+
|
||||
+// The module names one kind's setting switches on, checked against the
|
||||
+// kind's cardinality and the name pattern. A list may be empty.
|
||||
+export function namesFor(spec, setting, where, fail = raise) {
|
||||
+ if (spec.switch === "one") {
|
||||
+ if (typeof setting !== "string") fail("bad-setting", `${where} must be one module name`);
|
||||
+ } else if (!Array.isArray(setting)) {
|
||||
+ fail("bad-setting", `${where} must be a list of module names`);
|
||||
+ }
|
||||
+ const names = spec.switch === "one" ? [setting] : setting;
|
||||
+ const seen = new Set();
|
||||
+ for (const name of names) {
|
||||
+ if (typeof name !== "string" || !NAME.test(name)) {
|
||||
+ fail("bad-name", `${where} names ${JSON.stringify(name)}, which doesn't match ${NAME}`,
|
||||
+ typeof name === "string" ? name : null);
|
||||
+ }
|
||||
+ if (seen.has(name)) fail("bad-setting", `${where} names ${name} twice`, name);
|
||||
+ seen.add(name);
|
||||
+ }
|
||||
+ return names;
|
||||
+}
|
||||
+
|
||||
+// The organization file's `plugins` object: one key per kind, each a known kind.
|
||||
+export function checkPlugins(value, where, { kinds = KINDS, fail = raise } = {}) {
|
||||
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
||||
+ fail("bad-setting", `${where} must be an object with one key per kind`);
|
||||
+ }
|
||||
+ for (const [kind, setting] of Object.entries(value)) {
|
||||
+ if (!Object.hasOwn(kinds, kind)) {
|
||||
+ fail("unknown-kind", `${where} names unknown kind ${JSON.stringify(kind)}; adding a kind is a core change`);
|
||||
+ }
|
||||
+ namesFor(kinds[kind], setting, `${where}.${kind}`, fail);
|
||||
+ }
|
||||
+ return value;
|
||||
+}
|
||||
diff --git a/packages/plugins/src/loader.mjs b/packages/plugins/src/loader.mjs
|
||||
new file mode 100644
|
||||
index 000000000..a74721e2e
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/src/loader.mjs
|
||||
@@ -0,0 +1,144 @@
|
||||
+// The plug-in loader (REQ-PLUG-1). It switches on the modules the
|
||||
+// organization file's `plugins` object names, one key per kind, and loads
|
||||
+// only packages/plugins/<kind>/<name>/index.mjs from the tree this file runs
|
||||
+// from. It takes no path from config and loads nothing outside that tree
|
||||
+// (lead decision 143). A loaded module runs with the host's authority.
|
||||
+//
|
||||
+// A refusal keeps the kind's last good modules and is logged. A kind refused
|
||||
+// on its first load has nothing switched on. `loaded()` reports what each
|
||||
+// kind actually has switched on.
|
||||
+import { lstatSync, realpathSync } from "node:fs";
|
||||
+import { dirname, join, resolve } from "node:path";
|
||||
+import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
+import { KINDS, PluginError, namesFor } from "./kinds.mjs";
|
||||
+
|
||||
+const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
+
|
||||
+const refuse = (code, message, name) => {
|
||||
+ throw new PluginError(code, message, name);
|
||||
+};
|
||||
+
|
||||
+// lstat one path component: it must exist, be the expected type, and not be a symlink.
|
||||
+function component(path, directory) {
|
||||
+ let st;
|
||||
+ try {
|
||||
+ st = lstatSync(path);
|
||||
+ } catch (e) {
|
||||
+ if (e.code === "ENOENT" || e.code === "ENOTDIR") refuse("missing", `${path} is missing`);
|
||||
+ throw e;
|
||||
+ }
|
||||
+ if (st.isSymbolicLink()) refuse("symlink", `${path} is a symlink`);
|
||||
+ if (directory ? !st.isDirectory() : !st.isFile()) {
|
||||
+ refuse("missing", `${path} is not a ${directory ? "directory" : "regular file"}`);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+async function loadModule(spec, name, barrier) {
|
||||
+ const kindDir = join(ROOT, spec.kind);
|
||||
+ const nameDir = join(kindDir, name);
|
||||
+ const index = join(nameDir, "index.mjs");
|
||||
+ component(ROOT, true);
|
||||
+ component(kindDir, true);
|
||||
+ component(nameDir, true);
|
||||
+ component(index, false);
|
||||
+ barrier("checked", { kind: spec.kind, name });
|
||||
+ // Last check before import: the resolved file is still the one checked
|
||||
+ // above. Ancestors of packages/plugins are not checked (sage-0301).
|
||||
+ const expected = join(realpathSync(ROOT), spec.kind, name, "index.mjs");
|
||||
+ let real;
|
||||
+ try {
|
||||
+ real = realpathSync(index);
|
||||
+ } catch {
|
||||
+ refuse("missing", `${index} is missing`);
|
||||
+ }
|
||||
+ if (real !== expected) refuse("symlink", `${index} resolves to ${real}`);
|
||||
+ let module;
|
||||
+ try {
|
||||
+ module = await import(pathToFileURL(expected).href);
|
||||
+ } catch (e) {
|
||||
+ refuse("load-failed", `${spec.kind} ${name} failed to load: ${e.message}`);
|
||||
+ }
|
||||
+ for (const key of ["interfaceVersion", ...spec.exports]) {
|
||||
+ if (!Object.hasOwn(module, key)) refuse("missing-export", `${spec.kind} ${name} doesn't export ${key}`);
|
||||
+ }
|
||||
+ for (const key of spec.exports) {
|
||||
+ if (typeof module[key] !== "function") refuse("missing-export", `${spec.kind} ${name} export ${key} isn't a function`);
|
||||
+ }
|
||||
+ if (module.interfaceVersion !== spec.interfaceVersion) {
|
||||
+ refuse("interface-version",
|
||||
+ `${spec.kind} ${name} implements interface ${module.interfaceVersion}, not ${spec.interfaceVersion}`);
|
||||
+ }
|
||||
+ return Object.freeze({ name, module });
|
||||
+}
|
||||
+
|
||||
+export function createLoader({ log, barrier = () => {} }) {
|
||||
+ if (typeof log !== "function") throw new TypeError("createLoader needs a log callback");
|
||||
+ const current = new Map(Object.keys(KINDS).map(kind => [kind, Object.freeze([])]));
|
||||
+ let queue = Promise.resolve();
|
||||
+
|
||||
+ function refused(kind, name, e, report) {
|
||||
+ if (!(e instanceof PluginError)) throw e;
|
||||
+ // kept: what stays switched on, for the kind or (whole setting refused) for every kind.
|
||||
+ const entry = {
|
||||
+ event: "plugin-refused", kind, name: e.plugin ?? name, code: e.code, message: e.message,
|
||||
+ kept: kind === null ? loaded() : current.has(kind) ? current.get(kind).map(m => m.name) : [],
|
||||
+ };
|
||||
+ log(entry);
|
||||
+ report.push(entry);
|
||||
+ }
|
||||
+
|
||||
+ async function apply(plugins) {
|
||||
+ const report = [];
|
||||
+ // A malformed whole setting refuses every kind; an unknown kind refuses only itself.
|
||||
+ if (plugins === null || typeof plugins !== "object" || Array.isArray(plugins)) {
|
||||
+ refused(null, null, new PluginError("bad-setting", "plugins must be an object with one key per kind"), report);
|
||||
+ return { loaded: loaded(), refused: report };
|
||||
+ }
|
||||
+ for (const kind of Object.keys(plugins)) {
|
||||
+ if (!Object.hasOwn(KINDS, kind)) {
|
||||
+ refused(kind, null, new PluginError("unknown-kind", `plugins names unknown kind ${JSON.stringify(kind)}`), report);
|
||||
+ }
|
||||
+ }
|
||||
+ for (const [kind, spec] of Object.entries(KINDS)) {
|
||||
+ // An absent key switches the kind off.
|
||||
+ let names = [];
|
||||
+ try {
|
||||
+ if (Object.hasOwn(plugins, kind)) names = namesFor(spec, plugins[kind], `plugins.${kind}`, refuse);
|
||||
+ } catch (e) {
|
||||
+ refused(kind, typeof plugins[kind] === "string" ? plugins[kind] : null, e, report);
|
||||
+ continue;
|
||||
+ }
|
||||
+ const next = [];
|
||||
+ let ok = true;
|
||||
+ for (const name of names) {
|
||||
+ try {
|
||||
+ next.push(await loadModule(spec, name, barrier));
|
||||
+ } catch (e) {
|
||||
+ refused(kind, name, e, report);
|
||||
+ ok = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (ok) current.set(kind, Object.freeze(next));
|
||||
+ }
|
||||
+ return { loaded: loaded(), refused: report };
|
||||
+ }
|
||||
+
|
||||
+ // Loads run one at a time, so a kind's switch never interleaves.
|
||||
+ function load(plugins) {
|
||||
+ const run = queue.then(() => apply(plugins));
|
||||
+ queue = run.catch(() => {});
|
||||
+ return run;
|
||||
+ }
|
||||
+
|
||||
+ function loaded() {
|
||||
+ return Object.fromEntries([...current].map(([kind, modules]) => [kind, modules.map(m => m.name)]));
|
||||
+ }
|
||||
+
|
||||
+ function modules(kind) {
|
||||
+ if (!current.has(kind)) refuse("unknown-kind", `unknown kind ${JSON.stringify(kind)}`);
|
||||
+ return current.get(kind).map(m => m.module);
|
||||
+ }
|
||||
+
|
||||
+ return { load, loaded, modules };
|
||||
+}
|
||||
diff --git a/packages/plugins/tests/helpers.mjs b/packages/plugins/tests/helpers.mjs
|
||||
new file mode 100644
|
||||
index 000000000..e74e875ee
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/tests/helpers.mjs
|
||||
@@ -0,0 +1,38 @@
|
||||
+// A scratch tree per test: a copy of this package's src/ under
|
||||
+// <root>/packages/plugins, plus fixture modules. The loader finds modules
|
||||
+// from its own location, so each tree's copy loads only that tree's modules.
|
||||
+import { cpSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
+import { tmpdir } from "node:os";
|
||||
+import { dirname, join, resolve } from "node:path";
|
||||
+import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
+
|
||||
+export const SRC = resolve(dirname(fileURLToPath(import.meta.url)), "..", "src");
|
||||
+
|
||||
+export const USAGE = name => `export const interfaceVersion = 1;
|
||||
+export function readTurn() { return ${JSON.stringify(name)}; }
|
||||
+`;
|
||||
+export const LIMIT = name => `export const interfaceVersion = 1;
|
||||
+export function mayLaunch() { return ${JSON.stringify(name)}; }
|
||||
+export function mustStop() { return false; }
|
||||
+`;
|
||||
+
|
||||
+export function tree(t) {
|
||||
+ const root = mkdtempSync(join(tmpdir(), "mosaic-plugins-"));
|
||||
+ t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||
+ const pkg = join(root, "packages", "plugins");
|
||||
+ cpSync(SRC, join(pkg, "src"), { recursive: true });
|
||||
+ const write = (kind, name, body) => {
|
||||
+ const dir = join(pkg, kind, name);
|
||||
+ mkdirSync(dir, { recursive: true });
|
||||
+ writeFileSync(join(dir, "index.mjs"), body);
|
||||
+ return dir;
|
||||
+ };
|
||||
+ const loaderUrl = pathToFileURL(join(pkg, "src", "loader.mjs")).href;
|
||||
+ async function loader(options = {}) {
|
||||
+ const { createLoader } = await import(loaderUrl);
|
||||
+ const logged = [];
|
||||
+ const instance = createLoader({ log: entry => logged.push(entry), ...options });
|
||||
+ return { ...instance, logged };
|
||||
+ }
|
||||
+ return { root, pkg, write, loader, loaderUrl };
|
||||
+}
|
||||
diff --git a/packages/plugins/tests/kinds.test.mjs b/packages/plugins/tests/kinds.test.mjs
|
||||
new file mode 100644
|
||||
index 000000000..15b641245
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/tests/kinds.test.mjs
|
||||
@@ -0,0 +1,47 @@
|
||||
+// REQ-PLUG-1: the kind registry and the organization file's `plugins` shape (row 131).
|
||||
+import test from "node:test";
|
||||
+import assert from "node:assert/strict";
|
||||
+import { KINDS, NAME, PluginError, checkPlugins } from "../src/kinds.mjs";
|
||||
+
|
||||
+const code = expected => e => e instanceof PluginError && e.code === expected;
|
||||
+
|
||||
+test("REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list", () => {
|
||||
+ assert.deepEqual(Object.keys(KINDS), ["usage-source", "limit-check"]);
|
||||
+ assert.deepEqual({ ...KINDS["usage-source"], exports: [...KINDS["usage-source"].exports] },
|
||||
+ { kind: "usage-source", interfaceVersion: 1, exports: ["readTurn"], switch: "list" });
|
||||
+ assert.deepEqual({ ...KINDS["limit-check"], exports: [...KINDS["limit-check"].exports] },
|
||||
+ { kind: "limit-check", interfaceVersion: 1, exports: ["mayLaunch", "mustStop"], switch: "list" });
|
||||
+ assert.ok(Object.isFrozen(KINDS) && Object.isFrozen(KINDS["usage-source"]) && Object.isFrozen(KINDS["limit-check"].exports));
|
||||
+ assert.equal(String(NAME), "/^[a-z][a-z0-9-]*$/");
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included", () => {
|
||||
+ for (const value of [{}, { "usage-source": [] }, { "usage-source": ["a", "b-2"], "limit-check": ["cap"] }]) {
|
||||
+ assert.equal(checkPlugins(value, "plugins"), value);
|
||||
+ }
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates", () => {
|
||||
+ for (const value of [null, [], "x", 3]) assert.throws(() => checkPlugins(value, "plugins"), code("bad-setting"));
|
||||
+ assert.throws(() => checkPlugins({ "made-up": [] }, "plugins"), code("unknown-kind"));
|
||||
+ assert.throws(() => checkPlugins({ toString: [] }, "plugins"), code("unknown-kind"));
|
||||
+ assert.throws(() => checkPlugins({ "usage-source": "meter" }, "plugins"), code("bad-setting"));
|
||||
+ for (const name of ["Meter", "1m", "m_x", "../x", "a/b", ".x", "", 7, null]) {
|
||||
+ assert.throws(() => checkPlugins({ "usage-source": [name] }, "plugins"), code("bad-name"), String(name));
|
||||
+ }
|
||||
+ assert.throws(() => checkPlugins({ "limit-check": ["cap", "cap"] }, "plugins"), code("bad-setting"));
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a kind that switches on one module takes one name, not a list", () => {
|
||||
+ const kinds = { single: { kind: "single", interfaceVersion: 1, exports: ["run"], switch: "one" } };
|
||||
+ assert.ok(checkPlugins({ single: "only" }, "plugins", { kinds }));
|
||||
+ assert.throws(() => checkPlugins({ single: ["only"] }, "plugins", { kinds }), code("bad-setting"));
|
||||
+ assert.throws(() => checkPlugins({ single: "Only" }, "plugins", { kinds }), code("bad-name"));
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 checkPlugins reports through the caller's fail callback", () => {
|
||||
+ const seen = [];
|
||||
+ const fail = (c, message) => { seen.push(c); throw new Error(message); };
|
||||
+ assert.throws(() => checkPlugins({ "made-up": [] }, "x plugins", { fail }), /x plugins names unknown kind/);
|
||||
+ assert.deepEqual(seen, ["unknown-kind"]);
|
||||
+});
|
||||
diff --git a/packages/plugins/tests/loader.test.mjs b/packages/plugins/tests/loader.test.mjs
|
||||
new file mode 100644
|
||||
index 000000000..e10e670af
|
||||
--- /dev/null
|
||||
+++ b/packages/plugins/tests/loader.test.mjs
|
||||
@@ -0,0 +1,222 @@
|
||||
+// REQ-PLUG-1: the loader switches on in-repo modules only, and
|
||||
+// every refusal keeps the kind's old modules and is logged (row 131).
|
||||
+import test from "node:test";
|
||||
+import assert from "node:assert/strict";
|
||||
+import { spawnSync } from "node:child_process";
|
||||
+import { mkdirSync, mkdtempSync, renameSync, rmSync, symlinkSync, unlinkSync } from "node:fs";
|
||||
+import { tmpdir } from "node:os";
|
||||
+import { join } from "node:path";
|
||||
+import { LIMIT, USAGE, tree } from "./helpers.mjs";
|
||||
+import { businessDoc, rolesCopy, tmp as businessRoot, writeJson } from "../../business/tests/helpers.mjs";
|
||||
+import { validateBusinessDocument } from "../../business/src/business.mjs";
|
||||
+
|
||||
+const GOOD = { "usage-source": ["meter"], "limit-check": ["cap"] };
|
||||
+
|
||||
+// A tree with one good module of each kind, already loaded.
|
||||
+async function loadedTree(t, options) {
|
||||
+ const s = tree(t);
|
||||
+ s.write("usage-source", "meter", USAGE("meter"));
|
||||
+ s.write("limit-check", "cap", LIMIT("cap"));
|
||||
+ const loader = await s.loader(options);
|
||||
+ const first = await loader.load(GOOD);
|
||||
+ assert.deepEqual(first.refused, []);
|
||||
+ assert.deepEqual(loader.loaded(), GOOD);
|
||||
+ return { ...s, loader };
|
||||
+}
|
||||
+
|
||||
+// Switch usage-source to `names`: the load must refuse with `code`, keep
|
||||
+// ["meter"], log one entry naming the kind and `name`, and leave limit-check on.
|
||||
+async function refusesKeepingOld(s, names, code, name, message) {
|
||||
+ const before = s.loader.logged.length;
|
||||
+ const result = await s.loader.load({ "usage-source": names, "limit-check": ["cap"] });
|
||||
+ assert.deepEqual(s.loader.loaded(), GOOD, `${name}: old setting kept`);
|
||||
+ assert.equal(result.refused.length, 1, name);
|
||||
+ const [entry] = result.refused;
|
||||
+ assert.equal(entry.code, code, `${name}: ${entry.message}`);
|
||||
+ assert.equal(entry.kind, "usage-source");
|
||||
+ assert.equal(entry.name, name);
|
||||
+ assert.deepEqual(entry.kept, ["meter"]);
|
||||
+ if (message) assert.match(entry.message, message);
|
||||
+ assert.deepEqual(s.loader.logged.slice(before), [entry], `${name}: logged once`);
|
||||
+ assert.equal(s.loader.modules("usage-source")[0].readTurn(), "meter");
|
||||
+}
|
||||
+
|
||||
+test("REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed", async t => {
|
||||
+ const s = tree(t);
|
||||
+ s.write("usage-source", "fixture-usage", USAGE("fixture-usage"));
|
||||
+ s.write("limit-check", "fixture-limit", LIMIT("fixture-limit"));
|
||||
+ const root = businessRoot();
|
||||
+ t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||
+ const doc = businessDoc(root, "acme");
|
||||
+ doc.plugins = { "usage-source": ["fixture-usage"], "limit-check": ["fixture-limit"] };
|
||||
+ const file = writeJson(join(root, "businesses", "acme.json"), doc);
|
||||
+ const business = validateBusinessDocument(doc, file, { rolesDir: rolesCopy(root) });
|
||||
+ const loader = await s.loader();
|
||||
+ const result = await loader.load(business.plugins);
|
||||
+ assert.deepEqual(result.refused, []);
|
||||
+ assert.deepEqual(result.loaded, doc.plugins);
|
||||
+ assert.equal(loader.modules("usage-source")[0].readTurn(), "fixture-usage");
|
||||
+ assert.equal(loader.modules("limit-check")[0].mayLaunch(), "fixture-limit");
|
||||
+ assert.equal(loader.modules("limit-check")[0].mustStop(), false);
|
||||
+ assert.deepEqual(loader.logged, []);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ for (const name of ["Meter", "1meter", "me_ter", "../cap", "meter/index", ".hidden", ""]) {
|
||||
+ await refusesKeepingOld(s, ["meter", name], "bad-name", name);
|
||||
+ }
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ await refusesKeepingOld(s, ["meter", "absent"], "missing", "absent", /absent is missing/);
|
||||
+ mkdirSync(join(s.pkg, "usage-source", "empty"));
|
||||
+ await refusesKeepingOld(s, ["empty"], "missing", "empty", /index\.mjs is missing/);
|
||||
+ mkdirSync(join(s.pkg, "usage-source", "dir-index", "index.mjs"), { recursive: true });
|
||||
+ await refusesKeepingOld(s, ["dir-index"], "missing", "dir-index", /not a regular file/);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ const meter = join(s.pkg, "usage-source", "meter");
|
||||
+ symlinkSync(meter, join(s.pkg, "usage-source", "linked"));
|
||||
+ await refusesKeepingOld(s, ["linked"], "symlink", "linked", /usage-source\/linked is a symlink/);
|
||||
+ s.write("usage-source", "link-index", USAGE("x"));
|
||||
+ unlinkSync(join(s.pkg, "usage-source", "link-index", "index.mjs"));
|
||||
+ symlinkSync(join(meter, "index.mjs"), join(s.pkg, "usage-source", "link-index", "index.mjs"));
|
||||
+ await refusesKeepingOld(s, ["link-index"], "symlink", "link-index", /link-index\/index\.mjs is a symlink/);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ const real = join(s.pkg, "usage-real");
|
||||
+ renameSync(join(s.pkg, "usage-source"), real);
|
||||
+ symlinkSync(real, join(s.pkg, "usage-source"));
|
||||
+ await refusesKeepingOld(s, ["meter"], "symlink", "meter", /plugins\/usage-source is a symlink/);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it)", async t => {
|
||||
+ const s = tree(t);
|
||||
+ s.write("usage-source", "meter", USAGE("meter"));
|
||||
+ const other = mkdtempSync(join(tmpdir(), "mosaic-plugins-link-"));
|
||||
+ t.after(() => rmSync(other, { recursive: true, force: true }));
|
||||
+ mkdirSync(join(other, "packages"));
|
||||
+ symlinkSync(s.pkg, join(other, "packages", "plugins"));
|
||||
+ const url = new URL(`file://${join(other, "packages", "plugins", "src", "loader.mjs")}`).href;
|
||||
+ const script = `const { createLoader } = await import(${JSON.stringify(url)});
|
||||
+const logged = []; const loader = createLoader({ log: e => logged.push(e) });
|
||||
+const r = await loader.load({ "usage-source": ["meter"] });
|
||||
+console.log(JSON.stringify({ loaded: loader.loaded(), logged }));`;
|
||||
+ const run = spawnSync(process.execPath, ["--preserve-symlinks", "--input-type=module", "-e", script], { encoding: "utf8" });
|
||||
+ assert.equal(run.status, 0, run.stderr);
|
||||
+ const out = JSON.parse(run.stdout);
|
||||
+ assert.deepEqual(out.loaded["usage-source"], []);
|
||||
+ assert.equal(out.logged[0].code, "symlink");
|
||||
+ assert.match(out.logged[0].message, /packages\/plugins is a symlink/);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check", async t => {
|
||||
+ let swap = false;
|
||||
+ const s = await loadedTree(t, {
|
||||
+ barrier: (point, { name }) => {
|
||||
+ if (!swap || point !== "checked" || name !== "swapped") return;
|
||||
+ const index = join(s.pkg, "usage-source", "swapped", "index.mjs");
|
||||
+ unlinkSync(index);
|
||||
+ symlinkSync(join(s.pkg, "usage-source", "meter", "index.mjs"), index);
|
||||
+ },
|
||||
+ });
|
||||
+ s.write("usage-source", "swapped", USAGE("swapped"));
|
||||
+ swap = true;
|
||||
+ await refusesKeepingOld(s, ["swapped"], "symlink", "swapped", /swapped\/index\.mjs resolves to .*meter\/index\.mjs/);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a module that fails to load refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ s.write("usage-source", "syntax", "export const interfaceVersion = 1;\nexport function readTurn( {\n");
|
||||
+ await refusesKeepingOld(s, ["syntax"], "load-failed", "syntax");
|
||||
+ s.write("usage-source", "throws", "throw new Error('boom');\n");
|
||||
+ await refusesKeepingOld(s, ["throws"], "load-failed", "throws", /boom/);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a missing export refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ s.write("usage-source", "no-read", "export const interfaceVersion = 1;\n");
|
||||
+ await refusesKeepingOld(s, ["no-read"], "missing-export", "no-read", /doesn't export readTurn/);
|
||||
+ s.write("usage-source", "no-version", "export function readTurn() {}\n");
|
||||
+ await refusesKeepingOld(s, ["no-version"], "missing-export", "no-version", /doesn't export interfaceVersion/);
|
||||
+ s.write("usage-source", "not-fn", "export const interfaceVersion = 1;\nexport const readTurn = 1;\n");
|
||||
+ await refusesKeepingOld(s, ["not-fn"], "missing-export", "not-fn", /readTurn isn't a function/);
|
||||
+ // limit-check needs both of its exports.
|
||||
+ s.write("limit-check", "half", "export const interfaceVersion = 1;\nexport function mayLaunch() {}\n");
|
||||
+ const result = await s.loader.load({ "usage-source": ["meter"], "limit-check": ["cap", "half"] });
|
||||
+ assert.deepEqual(result.refused.map(e => [e.kind, e.name, e.code]), [["limit-check", "half", "missing-export"]]);
|
||||
+ assert.deepEqual(s.loader.loaded(), GOOD);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a different interface version refuses and keeps the old setting", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ s.write("usage-source", "v2", "export const interfaceVersion = 2;\nexport function readTurn() {}\n");
|
||||
+ await refusesKeepingOld(s, ["v2"], "interface-version", "v2", /implements interface 2, not 1/);
|
||||
+ s.write("usage-source", "v-string", "export const interfaceVersion = '1';\nexport function readTurn() {}\n");
|
||||
+ await refusesKeepingOld(s, ["v-string"], "interface-version", "v-string");
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name", async t => {
|
||||
+ const s = tree(t);
|
||||
+ s.write("usage-source", "meter", USAGE("meter"));
|
||||
+ s.write("limit-check", "cap", LIMIT("cap"));
|
||||
+ const loader = await s.loader();
|
||||
+ // meter loads, absent refuses: the whole kind stays off, not half on.
|
||||
+ const result = await loader.load({ "usage-source": ["meter", "absent"], "limit-check": ["cap"] });
|
||||
+ assert.deepEqual(result.loaded, { "usage-source": [], "limit-check": ["cap"] });
|
||||
+ assert.deepEqual(loader.loaded(), result.loaded);
|
||||
+ assert.deepEqual(loader.modules("usage-source"), []);
|
||||
+ assert.equal(loader.logged.length, 1);
|
||||
+ assert.equal(loader.logged[0].event, "plugin-refused");
|
||||
+ assert.equal(loader.logged[0].kind, "usage-source");
|
||||
+ assert.equal(loader.logged[0].name, "absent");
|
||||
+ assert.deepEqual(loader.logged[0].kept, []);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ let result = await s.loader.load({ ...GOOD, "made-up": ["x"] });
|
||||
+ assert.deepEqual(result.refused.map(e => [e.kind, e.code]), [["made-up", "unknown-kind"]]);
|
||||
+ assert.deepEqual(s.loader.loaded(), GOOD);
|
||||
+ for (const kind of ["made-up", "toString"]) {
|
||||
+ assert.throws(() => s.loader.modules(kind), e => e.code === "unknown-kind", kind);
|
||||
+ }
|
||||
+ for (const bad of [null, [], "meter"]) {
|
||||
+ result = await s.loader.load(bad);
|
||||
+ assert.deepEqual(result.refused.map(e => [e.kind, e.code]), [[null, "bad-setting"]]);
|
||||
+ assert.deepEqual(result.refused[0].kept, GOOD);
|
||||
+ assert.deepEqual(s.loader.loaded(), GOOD);
|
||||
+ }
|
||||
+ await refusesKeepingOld(s, "meter", "bad-setting", "meter");
|
||||
+ await refusesKeepingOld(s, ["meter", "meter"], "bad-setting", "meter", /twice/);
|
||||
+ // An absent key switches the kind off.
|
||||
+ result = await s.loader.load({ "limit-check": ["cap"] });
|
||||
+ assert.deepEqual(result.loaded, { "usage-source": [], "limit-check": ["cap"] });
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 loads run one at a time, so the last requested setting wins", async t => {
|
||||
+ const s = await loadedTree(t);
|
||||
+ let release;
|
||||
+ globalThis.__row131Gate = new Promise(resolve => { release = resolve; });
|
||||
+ t.after(() => { delete globalThis.__row131Gate; });
|
||||
+ s.write("usage-source", "slow", "await globalThis.__row131Gate;\nexport const interfaceVersion = 1;\nexport function readTurn() {}\n");
|
||||
+ s.write("usage-source", "fast", USAGE("fast"));
|
||||
+ const first = s.loader.load({ "usage-source": ["slow"] });
|
||||
+ const second = s.loader.load({ "usage-source": ["fast"] });
|
||||
+ await new Promise(resolve => setTimeout(resolve, 100));
|
||||
+ release();
|
||||
+ await Promise.all([first, second]);
|
||||
+ assert.deepEqual(s.loader.loaded()["usage-source"], ["fast"]);
|
||||
+});
|
||||
+
|
||||
+test("REQ-PLUG-1 the loader needs a log callback", async t => {
|
||||
+ const s = tree(t);
|
||||
+ const { createLoader } = await import(s.loaderUrl);
|
||||
+ assert.throws(() => createLoader({}), /log callback/);
|
||||
+});
|
||||
diff --git a/scripts/stack-copy.sh b/scripts/stack-copy.sh
|
||||
index f384a983d..769f91c5f 100755
|
||||
--- a/scripts/stack-copy.sh
|
||||
+++ b/scripts/stack-copy.sh
|
||||
@@ -28,6 +28,8 @@ COPY_PATHS=(
|
||||
packages/seat/src packages/tasks/src packages/tasks/fields.json packages/tasks/requirements.json
|
||||
packages/webui/src packages/webui/README.md packages/cli/README.md
|
||||
packages/queue/src
|
||||
+ # Whole directory: every in-repo plug-in module ships with the copy (row 131).
|
||||
+ packages/plugins
|
||||
)
|
||||
copy_commit() {
|
||||
[ -d "$REPO/.git" ] || [ "$ALLOW_WORKTREE" = 1 ] || die "refusing: $REPO is not the canonical checkout (its .git is not a directory); run copy from the canonical checkout"
|
||||
@@ -0,0 +1,13 @@
|
||||
9187b2a38ba387b5750e94b10b16870518f032489d784fa52563622932718e5d packages/business/README.md
|
||||
46f0e977d78e579362b57415996041670e36c04017136359ec11b69ecd18e112 packages/business/src/business.mjs
|
||||
f3858b6f4a35ad6fe3f451496a8b464a67104e3aebc645542f1e00655bde9bbe packages/business/src/plugin-settings.mjs
|
||||
445651b3d6ded8405fe6df2b62629bc37197b97173893a9db9cd6d7dbc80cc9b packages/business/tests/plugin-settings.test.mjs
|
||||
924df6c3844708306f379bc88c47387a3ed648ef176b56fa38f9f2ae73c0f46a packages/cli/tests/stack-copy.test.mjs
|
||||
90a9ac59a9ea2287e9a3d4b2f4286d025e727f2a6ce149464f8d0420fd9a8ef1 packages/plugins/package.json
|
||||
fdf3a99223451d9608297d6e4fdb46568428424798d61f1e604fc32265d81d91 packages/plugins/README.md
|
||||
ed9cba47f892554b78f4ae9803552e38005c2e11b608efebf9b9cf252b38e408 packages/plugins/src/kinds.mjs
|
||||
7a9cd3aba526f1bfffb89acb0c06af8d4aef608ef46ab6bcf9d1d90d39b42e41 packages/plugins/src/loader.mjs
|
||||
af18df7dacc775b28cc2c67c5755017e4850f5200b9b4eace6f23f8638109a7a packages/plugins/tests/helpers.mjs
|
||||
da606e8948ad26238084605c8d77042a64cf8f8ea1ca88247aa3931894c69bce packages/plugins/tests/kinds.test.mjs
|
||||
b9a9f84a89dc810203ef10f00b0f444e63d250c0f913e3ccc9f0aecb4c74199f packages/plugins/tests/loader.test.mjs
|
||||
0b6becaa237500d69a4977cb79a2c0da67f728be4cd0b930dd506d445698f43a scripts/stack-copy.sh
|
||||
@@ -0,0 +1,5 @@
|
||||
pkg-plugins start=2026-10-15T16:20:28Z end=2026-10-15T16:20:28Z rc=0 tests=19 pass=19 fail=0
|
||||
pkg-business start=2026-10-15T16:20:28Z end=2026-10-15T16:20:30Z rc=0 tests=91 pass=91 fail=0
|
||||
pkg-bus start=2026-10-15T16:20:30Z end=2026-10-15T16:20:35Z rc=0 tests=171 pass=171 fail=0
|
||||
pkg-webui start=2026-10-15T16:20:35Z end=2026-10-15T16:21:30Z rc=0 tests=112 pass=112 fail=0
|
||||
pkg-cli start=2026-10-15T16:21:30Z end=2026-10-15T16:21:48Z rc=0 tests=195 pass=195 fail=0
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Row 131 targeted builder gate (decision 136; list approved in sage-0301).
|
||||
# Same command land-work.sh runs per package. One log per package under gate/.
|
||||
set -uo pipefail
|
||||
WT=${1:-$HOME/dewey-scratch/r131/wt}
|
||||
OUT=$(cd "$(dirname "$0")" && pwd)/gate
|
||||
mkdir -p "$OUT"
|
||||
export TMPDIR=$HOME/dewey-scratch/tmp
|
||||
status=0
|
||||
for p in plugins business bus webui cli; do
|
||||
start=$(date -u +%FT%TZ)
|
||||
(cd "$WT/packages/$p" && node --test tests/*.test.mjs) >"$OUT/pkg-$p.log" 2>&1
|
||||
rc=$?
|
||||
counts=$(grep -E '^ℹ (tests|pass|fail) ' "$OUT/pkg-$p.log" | awk '{printf "%s=%s ", $2, $3}')
|
||||
echo "pkg-$p start=$start end=$(date -u +%FT%TZ) rc=$rc $counts"
|
||||
[ "$rc" -eq 0 ] || status=1
|
||||
done
|
||||
exit $status
|
||||
@@ -0,0 +1,179 @@
|
||||
✔ agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged (122.616889ms)
|
||||
✔ agents: working counts what the holder received and has not read; routed alone is not working (213.322634ms)
|
||||
✔ agents: input needed is the role's open decisions routed to the human, gated first, then oldest (319.47273ms)
|
||||
✔ agents: working wins over waiting, and Input needed still shows (180.070221ms)
|
||||
✔ agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role (216.056315ms)
|
||||
✔ agents: state reads only its own business, even for a run name both use (219.676207ms)
|
||||
✔ agents: a message the holder released unread is stranded; the next holder gets nothing and cannot read it (232.256043ms)
|
||||
✔ agents: a message the holder read is not stranded; one the current holder has not read is not listed (240.399496ms)
|
||||
✔ agents: stranded is oldest first and capped at 50 for a role (967.234959ms)
|
||||
✔ agents: stranded is per role and per business (353.720105ms)
|
||||
✔ agents: a message routed to a held role and not yet received is not stranded (140.789563ms)
|
||||
✔ launch identity is stamped, payload identity is refused and stale holder cannot send (163.12274ms)
|
||||
✔ decision classes route from policy; gated resolution is human-only, choice and target must match (241.298353ms)
|
||||
✔ claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic (279.260983ms)
|
||||
✔ launch events require a human CLI capability; generic emit cannot forge authority events (197.381125ms)
|
||||
✔ within-role decisions close atomically and invalid options or blocking omissions refuse (180.923981ms)
|
||||
✔ a recommendation that is not exactly one option key refuses invalid-recommendation after the options (306.922539ms)
|
||||
✔ observer capabilities read human inbox but cannot mutate or forge launch identity (203.194913ms)
|
||||
✔ task action subjects and linked decision trail are complete and ordered (217.36727ms)
|
||||
✔ launch binding is durable and reconnecting requires the identical trusted record (132.009857ms)
|
||||
✔ business isolation includes inherited object names and cross-business message references (218.70735ms)
|
||||
✔ authority never transfers between action, run, target, unresolved or replaced role holder (308.115523ms)
|
||||
✔ task projection uses schema current view, skipping earlier and equal-start polls (163.823648ms)
|
||||
✔ revocation permanently bars the old run from reclaiming first, including after broker restart (238.962724ms)
|
||||
✔ empty message references refuse before storage; refusal-evidence failure stays a typed error (162.41287ms)
|
||||
✔ both arbiters require human resolution when their cross-role route is themselves (246.400338ms)
|
||||
✔ the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role (181.420931ms)
|
||||
✔ S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input (3.926546ms)
|
||||
✔ credentials gives human and reader sessions service, account, role, date and state, and nothing else (109.54619ms)
|
||||
✔ credentials refuses a role session and any argument (173.351899ms)
|
||||
✔ credentials reads the status on each request, and a broker without one lists none (204.203918ms)
|
||||
✔ the broker process answers credentials without a token, path or variable in its output, log or store (208.488062ms)
|
||||
✔ only validated broker references load; returned data and exceptions cannot expose a known token (4.703346ms)
|
||||
✔ bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse (4.07566ms)
|
||||
✔ expiry refuses use and env references never become client data (0.903082ms)
|
||||
✔ S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state (1.932794ms)
|
||||
✔ opaque tokens shorter than 16 characters refuse before use (0.428552ms)
|
||||
✔ a human resolve sends the raising role one message from the human, and its request is the answer (228.048552ms)
|
||||
✔ a cross-role decision resolved by its arbiter comes from that role and run, with no request (227.639561ms)
|
||||
✔ a human withdraw sends one message with the note (233.440741ms)
|
||||
✔ a human seen before the close leaves the request on the close's answer, not the seen (314.49029ms)
|
||||
✔ the raising run's withdraw, a supersede, a within-role raise and seen send nothing (323.747425ms)
|
||||
✔ refused closes send nothing: invalid-choice, decision-closed, not-resolver (322.671224ms)
|
||||
✔ a raising role nobody holds at the close gets the message on the next claim (291.71435ms)
|
||||
✔ a human DECISION send keeps its own instruction as the request, not a close's answer (290.862568ms)
|
||||
✔ roles lists open decisions routed to a role, and never the human inbox (196.773608ms)
|
||||
✔ recent lists closed decisions of every route, newest close first, with how each closed (262.175146ms)
|
||||
✔ recent gives the closing event as closed when the decision was seen first (304.625565ms)
|
||||
✔ recent stops at RECENT rows (907.439159ms)
|
||||
✔ every row is what trail already gives the same session for that id (307.726342ms)
|
||||
✔ a role session can't list decisions, so it can't read another role's open decisions (448.063928ms)
|
||||
✔ decisions is a read: one business, strict arguments, nothing written (437.720072ms)
|
||||
✔ endLaunch writes session.ended, releases the run claim and kills its capabilities (134.273021ms)
|
||||
✔ endLaunch refuses an unknown run, a second end and a rebind of the ended run (129.796527ms)
|
||||
✔ a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound (137.40638ms)
|
||||
✔ endLaunch leaves a claim another run took alone (186.687008ms)
|
||||
✔ refuse records action.refused against the caller with the code only (154.640293ms)
|
||||
✔ launches off refuses role.launch with launch-revoked until launches on (209.140848ms)
|
||||
✔ broker process: launch ops authorize role.launch, record refusals and end runs (312.370283ms)
|
||||
✔ human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse (2.266478ms)
|
||||
✔ process reader gets own kernel identity without exposing environment values (0.831413ms)
|
||||
✔ EACCES ancestor environments skip only markers; commands and registered launches still refuse (0.855373ms)
|
||||
✔ real pid 1 remains inspectable when its environment is protected (0.374065ms)
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (192.145966ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (257.248018ms)
|
||||
✔ uncertain organization receipts leave bus startup and reads alone but refuse writes until reconciled (411.039393ms)
|
||||
✔ within-role sends cite an open gated launch decision without spending it or naming it in grants (195.225947ms)
|
||||
✔ missing and foreign-business citations refuse and roll back message and grant (180.353594ms)
|
||||
✔ cross-role sends still need a matching resolved decision and consume it once (242.935586ms)
|
||||
✔ messages pages all human messages newest first without writes; read state is history (2742.215961ms)
|
||||
✔ messages refuses role callers, invalid paging and cursors outside this human feed (276.715007ms)
|
||||
✔ views messages passes only its paging arguments through (0.241582ms)
|
||||
✔ messages isolates businesses even with a valid foreign cursor (171.770113ms)
|
||||
✔ the assistant sends to the user and to the chief of staff only (280.724437ms)
|
||||
✔ an assistant send to any other role, or to the tester, is refused and logged (323.614034ms)
|
||||
✔ only the user and the chief of staff may send to the assistant; the tester is refused by default (363.865201ms)
|
||||
✔ a sender-side list alone refuses a send to a role that has no list (345.058837ms)
|
||||
✔ a target-side list alone refuses a send from a role that has no list (370.5877ms)
|
||||
✔ the sender list is checked before the target list (296.679891ms)
|
||||
✔ roles without the field behave exactly as before (450.160597ms)
|
||||
✔ a business with no role definitions at all is unlimited (335.462907ms)
|
||||
✔ a malformed messaging field refuses at boot (132.373533ms)
|
||||
✔ the assistant's review.request to a reviewer is refused and logged, even with an approved decision (313.583501ms)
|
||||
✔ a review.verdict to the assistant from a role outside its receiveFrom is refused and logged (383.755063ms)
|
||||
✔ review requests and verdicts between roles without the field are unchanged (264.547848ms)
|
||||
✔ broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly (196.758558ms)
|
||||
✔ startup token refusal returns safe code without value or partial listening broker (44.688342ms)
|
||||
✔ loaded fixture token is absent from socket replies and SQLite, including refusal evidence (177.181753ms)
|
||||
✔ killed broker leaves an explicit stale lock; another process cannot silently reclaim it (195.462577ms)
|
||||
✔ trusted host registers later launches; socket clients never have a registration verb (193.85395ms)
|
||||
✔ runtime excludes declared project roots even when host supplies no repoRoots (43.21371ms)
|
||||
✔ a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it (197.016508ms)
|
||||
✔ a reply is listed for human and reader sessions, and its delivery rows are unchanged (224.389962ms)
|
||||
✔ the reply still reaches the human message.receive (mosaic talk) after the Console showed it (194.743371ms)
|
||||
✔ a message with no reply gives an empty list (161.762012ms)
|
||||
✔ replies come oldest first and stop at REPLIES (839.840337ms)
|
||||
✔ an id that names no message in the business refuses message-not-found, and the refusal is recorded (341.202527ms)
|
||||
✔ strict arguments; a role session gets human-required (429.39239ms)
|
||||
✔ views passes replies through as one call with the id (0.239612ms)
|
||||
✔ requirements returns the committed list to a holding role session, and no one else (211.192606ms)
|
||||
✔ the PM's prd.approve with no task, when no id fits, reaches the human's Inbox (148.840372ms)
|
||||
✔ the PM's non-blocking role.revoke with no task reaches the human's Inbox (180.66913ms)
|
||||
✔ a push is recorded as the action.allowed for git.push.working on the task, and only the host records one (245.893054ms)
|
||||
✔ review.request names the latest pushed commit and sends the reviewer a REVIEW-REQUEST (227.869838ms)
|
||||
✔ review.request says which run holds the reviewer role, or null, and a null request waits for a claim (323.927687ms)
|
||||
✔ review.request refuses a commit that isn't the latest push, a non-reviewer and a role without the action (417.532547ms)
|
||||
✔ reviewFetch answers only the addressed reviewer, for the request it cites (266.687352ms)
|
||||
✔ review.verdict answers one request once, to the role that asked (323.784035ms)
|
||||
✔ task.close on a pushed task needs an approve verdict for the latest push (430.021389ms)
|
||||
✔ a refusal the host decided is filed on the task it names, and only a task ref counts (277.781054ms)
|
||||
✔ v3b prototype refusals, views and append-only mutations (1089.055879ms)
|
||||
✔ gated approval authorizes once, survives store reopen, and fresh approval works (273.732055ms)
|
||||
✔ another run cannot consume an approval; a failed check leaves it usable (248.143891ms)
|
||||
✔ two scheduled callers have exactly one grant and one consumed refusal (187.453741ms)
|
||||
✔ failed commit rolls consumption back; cross-role consumes and within-role stays reusable (372.877976ms)
|
||||
✔ class drift gated to cross-role refuses before consumption (245.340255ms)
|
||||
✔ class drift cross-role to gated refuses before consumption (285.714235ms)
|
||||
✔ class drift gated to within-role refuses before consumption (250.205796ms)
|
||||
✔ class drift cross-role to within-role refuses before consumption (261.233495ms)
|
||||
✔ class drift within-role to gated refuses before consumption (224.065738ms)
|
||||
✔ class drift within-role to cross-role refuses before consumption (202.06831ms)
|
||||
✔ message.send consumes approval and prevents a later send or authorize (235.999112ms)
|
||||
✔ role.revoke consumes approval and prevents a later revoke or authorize (288.490446ms)
|
||||
✔ a business that never switched launches reads allowed with no time and no event (127.852385ms)
|
||||
✔ launches revoked and then restored read allowed, with the restore time and event id (164.494709ms)
|
||||
✔ a task closed on the tracker leaves the open list, and total counts the open ones (167.464985ms)
|
||||
✔ a tombstone is not open (171.460579ms)
|
||||
✔ the open list stops at the cap and says so; total still counts every open task (150.390206ms)
|
||||
✔ a role and a reader session read state; arguments, and an unbound cap, refuse (164.569781ms)
|
||||
✔ a human session reads the same state, with the same cap (160.011936ms)
|
||||
✔ reading state writes nothing: every table keeps its row count (162.403458ms)
|
||||
✔ creates private WAL store and excludes a second writer until explicit close (145.946444ms)
|
||||
✔ rollback is atomic and schema metadata is checked against trusted DDL, not just itself (194.945101ms)
|
||||
✔ existing empty database and symlink runtime directory refuse, never initialize over damage (208.637074ms)
|
||||
✔ crash during a transaction recovers no partial event after explicit fixture-only lock removal (192.903866ms)
|
||||
✔ writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers (131.366643ms)
|
||||
✔ async transactions refuse before invoking their function (114.295165ms)
|
||||
✔ the session default fits under the reply cap and pages to the end with next (346.885718ms)
|
||||
✔ the short form: no description, assignees by role, every listed key (282.993393ms)
|
||||
✔ each filter, alone and together, and total counts every match (379.809636ms)
|
||||
✔ task_ref reads one task in full, as the whole board has it (324.705959ms)
|
||||
✔ no arguments is the read the Console and mosaic make, unchanged (276.377834ms)
|
||||
✔ an unknown argument or a bad value refuses invalid-request (1093.291939ms)
|
||||
✔ tasks rows carry priority and requirement for every session that reads tasks (344.656201ms)
|
||||
✔ the read model rebuilds from the ledger: a reopened bus and each trail give the same values (376.331732ms)
|
||||
✔ an empty business and one with snapshots but no task.created read cleanly (135.176447ms)
|
||||
✔ recordTask keeps sync reads and a role write apart (191.698634ms)
|
||||
✔ read_at must be one canonical UTC format, so the projection compares strings safely (126.454044ms)
|
||||
✔ a bad entry refuses the whole record (117.660204ms)
|
||||
✔ taskView reads the projection for one business (137.090263ms)
|
||||
✔ requestTask hands only a holder and a task verb to the handler, and records refusals (272.236652ms)
|
||||
✔ the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous (441.522841ms)
|
||||
✔ without an adapter the server refuses every task verb (248.771833ms)
|
||||
✔ the runtime refuses an invalid adapter and closes a valid one (243.953359ms)
|
||||
✔ the process loads the S3 adapter from plain-data trackers (370.858909ms)
|
||||
✔ the tester binds only when the business sets bus.tester to exactly true (884.76292ms)
|
||||
✔ a business may not name a role tester, so the tester address is never a role (269.643239ms)
|
||||
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (587.258833ms)
|
||||
✔ a tester message is from tester, starts [mos test], and writes no human.input or authority (235.395203ms)
|
||||
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (276.720558ms)
|
||||
✔ the tester reads the human views a reader reads (167.727478ms)
|
||||
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.207237ms)
|
||||
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.354008ms)
|
||||
✔ testerNonce reads only the tester's variable and gives null on any read error (0.222645ms)
|
||||
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (90.324556ms)
|
||||
✔ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (842.328174ms)
|
||||
✔ socket capability stamps launch identity; shared views use wire, no SQL client (172.450558ms)
|
||||
✔ two wire claims serialize; a lost reply never automatically retries (199.693125ms)
|
||||
✔ malformed, oversized and identity-forging envelopes refuse without echoing input (132.42488ms)
|
||||
✔ client preserves UTF-8 when a response divides a multibyte character (11.461167ms)
|
||||
✔ committed mutation followed by dropped reply reports unknown and is never retried (148.637774ms)
|
||||
ℹ tests 171
|
||||
ℹ suites 0
|
||||
ℹ pass 171
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 4813.315624
|
||||
@@ -0,0 +1,99 @@
|
||||
✔ the role file loads and resolves through loadBusiness (8.263863ms)
|
||||
✔ the shipped file is exactly the approved list (1.279864ms)
|
||||
✔ the assistant's authority is message.send within role and nothing else (13.994902ms)
|
||||
✔ the assistant talks to the user and the chief of staff only, and no other shipped role is limited (0.933464ms)
|
||||
✔ a business grant through limits does not widen the role (2.061154ms)
|
||||
✔ a launch block whose by is the assistant is refused (2.791592ms)
|
||||
✔ the instance takes no credential references and no tracker (3.236434ms)
|
||||
✔ the contract passes work to the chief of staff and directs no one (0.652603ms)
|
||||
✔ config directory and file path follow MOSAIC_CONFIG (1.95993ms)
|
||||
✔ the fixture business validates and comes back frozen (6.118634ms)
|
||||
✔ two instances may share a definition (13.223991ms)
|
||||
✔ top-level refusals (6.087281ms)
|
||||
✔ arbiters and projects (8.050895ms)
|
||||
✔ role instances (5.750234ms)
|
||||
✔ Vikunja bots (6.791914ms)
|
||||
✔ a role without Vikunja takes no tracker block (2.192527ms)
|
||||
✔ credential references match the definition's services (2.791163ms)
|
||||
✔ launch (7.352658ms)
|
||||
✔ loadBusiness: file checks (1.791991ms)
|
||||
✔ loadBusiness: not a regular file (37.403137ms)
|
||||
✔ loading writes nothing (1.0575ms)
|
||||
✔ names that are Object.prototype properties don't count as declared (2.674819ms)
|
||||
✔ the shipped example refuses as written and validates once filled in (0.92968ms)
|
||||
✔ the role file loads and resolves through loadBusiness (8.923785ms)
|
||||
✔ the shipped file is exactly the approved list (0.30206ms)
|
||||
✔ the resolved record matches the approved list, so a widened file fails (2.337455ms)
|
||||
✔ the chief of staff holds role.launch and message.send; every other action is gated (1.974957ms)
|
||||
✔ the pm does not hold role.launch (10.231481ms)
|
||||
✔ a business grant of a gated action through limits does not widen the role (4.793563ms)
|
||||
✔ a limit that drops role.launch leaves the chief of staff with no launch block (1.435305ms)
|
||||
✔ a launch block whose by is the pm instance is refused (3.195612ms)
|
||||
✔ the contract names no duty to talk to the human and the pm contract no launch (0.451805ms)
|
||||
✔ the instance takes no credential references and no tracker (3.265046ms)
|
||||
✔ usage errors exit 4 (290.447019ms)
|
||||
✔ validate: a good business exits 0 and prints instance digests (64.44128ms)
|
||||
✔ validate: project files (307.578432ms)
|
||||
✔ validate: missing files and a broken system config (216.842734ms)
|
||||
✔ validate: credential reference problems exit 2 and name each one (60.302634ms)
|
||||
✔ validate: a token file inside the repository is refused (68.405838ms)
|
||||
✔ validate: role definitions come from MOSAIC_ROLES_DIR (196.699745ms)
|
||||
✔ resolve: prints one instance's record (267.461697ms)
|
||||
✔ resolve: refusals (417.951027ms)
|
||||
✔ parse: exactly one of file or env, plus the service's date (3.378321ms)
|
||||
✔ check: a good file has no problems (1.020996ms)
|
||||
✔ check never opens the file: a write-only token passes (0.441022ms)
|
||||
✔ check: file problems (1.135172ms)
|
||||
✔ check: token files can't live in the repository or dataRoot, even through a linked directory (12.60785ms)
|
||||
✔ check: dates and environment references (0.536922ms)
|
||||
✔ REQ-LIMIT-1 schema: every scope unset or zero, adjustable above four, bad values and unknown models refuse (28.466941ms)
|
||||
✔ REQ-LIMIT-1 counts each exact scope at/over limit, unlimited and old tuple after model reassignment (1.052466ms)
|
||||
✔ REQ-ROLE-3 writer: atomic validated revision, immutable previous bytes and authenticated actor/old/new receipt (190.271907ms)
|
||||
✔ REQ-ROLE-3 writer: pre-rename fault leaves old file, post-rename recovery records commit, conflicting recovery refuses (105.691647ms)
|
||||
✔ REQ-LIMIT-1 / decision145 migration prints only, preserves values, rejects ambiguity, and is idempotent (2.865704ms)
|
||||
✔ REQ-LIMIT-1 shared settings validates the complete proposed selection and logs exact actor (96.351501ms)
|
||||
✔ REQ-LIMIT-1 provider is table data: another provider routes separately and aliases share exact counts (1.753236ms)
|
||||
✔ REQ-ROLE-3 refuses live writer locks, symlink targets and uncertain recovery without changing bytes (63.202485ms)
|
||||
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (11.960715ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (179.554394ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (1.653656ms)
|
||||
✔ path and load (4.240359ms)
|
||||
✔ refusals (1.354171ms)
|
||||
✔ systemVars flattens the validated config (1.809772ms)
|
||||
✔ precedence: system, business, project, project role, agent (12.89165ms)
|
||||
✔ limits narrow the definition and never widen it (3.096124ms)
|
||||
✔ role.launch stays within-role only for the instance the launch block names (8.476862ms)
|
||||
✔ limits.authority without role.launch leaves the launcher with no launch block (4.344811ms)
|
||||
✔ limits.authority narrows cross-role actions too (1.882502ms)
|
||||
✔ classify (1.697006ms)
|
||||
✔ the record carries what the broker and launcher need (1.211188ms)
|
||||
✔ digest: key order doesn't matter, any value change does (8.601241ms)
|
||||
✔ refusals (1.889844ms)
|
||||
✔ the four shipped version 2 roles load (3.134369ms)
|
||||
✔ shipped role scopes match addendum B section 2 and the SR runbook (0.903041ms)
|
||||
✔ shipped authority follows the note's table (0.692882ms)
|
||||
✔ every role file in roles/ loads through the validator, and a v2 contract exists (0.916231ms)
|
||||
✔ version 1 files keep loading with no authority (1.111918ms)
|
||||
✔ the conductor policy isn't a role (0.235431ms)
|
||||
✔ a missing role file is exit 4, a symbolic link too (0.497439ms)
|
||||
✔ version 2 refusals (2.728143ms)
|
||||
✔ authority: closed vocabulary, no gated-only action, no overlap (2.393358ms)
|
||||
✔ messaging: optional, role definitions and human, never the tester (2.100656ms)
|
||||
✔ credentials: Gitea scopes (1.93914ms)
|
||||
✔ credentials: Vikunja scopes are a group-to-verbs map from the grantable list (1.409779ms)
|
||||
✔ credentials: services (0.769383ms)
|
||||
✔ contract: a non-empty regular Markdown file beside the role file (0.864863ms)
|
||||
✔ every key names known layers and a merge rule (0.736048ms)
|
||||
✔ unknown keys and wrong layers refuse (0.731079ms)
|
||||
✔ types (1.583684ms)
|
||||
✔ merge: defaults, then the most specific layer wins (0.231294ms)
|
||||
✔ merge: limits only narrow, and provenance lists each source (0.323263ms)
|
||||
✔ merge doesn't change its inputs (0.120226ms)
|
||||
ℹ tests 91
|
||||
ℹ suites 0
|
||||
ℹ pass 91
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 1967.194799
|
||||
@@ -0,0 +1,205 @@
|
||||
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1325.814042ms)
|
||||
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (98.29343ms)
|
||||
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (171.124876ms)
|
||||
✔ NO_COLOR: no escape codes, except reverse video on the selected row (257.230442ms)
|
||||
✔ 1-9 shows the decide flow's own lines and question; only y resolves (161.101458ms)
|
||||
✔ the app shows the same decide text as mosaic decide (118.880288ms)
|
||||
✔ any key but y or Y at the question answers No; nothing is sent (1486.059354ms)
|
||||
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (782.125396ms)
|
||||
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (1574.500756ms)
|
||||
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (86.325308ms)
|
||||
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (107.973847ms)
|
||||
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (936.710222ms)
|
||||
✔ quitting at the question answers No and sends nothing, armed or not (568.572638ms)
|
||||
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (189.698755ms)
|
||||
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (108.430128ms)
|
||||
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (972.201475ms)
|
||||
✔ at every size the decide box shows each line y depends on, or says it is hidden (8242.441282ms)
|
||||
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (157.713082ms)
|
||||
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (110.858466ms)
|
||||
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (57.705873ms)
|
||||
✔ keys: views, moving, trail of a selection, the command line, help and quit (230.854804ms)
|
||||
✔ one option: the status line says Press 1, not 1-1 (96.981806ms)
|
||||
✔ no business: the app says so and :business picks one (48.763766ms)
|
||||
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.862784ms)
|
||||
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (172.263599ms)
|
||||
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.453708ms)
|
||||
✔ decide with --note still asks; a No sends nothing (79.512519ms)
|
||||
✔ the app's business comes from a live bus host only (1.127008ms)
|
||||
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (6.238657ms)
|
||||
✔ draw is pure: same state, same frame (0.740601ms)
|
||||
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (134.36535ms)
|
||||
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (134.130417ms)
|
||||
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (106.047051ms)
|
||||
✔ decide prints a declining choice as declining (149.905161ms)
|
||||
✔ an unknown outcome is reported once and never resent (112.153208ms)
|
||||
✔ a decision closed before the answer arrives exits 2 and points at its trail (108.663386ms)
|
||||
✔ a prefix that matches two open decisions exits 2 and resolves neither (84.912476ms)
|
||||
✔ without --business a command uses the live host's business, and a stale host.json is not a host (138.883907ms)
|
||||
✔ every human command refuses inside an agent run before it touches the bus (100.512353ms)
|
||||
✔ usage errors exit 4; no business and no host is a usage error (92.416585ms)
|
||||
✔ agents and tasks print through the broker (96.667961ms)
|
||||
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.376871ms)
|
||||
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (68.788229ms)
|
||||
✔ trackers come from the tracker.* variables of the one project that names a tracker project (84.439941ms)
|
||||
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (41.726414ms)
|
||||
✔ two projects that each name a tracker project refuse, since the boot shape holds one (35.702561ms)
|
||||
✔ a business without tracker.baseUrl gets no trackers entry (38.600612ms)
|
||||
✔ an unknown business and a broken system config refuse with exit 3 (65.509721ms)
|
||||
✔ follow prints an unsolicited message after plain talk returned (183.563341ms)
|
||||
✔ talk --follow continues after reply and prints a later unsolicited message (178.109003ms)
|
||||
✔ inbox lists all unread human messages under decisions, does not deliver or read them (2389.837776ms)
|
||||
✔ follow refuses agent context and bad arguments (95.827573ms)
|
||||
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (88.823977ms)
|
||||
✔ plain talk leaves the process SIGINT handlers unchanged (258.679145ms)
|
||||
✔ empty views say so (1.046784ms)
|
||||
✔ the trail keeps the broker's order and names a decision's task without its rows (1.289911ms)
|
||||
✔ tasks print the tracker fields the snapshot carries (0.225299ms)
|
||||
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (724.549762ms)
|
||||
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (633.568902ms)
|
||||
✔ the size cap refuses a push before any byte (349.985527ms)
|
||||
✔ a fetch over the cap refuses before any byte reaches the reviewer (543.18068ms)
|
||||
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (371.094846ms)
|
||||
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (731.463074ms)
|
||||
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (536.507635ms)
|
||||
✔ a review of a project the business no longer has refuses unknown-project (707.200595ms)
|
||||
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (274.860539ms)
|
||||
✔ close() answers host-closing to a connection still sending its request line (311.617676ms)
|
||||
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (1071.622924ms)
|
||||
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (826.822435ms)
|
||||
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (986.954315ms)
|
||||
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (40.62895ms)
|
||||
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (602.715104ms)
|
||||
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (24.971668ms)
|
||||
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (301.326213ms)
|
||||
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (517.566439ms)
|
||||
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (941.818429ms)
|
||||
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (233.298195ms)
|
||||
✔ a second host for the same data root refuses with exit 3 while the first runs (171.083542ms)
|
||||
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (603.911775ms)
|
||||
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.32365ms)
|
||||
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (2.679643ms)
|
||||
✔ a live host's lock stays, however old the file is (0.571354ms)
|
||||
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (812.434207ms)
|
||||
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (219.605827ms)
|
||||
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (27.984179ms)
|
||||
✔ a broker fork that throws leaves no host.lock and no host.json (29.244812ms)
|
||||
✔ a broker send that throws leaves no host.lock and no host.json (41.588296ms)
|
||||
✔ a broker that misses its boot wait leaves no host.lock and no host.json (30.00364ms)
|
||||
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (172.599828ms)
|
||||
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (286.439005ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (173.483994ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (185.685125ms)
|
||||
✔ a host.json that can't be written stops both children and leaves no host.lock (467.002995ms)
|
||||
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (33.395138ms)
|
||||
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (160.109335ms)
|
||||
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (277.639724ms)
|
||||
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (247.362201ms)
|
||||
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (404.212007ms)
|
||||
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1321.817115ms)
|
||||
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (681.245943ms)
|
||||
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (188.977399ms)
|
||||
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (212.512221ms)
|
||||
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (213.001366ms)
|
||||
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (140.833829ms)
|
||||
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (166.4697ms)
|
||||
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (150.801288ms)
|
||||
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (192.741254ms)
|
||||
✔ watchChildren reports a child that died before it was called, and one that dies later (22.577293ms)
|
||||
✔ bus stop refuses to signal a live pid that is not a bus host (202.642101ms)
|
||||
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (243.470052ms)
|
||||
✔ bus start refuses with exit 3 without a notifier config (109.862339ms)
|
||||
✔ bus start runs until bus stop; status reports it while it runs (708.056946ms)
|
||||
✔ bus-service.sh renders the unit and installs it into a given directory (54.758139ms)
|
||||
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (61.432948ms)
|
||||
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (12.725368ms)
|
||||
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (8.350693ms)
|
||||
✔ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (47.944019ms)
|
||||
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1413.317683ms)
|
||||
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (786.221271ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (2081.328369ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (280.481576ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (318.629574ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (229.809162ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (515.814539ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (350.704601ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (197.021869ms)
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (1628.217088ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (837.500267ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3685.024053ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (150.503222ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (152.734437ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (146.022097ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1279.765002ms)
|
||||
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.58605ms)
|
||||
✔ migration needs no bus/config, prints whole converted document, is idempotent and never writes (16.007363ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (1.831072ms)
|
||||
✔ post-119 example and Jason fixture migrate with checked inherited models; wrong or absent config refuses (223.945694ms)
|
||||
✔ zoned uses the IANA zone across DST (26.487944ms)
|
||||
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (137.183772ms)
|
||||
✔ two blocking decisions get two DMs with different nonces (129.671674ms)
|
||||
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.326597ms)
|
||||
✔ a failed DM is journaled, backs off, and is retried until it lands (105.332101ms)
|
||||
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (104.848987ms)
|
||||
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (147.575782ms)
|
||||
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (111.339632ms)
|
||||
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (165.095163ms)
|
||||
✔ a restart after the second refusal does not send before that refusal's 30 min are up (167.164494ms)
|
||||
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (117.518585ms)
|
||||
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (93.187725ms)
|
||||
✔ an inbox read failure is logged and the next poll retries (1.14894ms)
|
||||
✔ no Discord id reaches the journal or the log (157.632903ms)
|
||||
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (19.756979ms)
|
||||
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (49.697135ms)
|
||||
✔ the journal: a whole file that is one torn line truncates to empty (44.902695ms)
|
||||
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (2.08755ms)
|
||||
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (0.718088ms)
|
||||
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (4.459054ms)
|
||||
✔ the journal: a symlinked directory refuses and says it is a link (2.184752ms)
|
||||
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (0.553131ms)
|
||||
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (0.429727ms)
|
||||
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.511181ms)
|
||||
✔ digest content stays within Discord's 2000 characters (0.32266ms)
|
||||
✔ runLoop never overlaps ticks and stops after the one in flight (110.541242ms)
|
||||
✔ a human command refused with human-required prints the other-tree line and exits 3 (3.475838ms)
|
||||
✔ a --tester command refused with tester-required prints the other-tree line and exits 3 (1.289049ms)
|
||||
✔ other exit-3 refusals print no other-tree line (2.214808ms)
|
||||
✔ the line names no path (0.151192ms)
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (513.12094ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (414.665863ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (455.066561ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (309.870049ms)
|
||||
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (4007.647111ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (475.278675ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (184.614484ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (198.839373ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (218.595144ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (216.930351ms)
|
||||
✔ inherited service.d override refuses without changing the unit (196.476437ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (356.194491ms)
|
||||
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (153.274809ms)
|
||||
✔ talk --tester refuses text without the [mos test] prefix before any call (99.834097ms)
|
||||
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (104.89727ms)
|
||||
✔ decide, stop and launches take no --tester (104.440367ms)
|
||||
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.347595ms)
|
||||
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (0.531391ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (435.521382ms)
|
||||
✔ the transport writes {business, verb, args} to the child and reads its JSON (51.584323ms)
|
||||
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2171.99681ms)
|
||||
✔ busExit and refuseInsideAgent (0.702256ms)
|
||||
✔ talk sends a REQUEST, prints and reads everything that arrives, and stops at the reply (217.521588ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1109.866931ms)
|
||||
✔ a late reply the Console has listed still reaches the next talk (2155.106616ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (110.338774ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (130.237987ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (317.382941ms)
|
||||
ℹ tests 195
|
||||
ℹ suites 0
|
||||
ℹ pass 195
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 18306.618783
|
||||
@@ -0,0 +1,27 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (0.984321ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.220052ms)
|
||||
✔ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (4.127979ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.166159ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.144692ms)
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.527967ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.356774ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.194607ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.316974ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.004169ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.90026ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.621211ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.743246ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (6.771389ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.461101ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.732925ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.541202ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.690898ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.091345ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 19
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 221.966687
|
||||
@@ -0,0 +1,122 @@
|
||||
✔ the Board: held roles with no machine sessions, a claim with no address, the toggle kept across a reload, and Message addressed to the role (6303.10561ms)
|
||||
✔ a redirect answer on a Board read, a bus read, a conversation read, a board POST, a module read and a send signs the page out: one line, nothing stale, no further reads (8076.148612ms)
|
||||
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (5392.68844ms)
|
||||
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
|
||||
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (6274.115052ms)
|
||||
✔ the README says a refused field table names the file or the key at fault, never a path (1.599393ms)
|
||||
✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (9036.292084ms)
|
||||
✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (315.99851ms)
|
||||
✔ decisions route serves the roles and recent lists from the reader view (802.021065ms)
|
||||
✔ credentials route serves the broker credential status from the reader view (650.940435ms)
|
||||
✔ replies route serves the replies to one message from the reader view (1279.242281ms)
|
||||
✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (76.02534ms)
|
||||
✔ bus refusals map to statuses and never carry a path or a stack (27.788262ms)
|
||||
✔ humanCall speaks the human transport protocol without blocking the server (1679.524669ms)
|
||||
✔ busReader takes --business, else the live bus host, else refuses (390.796091ms)
|
||||
✔ humanCall kills a transport that runs past its timeout (530.429503ms)
|
||||
✔ serve refuses a --business value that is not a business id (608.11661ms)
|
||||
✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (4253.30008ms)
|
||||
✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (4349.654833ms)
|
||||
✔ conversation view: a newer session with no readable history keeps the marker (2754.638777ms)
|
||||
✔ conversation view: seats without history say so and offer no reply (2781.092367ms)
|
||||
✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4175.723547ms)
|
||||
✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (54728.527208ms)
|
||||
✔ messages HTTP read pages and preserves metadata; bad arguments refuse before a read; other reads unchanged (370.364872ms)
|
||||
✔ Console Messages lists late unsolicited messages on polling with sender class time read state and trail; nav count includes beyond the page; reads never deliver (11991.789674ms)
|
||||
✔ Messages nav count polls on Tasks and Board and clears on a Board refusal; messages 403 refuses local pages (3406.312095ms)
|
||||
✔ copy writes the Console paths at the full id, read-only, and leaves an existing copy alone (3568.755608ms)
|
||||
✔ copy refuses a commit off refactor, an unknown one, a worktree and a bad copies directory (8864.728034ms)
|
||||
✔ copy writes nothing when an archived path is missing at the commit (1988.76524ms)
|
||||
✔ a copy that loses the rename race leaves no read-only temp directory behind (469.245198ms)
|
||||
✔ a copy whose rename fails with no target refuses, writes no copy and leaves no temp directory (451.873184ms)
|
||||
✔ a copy that meets a target holding files says exists: and moves nothing into it (450.58999ms)
|
||||
✔ a copy that meets an empty target directory replaces it by rename, not by moving into it (388.163785ms)
|
||||
✔ serve runs from a copy: /healthz 200, the config check, roles and RELEASE from the copy, the queue from --checkout (641.361453ms)
|
||||
✔ serve refuses a --checkout that is not an absolute directory path (211.29901ms)
|
||||
✔ consoleReads runs the queue read under queueRoot and reads RELEASE under root (48.362371ms)
|
||||
✔ preview options are all three or none, and each is checked (10.963538ms)
|
||||
✔ the CLI refuses a partial or invalid preview flag set at start (2426.423296ms)
|
||||
✔ the CLI with all three flags serves the preview mode (270.471087ms)
|
||||
✔ a request for the public name needs the header equal to the user id, else 401 and nothing read (17.604995ms)
|
||||
✔ the header name matches without regard to case, and the value compare is exact (3.923416ms)
|
||||
✔ the public name with the header reads the bus views, and the Host and Origin are checked first (30.263768ms)
|
||||
✔ in preview mode every write answers 403 read-only, from the public name and loopback, and reaches nothing (11.894315ms)
|
||||
✔ loopback requests are unchanged in preview mode, and the bus views work with the board down (4.775059ms)
|
||||
✔ a proxy that rewrites Host to the loopback port gets 403 on its first request, whatever the user (16.895379ms)
|
||||
✔ a repeated Host is 400 before any other check, in preview mode and without it (8.168507ms)
|
||||
✔ without the preview flags the public name is refused and writes still reach the board (4.860659ms)
|
||||
✔ redactor: config, dataRoot, any absolute path, Discord ids and the JSON parser quote (2.303622ms)
|
||||
✔ credential state from the date alone, as the bus states it (0.28922ms)
|
||||
✔ queue: rows, one row, ids and methods, notes; no path or id from a row (1723.356497ms)
|
||||
✔ queue: a refused read fails closed with the store's text, redacted (1609.79683ms)
|
||||
✔ queue: a store that fails to load, or a child that dies, gives a fixed message with no path or stack (4220.915199ms)
|
||||
✔ business: names, vars on the allowlist, authority, credential metadata only (21.773093ms)
|
||||
✔ business: missing or invalid file refuses with the module's text, redacted (47.954711ms)
|
||||
✔ business without --business: the live bus host, else no-bus-host; no system config: not-configured (16.459548ms)
|
||||
✔ settings: release, board, loopback address, notifier binding name only (1007.810372ms)
|
||||
✔ task fields: the committed table with no reads configured, GET only; a bad table refuses with no path (150.170504ms)
|
||||
✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (3928.868296ms)
|
||||
✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (23164.214902ms)
|
||||
✔ the send box: held roles, the draft and caret across a refresh, each receipt, one POST per Send, and the trail link; the board Reply on a 4xx and a 5xx (7408.256554ms)
|
||||
✔ a sent receipt lists its replies as the page refreshes, oldest first and capped, and marks none delivered or read (13817.370495ms)
|
||||
✔ startServer takes send only as a function and only with the preview mode (6.222994ms)
|
||||
✔ the CLI refuses --send without the preview flags, and without a configured bus (480.774964ms)
|
||||
✔ the CLI with --send and a configured bus sends through the human transport and logs one line (129.214383ms)
|
||||
✔ without --send the route is read-only like every other write, and config says no send (11.411492ms)
|
||||
✔ with --send every other write is still 403 read-only, and nothing reaches the board or bus (8.256153ms)
|
||||
✔ config says send only on the public name with --send on (2.250413ms)
|
||||
✔ a send without the signed-in user is 401 and is neither sent nor logged, loopback included (4.739116ms)
|
||||
✔ each request check refuses before anything is sent, and logs the refusal without the body (23.25476ms)
|
||||
✔ a send passes exactly to, body and in_reply_to, answers the id, and logs it (4.072221ms)
|
||||
✔ a crafted role name cannot forge a log line (4.278053ms)
|
||||
✔ a bus refusal is not sent, with its status; an outcome the bus could not confirm is unknown and never retried (13.20471ms)
|
||||
✔ through the human transport the request is exactly the business, message.send and the keys (133.201576ms)
|
||||
✔ against a real broker: the message is written once as a human send, and its refusals map (1560.542642ms)
|
||||
✔ loopback host and board origin fail closed (6.133024ms)
|
||||
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (372.965949ms)
|
||||
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (67.930758ms)
|
||||
✔ unreachable board reports URL; CLI rejects unsupported options (619.048779ms)
|
||||
✔ render prints the unit without the preview flags (10.732396ms)
|
||||
✔ render carries every serve flag, the preview set included (6.755057ms)
|
||||
✔ a partial preview set is refused (16.941438ms)
|
||||
✔ a value the unit cannot carry is refused, for every flag (493.548487ms)
|
||||
✔ the rendered unit names none of the human proof agent markers and sets no agent variable (33.532995ms)
|
||||
✔ install into --dir with --no-reload writes the file whole, then reports unchanged (231.568575ms)
|
||||
✔ install without --no-reload runs daemon-reload and nothing that starts the unit (118.062339ms)
|
||||
✔ uninstall refuses while the unit is running, with or without --no-reload, and removes it once it is not (354.889142ms)
|
||||
✔ status prints the unit state and GET /healthz on the installed port (395.642259ms)
|
||||
✔ usage: an unknown verb or flag, and start or enable, exit 4 (319.763513ms)
|
||||
✔ without --send, render is the template with its placeholders filled, byte for byte (112.146814ms)
|
||||
✔ render --send with the preview set ends ExecStart with --send and changes nothing else (171.025541ms)
|
||||
✔ --send without the whole preview set is refused and writes nothing (320.692025ms)
|
||||
✔ install --send into --dir with --no-reload writes the sending unit, and status says whether it sends (420.426794ms)
|
||||
✔ uninstall and status take no --send (82.628457ms)
|
||||
✔ install refuses while the unit is running, in any state but inactive or failed, and changes nothing (781.667238ms)
|
||||
✔ when the state read fails, install and uninstall refuse with one line and change nothing (110.551737ms)
|
||||
✔ install needs --copy naming a copy that exists, and refuses outside the canonical checkout without --allow-worktree (117.277604ms)
|
||||
✔ install refuses unless the bus unit runs from the same copy, naming both paths, and changes nothing (432.402023ms)
|
||||
✔ render --copy runs the copy and reads the queue in the checkout; without --copy the unit is unchanged (29.522255ms)
|
||||
✔ the uid header takes only an Authentik uid; the username header still takes a username (594.83823ms)
|
||||
✔ a preview value cannot start with - or . (39.638245ms)
|
||||
✔ status names the copy and whether refactor has moved past it, and says when the unit runs from no copy (643.425632ms)
|
||||
✔ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (4131.322546ms)
|
||||
2026-10-15T16:20:40.813Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (31.461326ms)
|
||||
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (12.087476ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (8.730245ms)
|
||||
✔ tokens.css and icons.svg are byte copies of docs/design (1.107613ms)
|
||||
✔ JetBrains Mono files match the digests in their sources file, with the OFL text (2.027698ms)
|
||||
✔ shipped strings are unchanged, and the web keeps its write boundary (2.198961ms)
|
||||
✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (7495.88541ms)
|
||||
✔ five states on Board, Inbox, Tasks, Agents and Trail (3080.498888ms)
|
||||
✔ Queue, Business and Settings in their five states, with no move button (5051.251662ms)
|
||||
✔ seeded secrets, Discord ids and paths reach no response and no page; business refusals in the module's words (3675.843699ms)
|
||||
✔ the server log names no config path when the system config refuses (316.769625ms)
|
||||
ℹ tests 112
|
||||
ℹ suites 0
|
||||
ℹ pass 112
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 55175.021453
|
||||
@@ -0,0 +1,44 @@
|
||||
2026-10-15T16:21:54Z
|
||||
01-name-pattern KILLED 1
|
||||
02-list-cardinality KILLED 1
|
||||
03-one-cardinality KILLED 1
|
||||
04-no-duplicates KILLED 1
|
||||
05-known-kind KILLED 1
|
||||
06-plugins-object KILLED 1
|
||||
07-registry-exports KILLED 1
|
||||
08-registry-version KILLED 1
|
||||
09-missing-directory KILLED 1
|
||||
10-component-type KILLED 1
|
||||
11-symlink-test KILLED 1
|
||||
12-plugins-dir-checked KILLED 1
|
||||
13-kind-dir-checked KILLED 1
|
||||
14-name-dir-checked KILLED 1
|
||||
15-index-checked KILLED 1
|
||||
16-realpath-before-import KILLED 1
|
||||
17-load-failure KILLED 1
|
||||
18-export-present KILLED 1
|
||||
19-export-function KILLED 1
|
||||
20-interface-version KILLED 1
|
||||
21-version-strict KILLED 1
|
||||
22-keep-old-setting KILLED 1
|
||||
23-first-load-nothing-on KILLED 1
|
||||
24-refusal-logged KILLED 1
|
||||
25-log-names-module KILLED 1
|
||||
26-log-kept KILLED 1
|
||||
27-whole-setting-object KILLED 1
|
||||
28-unknown-kind-logged KILLED 1
|
||||
29-absent-key-off KILLED 1
|
||||
30-loads-serialized KILLED 1
|
||||
31-log-required KILLED 1
|
||||
42-modules-known-kind KILLED 1
|
||||
32-schema-key KILLED 1
|
||||
33-schema-check KILLED 1
|
||||
34-schema-returned KILLED 1
|
||||
35-schema-copy KILLED 1
|
||||
36-setter-strict-keys KILLED 1
|
||||
37-setter-revision-format KILLED 1
|
||||
38-setter-checks-names KILLED 1
|
||||
39-setter-actor-logged KILLED 1
|
||||
40-setter-writes-plugins KILLED 1
|
||||
41-copy-ships-plugins KILLED 1
|
||||
2026-10-15T16:22:09Z
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Row 131: one fault per check. Sequential process groups; whole-group timeout cleanup.
|
||||
--dry checks every mutation site matches and changes source, and runs nothing."""
|
||||
import json,os,pathlib,signal,subprocess,sys
|
||||
args=[a for a in sys.argv[1:] if a!='--dry'];DRY='--dry' in sys.argv
|
||||
ROOT=pathlib.Path(args[0] if args else os.path.expanduser('~/dewey-scratch/r131/wt'))
|
||||
OUT=pathlib.Path(__file__).resolve().parent/'mutants'
|
||||
LT='packages/plugins/tests/loader.test.mjs';KT='packages/plugins/tests/kinds.test.mjs';PT=[KT,LT]
|
||||
ST='packages/business/tests/plugin-settings.test.mjs';CT='packages/cli/tests/stack-copy.test.mjs'
|
||||
cases=[]
|
||||
def add(id,path,old,new,test):cases.append(dict(id=id,path=path,old=old,new=new,test=test if isinstance(test,list) else [test]))
|
||||
p='packages/plugins/src/kinds.mjs'
|
||||
add('01-name-pattern',p,'if (typeof name !== "string" || !NAME.test(name)) {','if (typeof name !== "string") {',PT)
|
||||
add('02-list-cardinality',p,'} else if (!Array.isArray(setting)) {','} else if (false) {',PT)
|
||||
add('03-one-cardinality',p,'if (typeof setting !== "string") fail(','if (false) fail(',KT)
|
||||
add('04-no-duplicates',p,'if (seen.has(name)) fail(','if (false) fail(',PT)
|
||||
add('05-known-kind',p,'if (!Object.hasOwn(kinds, kind)) {','if (false) {',KT)
|
||||
add('06-plugins-object',p,'if (value === null || typeof value !== "object" || Array.isArray(value)) {','if (value === null) {',KT)
|
||||
add('07-registry-exports',p,'exports: Object.freeze(["mayLaunch", "mustStop"])','exports: Object.freeze(["mayLaunch"])',PT)
|
||||
add('08-registry-version',p,'kind: "usage-source", interfaceVersion: 1,','kind: "usage-source", interfaceVersion: 2,',PT)
|
||||
p='packages/plugins/src/loader.mjs'
|
||||
add('09-missing-directory',p,'if (e.code === "ENOENT" || e.code === "ENOTDIR") refuse("missing", `${path} is missing`);','/* missing not mapped */',LT)
|
||||
add('10-component-type',p,'if (directory ? !st.isDirectory() : !st.isFile()) {','if (false) {',LT)
|
||||
add('11-symlink-test',p,'if (st.isSymbolicLink()) refuse("symlink", `${path} is a symlink`);','/* symlinks allowed */',LT)
|
||||
add('12-plugins-dir-checked',p,' component(ROOT, true);\n','',LT)
|
||||
add('13-kind-dir-checked',p,' component(kindDir, true);\n','',LT)
|
||||
add('14-name-dir-checked',p,' component(nameDir, true);\n','',LT)
|
||||
add('15-index-checked',p,' component(index, false);\n','',LT)
|
||||
add('16-realpath-before-import',p,'if (real !== expected) refuse(','if (false) refuse(',LT)
|
||||
add('17-load-failure',p,'refuse("load-failed", `${spec.kind} ${name} failed to load: ${e.message}`);','throw e;',LT)
|
||||
add('18-export-present',p,'if (!Object.hasOwn(module, key)) refuse(','if (false) refuse(',LT)
|
||||
add('19-export-function',p,'if (typeof module[key] !== "function") refuse(','if (false) refuse(',LT)
|
||||
add('20-interface-version',p,'if (module.interfaceVersion !== spec.interfaceVersion) {','if (false) {',LT)
|
||||
add('21-version-strict',p,'if (module.interfaceVersion !== spec.interfaceVersion) {','if (module.interfaceVersion != spec.interfaceVersion) {',LT)
|
||||
add('22-keep-old-setting',p,'if (ok) current.set(kind, Object.freeze(next));','current.set(kind, Object.freeze(next));',LT)
|
||||
add('23-first-load-nothing-on',p,'if (ok) current.set(kind, Object.freeze(next));','if (ok || current.get(kind).length === 0) current.set(kind, Object.freeze(next));',LT)
|
||||
add('24-refusal-logged',p,' log(entry);\n','',LT)
|
||||
add('25-log-names-module',p,'name: e.plugin ?? name, code','name, code',LT)
|
||||
add('26-log-kept',p,'kept: kind === null ? loaded() : current.has(kind) ? current.get(kind).map(m => m.name) : [],','kept: [],',LT)
|
||||
add('27-whole-setting-object',p,'if (plugins === null || typeof plugins !== "object" || Array.isArray(plugins)) {','if (plugins === null || typeof plugins !== "object") {',LT)
|
||||
add('28-unknown-kind-logged',p,'refused(kind, null, new PluginError("unknown-kind"','void (kind, null, new PluginError("unknown-kind"',LT)
|
||||
add('29-absent-key-off',p,'if (Object.hasOwn(plugins, kind)) names = namesFor(','if (!Object.hasOwn(plugins, kind)) continue; names = namesFor(',LT)
|
||||
add('30-loads-serialized',p,'const run = queue.then(() => apply(plugins));','const run = apply(plugins);',LT)
|
||||
add('31-log-required',p,'if (typeof log !== "function") throw','if (false) throw',LT)
|
||||
add('42-modules-known-kind',p,'if (!current.has(kind)) refuse("unknown-kind"','if (false) refuse("unknown-kind"',LT)
|
||||
p='packages/business/src/business.mjs'
|
||||
add('32-schema-key',p,'"roles", "launch", "plugins"];','"roles", "launch"];',[ST,LT])
|
||||
add('33-schema-check',p,'structuredClone(checkPlugins(document.plugins, `${file} plugins`, { fail: (_code, message) => refuse(message) }))','structuredClone(document.plugins)',ST)
|
||||
add('34-schema-returned',p,'launch, plugins, definitions,','launch, definitions,',[ST,LT])
|
||||
add('35-schema-copy',p,' : structuredClone(checkPlugins(',' : (checkPlugins(',ST)
|
||||
p='packages/business/src/plugin-settings.mjs'
|
||||
add('36-setter-strict-keys',p,'Object.keys(args).some(key => key !== "revision" && key !== "plugins")','false',ST)
|
||||
add('37-setter-revision-format',p,'if (typeof args.revision !== "string" || !/^[a-f0-9]{64}$/.test(args.revision)) {','if (false) {',ST)
|
||||
add('38-setter-checks-names',p,' checkPlugins(args.plugins, "plugins");\n','',ST)
|
||||
add('39-setter-actor-logged',p,'{ revision: args.revision, actor }','{ revision: args.revision, actor: "host" }',ST)
|
||||
add('40-setter-writes-plugins',p,' next.plugins = structuredClone(args.plugins);\n','',ST)
|
||||
add('41-copy-ships-plugins','scripts/stack-copy.sh',' packages/plugins\n','',CT)
|
||||
results=[]
|
||||
if not DRY:OUT.mkdir(exist_ok=True)
|
||||
for c in cases:
|
||||
file=ROOT/c['path'];before=file.read_text();matches=before.count(c['old'])
|
||||
if not matches:raise RuntimeError('missing mutation site '+c['id'])
|
||||
after=before.replace(c['old'],c['new'])
|
||||
if after==before:raise RuntimeError('no change '+c['id'])
|
||||
if DRY:print(c['id'],'sites',matches,flush=True);continue
|
||||
file.write_text(after)
|
||||
try:
|
||||
env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'}
|
||||
with (OUT/(c['id']+'.log')).open('w') as log:
|
||||
p=subprocess.Popen(['node','--test',*c['test']],cwd=ROOT,env=env,stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||
try:rc=p.wait(timeout=300)
|
||||
except subprocess.TimeoutExpired:os.killpg(p.pid,signal.SIGKILL);p.wait();rc='timeout'
|
||||
verdict='KILLED' if isinstance(rc,int) and rc!=0 else 'SURVIVED' if rc==0 else 'TIMEOUT'
|
||||
row={k:c[k] for k in ['id','path','test']};row.update(result=verdict,exit=rc,sites=matches);results.append(row);print(c['id'],verdict,rc,flush=True)
|
||||
finally:file.write_text(before)
|
||||
if not DRY:(OUT/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
@@ -0,0 +1,83 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (1.019749ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.19619ms)
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (4.019474ms)
|
||||
✖ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.197387ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.14334ms)
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.327215ms)
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.03219ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.869298ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.878709ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.062596ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.283014ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.635104ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.773907ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.097903ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.445512ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.700789ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.427419ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.797037ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.927329ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 16
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 221.237262
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:24:1
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (4.019474ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception: Meter
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:30:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:35:1
|
||||
✖ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.197387ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:39:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:64:1
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.03219ms)
|
||||
AssertionError [ERR_ASSERTION]: Meter: /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-JnGnKV/packages/plugins/usage-source/Meter is missing
|
||||
+ actual - expected
|
||||
|
||||
+ 'missing'
|
||||
- 'bad-name'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:35:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:67:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'missing',
|
||||
expected: 'bad-name',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (0.992413ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.223062ms)
|
||||
✔ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (3.778864ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.155215ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.132822ms)
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.264915ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.291846ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.181509ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.387816ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.019959ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (28.057863ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.119103ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.769964ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.762968ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.392455ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.676599ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.875753ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.700288ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.033515ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 18
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 221.082439
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.875753ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
'e' !== 'meter'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:37:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:196:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'e',
|
||||
expected: 'meter',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (0.930082ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.223975ms)
|
||||
✔ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (0.969163ms)
|
||||
✖ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.4663ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.156446ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 46.619363
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:35:1
|
||||
✖ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.4663ms)
|
||||
AssertionError [ERR_ASSERTION]: The validation function is expected to return "true". Received false
|
||||
|
||||
Caught error:
|
||||
|
||||
PluginError: plugins.single names ["only"], which doesn't match /^[a-z][a-z0-9-]*$/
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:38:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: PluginError: plugins.single names ["only"], which doesn't match /^[a-z][a-z0-9-]*$/
|
||||
at raise (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:30:9)
|
||||
at namesFor (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:45:7)
|
||||
at checkPlugins (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:63:5)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:38:23
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:38:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18),
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (0.95784ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.21576ms)
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (4.189325ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.177823ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.140868ms)
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.852303ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.447333ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.626598ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.494359ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.220796ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.026034ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.683959ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.82915ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.830976ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.417758ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.651658ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (3.300099ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.696203ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.086076ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 17
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 212.526387
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:24:1
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (4.189325ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:32:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (3.300099ms)
|
||||
AssertionError [ERR_ASSERTION]: meter: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
'usage-source': [
|
||||
'meter',
|
||||
+ 'meter'
|
||||
]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:197:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'meter', 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (0.905149ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.198894ms)
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (1.017801ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.145613ms)
|
||||
✖ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.197794ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 44.992544
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:24:1
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (1.017801ms)
|
||||
AssertionError [ERR_ASSERTION]: The validation function is expected to return "true". Received false
|
||||
|
||||
Caught error:
|
||||
|
||||
TypeError: Cannot read properties of undefined (reading 'switch')
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:26:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: TypeError: Cannot read properties of undefined (reading 'switch')
|
||||
at namesFor (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:36:12)
|
||||
at checkPlugins (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:63:5)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:26:23
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:26:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19),
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:42:1
|
||||
✖ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.197794ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /x plugins names unknown kind/. Input:
|
||||
|
||||
"TypeError: Cannot read properties of undefined (reading 'switch')"
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:45:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: TypeError: Cannot read properties of undefined (reading 'switch')
|
||||
at namesFor (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:36:12)
|
||||
at checkPlugins (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:63:5)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:45:23
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:45:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19),
|
||||
expected: /x plugins names unknown kind/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (0.986263ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.223227ms)
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (0.652142ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.199955ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.154114ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 46.622015
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:24:1
|
||||
✖ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (0.652142ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:25:50)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
✖ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (1.599459ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.26875ms)
|
||||
✔ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (3.810855ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.177014ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.131927ms)
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.204067ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.272346ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.219628ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.350046ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.002748ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.717132ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.082999ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.703152ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.445377ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.507044ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.655494ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.548617ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.841555ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.106435ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 17
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 216.916959
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:8:1
|
||||
✖ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (1.599459ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
exports: [
|
||||
'mayLaunch',
|
||||
- 'mustStop'
|
||||
],
|
||||
interfaceVersion: 1,
|
||||
kind: 'limit-check',
|
||||
switch: 'list'
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:12:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { kind: 'limit-check', interfaceVersion: 1, exports: [ 'mayLaunch' ], switch: 'list' },
|
||||
expected: { kind: 'limit-check', interfaceVersion: 1, exports: [ 'mayLaunch', 'mustStop' ], switch: 'list' },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.445377ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- [
|
||||
- 'limit-check',
|
||||
- 'half',
|
||||
- 'missing-export'
|
||||
- ]
|
||||
- ]
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:153:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ [ 'limit-check', 'half', 'missing-export' ] ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
✖ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (1.636999ms)
|
||||
✔ REQ-PLUG-1 checkPlugins accepts one key per kind, each a list of names, empty included (0.284927ms)
|
||||
✔ REQ-PLUG-1 checkPlugins refuses bad shapes, unknown kinds, bad names and duplicates (3.752159ms)
|
||||
✔ REQ-PLUG-1 a kind that switches on one module takes one name, not a list (0.176765ms)
|
||||
✔ REQ-PLUG-1 checkPlugins reports through the caller's fail callback (0.133452ms)
|
||||
✖ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (8.131187ms)
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (2.299204ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.173819ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.040617ms)
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.392711ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.450577ms)
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.230341ms)
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (1.977788ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (1.998245ms)
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.129628ms)
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.007332ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.384492ms)
|
||||
✖ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (1.753096ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.950668ms)
|
||||
ℹ tests 19
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 13
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 112.266641
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/kinds.test.mjs:8:1
|
||||
✖ REQ-PLUG-1 REQ-LIMIT-4 the registry: usage-source and limit-check at interface version 1, each a list (1.636999ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
exports: [
|
||||
'readTurn'
|
||||
],
|
||||
+ interfaceVersion: 2,
|
||||
- interfaceVersion: 1,
|
||||
kind: 'usage-source',
|
||||
switch: 'list'
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/kinds.test.mjs:10:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { kind: 'usage-source', interfaceVersion: 2, exports: [ 'readTurn' ], switch: 'list' },
|
||||
expected: { kind: 'usage-source', interfaceVersion: 1, exports: [ 'readTurn' ], switch: 'list' },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:44:1
|
||||
✖ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (8.131187ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source fixture-usage implements interface 1, not 2',
|
||||
+ name: 'fixture-usage'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:56:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'fixture-usage', code: 'interface-version', message: 'usage-source fixture-usage implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:64:1
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (2.299204ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:65:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.173819ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:72:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.040617ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:81:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:91:1
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.392711ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:92:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:119:1
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.230341ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:121:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:134:1
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (1.977788ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:135:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (1.998245ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:143:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:157:1
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.129628ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:158:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:165:1
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.007332ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
'meter' !== 'absent'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:178:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'meter',
|
||||
expected: 'absent',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.384492ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:183:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:203:1
|
||||
✖ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (1.753096ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'interface-version',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: [],
|
||||
+ kind: 'usage-source',
|
||||
+ message: 'usage-source meter implements interface 1, not 2',
|
||||
+ name: 'meter'
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at loadedTree (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:22:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:204:13)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'interface-version', message: 'usage-source meter implements interface 1, not 2', kept: [] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.833324ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.351686ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.261896ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (3.081717ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.242198ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.898108ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.640177ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.812263ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.885226ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.529495ms)
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.461865ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.649674ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.375855ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.922027ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 12
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 208.085813
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.261896ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ti9sln/packages/plugins/usage-source/absent'
|
||||
at lstatSync (node:fs:2138:25)
|
||||
at component (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ti9sln/packages/plugins/src/loader.mjs:25:10)
|
||||
at loadModule (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ti9sln/packages/plugins/src/loader.mjs:42:3)
|
||||
at apply (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ti9sln/packages/plugins/src/loader.mjs:115:27) {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ti9sln/packages/plugins/usage-source/absent'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:165:1
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.461865ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-BynJ1f/packages/plugins/usage-source/absent'
|
||||
at lstatSync (node:fs:2138:25)
|
||||
at component (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-BynJ1f/packages/plugins/src/loader.mjs:25:10)
|
||||
at loadModule (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-BynJ1f/packages/plugins/src/loader.mjs:42:3)
|
||||
at apply (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-BynJ1f/packages/plugins/src/loader.mjs:115:27) {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-BynJ1f/packages/plugins/usage-source/absent'
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.877318ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.364457ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (4.180545ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.43889ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.015758ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (27.897067ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.677038ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.845477ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.07145ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.490785ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.70964ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.407065ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.77907ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.005272ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 215.391262
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (4.180545ms)
|
||||
AssertionError [ERR_ASSERTION]: dir-index: usage-source dir-index failed to load: Directory import '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-2d8rfF/packages/plugins/usage-source/dir-index/index.mjs' is not supported resolving ES modules imported from /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-2d8rfF/packages/plugins/src/loader.mjs
|
||||
+ actual - expected
|
||||
|
||||
+ 'load-failed'
|
||||
- 'missing'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:35:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:77:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'load-failed',
|
||||
expected: 'missing',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.88192ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.258634ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.253365ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.617817ms)
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.004227ms)
|
||||
✖ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.289127ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.536292ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.911378ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.87808ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.462569ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.668134ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.46598ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.358423ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.097693ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 11
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 212.729308
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.617817ms)
|
||||
AssertionError [ERR_ASSERTION]: linked: /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-nN0MjR/packages/plugins/usage-source/linked is not a directory
|
||||
+ actual - expected
|
||||
|
||||
+ 'missing'
|
||||
- 'symlink'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:35:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:84:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'missing',
|
||||
expected: 'symlink',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:91:1
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.004227ms)
|
||||
AssertionError [ERR_ASSERTION]: meter: /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-hKFPYI/packages/plugins/usage-source is not a directory
|
||||
+ actual - expected
|
||||
|
||||
+ 'missing'
|
||||
- 'symlink'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:35:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:96:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'missing',
|
||||
expected: 'symlink',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:99:1
|
||||
✖ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.289127ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
+ actual - expected
|
||||
|
||||
+ 'missing'
|
||||
- 'symlink'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:115:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'missing',
|
||||
expected: 'symlink',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.998377ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.143351ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.865685ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.848392ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.099821ms)
|
||||
✖ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.435447ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.569113ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.773836ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.82258ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.429166ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.71285ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.428391ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.65503ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.099315ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 214.429386
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:99:1
|
||||
✖ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.435447ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ 'meter'
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:114:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ 'meter' ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.593701ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.212895ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.888251ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.509948ms)
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.306208ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (27.377016ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.551264ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.747411ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.81103ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.484707ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.722459ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.32935ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (101.563951ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.939414ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 212.880268
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:91:1
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.306208ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /plugins\/usage-source is a symlink/. Input:
|
||||
|
||||
'/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-UIXF8X/packages/plugins/usage-source/meter/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-UIXF8X/packages/plugins/usage-real/meter/index.mjs'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:39:23)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:96:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-UIXF8X/packages/plugins/usage-source/meter/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-UIXF8X/packages/plugins/usage-real/meter/index.mjs',
|
||||
expected: /plugins\/usage-source is a symlink/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.069078ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.363505ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.770453ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.769557ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.135156ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.54869ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.563781ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.671021ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.916433ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.531167ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.659198ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.33605ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.00535ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.977649ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 12
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 211.789602
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.770453ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /absent is missing/. Input:
|
||||
|
||||
'/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-lzldLH/packages/plugins/usage-source/absent/index.mjs is missing'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:39:23)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:73:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-lzldLH/packages/plugins/usage-source/absent/index.mjs is missing',
|
||||
expected: /absent is missing/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.769557ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /usage-source\/linked is a symlink/. Input:
|
||||
|
||||
'/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-6cGaEj/packages/plugins/usage-source/linked/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-6cGaEj/packages/plugins/usage-source/meter/index.mjs'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:39:23)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:84:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-6cGaEj/packages/plugins/usage-source/linked/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-6cGaEj/packages/plugins/usage-source/meter/index.mjs',
|
||||
expected: /usage-source\/linked is a symlink/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.669425ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.288117ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.996879ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.389418ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.958031ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.137076ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.648837ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.830627ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.837263ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.514245ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.731791ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.506587ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.096339ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.089699ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 12
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 211.346926
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.996879ms)
|
||||
AssertionError [ERR_ASSERTION]: dir-index: usage-source dir-index failed to load: Directory import '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-FLeWxh/packages/plugins/usage-source/dir-index/index.mjs' is not supported resolving ES modules imported from /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-FLeWxh/packages/plugins/src/loader.mjs
|
||||
+ actual - expected
|
||||
|
||||
+ 'load-failed'
|
||||
- 'missing'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:35:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:77:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'load-failed',
|
||||
expected: 'missing',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.389418ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /link-index\/index\.mjs is a symlink/. Input:
|
||||
|
||||
'/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ptff10/packages/plugins/usage-source/link-index/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ptff10/packages/plugins/usage-source/meter/index.mjs'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:39:23)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:88:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ptff10/packages/plugins/usage-source/link-index/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Ptff10/packages/plugins/usage-source/meter/index.mjs',
|
||||
expected: /link-index\/index\.mjs is a symlink/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.922864ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.390817ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.223786ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.351304ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.026554ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.327643ms)
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.412784ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.773448ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.081731ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.556199ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.771353ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.509257ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.911073ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.097565ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 208.743698
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:119:1
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.412784ms)
|
||||
AssertionError [ERR_ASSERTION]: swapped: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
'usage-source': [
|
||||
+ 'swapped'
|
||||
- 'meter'
|
||||
]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:131:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'swapped' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.809289ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.219533ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.187227ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.249774ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.990612ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (24.645016ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.530895ms)
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.190033ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.72017ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.421533ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.334617ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.518576ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.747627ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.008007ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 208.82718
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:134:1
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.190033ms)
|
||||
SyntaxError: Unexpected end of input
|
||||
at compileSourceTextModule (node:internal/modules/esm/utils:355:16)
|
||||
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:93:18)
|
||||
at #translate (node:internal/modules/esm/loader:441:20)
|
||||
at afterLoad (node:internal/modules/esm/loader:509:29)
|
||||
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:514:12)
|
||||
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:567:36)
|
||||
at afterResolve (node:internal/modules/esm/loader:614:52)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:620:12)
|
||||
at node:internal/modules/esm/loader:639:32
|
||||
at TracingChannel.tracePromise (node:diagnostics_channel:547:22)
|
||||
@@ -0,0 +1,42 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.406725ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.475628ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.308359ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.407971ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.040936ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.352842ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.47606ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.68165ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.066011ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.569421ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.71873ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.363872ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.290582ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.912748ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 215.51481
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.066011ms)
|
||||
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /doesn't export readTurn/. Input:
|
||||
|
||||
"usage-source no-read export readTurn isn't a function"
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:39:23)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:145:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: "usage-source no-read export readTurn isn't a function",
|
||||
expected: /doesn't export readTurn/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.844388ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.22488ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.207108ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.403113ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.954469ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.825422ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.6038ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.753518ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.45008ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.463883ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.757319ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.496356ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.668213ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.054778ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 210.457666
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.45008ms)
|
||||
AssertionError [ERR_ASSERTION]: not-fn: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
'usage-source': [
|
||||
+ 'not-fn'
|
||||
- 'meter'
|
||||
]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:149:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'not-fn' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.986754ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.379131ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.511931ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.699931ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.105484ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.094191ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.606943ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (3.001531ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.8912ms)
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.832185ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.757138ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.528069ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.008723ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.954085ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 213.202544
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:157:1
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.832185ms)
|
||||
AssertionError [ERR_ASSERTION]: v2: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
'usage-source': [
|
||||
+ 'v2'
|
||||
- 'meter'
|
||||
]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:160:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'v2' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.99163ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.465303ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.320673ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.422629ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.134835ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (29.945876ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.660907ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (3.034549ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (7.001891ms)
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (3.310869ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.683265ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.451737ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.625381ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (0.997343ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 215.248193
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:157:1
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (3.310869ms)
|
||||
AssertionError [ERR_ASSERTION]: v-string: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
'usage-source': [
|
||||
+ 'v-string'
|
||||
- 'meter'
|
||||
]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:162:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'v-string' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.8395ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.239847ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.596576ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.113078ms)
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.991423ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (29.529134ms)
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.697901ms)
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.43814ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (2.263911ms)
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.635264ms)
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.802495ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.450199ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.301695ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.139123ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 6
|
||||
ℹ fail 8
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 214.201489
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.596576ms)
|
||||
AssertionError [ERR_ASSERTION]: empty: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:75:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.113078ms)
|
||||
AssertionError [ERR_ASSERTION]: linked: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:84:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:91:1
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.991423ms)
|
||||
AssertionError [ERR_ASSERTION]: meter: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:96:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:119:1
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.697901ms)
|
||||
AssertionError [ERR_ASSERTION]: swapped: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:131:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:134:1
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.43814ms)
|
||||
AssertionError [ERR_ASSERTION]: syntax: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:137:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (2.263911ms)
|
||||
AssertionError [ERR_ASSERTION]: no-read: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:145:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:157:1
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.635264ms)
|
||||
AssertionError [ERR_ASSERTION]: v2: old setting kept
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': []
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
}
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:32:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:160:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:165:1
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.802495ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': [
|
||||
+ 'meter'
|
||||
+ ]
|
||||
- 'usage-source': []
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:172:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.718935ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.889936ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.781559ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.560221ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.145269ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.53739ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.714359ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.87242ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.845104ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.528986ms)
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.540733ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.524789ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.77856ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.126618ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 216.678541
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:165:1
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.540733ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': [
|
||||
+ 'meter'
|
||||
+ ]
|
||||
- 'usage-source': []
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:172:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.182235ms)
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.222902ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.65768ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.694535ms)
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.361319ms)
|
||||
✖ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.628682ms)
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.698805ms)
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.4078ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (2.384788ms)
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.870483ms)
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.930742ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.492929ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.153904ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.002101ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 11
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 212.877553
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:64:1
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.222902ms)
|
||||
AssertionError [ERR_ASSERTION]: Meter: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'bad-name',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: `plugins.usage-source names "Meter", which doesn't match /^[a-z][a-z0-9-]*$/`,
|
||||
- name: 'Meter'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:67:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'Meter', code: 'bad-name', message: `plugins.usage-source names "Meter", which doesn't match /^[a-z][a-z0-9-]*$/`, kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.65768ms)
|
||||
AssertionError [ERR_ASSERTION]: absent: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'missing',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-fezqA2/packages/plugins/usage-source/absent is missing',
|
||||
- name: 'absent'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:73:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'absent', code: 'missing', message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-fezqA2/packages/plugins/usage-source/absent is missing', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.694535ms)
|
||||
AssertionError [ERR_ASSERTION]: linked: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'symlink',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-s1cgVI/packages/plugins/usage-source/linked is a symlink',
|
||||
- name: 'linked'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:84:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'linked', code: 'symlink', message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-s1cgVI/packages/plugins/usage-source/linked is a symlink', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:91:1
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.361319ms)
|
||||
AssertionError [ERR_ASSERTION]: meter: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'symlink',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-rkYMNt/packages/plugins/usage-source is a symlink',
|
||||
- name: 'meter'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:96:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'symlink', message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-rkYMNt/packages/plugins/usage-source is a symlink', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:99:1
|
||||
✖ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.628682ms)
|
||||
TypeError: Cannot read properties of undefined (reading 'code')
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:115:30)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:119:1
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.698805ms)
|
||||
AssertionError [ERR_ASSERTION]: swapped: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'symlink',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Wjfc7m/packages/plugins/usage-source/swapped/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Wjfc7m/packages/plugins/usage-source/meter/index.mjs',
|
||||
- name: 'swapped'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:131:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'swapped', code: 'symlink', message: '/home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Wjfc7m/packages/plugins/usage-source/swapped/index.mjs resolves to /home/jwoltje/dewey-scratch/tmp/mosaic-plugins-Wjfc7m/packages/plugins/usage-source/meter/index.mjs', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:134:1
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.4078ms)
|
||||
AssertionError [ERR_ASSERTION]: syntax: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'load-failed',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: 'usage-source syntax failed to load: Unexpected end of input',
|
||||
- name: 'syntax'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:137:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'syntax', code: 'load-failed', message: 'usage-source syntax failed to load: Unexpected end of input', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (2.384788ms)
|
||||
AssertionError [ERR_ASSERTION]: no-read: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'missing-export',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: "usage-source no-read doesn't export readTurn",
|
||||
- name: 'no-read'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:145:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'no-read', code: 'missing-export', message: "usage-source no-read doesn't export readTurn", kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:157:1
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.870483ms)
|
||||
AssertionError [ERR_ASSERTION]: v2: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'interface-version',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: 'usage-source v2 implements interface 2, not 1',
|
||||
- name: 'v2'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:160:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'v2', code: 'interface-version', message: 'usage-source v2 implements interface 2, not 1', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:165:1
|
||||
✖ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.930742ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:175:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.492929ms)
|
||||
AssertionError [ERR_ASSERTION]: meter: logged once
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- {
|
||||
- code: 'bad-setting',
|
||||
- event: 'plugin-refused',
|
||||
- kept: [
|
||||
- 'meter'
|
||||
- ],
|
||||
- kind: 'usage-source',
|
||||
- message: 'plugins.usage-source must be a list of module names',
|
||||
- name: 'meter'
|
||||
- }
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:40:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:196:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ { event: 'plugin-refused', kind: 'usage-source', name: 'meter', code: 'bad-setting', message: 'plugins.usage-source must be a list of module names', kept: [Array] } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.632796ms)
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (2.753212ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.836629ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.810412ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.033716ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (27.31341ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.582536ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.719239ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.065324ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.731089ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.972685ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.631946ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.316851ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.006712ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 12
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 208.891452
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:64:1
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (2.753212ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
null !== 'Meter'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:37:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:67:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: 'Meter',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.631946ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
null !== 'meter'
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:37:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:197:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: null,
|
||||
expected: 'meter',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.072996ms)
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.122063ms)
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.514345ms)
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.271425ms)
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.654462ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (25.55133ms)
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.620809ms)
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.342699ms)
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (2.32443ms)
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.295485ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.817804ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.353885ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (101.834887ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.114604ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 5
|
||||
ℹ fail 9
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 208.112329
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:64:1
|
||||
✖ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.122063ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:67:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:71:1
|
||||
✖ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (2.514345ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:73:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:80:1
|
||||
✖ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.271425ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:84:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:91:1
|
||||
✖ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.654462ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:96:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:119:1
|
||||
✖ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.620809ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:131:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:134:1
|
||||
✖ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.342699ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:137:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:142:1
|
||||
✖ REQ-PLUG-1 a missing export refuses and keeps the old setting (2.32443ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:145:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:157:1
|
||||
✖ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.295485ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- 'meter'
|
||||
- ]
|
||||
|
||||
at refusesKeepingOld (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:38:10)
|
||||
at async TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:160:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ 'meter' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.353885ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- {
|
||||
- 'limit-check': [
|
||||
- 'cap'
|
||||
- ],
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
- }
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:193:12)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.821612ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.263019ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.343928ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.599749ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.172649ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (28.376672ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.710912ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.787536ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.024711ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.526155ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.705364ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.880786ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (101.916601ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.0899ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 215.858895
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.880786ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- [
|
||||
- null,
|
||||
- 'bad-setting'
|
||||
- ]
|
||||
- ]
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:192:12)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ [ null, 'bad-setting' ] ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.915724ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.336951ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.097832ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.327882ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.970929ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.963609ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.61179ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.70741ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.25572ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.444816ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.691608ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.514607ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.701729ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.179424ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 214.626067
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.514607ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ []
|
||||
- [
|
||||
- [
|
||||
- 'made-up',
|
||||
- 'unknown-kind'
|
||||
- ]
|
||||
- ]
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:185:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [],
|
||||
expected: [ [ 'made-up', 'unknown-kind' ] ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.725011ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.293591ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.31681ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.420713ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (1.937332ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.147018ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.716228ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (3.283449ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.856648ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.570609ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.712432ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (3.255117ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.485727ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.02065ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 212.674943
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (3.255117ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
{
|
||||
'limit-check': [
|
||||
'cap'
|
||||
],
|
||||
+ 'usage-source': [
|
||||
+ 'meter'
|
||||
+ ]
|
||||
- 'usage-source': []
|
||||
}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:200:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: { 'usage-source': [ 'meter' ], 'limit-check': [ 'cap' ] },
|
||||
expected: { 'usage-source': [], 'limit-check': [ 'cap' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (6.946924ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.245391ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.395265ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.517284ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.181388ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.223094ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.71118ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.794417ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.970293ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.546724ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.748063ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.564548ms)
|
||||
✖ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.281619ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.564009ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 215.310585
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:203:1
|
||||
✖ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.281619ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
[
|
||||
+ 'slow'
|
||||
- 'fast'
|
||||
]
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:215:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ 'slow' ],
|
||||
expected: [ 'fast' ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (8.133845ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.833528ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (4.715311ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.951368ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.210481ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (37.264201ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.680476ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (3.722472ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (6.169751ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (3.580114ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (3.074277ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (5.360314ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.789793ms)
|
||||
✖ REQ-PLUG-1 the loader needs a log callback (2.626562ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 247.556609
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:218:1
|
||||
✖ REQ-PLUG-1 the loader needs a log callback (2.626562ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:221:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /log callback/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (5.909884ms)
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (38.81033ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (2.49137ms)
|
||||
✖ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (4.753088ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (5.156712ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.941754ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (4.001745ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.995627ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (34.859618ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.431905ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (4.128101ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (5.468892ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (3.212562ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.572052ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.961947ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.237844ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.201948ms)
|
||||
ℹ tests 17
|
||||
ℹ suites 0
|
||||
ℹ pass 14
|
||||
ℹ fail 3
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 255.659538
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:28:1
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (5.909884ms)
|
||||
Error [BusinessError]: unsupported business file key: "plugins"
|
||||
at refuse (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/errors.mjs:12:9)
|
||||
at rejectUnknownKeys (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/util.mjs:17:33)
|
||||
at validateBusinessDocument (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/business.mjs:140:3)
|
||||
at check (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:30:22)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:33:20)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:42:1
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (38.81033ms)
|
||||
Error [BusinessError]: unsupported business file key: "plugins"
|
||||
at refuse (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/errors.mjs:12:9)
|
||||
at rejectUnknownKeys (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/util.mjs:17:33)
|
||||
at validateBusinessDocument (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/business.mjs:140:3)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:186:7
|
||||
at withLock (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:128:14)
|
||||
at Object.write (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:180:12)
|
||||
at Object.set (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/plugin-settings.mjs:33:28)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:46:27)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25) {
|
||||
exitCode: 2
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:44:1
|
||||
✖ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (4.753088ms)
|
||||
Error [BusinessError]: unsupported business file key: "plugins"
|
||||
at refuse (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/errors.mjs:12:9)
|
||||
at rejectUnknownKeys (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/util.mjs:17:33)
|
||||
at validateBusinessDocument (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/business.mjs:140:3)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:53:20)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
exitCode: 2
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (8.505894ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (99.731971ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (1.569722ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 167.144527
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:28:1
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (8.505894ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception (BusinessError): {"made-up":[]}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:38:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (5.953642ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (114.027752ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (1.942631ms)
|
||||
✖ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (8.989553ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (4.728041ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.634174ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (3.569675ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.564529ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (30.475345ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (3.392ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (3.634274ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (4.922906ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (3.164925ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (2.283272ms)
|
||||
✔ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.964489ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (103.294067ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.469376ms)
|
||||
ℹ tests 17
|
||||
ℹ suites 0
|
||||
ℹ pass 15
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 247.482272
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:28:1
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (5.953642ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
|
||||
undefined !== {}
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:31:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: {},
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:44:1
|
||||
✖ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (8.989553ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ [
|
||||
+ {
|
||||
+ code: 'bad-setting',
|
||||
+ event: 'plugin-refused',
|
||||
+ kept: {
|
||||
+ 'limit-check': [],
|
||||
+ 'usage-source': []
|
||||
+ },
|
||||
+ kind: null,
|
||||
+ message: 'plugins must be an object with one key per kind',
|
||||
+ name: null
|
||||
+ }
|
||||
+ ]
|
||||
- []
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:56:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { event: 'plugin-refused', kind: null, name: null, code: 'bad-setting', message: 'plugins must be an object with one key per kind', kept: [Object] } ],
|
||||
expected: [],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (5.453961ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (109.660944ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (2.284831ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 172.649417
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:28:1
|
||||
✖ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (5.453961ms)
|
||||
AssertionError [ERR_ASSERTION]: the document itself stays mutable
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:36:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (8.628537ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (119.966425ms)
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (58.039007ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 251.130511
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:63:1
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (58.039007ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception: {"revision":"7d713440bac5d73780f79d370be9053848788f24bbda61b285a94841ac5b2a4a","plugins":{},"limits":{}}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:81:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (9.309187ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (99.966774ms)
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (21.552171ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 191.132875
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:63:1
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (21.552171ms)
|
||||
AssertionError [ERR_ASSERTION]: {"revision":"nope","plugins":{}}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:81:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: Error: organization revision changed; read again
|
||||
at fail (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:20:9)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:185:32
|
||||
at withLock (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:128:14)
|
||||
at Object.write (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:180:12)
|
||||
at Object.set (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/plugin-settings.mjs:33:28)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:81:36
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:81:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14),
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (7.506489ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (95.204781ms)
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (21.754824ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 178.271573
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:63:1
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (21.754824ms)
|
||||
AssertionError [ERR_ASSERTION]: {"revision":"857491f64b4cf557c4158834969e269ac02d37ca0c68c2998bf03970570b050f","plugins":{"made-up":["x"]}}
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:81:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: BusinessError: /home/jwoltje/dewey-scratch/tmp/mosaic-business-awvc8I/businesses/acme.json plugins names unknown kind "made-up"; adding a kind is a core change
|
||||
at refuse (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/errors.mjs:12:9)
|
||||
at fail (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/business.mjs:185:101)
|
||||
at checkPlugins (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/src/kinds.mjs:61:7)
|
||||
at validateBusinessDocument (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/business.mjs:185:23)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:186:7
|
||||
at withLock (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:128:14)
|
||||
at Object.write (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/organization.mjs:180:12)
|
||||
at Object.set (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/src/plugin-settings.mjs:32:28)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:81:36
|
||||
at getActual (node:assert:580:5),
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (7.094138ms)
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (54.057314ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (1.321911ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 110.902522
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:42:1
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (54.057314ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
'host' !== 'jason'
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:52:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 'host',
|
||||
expected: 'jason',
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
✔ REQ-PLUG-1 schema: plugins is optional, names known kinds and checked module names (7.142387ms)
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (55.630027ms)
|
||||
✔ REQ-PLUG-1 REQ-ROLE-3 a refused setter write throws a code, changes nothing and logs nothing (1.215772ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 110.48639
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/business/tests/plugin-settings.test.mjs:42:1
|
||||
✖ REQ-PLUG-1 REQ-ROLE-3 the setter writes plugins through the organization writer and logs old and new names (55.630027ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
+ undefined
|
||||
- {
|
||||
- 'usage-source': [
|
||||
- 'meter'
|
||||
- ]
|
||||
- }
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/business/tests/plugin-settings.test.mjs:47:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: { 'usage-source': [ 'meter' ] },
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
✖ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (335.775914ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (374.038444ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (383.625565ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (222.422533ms)
|
||||
✖ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (2216.368185ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (433.30476ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (150.490483ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (146.033353ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (137.711332ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (156.933026ms)
|
||||
✔ inherited service.d override refuses without changing the unit (154.245135ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (131.568501ms)
|
||||
ℹ tests 12
|
||||
ℹ suites 0
|
||||
ℹ pass 10
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 4893.420664
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/stack-copy.test.mjs:34:1
|
||||
✖ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (335.775914ms)
|
||||
AssertionError [ERR_ASSERTION]: packages/plugins/src/kinds.mjs
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/cli/tests/stack-copy.test.mjs:37:234)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: '==',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/stack-copy.test.mjs:101:1
|
||||
✖ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (2216.368185ms)
|
||||
AssertionError [ERR_ASSERTION]: node:internal/modules/esm/resolve:272
|
||||
throw new ERR_MODULE_NOT_FOUND(
|
||||
^
|
||||
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/jwoltje/dewey-scratch/tmp/stack-copy-pSa3Jz/copies/2a913bf71e8830fc2f219cf91b88251feec289fa/packages/plugins/src/kinds.mjs' imported from /home/jwoltje/dewey-scratch/tmp/stack-copy-pSa3Jz/copies/2a913bf71e8830fc2f219cf91b88251feec289fa/packages/business/src/business.mjs
|
||||
at finalizeResolution (node:internal/modules/esm/resolve:272:11)
|
||||
at moduleResolve (node:internal/modules/esm/resolve:879:10)
|
||||
at defaultResolve (node:internal/modules/esm/resolve:1006:11)
|
||||
at #cachedDefaultResolve (node:internal/modules/esm/loader:708:20)
|
||||
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:728:38)
|
||||
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:766:56)
|
||||
at #resolve (node:internal/modules/esm/loader:690:17)
|
||||
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:610:35)
|
||||
at ModuleJob.syncLink (node:internal/modules/esm/module_job:277:33)
|
||||
at ModuleJob.link (node:internal/modules/esm/module_job:389:17) {
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
url: 'file:///home/jwoltje/dewey-scratch/tmp/stack-copy-pSa3Jz/copies/2a913bf71e8830fc2f219cf91b88251feec289fa/packages/plugins/src/kinds.mjs'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/cli/tests/stack-copy.test.mjs:111:84)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '',
|
||||
expected: /bus host up/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
✔ REQ-PLUG-1 fixture modules of each kind switch on from a test organization file, no core file changed (7.745043ms)
|
||||
✔ REQ-PLUG-1 a name not matching ^[a-z][a-z0-9-]*$ refuses and keeps the old setting (3.471768ms)
|
||||
✔ REQ-PLUG-1 a missing module directory or index.mjs refuses and keeps the old setting (3.419603ms)
|
||||
✔ REQ-PLUG-1 a symlinked module directory or index.mjs refuses and keeps the old setting (2.480328ms)
|
||||
✔ REQ-PLUG-1 a symlinked kind directory refuses and keeps the old setting (2.213009ms)
|
||||
✔ REQ-PLUG-1 a symlinked packages/plugins refuses (run with --preserve-symlinks so the path keeps it) (26.330237ms)
|
||||
✔ REQ-PLUG-1 index.mjs swapped for a symlink after the lstat checks refuses at the realpath check (2.766962ms)
|
||||
✔ REQ-PLUG-1 a module that fails to load refuses and keeps the old setting (2.782821ms)
|
||||
✔ REQ-PLUG-1 a missing export refuses and keeps the old setting (3.897327ms)
|
||||
✔ REQ-PLUG-1 a different interface version refuses and keeps the old setting (2.593477ms)
|
||||
✔ REQ-PLUG-1 a kind refused on its first load has nothing switched on, and the log names kind and name (1.766915ms)
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.409866ms)
|
||||
✔ REQ-PLUG-1 loads run one at a time, so the last requested setting wins (102.429521ms)
|
||||
✔ REQ-PLUG-1 the loader needs a log callback (1.177561ms)
|
||||
ℹ tests 14
|
||||
ℹ suites 0
|
||||
ℹ pass 13
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 221.228312
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/plugins/tests/loader.test.mjs:182:1
|
||||
✖ REQ-PLUG-1 the setting's shape: unknown kinds refuse alone, a bad whole setting keeps everything (2.409866ms)
|
||||
AssertionError [ERR_ASSERTION]: made-up
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:188:12)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: TypeError: Cannot read properties of undefined (reading 'map')
|
||||
at Object.modules (file:///home/jwoltje/dewey-scratch/tmp/mosaic-plugins-ixWRKD/packages/plugins/src/loader.mjs:140:29)
|
||||
at file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:188:34
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/dewey-scratch/r131/wt/packages/plugins/tests/loader.test.mjs:188:12)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7),
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
[
|
||||
{
|
||||
"id": "01-name-pattern",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "02-list-cardinality",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "03-one-cardinality",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "04-no-duplicates",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "05-known-kind",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "06-plugins-object",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "07-registry-exports",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "08-registry-version",
|
||||
"path": "packages/plugins/src/kinds.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/kinds.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "09-missing-directory",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "10-component-type",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "11-symlink-test",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "12-plugins-dir-checked",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "13-kind-dir-checked",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "14-name-dir-checked",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "15-index-checked",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "16-realpath-before-import",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "17-load-failure",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "18-export-present",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "19-export-function",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "20-interface-version",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "21-version-strict",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "22-keep-old-setting",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "23-first-load-nothing-on",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "24-refusal-logged",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "25-log-names-module",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "26-log-kept",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "27-whole-setting-object",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "28-unknown-kind-logged",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "29-absent-key-off",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "30-loads-serialized",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "31-log-required",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "42-modules-known-kind",
|
||||
"path": "packages/plugins/src/loader.mjs",
|
||||
"test": [
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "32-schema-key",
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "33-schema-check",
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "34-schema-returned",
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs",
|
||||
"packages/plugins/tests/loader.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "35-schema-copy",
|
||||
"path": "packages/business/src/business.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "36-setter-strict-keys",
|
||||
"path": "packages/business/src/plugin-settings.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "37-setter-revision-format",
|
||||
"path": "packages/business/src/plugin-settings.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "38-setter-checks-names",
|
||||
"path": "packages/business/src/plugin-settings.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "39-setter-actor-logged",
|
||||
"path": "packages/business/src/plugin-settings.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "40-setter-writes-plugins",
|
||||
"path": "packages/business/src/plugin-settings.mjs",
|
||||
"test": [
|
||||
"packages/business/tests/plugin-settings.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
},
|
||||
{
|
||||
"id": "41-copy-ships-plugins",
|
||||
"path": "scripts/stack-copy.sh",
|
||||
"test": [
|
||||
"packages/cli/tests/stack-copy.test.mjs"
|
||||
],
|
||||
"result": "KILLED",
|
||||
"exit": 1,
|
||||
"sites": 1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,57 @@
|
||||
c3ef59884b9a37046393fa1b275acc9d0d5246a91b68ea984b8f1151d72bb67e agents/dewey/work/queue-131/r1/base.txt
|
||||
9d2e752cf867d0c305106499316e80644abbee81aa76af77ef1532adef1a1400 agents/dewey/work/queue-131/r1/BUILD.md
|
||||
47eb6a84112ff9a6950d34cf8ff61e241c1378346d9f73e973654eda8d00c1f1 agents/dewey/work/queue-131/r1/build.patch
|
||||
80b4ce21ac419bd3a57d5e4f842790f684a9a88ce1653da838c8953a2bbd27e5 agents/dewey/work/queue-131/r1/candidate-manifest.sha256
|
||||
8e5672baa0c759580df057f287d926bc8d102e61d371f88077aa87ef71e21105 agents/dewey/work/queue-131/r1/gate/pkg-business.log
|
||||
adc752ea19487413c9eb2786d6fac03a2aa99ae7829a3ce65dc0f1abdb9977e0 agents/dewey/work/queue-131/r1/gate/pkg-bus.log
|
||||
1214da0b593afe454f640860f936d95f0bb095aae5d2a256e15b968b0c4861e5 agents/dewey/work/queue-131/r1/gate/pkg-cli.log
|
||||
7b25f88820beadaeaf1fe8b27fbac202144c2087f07e2ef02a9bb4e5c960d46f agents/dewey/work/queue-131/r1/gate/pkg-plugins.log
|
||||
8b93e798ed5f0014b9efa760aae2b742924093de4c8fead8ab2863412d383d7f agents/dewey/work/queue-131/r1/gate/pkg-webui.log
|
||||
405eeb04c81623c9d577f6ca83c2025b2b9e76c37945450b342e9f899edd2b3a agents/dewey/work/queue-131/r1/gate-run.log
|
||||
a9b6f95d44b7e7a822d8e6fb8cae27cd71dad5faef151e8c1550659bd1ebeb8f agents/dewey/work/queue-131/r1/gate.sh
|
||||
89df99c041a3d157e6b3e4d9f843f829bb13374be4623e6eec119e301a933ad2 agents/dewey/work/queue-131/r1/mutants/01-name-pattern.log
|
||||
23f7432c8bd9e0a17d8931f29cb4fe1498033eeacdc0831cc38d913787f20c3c agents/dewey/work/queue-131/r1/mutants/02-list-cardinality.log
|
||||
0f8347f5bd2539cf1080bf94f46e0840c5624633a2a886d96ea3cf040954f672 agents/dewey/work/queue-131/r1/mutants/03-one-cardinality.log
|
||||
0a90b93de0cb5bc8567a33696d3468cae50fe71a44747e5900ab00e3e4c2883b agents/dewey/work/queue-131/r1/mutants/04-no-duplicates.log
|
||||
57f4ed3cbd6b59fa363eaabde5f570ae2e6318dee1b49d28300004e5c4bcf28f agents/dewey/work/queue-131/r1/mutants/05-known-kind.log
|
||||
1fe904c0fdf50b4d2ae046e4cb55855418f64b87df6b411f98b4f17bce2c95da agents/dewey/work/queue-131/r1/mutants/06-plugins-object.log
|
||||
2edf8819fe4e06d424f3a512a19510b2718703b5d76ef90934cb71d448cadc2f agents/dewey/work/queue-131/r1/mutants/07-registry-exports.log
|
||||
e208344ce5564804a377133c00da6d14cd0ba5c91ff3f4058bf14950db6cdc2a agents/dewey/work/queue-131/r1/mutants/08-registry-version.log
|
||||
13eb8b1400d9c891717e26da7f7d70a3db78d815d17253ac788d830d55e9c8ee agents/dewey/work/queue-131/r1/mutants/09-missing-directory.log
|
||||
c9528aefc67dc06c74c8f4ace0a052965594be510c0599862dc29c03ac563464 agents/dewey/work/queue-131/r1/mutants/10-component-type.log
|
||||
f5c9efe600d8187c4cf289af28c34fccdade8a2b5f57a954ede8c6830b8c455e agents/dewey/work/queue-131/r1/mutants/11-symlink-test.log
|
||||
63de70674ca1e08cb438ac9ed9773dfdcbadefe31240947d85a1cee5805c098b agents/dewey/work/queue-131/r1/mutants/12-plugins-dir-checked.log
|
||||
60a08c05d519b1647b38783232f4b02d5b6426a5d30578f65a09ea3531d86ada agents/dewey/work/queue-131/r1/mutants/13-kind-dir-checked.log
|
||||
4ef19feb906ca0f4e08344f7897ebf55cdd66858b234bae8452156826cbd559a agents/dewey/work/queue-131/r1/mutants/14-name-dir-checked.log
|
||||
1e5d799983277c2ff63dc8800d012f2242e26645e7493369efa35919616bcd18 agents/dewey/work/queue-131/r1/mutants/15-index-checked.log
|
||||
cd2a3cfcdef0a99dcae9d7e29362555541f9c079df9a82ca757ac583f5b04f56 agents/dewey/work/queue-131/r1/mutants/16-realpath-before-import.log
|
||||
8a268b15b4ee887b2b97f20fc64cb1d7f18a570c473ac4cc76ae02c6558c5508 agents/dewey/work/queue-131/r1/mutants/17-load-failure.log
|
||||
a87ae8b2e5f1a7fc7aba8147da5e3492c50b335c219afb4ef0d7090347209d07 agents/dewey/work/queue-131/r1/mutants/18-export-present.log
|
||||
6785b4c97be4bd002c978c598a12133d1c5acb6357313ceb9e7a1d56007b9851 agents/dewey/work/queue-131/r1/mutants/19-export-function.log
|
||||
d04b8829cd992075915c4dad99dd1de514a72b71e2daa3754f49ceac6a86ce5a agents/dewey/work/queue-131/r1/mutants/20-interface-version.log
|
||||
7fdd33177df9f4989c3df83b98be5804e43c7fce199e4ea6321324a4c32d809c agents/dewey/work/queue-131/r1/mutants/21-version-strict.log
|
||||
1418da52940e1e6f953220d657bb071a5181e4f3acf903adf280abc82a184bbe agents/dewey/work/queue-131/r1/mutants/22-keep-old-setting.log
|
||||
43f1277ddd8446bce328cf974c35f543e8b3e3c740b0f8e46613c2dec9ea522e agents/dewey/work/queue-131/r1/mutants/23-first-load-nothing-on.log
|
||||
98aecca2d7fc77696db96ccb3e9b3aee8698fc30f6820d6a3d3990fa2cdb6855 agents/dewey/work/queue-131/r1/mutants/24-refusal-logged.log
|
||||
1c9bbcd4677cd7364653241ce02731d58d15db9f2543fab56d5c428cbfab18b4 agents/dewey/work/queue-131/r1/mutants/25-log-names-module.log
|
||||
7760c3ad76c7ab65f07a3bbd907b5da1b5f8e600e1125a71a957cc08abd88a84 agents/dewey/work/queue-131/r1/mutants/26-log-kept.log
|
||||
341632a7b3383b18de4f8f85dab31742a8e194ca551fb8c52ab94ff0504ce3c9 agents/dewey/work/queue-131/r1/mutants/27-whole-setting-object.log
|
||||
efb87db99b3edb756492d483fd3ce0217de4bffc18751c068887ff3f153d6354 agents/dewey/work/queue-131/r1/mutants/28-unknown-kind-logged.log
|
||||
a724428b430031dc444b2430a01f2227a669e1ab3e0dc97477f7d388fa3f78f0 agents/dewey/work/queue-131/r1/mutants/29-absent-key-off.log
|
||||
f5adf4ce0c9fd90cb48025954abf1d0745591ef103e9bee900ba5d4e9865bdf4 agents/dewey/work/queue-131/r1/mutants/30-loads-serialized.log
|
||||
8893b780118d312f49470f7dfd01681b40cb504953e62d19f8106b4241ac3e86 agents/dewey/work/queue-131/r1/mutants/31-log-required.log
|
||||
f249067c7c0113107ba658f1967cb439f3060c658654bf32e6c96fbf30e1455c agents/dewey/work/queue-131/r1/mutants/32-schema-key.log
|
||||
a436d600929e7c8598ccb9872c7f52c97d8d733484a65b0c5034512ddcc25519 agents/dewey/work/queue-131/r1/mutants/33-schema-check.log
|
||||
3f0f599cf19a99eab5e762bb046ffd30f7e74fa67e58a76c080c142d4171ad7e agents/dewey/work/queue-131/r1/mutants/34-schema-returned.log
|
||||
2c4d525cb1483c7a71475e5597eb652f9fafe04141ec02b77ea6200abdf4f796 agents/dewey/work/queue-131/r1/mutants/35-schema-copy.log
|
||||
b9bb61bd5d8d3758d8d97787b74e885c1b14931eb0d0667dd4195443d0a173f4 agents/dewey/work/queue-131/r1/mutants/36-setter-strict-keys.log
|
||||
464218397b4dcf106725b259bc2195e6a99d85641f8e2c88f4eba056702fffab agents/dewey/work/queue-131/r1/mutants/37-setter-revision-format.log
|
||||
52fc1dfc49a2eea08c1ac26ea20b120ed637859c2a62caf2bd8c760c5fb32121 agents/dewey/work/queue-131/r1/mutants/38-setter-checks-names.log
|
||||
50111b32180b07269724ad707914db6f23a19ec0c8d50e1a1a4e1e2c2e27641e agents/dewey/work/queue-131/r1/mutants/39-setter-actor-logged.log
|
||||
8ccf6d25d1c6fcc18c772ee19e9fbd713e50744b9cb6c41807333479bbd8a9e8 agents/dewey/work/queue-131/r1/mutants/40-setter-writes-plugins.log
|
||||
35be573fe968be669fbdf8bb1d62932cd500e219e194d80f8e50344e8bc6db2c agents/dewey/work/queue-131/r1/mutants/41-copy-ships-plugins.log
|
||||
0acedd36d78c2f7c4d543b50e45abb2ec62f3542c67fff97de46e9d9078ba6d1 agents/dewey/work/queue-131/r1/mutants/42-modules-known-kind.log
|
||||
17c5a2545269118e92ca2a71f9f691bc0db3594adfa45784e5f0cc5eeb336a6d agents/dewey/work/queue-131/r1/MUTANTS.md
|
||||
1cf81cdff754bfb6b8133f00e4128cc077f049590641c558b17a8e34f23b135e agents/dewey/work/queue-131/r1/mutants.py
|
||||
42dd219e424d538123e40b9c8601508ec1c15be491d101b7f88b0bd8a2708984 agents/dewey/work/queue-131/r1/mutants/results.json
|
||||
dcd947e7c5c33aa970f0786b8bd0ac4d1ed533e1d9e61892e7df002e56a43205 agents/dewey/work/queue-131/r1/mutants-run.log
|
||||
Reference in New Issue
Block a user