Commit Graph
4 Commits
Author SHA1 Message Date
dc ad732f42b6 fix(mocks): the other two getrawdata aborts, and synchronous headers
Build / Build-and-ng-test (pull_request) Successful in 7m46s
Build / lighthouse (pull_request) Successful in 6m32s
Build / Build-and-test-development (pull_request) Successful in 29m16s
Review 886 on #517, both findings.

Finding 1 - getrawdata validates three inputs, and the mock only had the third.
getrawdata.sas aborts, in this order and all with mac=&_program..sas, before it
streams anything:

  table shape    -> "Invalid table"
  filter integer -> "Invalid filter"
  type list      -> "Invalid type"

The mock now reproduces all three, from the rules of the macros the service
calls: %mpe_validatecol(...,LIBDS,...) strips a trailing -FC and applies
%mp_validatecol's /^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i, and
%mp_validatecol(...,ISINT,...) is input(??best32.) with mod 1 = 0, so 7.0 and
1e3 are integers and abc and 1.5 are not. Each answer was recorded from the
synthetic estate first:

  {table:'NOT_A_LIBDS'}                      -> Invalid table
  {filter:'abc'}                             -> Invalid filter
  no table at all                            -> Invalid table (was a
                                                ReferenceError before)
  {type:'FOOBAR',table:'NOT_A_LIBDS',filter:'abc'} -> Invalid table

Finding 2 - the tests waited 100ms for a fire-and-forget write. The cause was
the writers, not the tests: getddl, getrawdata and exportdb used the async
fs.writeFile for the headers file, while %mfs_httpheader (fopen/fput/fclose)
and dcMockUtils.mpStreamfile are synchronous. Those three now use
fs.writeFileSync, so the file is complete when the program returns; the waits
are gone, the positive assertions read the file directly, and the absence
assertions mean "never written" rather than "not written yet". No polling
remains in the file.

Also: mock-settings.test.js renamed the control library to DC7QATEST to prove
getrawdata follows the settings file - nine characters, which the estate
rejects as "Invalid table" for a LIBREF. The fixture is now DC7QATST. That was
a test defect the new validation exposed, not a product one.

Tests: download-headers.test.js is 11 tests, and the two new ones were run
against the old code first - dropping either check fails its own test. Whole
mock suite: 144 tests, 144 pass. parity/check.js unchanged.
2026-11-07 23:23:09 +00:00
dc bb771e9f6f fix(mocks): the download headers the estate actually sends
Build / Build-and-ng-test (pull_request) Successful in 4m13s
Build / lighthouse (pull_request) Successful in 6m6s
Build / Build-and-test-development (pull_request) Canceled after 9m7s
Finding 1 on #510 was that getddl sent an octet-stream, quoted-filename header
the estate never sends. The same defect was in every other download path, so
this fixes the class rather than the one service. Every value below was read
from the synthetic estate's own response, except where noted.

public/getrawdata, from getrawdata.sas and its recorded answers:

  SAS       application/text        LIBREF.DS.sas
  CSV       application/csv         LIBREF.DS.csv
  EXCEL     openxml sheet           LIBREF.DS.xlsx   (from the service source:
                                     PROC EXPORT xlsx fails on the synthetic
                                     estate with syscc=1012, so it cannot be
                                     recorded there)
  MARKDOWN  text/markdown           LIBREF.DS.md
  PDF       application/pdf         LIBREF.DS.pdf

- the filename is the upcased LIBREF.DS plus the type's extension, unquoted
- WEBCSV and WEBTAB send no headers at all: the estate writes those rows
  straight to _webout, and a content-disposition would advertise a download it
  does not offer
- a type outside that list aborts "Invalid type" with mac=&_program..sas before
  anything is streamed, which is what the estate answers for FOOBAR

admin/exportdb: %mp_streamfile(contenttype=TEXT, outname=&dc_libref..ddl), so
application/text and an unquoted <libref>.ddl - the mock sent text/plain.

