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.
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
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.
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.
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.
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
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
-FCrequest named a format catalog, and was answered with the sibling datasetStripping the suffix for validation made the name canonical but also changed which object was resolved:
LIBREF.NAME-FCcame back asNAME'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_TABLESregistration now decides. A row forNAME-FCmakes the request a catalog, and the member is streamed asLIBREF.NAME.ext- the estate reads it through%mp_cntloutand resets the name the same way. No such row means it is not a catalog, and the estate's own answer is reproduced:syscc=1012from%mp_cntlout, recorded aspublic/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_cntloutwould 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.sasvalidates the SHAPE first (%mpe_validatecol(...,LIBDS,...)) and that is the only "Invalid libds"; the table is then left to%mp_derivedvars, which abortsTarget table not found: <LIBDS>with its own MAC. Both are recorded now:public/getcolvals/wrong_librefuses a valid-lengthNOLIBand pins the resolution abort (golden re-recorded from the estate)public/getcolvals/malformed_libds(new) pins the shape abort with an 11-character libref893-2 and 893-3 - the two file-loading findings
loadTableFromduplicatedloadTableData: oneloadTableFile(libref, tableName)now serves both, control library as the default.nulland surfaced as "Target table not found". It now throws naming the file; a genuinely absent member still returnsnulland 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-recordedwrong_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
Lighthouse
#/home/tables#/editor/DC996664.MPE_X_TEST#/view/data#/view/data/DC996664#/view/data/DC996664.MPE_X_TEST#/view/usernav/groups#/view/usernav/groups/1#/view/usernav/users/1#/home/excel-maps#/home/excel-maps/BASEL-CR2#/home/multi-load#/review/submitted#/review/approve#/review/history#/stage/DC20221006T142649516_059582_7169#/review/submitted/DC20221006T142649516_059582_7169#/systemLowest 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
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 :96if (!LIBDS_SHAPE.test(libdsWithoutCatalog.trim())): the stripped name is used for the shape test and then dropped - the resolution at :101-111 readsnamedLibref/tableName, which are split from the unstrippedlibdsat :71-74. Probed at this head, libdsDC_JSLIB.MPE_TABLES-FCanswers{"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 takenamedLibref/tableNamefrom 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}$/iis 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 bothevaldcMockUtils.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 :220if (!tableData) abortInput(...): the!tableData.columns || !tableData.rowshalf of the guard the previous version had is gone, so a member file that parses but carries nocolumnsreaches :228tableData.columns.filter(...)and dies with a raw TypeError. Probed at this head with a member{name: "WEIRD", rows: []}and aDC_JSLIB.WEIRDrequest: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 nocolumns/rowsarray and the next broken fixture says what is wrong.3 findings above for review.
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-FCpassed the shape test and was refused asTarget table not found: DC_JSLIB.MPE_TABLES-FC. The stripped pair now drives the lookup and the abort message, and the-FCcase gets the estate's own answer. I recorded both services because they differ:A
NAME-FCtheMPE_TABLESregistration carries is a catalog (getcolvals.sasreads it through%mp_cntloutintowork.fmtextract), so the mock reads the catalog member -MPE_X_CATALOG-FCanswers its empty listing. Anything else is not a catalog and gets the recorded abort. New gated scenariopublic/getcolvals/catalog_suffix_on_dataset;check.jsreports 0 unaccepted differences on it.2. The third copy of the LIBDS rule. It now lives in
services/dcLibds.js-libdsWithoutCatalog()andisValidLibds()- 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 indcMockUtilsbecause getrawdata deliberately does not load the utilities (its own helpers collide), so a utilities-only home would have left two copies. Two static assertions inmock-settings.test.jskeep 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 -loadTableFilenow rejects a document whosecolumns/rowsare 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 saysmock table file has no columns and rows arrays: .../mpe_selectbox.jsoninstead of a TypeError.Verification at
eedc6241: 152 mock tests, 152 pass;parity/check.jsok 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).Re-review at
eedc6241. Delta since the review atbda5dea3is 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-FCnow 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.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.