Repository navigation
Live-cloud file-series round-trip test (#304) - #305
Merged
Merged
Conversation
A Python analog of NDI-matlab's FileSeriesRoundTripTest -- the acceptance test the closing note on #300 flagged as missing. It would have caught the retracted retirement's regression (NDI-matlab#989 / NDI-python#301) independently of the mocked path: without the manifest's second ndicloud location or an equivalent mechanism, every member of a downloaded series reads as absent because DID reads a handler that produces nothing as a plain miss. Uploads a fresh cloud dataset holding one demoNDISeries document with four members of distinguishable bytes, waits for server-side bulk extraction, and reads each member back out through: 1. SyncFiles=true: the manifest arrives with its bytes; each member open goes through the DID custom_file_handler to fetch by uid. One signer_call, no per-uid fallbacks. 2. SyncFiles=false: neither manifest nor members come down with the dataset. The manifest itself is fetched through the handler (VH-Lab/DID-python#88 / VH-Lab/DID-matlab#201) and its ingest_locations are rebuilt on the way in by updateFileInfoForRemoteFiles (VH-Lab/NDI-matlab#988, ported in NDI-python#302 / PR #303). No per-uid fallbacks; signer_calls is left loose because the server may answer both manifest and members from one whole-document scope or ask for a series-scoped one on the first member. Byte-for-byte per-slot comparison, not length. Two members swapped by a uid mixup -- the failure this path is most prone to, since a member is addressed by uid the whole way through -- come back the right size and the wrong file, so a length check would catch nothing. Uses ndi.cloud.batch_signed_url.get_default().clear() before each open loop to make the uid_misses assertion measure this test's opens and nothing else. Without that, a run of per-uid getFileDetails could quietly do the work and the test would pass having proved nothing about the path this design exists for (NDI-matlab#968). Best-effort teardown deletes the cloud dataset with when=now. Closes #304. Refs: VH-Lab/NDI-matlab#986, VH-Lab/NDI-matlab#966, VH-Lab/NDI-matlab#987, VH-Lab/NDI-matlab#988, VH-Lab/NDI-matlab#989 (retracted), VH-Lab/DID-matlab#185, VH-Lab/DID-matlab#201, VH-Lab/DID-python#88, #300, #302. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdGZ8fRPeY9JSpUHgXm9ao
The CI test accounts share a quota, and the ingest lane may already have run out of upload slots or dataset-creation privileges by the time this test runs (test (3.12) tripped on HTTP 400 "This user does not have any more uploads available, please purchase another."). Both failure modes come back from createDataset as HTTP 400 with a message that names the reason -- neither is a defect this test can detect or repair, so skip rather than fail. Same shape test_cloud_live.py uses through its ``can_write`` fixture. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdGZ8fRPeY9JSpUHgXm9ao
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #304. Ports NDI-matlab's
FileSeriesRoundTripTest.testMembersSurviveADownloadFromTheCloud[WithSyncFilesFalse]-- the acceptance test the closing note on #300 flagged as missing.Why this test
The retracted retirement PRs (VH-Lab/NDI-matlab#989 / #301) got all the way to green on the mocked path while breaking the actual read: without the manifest's second
ndicloudlocation or an equivalent mechanism, NDI'sdownload_file_from_cloudrefuses anysourcePaththat does not start withndic://, 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 this onFileSeriesRoundTripTest. NDI-python had no equivalent until now.Both offline suites (
tests/test_cloud_series_reconstruction.py,tests/test_cloud_series_reconstruction_remote.py) mockfetch_cloud_fileor install a mock handler. They pin the reconstruction shape but cannot detect a real regression in the resolve path. This file closes that gap.What it does
Module-scoped setup (once per test run):
demoNDISeriesdocument,chunkdata.binnaming four members of distinct bytes (viadid.document.Document.add_file_series, whichndi_documentdoes not wrap).uploadDataset(sync_files=True)into a fresh cloud dataset namedNDI_PYTEST_FILE_SERIES_<uuid>.waitForAllBulkUploadsso server-side zip extraction is finished before anything reads.when="now".Two acceptance tests:
test_members_survive_a_download_from_the_cloud-- SyncFiles=true. Downloads into a fresh temp dir, asserts the downloaded manifest names the same uids in the same slots (so a reshuffle would resolve every member to the wrong file), then opens each member end-to-end and compares bytes byte-for-byte against the uploaded content. Batch counters:uid_misses == 0andsigner_calls == 1.test_members_survive_a_download_from_the_cloud_with_sync_files_false-- SyncFiles=false. Precondition: no member is on this machine yet (an install would mask the fetch this test exists to exercise). Opens each member end-to-end through the fetch-manifest-through-handler path Fetch a remote-only series manifest through the custom_file_handler (#87) VH-Lab/DID-python#88 + PR Rebuild series ingest_locations on SyncFiles=false download (#302) #303 laid; compares bytes byte-for-byte. Batch counters:uid_misses == 0.signer_callsis left loose because the server may answer both manifest and members from one whole-document scope or use a series-scoped one on the first member, and pinning one over the other would guess at server behaviour this suite does not otherwise cover (matches NDI-matlab#988's comment).Notes
ndi.cloud.batch_signed_url.get_default()before the open loop, so theuid_missesassertion measures this test's opens and nothing else. Without that, a run of per-uidgetFileDetailscould quietly do the work (NDI-matlab#968).NDI_CLOUD_USERNAME/NDI_CLOUD_PASSWORDare not set. The scheduledtest-cloud-api.ymlworkflow picks the file up by thetest_cloud_*.pyglob; the linuxtestlane inci.ymlalso runs it with the same credentials injected on every push.Verification
Locally:
pytest tests/test_cloud_file_series_round_trip.py -vcollects 2 tests and skips both cleanly without credentials. The doc-building half of the fixture was smoke-tested against a real localndi_dataset_dir(four members added viadid.Document.add_file_series; manifest reads back with the four uids; a localdatabase_openbinarydoc("chunkdata.bin_1")returns the right bytes).ruff checkandblack --checkclean on the new file.References
MembersNotLocatableguard the reconstruction satisfies)🤖 Generated with Claude Code
https://claude.ai/code/session_01AdGZ8fRPeY9JSpUHgXm9ao
Generated by Claude Code