The shared mpStreamfile helper in dcMockUtils (exportconfig, getauditfile) now
writes one header per line with the filename unquoted, as %mfs_httpheader does,
so the zip downloads stop quoting a name the estate does not quote.

Tests: sas/mocks/test/download-headers.test.js (renamed from
getddl-headers.test.js) now covers all four paths - 9 tests. Each of the new
assertions was run against the old behaviour first and fails there: text/csv
instead of application/csv, a quoted filename, and WEBCSV aborting instead of
streaming. Whole mock suite: 142 tests, 142 pass.
2026-11-07 23:09:31 +00:00
dc 05126ae73a fix(mocks): read MPE_CONFIG correctly, and pin the limits to it
Build / Build-and-ng-test (pull_request) Successful in 5m27s
Lighthouse Checks / lighthouse (pull_request) Successful in 22m3s
Build / Build-and-test-development (pull_request) Successful in 31m9s
Review feedback on this PR.

- getdata.js read MPE_CONFIG from the requested table's own library, so the
  read failed for every non-control libref and both limits silently fell back
  to the shipped defaults.  It now reads mpeDataDir, as viewdata.js already
  did.  Reproduced first: with DC_MAXOBS_WEBEDIT=5, DC_JSLIB.MPE_X_TEST
  aborted while TESTDATA.DEMO_01 loaded untouched.
- exportdb.js mapped DATETIME to TIMESTAMP for TSQL as well, and T-SQL's
  TIMESTAMP is a deprecated synonym for rowversion, so datetime columns were
  declared as rowversions.  TSQL now gets DATETIME2; PGSQL still gets
  TIMESTAMP.  DOUBLE PRECISION is left alone - it is a T-SQL synonym for
  float, not an invalid type.
- loadDcConfig read the config row as direct properties, but a row that has
  been through the app's own edit-and-approve flow comes back from the adapter
  with upper-case keys, so the approved option was skipped and fell back to
  its default - the same silent-default failure by another route.  It now
  reads every field through colVal, like the rest of the mocks.
- row-cell-limits.cy.ts gains a case that moves DC_MAXCELLS_WEBEDIT to a
  non-default value through the editor, asserts that a non-control-libref
  table is then refused, and puts the option back.  It fails if the read is
  dropped: verified by reinstating the getdata.js bug and watching it fail.
2026-10-04 11:18:49 +00:00
dc edac9a987a feat(mocks): read the DC_MAX* options from MPE_CONFIG, and mock the DDL export
Build / Build-and-ng-test (pull_request) Successful in 5m22s
Lighthouse Checks / lighthouse (pull_request) Successful in 22m5s
Build / Build-and-test-development (pull_request) Successful in 30m22s
The mocked estate could not exercise what 7.17 changed.

- getdata.js and viewdata.js hard-coded their limits, so editing
  DC_MAXOBS_WEBEDIT / DC_MAXCELLS_WEBEDIT / DC_MAXOBS_WEBVIEW in DC made
  no difference.  They now read them from MPE_CONFIG via a new
  loadDcConfig/dcConfigNumber pair in dcMockUtils, which mirrors the loop
  in the generated settings.sas: DC-scope rows only, var_active=1 only,
  current rows only (now < tx_to), latest tx_from wins.  An option that is
  absent or switched off falls back to the service's own default, which is
  what %symexist does in the real service.

- There was no mock for services/admin/exportdb, so the System screen's
  Export DC Library DDL action hit a service that did not exist.  The new
  mock renders every table in the DC libref as basic DDL - SAS, PGSQL and
  TSQL flavours, schema defaulting to the libref, a unique index from the
  MPE_TABLES buskey, and the download headers mp_streamfile produces.  DDL
  only: the real service appends inserts for SAS and PGSQL, but
  serialising the library's rows in a mock buys no test value.

ddl-export.cy.ts gains two cases that fetch the URL the action opens and
assert the DDL, so the spec covers the service and not just the URL.
2026-10-03 22:34:57 +00:00