Skip to content

Live-cloud round-trip test: a downloaded series' members must be readable (SyncFiles=true and =false) #304

Closed

Description

@stevevanhooser

Follow-up carved out of the closing note on #300. Second of the two follow-ups (the first was #302 -- the SyncFiles=false ingest_locations rebuild, on its way to landing as PR #303).

What is missing

NDI-python has no live-cloud test that a downloaded file series' members are actually readable end to end. Today's series coverage is:

  • tests/test_cloud_series_reconstruction.py::TestThroughARealDatabase -- offline; DID dispatch is real, fetch_cloud_file is mocked. Good for pinning the ingest_locations reconstruction shape and the manifest's local read path.
  • tests/test_cloud_series_reconstruction_remote.py (added in PR Rebuild series ingest_locations on SyncFiles=false download (#302) #303) -- offline; a mock customFileHandler serves manifest bytes by uid. Good for pinning the SyncFiles=false reconstruction shape without cloud credentials.

Neither exercises the real cloud round trip. That gap is what let the retirement PRs (VH-Lab/NDI-matlab#989, #301) get all the way to "green" on the mocked path while breaking the actual read: without the second ndicloud location on a manifest, NDI's download_file_from_cloud refuses any sourcePath that does not start with ndic://, DID reads a handler that produces nothing as a plain miss, and every member of a downloaded series reads as absent -- silently. NDI-matlab caught the same regression on FileSeriesRoundTripTest.testMembersSurviveADownloadFromTheCloud and testMembersSurviveADownloadFromTheCloudWithSyncFilesFalse. NDI-python has no equivalent.

What to add

A Python analog of NDI-matlab's tests/+ndi/+unittest/+cloud/FileSeriesRoundTripTest.m, in whatever the current NDI-python cloud-test conventions call for. Two acceptance tests, both live-cloud:

  1. SyncFiles=true -- upload a small series document (say 3-4 members with distinct byte contents), download it into a fresh folder with sync_files=True, open each member end to end, verify bytes byte-for-byte (not by length; a uid mixup returns the right size and wrong file). Mirrors testMembersSurviveADownloadFromTheCloud.

  2. SyncFiles=false -- upload the same shape, download with sync_files=False (manifest arrives as ndic:// only, no bytes on disk), open each member. This exercises DID#201 / DID-python#88's lazy manifest fetch plus the ingest_locations reconstruction Rebuild series ingest_locations on SyncFiles=false download (companion to VH-Lab/NDI-matlab#988) #302 / PR Rebuild series ingest_locations on SyncFiles=false download (#302) #303 landed. Mirrors testMembersSurviveADownloadFromTheCloudWithSyncFilesFalse. Precondition assertion: neither the manifest nor any member on this machine before the first open, so a pre-existing file cache cannot mask a real fetch.

Both tests should:

  • assert every member came back openable and byte-for-byte correct, per-slot so a failure diagnostic names which members made the trip and which did not (testMembersSurviveADownloadFromTheCloud's slot-by-slot loop is the model).
  • pin the batch-signed-URL path so the test does not silently fall back to per-uid getFileDetails and report success on a path it is not exercising (batchStats.uidMisses == 0, matching the MATLAB assertion). The Python equivalent lives in ndi.cloud.batch_signed_url; a counter query pattern is what the MATLAB test uses -- see ndi.cloud.download.internal.batchSignedUrlLookup's clearCache / counters mode.

Notes

  • Cloud credentials required; slots naturally into whatever cloud-test lane the repo already runs (the CI has Test Cloud API on a schedule).
  • A member-uid nonce per run is important on this side too: DID's file cache is machine-global and keyed by uid, so a constant uid would let the fetch pass once and resolve from cache forever after -- silently regressing the very fetch the test exists to prove. tests/test_cloud_series_reconstruction.py's tag fixture is the pattern.
  • Test data can be small (a few kilobytes total); the test is about the mechanism, not throughput.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions