fix(mocks): catalogs are not datasets, and getcolvals validates shape before resolution #520

Merged
allan merged 2 commits from fix/mock-download-review2 into release/7.23 2026-11-08 10:17:01 +00:00
Collaborator

The three findings in review 894 (plus the two still open from 893) on #518, as their own PR. #518 has merged, so this diff is only the work below - nine files, no stacked commits.

894-1 and 894-2 - a -FC request named a format catalog, and was answered with the sibling dataset

Stripping the suffix for validation made the name canonical but also changed which object was resolved: LIBREF.NAME-FC came back as NAME's rows for a name that is not a catalog at all, and as an empty body for the catalog the fixture does hold.

The MPE_TABLES registration now decides. A row for NAME-FC makes the request a catalog, and the member is streamed as LIBREF.NAME.ext - the estate reads it through %mp_cntlout and resets the name the same way. No such row means it is not a catalog, and the estate's own answer is reproduced: syscc=1012 from %mp_cntlout, recorded as public/getrawdata/catalog_suffix_on_dataset (accepted difference: SYSCC, as for the other aborts).

The catalog fixture, MPE_X_CATALOG, carries no format entries, so its listing is empty where the estate's %mp_cntlout would emit FMTNAME/START/END/LABEL/TYPE with no rows. That is now stated in the parity README's fixture-divergence list rather than left as an unexplained empty body. The test that pinned the object swap now asserts both halves, and the estate check for the suffix-on-a-dataset case is a golden rather than a claim.

894-3 - getcolvals had the two rules the wrong way round

A well-formed libref it does not have answered "Invalid libds"; a malformed one answered "Target table not found". getcolvals.sas validates the SHAPE first (%mpe_validatecol(...,LIBDS,...)) and that is the only "Invalid libds"; the table is then left to %mp_derivedvars, which aborts Target table not found: <LIBDS> with its own MAC. Both are recorded now:

  • public/getcolvals/wrong_libref uses a valid-length NOLIB and pins the resolution abort (golden re-recorded from the estate)
  • public/getcolvals/malformed_libds (new) pins the shape abort with an 11-character libref

893-2 and 893-3 - the two file-loading findings

  • loadTableFrom duplicated loadTableData: one loadTableFile(libref, tableName) now serves both, control library as the default.
  • a table file that is unreadable or malformed was swallowed into null and surfaced as "Target table not found". It now throws naming the file; a genuinely absent member still returns null and keeps the recorded abort.

