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]

Reply via email to