aglinxinyuan opened a new pull request, #5740: URL: https://github.com/apache/texera/pull/5740
### What changes were proposed in this PR? Pin the abstract-base / trait contracts for two storage-model classes in `common/workflow-core/core/storage/model/`. Tested via minimal in-memory test-only concrete subclasses (no temp-file harness needed). No production-code changes. | Spec | Source class | Tests | | --- | --- | --- | | `VirtualCollectionSpec` | `VirtualCollection` (abstract class) | 7 | | `ReadonlyVirtualDocumentSpec` | `ReadonlyVirtualDocument[T]` (trait) | 11 | Both spec files follow the `<srcClassName>Spec.scala` one-to-one convention. **Behavior pinned — `VirtualCollection`** | Surface | Contract | | --- | --- | | Abstract members (`getURI` / `getDocuments` / `getDocument` / `remove`) | pinned via a minimal `LinkedHashMap`-backed test-only subclass | | `getDocuments` after two `addChild` calls | yields both documents in insertion order (URI sequence pinned to catch a `HashMap`-backed regression) | | `getDocument(name)` for a registered name | returns the same `VirtualDocument[_]` reference (no copy) | | `getDocument(name)` for an unregistered name | impl-defined throw (stub raises `NoSuchElementException`) | | `remove()` | clears the child set (impl-defined side effect; mirrors production "delete folder" semantics) | | Pattern matching | `case _: VirtualCollection` matches a concrete impl; does NOT match an unrelated type (`String`) | **Behavior pinned — `ReadonlyVirtualDocument[T]`** | Surface | Contract | | --- | --- | | Eight abstract methods (`getURI` / `getItem` / `get` / `getRange` / `getAfter` / `getCount` / `asInputStream` / `asFile`) | each is observable through a stub concrete subclass returning sentinel values | | `getRange(from, until)` | half-open interval — `until` is exclusive | | `getRange` call-site | `columns: Option[Seq[String]] = None` default lets the third argument be omitted | | `getAfter(offset)` | skips the item AT `offset` and yields every strictly-later item | | `asInputStream()` | non-null `InputStream` reading the impl-supplied bytes (read-1 / read-2 / EOF round-trip) | | `asFile()` | non-null `File` | | `getCount` | typed as `Long` (compile-time enforced) | | Type parameter `T` | preserved across `getItem` / `get` / `getRange` / `getAfter` (verified with `T = Int`) | | Pattern matching | `case _: ReadonlyVirtualDocument[_]` matches a concrete impl | ### Notes `ReadonlyLocalFileDocument` (the concrete `private[storage]` impl of `ReadonlyVirtualDocument[Nothing]`) is **deliberately out of scope** for this PR — an existing spec at `amber/src/test/scala/org/apache/texera/workflow/common/storage/ReadonlyLocalFileDocumentSpec.scala` already pins its URI / `asInputStream` round-trip / `asFile` / five `NotImplementedError` cases via the `DocumentFactory.openReadonlyDocument(URI)` factory. Adding a parallel spec here would be the duplicate-spec failure mode the spec-filename convention is designed to prevent. ### Any related issues, documentation, discussions? Closes #5736. ### How was this PR tested? Pure unit-test additions; verified locally with: - `sbt "WorkflowCore/testOnly org.apache.texera.amber.core.storage.model.VirtualCollectionSpec org.apache.texera.amber.core.storage.model.ReadonlyVirtualDocumentSpec"` — 18 tests, all green - `sbt scalafmtCheckAll` — clean - CI to confirm ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Opus 4.7 [1M context]) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