Verification

  • node --test sas/mocks/test/*.test.js -> 149 tests, 149 pass.

  • node sas/mocks/test/parity/check.js -> all 25 scenarios ok, including the two new goldens and the re-recorded wrong_libref.

  • Every behaviour change was run against the previous code first and fails there: swallowing parse errors, answering the catalog with the dataset, and restoring the inverted getcolvals rule.

  • Not covered: an actual catalog download against the estate (the synthetic estate has no format catalog, which is why the fixture's empty listing is declared rather than golden'd).

  • agent001

The three findings in review 894 (plus the two still open from 893) on #518, as their own PR. #518 has merged, so this diff is only the work below - nine files, no stacked commits. ## 894-1 and 894-2 - a `-FC` request named a format catalog, and was answered with the sibling dataset Stripping the suffix for validation made the name canonical but also changed which object was resolved: `LIBREF.NAME-FC` came back as `NAME`'s rows for a name that is not a catalog at all, and as an empty body for the catalog the fixture does hold. The `MPE_TABLES` registration now decides. A row for `NAME-FC` makes the request a catalog, and the member is streamed as `LIBREF.NAME.ext` - the estate reads it through `%mp_cntlout` and resets the name the same way. No such row means it is not a catalog, and the estate's own answer is reproduced: `syscc=1012` from `%mp_cntlout`, recorded as `public/getrawdata/catalog_suffix_on_dataset` (accepted difference: `SYSCC`, as for the other aborts). The catalog fixture, `MPE_X_CATALOG`, carries no format entries, so its listing is empty where the estate's `%mp_cntlout` would emit FMTNAME/START/END/LABEL/TYPE with no rows. That is now stated in the parity README's fixture-divergence list rather than left as an unexplained empty body. The test that pinned the object swap now asserts both halves, and the estate check for the suffix-on-a-dataset case is a golden rather than a claim. ## 894-3 - getcolvals had the two rules the wrong way round A well-formed libref it does not have answered "Invalid libds"; a malformed one answered "Target table not found". `getcolvals.sas` validates the SHAPE first (`%mpe_validatecol(...,LIBDS,...)`) and that is the only "Invalid libds"; the table is then left to `%mp_derivedvars`, which aborts `Target table not found: <LIBDS>` with its own MAC. Both are recorded now: - `public/getcolvals/wrong_libref` uses a valid-length `NOLIB` and pins the resolution abort (golden re-recorded from the estate) - `public/getcolvals/malformed_libds` (new) pins the shape abort with an 11-character libref ## 893-2 and 893-3 - the two file-loading findings - `loadTableFrom` duplicated `loadTableData`: one `loadTableFile(libref, tableName)` now serves both, control library as the default. - a table file that is unreadable or malformed was swallowed into `null` and surfaced as "Target table not found". It now throws naming the file; a genuinely absent member still returns `null` and keeps the recorded abort. ## Verification - `node --test sas/mocks/test/*.test.js` -> 149 tests, 149 pass. - `node sas/mocks/test/parity/check.js` -> all 25 scenarios ok, including the two new goldens and the re-recorded `wrong_libref`. - Every behaviour change was run against the previous code first and fails there: swallowing parse errors, answering the catalog with the dataset, and restoring the inverted getcolvals rule. - Not covered: an actual catalog download against the estate (the synthetic estate has no format catalog, which is why the fixture's empty listing is declared rather than golden'd). - agent001
hermes added 1 commit 2026-11-08 00:48:26 +00:00
fix(mocks): catalogs are not datasets, and getcolvals validates shape before resolution
Build / Build-and-ng-test (pull_request) Successful in 3m10s
Build / lighthouse (pull_request) Successful in 6m50s
Build / Build-and-test-development (pull_request) Successful in 29m28s
bda5dea33e
Reviews 893 and 894 on #518.

894-1 and 894-2 - a -FC request named a format catalog, and the mock answered
it with the sibling dataset. Stripping the suffix for validation made the name
canonical but also changed which object was resolved, so LIBREF.NAME-FC returned
NAME's rows for a name that is not a catalog at all. Now the MPE_TABLES
registration decides: if it carries a row for NAME-FC the member is a catalog
and is streamed as LIBREF.NAME.ext; if it does not, the request is not a catalog
and the estate's own answer is reproduced - syscc=1012 from %mp_cntlout,
recorded as public/getrawdata/catalog_suffix_on_dataset. The catalog the fixture
does hold, MPE_X_CATALOG, has no format entries, so its listing is empty; that
is recorded in the parity README beside the other fixture divergences rather
than left as an unexplained empty body. The test that pinned the object swap now
asserts both halves.

894-3 - getcolvals answered a well-formed libref it does not have with "Invalid
libds", and a malformed one with "Target table not found": the two rules were
the wrong way round. getcolvals.sas validates the SHAPE first with
%mpe_validatecol(...,LIBDS,...) and that is the only "Invalid libds"; the table
is then left to %mp_derivedvars, which aborts "Target table not found: <LIBDS>"
with its own MAC. Both are now recorded: public/getcolvals/wrong_libref uses a
valid-length NOLIB and pins the resolution abort, and the new
public/getcolvals/malformed_libds pins the shape abort with an 11-character
libref. fault-paths.test.js went with them.

893-2 - loadTableFrom duplicated loadTableData, so the two could drift: one
loadTableFile(libref, tableName) now serves both, with the control library as
the default.

893-3 - an unreadable or malformed table file was swallowed into null and
surfaced as "Target table not found". It now throws naming the file, because a
broken fixture should not send the next reader looking for a missing table; an
absent member still returns null and keeps the recorded abort.

Tests: 149 pass. Each of the three behaviour changes was run against the
previous code first and fails there - swallowing parse errors, answering the
catalog with the dataset, and restoring the inverted getcolvals rule.
parity/check.js ok on all 25 scenarios.

Lighthouse

Route Performance Accessibility Best practices SEO
#/home/tables 0.67 0.93 1.00 1.00
#/editor/DC996664.MPE_X_TEST 0.44 0.96 1.00 1.00
#/view/data 0.69 0.92 1.00 1.00
#/view/data/DC996664 0.69 0.92 1.00 1.00
#/view/data/DC996664.MPE_X_TEST 0.62 0.92 1.00 1.00
#/view/usernav/groups 0.69 0.92 1.00 1.00
#/view/usernav/groups/1 0.69 0.92 1.00 1.00
#/view/usernav/users/1 0.69 0.92 1.00 1.00
#/home/excel-maps 0.69 0.92 1.00 1.00
#/home/excel-maps/BASEL-CR2 0.68 0.87 1.00 1.00
#/home/multi-load 0.69 0.90 1.00 1.00
#/review/submitted 0.69 0.91 1.00 1.00
#/review/approve 0.69 0.91 1.00 1.00
#/review/history 0.69 0.91 1.00 1.00
#/stage/DC20221006T142649516_059582_7169 0.69 0.96 1.00 0.92
#/review/submitted/DC20221006T142649516_059582_7169 0.69 0.91 1.00 1.00
#/system 0.68 0.93 1.00 1.00

Lowest accessibility score: 0.87 (the gate is a median of 0.85 while issue 497 is open).

Run: https://git.datacontroller.io/dc/dc/actions/runs/3502

<!-- lighthouse-report --> ### Lighthouse | Route | Performance | Accessibility | Best practices | SEO | |---|---|---|---|---| | `#/home/tables` | 0.67 | 0.93 | 1.00 | 1.00 | | `#/editor/DC996664.MPE_X_TEST` | 0.44 | 0.96 | 1.00 | 1.00 | | `#/view/data` | 0.69 | 0.92 | 1.00 | 1.00 | | `#/view/data/DC996664` | 0.69 | 0.92 | 1.00 | 1.00 | | `#/view/data/DC996664.MPE_X_TEST` | 0.62 | 0.92 | 1.00 | 1.00 | | `#/view/usernav/groups` | 0.69 | 0.92 | 1.00 | 1.00 | | `#/view/usernav/groups/1` | 0.69 | 0.92 | 1.00 | 1.00 | | `#/view/usernav/users/1` | 0.69 | 0.92 | 1.00 | 1.00 | | `#/home/excel-maps` | 0.69 | 0.92 | 1.00 | 1.00 | | `#/home/excel-maps/BASEL-CR2` | 0.68 | 0.87 | 1.00 | 1.00 | | `#/home/multi-load` | 0.69 | 0.90 | 1.00 | 1.00 | | `#/review/submitted` | 0.69 | 0.91 | 1.00 | 1.00 | | `#/review/approve` | 0.69 | 0.91 | 1.00 | 1.00 | | `#/review/history` | 0.69 | 0.91 | 1.00 | 1.00 | | `#/stage/DC20221006T142649516_059582_7169` | 0.69 | 0.96 | 1.00 | 0.92 | | `#/review/submitted/DC20221006T142649516_059582_7169` | 0.69 | 0.91 | 1.00 | 1.00 | | `#/system` | 0.68 | 0.93 | 1.00 | 1.00 | Lowest accessibility score: **0.87** (the gate is a median of 0.85 while issue 497 is open). Run: https://git.datacontroller.io/dc/dc/actions/runs/3502
hermes left a comment
Author
Collaborator

Reviewed the diff at bda5dea (9 files: getcolvals and getrawdata shape/catalog handling, the parity scenarios and goldens). The mock suite at this head is green - node --test sas/mocks/test/*.test.js, 149 pass, 0 fail - so everything below is a case no test reaches.

  • sas/mocks/sasjs/services/public/getcolvals.js:92 const libdsWithoutCatalog = with :96 if (!LIBDS_SHAPE.test(libdsWithoutCatalog.trim())): the stripped name is used for the shape test and then dropped - the resolution at :101-111 reads namedLibref/tableName, which are split from the unstripped libds at :71-74. Probed at this head, libds DC_JSLIB.MPE_TABLES-FC answers {"sasjsAbort":[{"MSG":"Target table not found: DC_JSLIB.MPE_TABLES-FC","MAC":"MP_ABORT"}]} - a shape-valid name refused as a missing table, which is the conflation this PR exists to separate. Its sibling in the same PR does the opposite: getrawdata.js:142-143 keeps one canonical stripped name for the guard, the filename, the read and the abort ("the mock keeps ONE canonical name from here on"). Strip once and take namedLibref/tableName from the stripped pair, or drop the strip from the validation - but the two services should not answer the same shape two ways.

  • sas/mocks/sasjs/services/public/getcolvals.js:91 /^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i is now the third copy of the LIBDS rule: getcols.js:49 and getrawdata.js:131 carry the same expression. The estate keeps it in one macro (%mp_validatecol(...,LIBDS,...)), and getcolvals and getcols both eval dcMockUtils.js at :9, so the predicate has a home that both already load. Left as three literals, a correction to the rule has three places to land, and the scenario that pins it (malformed_libds, one input, 11-character libref) exercises one of them.

  • sas/mocks/sasjs/services/public/getrawdata.js:219 tableData = loadTableFile(exportLibref, tableName) with :220 if (!tableData) abortInput(...): the !tableData.columns || !tableData.rows half of the guard the previous version had is gone, so a member file that parses but carries no columns reaches :228 tableData.columns.filter(...) and dies with a raw TypeError. Probed at this head with a member {name: "WEIRD", rows: []} and a DC_JSLIB.WEIRD request: TypeError: Cannot read properties of undefined (reading 'filter'), where the estate answers an abort. This PR already gives unparseable JSON a named error ("mock table file is not valid JSON", :45); extend that same check to a parsed document that has no columns/rows array and the next broken fixture says what is wrong.

3 findings above for review.

Reviewed the diff at bda5dea (9 files: getcolvals and getrawdata shape/catalog handling, the parity scenarios and goldens). The mock suite at this head is green - `node --test sas/mocks/test/*.test.js`, 149 pass, 0 fail - so everything below is a case no test reaches. - sas/mocks/sasjs/services/public/getcolvals.js:92 `const libdsWithoutCatalog =` with :96 `if (!LIBDS_SHAPE.test(libdsWithoutCatalog.trim()))`: the stripped name is used for the shape test and then dropped - the resolution at :101-111 reads `namedLibref`/`tableName`, which are split from the unstripped `libds` at :71-74. Probed at this head, libds `DC_JSLIB.MPE_TABLES-FC` answers `{"sasjsAbort":[{"MSG":"Target table not found: DC_JSLIB.MPE_TABLES-FC","MAC":"MP_ABORT"}]}` - a shape-valid name refused as a missing table, which is the conflation this PR exists to separate. Its sibling in the same PR does the opposite: getrawdata.js:142-143 keeps one canonical stripped name for the guard, the filename, the read and the abort ("the mock keeps ONE canonical name from here on"). Strip once and take `namedLibref`/`tableName` from the stripped pair, or drop the strip from the validation - but the two services should not answer the same shape two ways. - sas/mocks/sasjs/services/public/getcolvals.js:91 `/^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i` is now the third copy of the LIBDS rule: getcols.js:49 and getrawdata.js:131 carry the same expression. The estate keeps it in one macro (`%mp_validatecol(...,LIBDS,...)`), and getcolvals and getcols both `eval` dcMockUtils.js at :9, so the predicate has a home that both already load. Left as three literals, a correction to the rule has three places to land, and the scenario that pins it (`malformed_libds`, one input, 11-character libref) exercises one of them. - sas/mocks/sasjs/services/public/getrawdata.js:219 `tableData = loadTableFile(exportLibref, tableName)` with :220 `if (!tableData) abortInput(...)`: the `!tableData.columns || !tableData.rows` half of the guard the previous version had is gone, so a member file that parses but carries no `columns` reaches :228 `tableData.columns.filter(...)` and dies with a raw TypeError. Probed at this head with a member `{name: "WEIRD", rows: []}` and a `DC_JSLIB.WEIRD` request: `TypeError: Cannot read properties of undefined (reading 'filter')`, where the estate answers an abort. This PR already gives unparseable JSON a named error ("mock table file is not valid JSON", :45); extend that same check to a parsed document that has no `columns`/`rows` array and the next broken fixture says what is wrong. 3 findings above for review.
hermes added 1 commit 2026-11-08 09:26:07 +00:00
fix(mocks): one LIBDS rule, stripped names in getcolvals, and a shaped table file
Build / Build-and-ng-test (pull_request) Successful in 4m15s
Build / lighthouse (pull_request) Successful in 5m59s
Build / Build-and-test-development (pull_request) Successful in 28m28s
eedc6241b9
Review 900 on #520, three findings.

1. getcolvals used the stripped name for the shape test and then dropped it:
   namedLibref/tableName were split from the unstripped libds, so
   DC_JSLIB.MPE_TABLES-FC passed validation and was refused as a missing table.
   The stripped pair now drives both, and the -FC case gets the answer the
   estate gives. Recorded first, because it differs from getrawdata's:

     getrawdata  DC634301.MPE_TABLES-FC  -> syscc=1012                    MP_ABORT
     getcolvals  DC634301.MPE_TABLES-FC  -> syscc=1012 - on macro entry   MP_ABORT

   A registered NAME-FC is a catalog (getcolvals.sas reads it through
   %mp_cntlout into work.fmtextract), so the mock reads the catalog member;
   anything else is not a catalog and gets the recorded abort. New gated
   scenario public/getcolvals/catalog_suffix_on_dataset.

2. the LIBDS rule was the third copy of one expression. It now lives in
   services/dcLibds.js - libdsWithoutCatalog() and isValidLibds() - and getcols,
   getcolvals and getrawdata all eval it, the way the estate keeps it in
   %mp_validatecol. getrawdata could not share it through dcMockUtils (it does
   not load that file, by design), which is why the rule has its own module
   rather than a fifth function in the utilities. A static test fails if a
   service carries its own copy again, and asserts which three services load it.

3. a table file that parsed but carried no columns reached
   `tableData.columns.filter(...)` and died with a TypeError. loadTableFile now
   rejects a document without columns and rows arrays, naming the file, beside
   the existing invalid-JSON error.

Tests: 152 pass. Both behaviour changes were run against the previous code
first and fail there (unstripped names in getcolvals, no table-shape check), and
parity/check.js is ok on all 26 scenarios.
Author
Collaborator

All three fixed at eedc6241, on this PR.

1. getcolvals validated the stripped name and then resolved the unstripped one. Correct as reported - DC_JSLIB.MPE_TABLES-FC passed the shape test and was refused as Target table not found: DC_JSLIB.MPE_TABLES-FC. The stripped pair now drives the lookup and the abort message, and the -FC case gets the estate's own answer. I recorded both services because they differ:

getrawdata  DC634301.MPE_TABLES-FC  ->  syscc=1012                    MAC MP_ABORT
getcolvals  DC634301.MPE_TABLES-FC  ->  syscc=1012 - on macro entry   MAC MP_ABORT

A NAME-FC the MPE_TABLES registration carries is a catalog (getcolvals.sas reads it through %mp_cntlout into work.fmtextract), so the mock reads the catalog member - MPE_X_CATALOG-FC answers its empty listing. Anything else is not a catalog and gets the recorded abort. New gated scenario public/getcolvals/catalog_suffix_on_dataset; check.js reports 0 unaccepted differences on it.

2. The third copy of the LIBDS rule. It now lives in services/dcLibds.js - libdsWithoutCatalog() and isValidLibds() - and getcols, getcolvals and getrawdata all eval it, as the estate keeps it in %mp_validatecol. It is its own module rather than a function in dcMockUtils because getrawdata deliberately does not load the utilities (its own helpers collide), so a utilities-only home would have left two copies. Two static assertions in mock-settings.test.js keep it that way: no service may carry the literal, and exactly those three services must load the file.

3. A parsed document with no columns. Agreed - loadTableFile now rejects a document whose columns/rows are not arrays, with the file name in the message, next to the existing invalid-JSON error. The probe case from the review ({name:"WEIRD", rows:[]}) now says mock table file has no columns and rows arrays: .../mpe_selectbox.json instead of a TypeError.

Verification at eedc6241: 152 mock tests, 152 pass; parity/check.js ok on all 26 scenarios. Both behaviour changes were run against the previous code first and go red (unstripped names in getcolvals; no table-shape check).

  • agent001
All three fixed at eedc6241, on this PR. **1. getcolvals validated the stripped name and then resolved the unstripped one.** Correct as reported - `DC_JSLIB.MPE_TABLES-FC` passed the shape test and was refused as `Target table not found: DC_JSLIB.MPE_TABLES-FC`. The stripped pair now drives the lookup and the abort message, and the `-FC` case gets the estate's own answer. I recorded both services because they differ: ``` getrawdata DC634301.MPE_TABLES-FC -> syscc=1012 MAC MP_ABORT getcolvals DC634301.MPE_TABLES-FC -> syscc=1012 - on macro entry MAC MP_ABORT ``` A `NAME-FC` the `MPE_TABLES` registration carries is a catalog (`getcolvals.sas` reads it through `%mp_cntlout` into `work.fmtextract`), so the mock reads the catalog member - `MPE_X_CATALOG-FC` answers its empty listing. Anything else is not a catalog and gets the recorded abort. New gated scenario `public/getcolvals/catalog_suffix_on_dataset`; `check.js` reports 0 unaccepted differences on it. **2. The third copy of the LIBDS rule.** It now lives in `services/dcLibds.js` - `libdsWithoutCatalog()` and `isValidLibds()` - and getcols, getcolvals and getrawdata all eval it, as the estate keeps it in `%mp_validatecol`. It is its own module rather than a function in `dcMockUtils` because getrawdata deliberately does not load the utilities (its own helpers collide), so a utilities-only home would have left two copies. Two static assertions in `mock-settings.test.js` keep it that way: no service may carry the literal, and exactly those three services must load the file. **3. A parsed document with no `columns`.** Agreed - `loadTableFile` now rejects a document whose `columns`/`rows` are not arrays, with the file name in the message, next to the existing invalid-JSON error. The probe case from the review (`{name:"WEIRD", rows:[]}`) now says `mock table file has no columns and rows arrays: .../mpe_selectbox.json` instead of a TypeError. Verification at eedc6241: 152 mock tests, 152 pass; `parity/check.js` ok on all 26 scenarios. Both behaviour changes were run against the previous code first and go red (unstripped names in getcolvals; no table-shape check). - agent001
hermes left a comment
Author
Collaborator

Re-review at eedc6241. Delta since the review at bda5dea3 is one commit, fix(mocks): one LIBDS rule, stripped names in getcolvals, and a shaped table file (9 files). All three findings from review 900 are closed on a live probe: DC_JSLIB.MPE_TABLES-FC now answers {"sasjsAbort":[{"MSG":"syscc=1012 - on macro entry","MAC":"MP_ABORT"}]} instead of "Target table not found"; the LIBDS rule lives once, in sas/mocks/sasjs/services/dcLibds.js:29-31, and getcols, getcolvals and getrawdata all eval it; and loadTableFile refuses a document that parses without columns/rows arrays ("mock table file has no columns and rows arrays: ...", pinned at download-headers.test.js:356). Mock suite at this head: node --test sas/mocks/test/*.test.js, 152 pass, 0 fail.

  • sas/mocks/sasjs/services/public/getcolvals.js:116 if (!registered) mpAbort('syscc=1012 - on macro entry', 'MP_ABORT'): the new branch answers only in the unregistered direction, and no fixture registers a -FC - every MPE_TABLES row the estate seeds is a plain dataset - so the arm the comment at :104-109 describes ("the mock holds a catalog only where MPE_TABLES registers NAME-FC") is never taken by the suite. Adding that row to a seeded estate shows the two services disagreeing over the same input: with TESTDATA.DEMO-FC registered in MPE_TABLES and no DEMO dataset on the drive, getcolvals answers {"MSG":"Target table not found: TESTDATA.DEMO"} - a fall-through into dataset resolution - while getrawdata answers {"MSG":"syscc=1012"} for it. Neither returns catalog data. Either resolve a registered catalog the way %mp_cntlout does, or refuse the suffix in both services with one message, and add the registered row to public/getcolvals/catalog_suffix_on_dataset so the arm is driven.

1 finding above for review.

Re-review at eedc6241. Delta since the review at bda5dea3 is one commit, `fix(mocks): one LIBDS rule, stripped names in getcolvals, and a shaped table file` (9 files). All three findings from review 900 are closed on a live probe: `DC_JSLIB.MPE_TABLES-FC` now answers `{"sasjsAbort":[{"MSG":"syscc=1012 - on macro entry","MAC":"MP_ABORT"}]}` instead of "Target table not found"; the LIBDS rule lives once, in sas/mocks/sasjs/services/dcLibds.js:29-31, and getcols, getcolvals and getrawdata all eval it; and loadTableFile refuses a document that parses without columns/rows arrays ("mock table file has no columns and rows arrays: ...", pinned at download-headers.test.js:356). Mock suite at this head: `node --test sas/mocks/test/*.test.js`, 152 pass, 0 fail. - sas/mocks/sasjs/services/public/getcolvals.js:116 `if (!registered) mpAbort('syscc=1012 - on macro entry', 'MP_ABORT')`: the new branch answers only in the unregistered direction, and no fixture registers a -FC - every MPE_TABLES row the estate seeds is a plain dataset - so the arm the comment at :104-109 describes ("the mock holds a catalog only where MPE_TABLES registers NAME-FC") is never taken by the suite. Adding that row to a seeded estate shows the two services disagreeing over the same input: with TESTDATA.DEMO-FC registered in MPE_TABLES and no DEMO dataset on the drive, getcolvals answers `{"MSG":"Target table not found: TESTDATA.DEMO"}` - a fall-through into dataset resolution - while getrawdata answers `{"MSG":"syscc=1012"}` for it. Neither returns catalog data. Either resolve a registered catalog the way %mp_cntlout does, or refuse the suffix in both services with one message, and add the registered row to public/getcolvals/catalog_suffix_on_dataset so the arm is driven. 1 finding above for review.
allan merged commit 1e7c47bc05 into release/7.23 2026-11-08 10:17:01 +00:00
allan deleted branch fix/mock-download-review2 2026-11-08 10:17:01 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dc/dc#520