[AIT-1231][LiveObjects] Enable UTS integration test suites (17/17 objects tier passing) - #2235
Conversation
…t tiers) Applies the UTS integration test suites translated in #2226, now runnable against the completed LiveObjects implementation. The compile-only .disabled traits are removed; all suites pass against the Ably sandbox exactly as originally written (17/17 objects-tier + 27/27 rest-tier): - standard/objects: sync, lifecycle, and GC suites + helpers - proxy/objects: fault-injection suite (self-provisioning uts-proxy) - standard/rest: History/Presence/Publish suites - Package.swift: AblyLiveObjects dependency for the UTS target - deviations.md records and uts-to-swift skill routing updates
WalkthroughThe PR adds Objects-specific UTS translation guidance, resolver path overrides, a dedicated ChangesLiveObjects UTS workflow
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Covers the questions that the LiveObjects monorepo merge left
unanswered in the contributor docs.
CONTRIBUTING.md:
- Running tests: a table of the package's four test targets and the CI
workflows that run each. Records that every target selects its files
by directory, so new tests need no manifest, test-plan or workflow
change, and that the LiveObjects UTS ports live in
AblyLiveObjectsTests rather than the UTS target. Notes the
AllTests/UnitTests asymmetry between the Xcode and coverage jobs.
- New LiveObjects section:
- Supported OS versions: the macOS 11 / iOS 14 / tvOS 14 floor and
its provenance in ADR-114; the @available mechanism that lets one
package host two floors, with the command that applies it and the
two CI checks that enforce it; and why test code instead raises its
build's deployment target (the @suite macro rejects @available),
listing both places that do so.
- Distribution: the channel/product matrix and the four independent
reasons AblyLiveObjects is SPM-only, plus the note that OS version
requirements are not among them.
- Release Process: a Versioning preamble recording that the repository
has one version number for all products, that the standalone
plugin's 0.x line does not continue, that a tag does not mean the
same thing on every channel, and that AblyLiveObjects is exempt from
semver while experimental. Adds an SPM resolution check to the
release steps, and fixes a stale bullet that described
_AblyPluginSupportPrivate as an external dependency needing its own
release.
LiveObjects/CONTRIBUTING.md: its release-process pointer now links the
two new sections and summarises them inline, and the description of
where the standalone plugin was released is reworded — "released
independently from the ably-liveobjects-swift-plugin repository" reads
as "released separately from that repository", i.e. not in it, which
is the opposite of what happened.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The UTS test target links AblyLiveObjects (iOS 14 / tvOS 14 / macOS 11), but the package's platform floor is lower and SwiftPM has no per-target floor. The core SDK's fastlane integration build compiles the `ably-cocoa` scheme's test target at that low floor, so the UTS harness's direct references to AblyLiveObjects types failed on the iOS/tvOS simulators with "'ProtocolTypes' is only available in iOS 14.0 or newer". Rather than annotate/erase the harness, raise the deployment target of the test build itself via fastlane xcargs (IPHONEOS/TVOS_DEPLOYMENT_TARGET = 14.0), mirroring LiveObjects/BuildTool's `testDeploymentTargetOverrides`. This affects the test build only — shipped artifacts and the package's declared floor are unchanged (respecting the ADR-128 / #2222 decision to keep ably-cocoa's platforms low and gate LiveObjects via @available). It also lets the UTS harness embed the plugin's OBJECT/OBJECT_SYNC types verbatim (no erasure) and lets future objects @suite tests compile without @available/#available guards (the Swift Testing macros reject @available). macOS needs no override (its default test-build floor already satisfies AblyLiveObjects). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 9b844bb)
Extract all test-only plumbing from the shipped LiveObjects sources and consolidate the objects UTS unit tier into the standard UTS layout: - Add the Test/AblyLiveObjectsTesting test-support target: the 57 testsOnly_ internal-access extensions (moved out of LiveObjects/Sources, which now carries only 5 physically-immovable instrumentation seams behind marker comments) plus the shared test helpers/mocks (TestFactories, UTSTestPoolFactories, TestLogger, Subscriber, Assertions, 4 mocks), consumed via @testable import by both test targets and unreachable from any product. - Raise the seams' backing members from private to internal (module- scoped; each carries an intent comment) and delete 3 dead seams. - Move the 16 objects UTS unit-spec suites to Test/UTS/unit/objects/ (UTS target, resolver-default <Stem>Tests names, canonical "// UTS: <id>" tags so audit_translation.py works again); unlike ably-java, cocoa's cross-target @testable access means these ports need not live inside the plugin module. - Remove 20 native tests proven duplicated by the UTS ports (each verified against a UTS counterpart asserting a superset; one statusCode assertion ported into the UTS RTLC12e1 tests first); renumber the affected @specOneOf groups. - Add Scripts/check-liveobjects-test-seams.sh, wired into make lint and CI, failing if LiveObjects/Sources grows testsOnly_ declarations outside the sanctioned allowlist. - Align the uts-to-swift skill (routing, reading lists, naming rules, spec-helper coverage tables, publish-capture recipe) with the new layout; scope the SPM release CI job to --target AblyLiveObjects and run the UTS job with -warnings-as-errors. Test counts: native suite 399 -> 379 (zero coverage loss); UTS tier 330 green; public API and shipped sources behaviour unchanged.
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (6)
Test/UTS/unit/objects/InternalLiveCounterApiTests.swift (1)
72-102: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueFold the ported assertion into the table test and drop the duplicate.
RTLC12e1_increment_non_finite_throwsnow asserts exactly whatRTLC12e1_increment_invalid_amounts_tableasserts for its.nanrow:code == 40003andstatusCode == 400. The single-case test adds no coverage. Move the porting note onto the table test and remove the duplicate.♻️ Proposed change
- // UTS: objects/unit/RTLC12e1/increment-non-number-0 — the representable non-finite doubles throw 40003. - `@Test` - func RTLC12e1_increment_non_finite_throws() async throws { - let (counter, _) = try makeCounter(objectID: "counter:score@1000", data: 100) - let error = await `#expect`(throws: ARTErrorInfo.self) { - try await counter.increment(amount: .nan) - } - `#expect`(error?.code == 40003) - // Ported from the native IncrementTests.throwsErrorForInvalidAmount before its removal - // (Wave-1 dedup): the invalid-amount error also carries HTTP status 400. - `#expect`(error?.statusCode == 400) - } - // UTS: objects/unit/RTLC12e1/increment-invalid-amounts-table-0 — every representable non-finite amount - // throws 40003. The non-numeric rows are compile-time-unrepresentable (Double parameter). + // throws 40003. The non-numeric rows are compile-time-unrepresentable (Double parameter). + // Ported from the native IncrementTests.throwsErrorForInvalidAmount before its removal + // (Wave-1 dedup): the invalid-amount error also carries HTTP status 400. `@Test`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Test/UTS/unit/objects/InternalLiveCounterApiTests.swift` around lines 72 - 102, Remove the redundant RTLC12e1_increment_non_finite_throws test, move its native-test porting note to RTLC12e1_increment_invalid_amounts_table, and retain the existing code and status assertions in the table test, including the .nan case.Test/UTS/integration/standard/rest/PresenceTests.swift (1)
25-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the repeated REST client setup into one helper.
The same four-line block appears in all 15 tests: build
ARTClientOptions, setrestHost, setuseBinaryProtocol, and constructARTRest. The realtime variant repeats six lines in six tests. Two small helpers remove that duplication and keep the per-test body focused on the spec steps.♻️ Proposed helpers
Add to the
extension PresenceTestsblock:private func restClient(_ app: SandboxApp, useBinaryProtocol: Bool, clientId: String? = nil) -> ARTRest { let options = ARTClientOptions(key: app.defaultKey) options.restHost = SandboxApp.sandboxHost // the spec's endpoint: "nonprod:sandbox" options.useBinaryProtocol = useBinaryProtocol options.clientId = clientId return ARTRest(options: options) } private func realtimeOptions(_ app: SandboxApp, useBinaryProtocol: Bool, clientId: String) -> ARTClientOptions { let options = ARTClientOptions(key: app.defaultKey) options.realtimeHost = SandboxApp.sandboxHost options.restHost = SandboxApp.sandboxHost options.useBinaryProtocol = useBinaryProtocol options.clientId = clientId options.autoConnect = false return options }Then each test body reduces to:
- let options = ARTClientOptions(key: app.defaultKey) - options.restHost = SandboxApp.sandboxHost // the spec's endpoint: "nonprod:sandbox" - options.useBinaryProtocol = useBinaryProtocol - let client = ARTRest(options: options) + let client = self.restClient(app, useBinaryProtocol: useBinaryProtocol)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Test/UTS/integration/standard/rest/PresenceTests.swift` around lines 25 - 28, Add private restClient and realtimeOptions helpers to the PresenceTests extension, encapsulating the repeated REST and realtime ARTClientOptions setup shown in the tests. Replace each duplicated setup block with the appropriate helper call, preserving useBinaryProtocol, optional clientId, host values, and autoConnect behavior.Test/UTS/integration/standard/objects/helpers/ObjectsIntegrationHelpers.swift (1)
60-71: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThrow a purpose-built error instead of
HTTPError.
counterInstanceIdthrowsHTTPErrorwhen the resolved instance is not a counter.HTTPErrordescribes a sandbox provisioning or HTTP transport failure, not a type mismatch in an objects instance. A reader who seesHTTPErrorin a CI log will look for a network problem. TheIssue.recordcall on line 66 carries the real cause, so the thrown type only needs to unwind the test.Define a small dedicated error, or return the failure through
#requirealone.♻️ Proposed refactor
+/// Signals that a UTS objects helper could not satisfy its expected-type contract. The paired +/// `Issue.record` call carries the diagnostic; this type only unwinds the test. +struct ObjectsHelperError: Error, CustomStringConvertible { + let description: String +} + /// The spec's `pathObj.instance().id` against an expected **counter** — unwraps the `Instance` enum /// (`objects-mapping.md` §5), stopping the test if nothing resolves or the instance isn't a counter. func counterInstanceId(at node: any PathObject, sourceLocation: SourceLocation = `#_sourceLocation`) throws -> String { let instance = try `#require`(try node.instance(), "expected an instance at path '\(node.path)'", sourceLocation: sourceLocation) guard case let .liveCounter(counter) = instance else { Issue.record("expected a liveCounter instance at path '\(node.path)', got \(instance.type)", sourceLocation: sourceLocation) - throw HTTPError("expected a liveCounter instance at path '\(node.path)'") + throw ObjectsHelperError(description: "expected a liveCounter instance at path '\(node.path)'") } return counter.id }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Test/UTS/integration/standard/objects/helpers/ObjectsIntegrationHelpers.swift` around lines 60 - 71, Update counterInstanceId so the non-liveCounter branch no longer throws HTTPError; define and throw a small purpose-built local error for this type-mismatch failure, or rely solely on `#require` to unwind after Issue.record. Preserve the existing diagnostic message and successful counter.id return path.Test/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects+TestsOnly.swift (1)
94-94: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUpdate the stale comment.
This comment describes the member as exposed "in the early days of the SDK" and predicts it will become private later. The member now lives in a dedicated testing target, so the stated plan no longer applies. Rewrite the comment to state what the seam does for tests.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Test/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects`+TestsOnly.swift at line 94, Update the comment above the exposed member to describe its current purpose as a testing seam for sending an OBJECT ProtocolMessage, and remove the outdated references to the SDK’s early days and making it private later.Test/UTS/integration/standard/rest/PublishTests.swift (1)
128-145: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDrop the protocol parameterization on the deviation placeholder.
The body only calls
Issue.record. It never usesuseBinaryProtocol, so the two arguments record the same issue twice with no added coverage. The signature is alsoasync throwswith noawaitand notryin the body.♻️ Proposed simplification
- `@Test`(.enabled(if: ProcessInfo.processInfo.environment["RUN_DEVIATIONS"] != nil), - arguments: [false, true]) // useBinaryProtocol: false = JSON, true = msgpack - func test_RSL1l1_publish_params_with_forceNack(useBinaryProtocol: Bool) async throws { + `@Test`(.enabled(if: ProcessInfo.processInfo.environment["RUN_DEVIATIONS"] != nil)) + func test_RSL1l1_publish_params_with_forceNack() {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Test/UTS/integration/standard/rest/PublishTests.swift` around lines 128 - 145, Simplify test_RSL1l1_publish_params_with_forceNack by removing the unused useBinaryProtocol argument and its protocol parameterization, leaving a single non-async, non-throwing test that records the deviation once. Preserve the existing Issue.record message and test enablement condition.Test/AblyLiveObjectsTesting/LiveObjectMutableState+TestsOnly.swift (1)
14-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider a non-optional parameter with an empty-dictionary default.
siteTimeserialsis declared optional and then collapsed to[:]with?? [:]. Callers cannot distinguish "not supplied" from "supplied as empty", so the optional adds no information. A non-optional parameter with a default removes the coalescing operator.♻️ Proposed simplification
init( objectID: String, - testsOnly_siteTimeserials siteTimeserials: [String: String]? = nil, + testsOnly_siteTimeserials siteTimeserials: [String: String] = [:], testsOnly_tombstonedAt tombstonedAt: Date? = nil, ) { self.init(objectID: objectID) - self.siteTimeserials = siteTimeserials ?? [:] + self.siteTimeserials = siteTimeserials self.tombstonedAt = tombstonedAt }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Test/AblyLiveObjectsTesting/LiveObjectMutableState`+TestsOnly.swift around lines 14 - 18, Update the tests-only initializer’s siteTimeserials parameter to be non-optional with an empty-dictionary default, then assign it directly to self.siteTimeserials and remove the nil-coalescing fallback. Preserve the existing initializer behavior for callers that omit the parameter or provide an explicit dictionary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@LiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift`:
- Line 572: The testsOnly_publish seam must remain a pass-through instead of
duplicating publish behavior. Extract the mutex hop, validation, error handling,
and coreSDK.nosync_publish logic from ensureMessageSizeWithinLimit into a tested
internal production method, then have the test helper delegate directly to it;
otherwise obtain approval for and record a residual exception.
In `@Test/AblyLiveObjectsTesting/Subscriber.swift`:
- Line 6: Update the availability annotations for every test path that
constructs Subscriber, including DefaultInstanceTests, to require macOS 14.0
alongside the existing iOS and tvOS requirements. Alternatively, revise
Subscriber so it remains compatible with the package’s macOS 10.11 baseline,
while preserving the existing test behavior.
In `@Test/AblyLiveObjectsTesting/TestFactories.swift`:
- Line 185: Align TestFactories availability with the package’s declared
deployment floors: either remove the newer availability restriction and keep it
usable on macOS 10.11, iOS 9, and tvOS 10, or ensure TestFactories is not
exposed to callers on those older platforms while preserving the existing
Package.swift support declarations.
In `@Test/UTS/integration/standard/rest/HistoryTests.swift`:
- Around line 175-193: The timestamp split in the history test can exclude all
late messages when maxEarlyTs equals minLateTs. Update the timeBoundary and
lateQuery setup in this test to detect the collapsed-timestamp case and skip the
split or widen the boundary so lateHistory still includes the late messages,
while preserving the existing behavior for distinct timestamps.
- Around line 250-266: Split historyItems into reporting and non-reporting
variants: retain Issue.record behavior for final reads, while the variant used
by pollUntil predicates returns history results and errors without recording
issues. Update every poll predicate calling historyItems (including the usages
near lines 39, 81, 116, and 159) to use the non-reporting variant, preserving
the existing reporting behavior elsewhere.
---
Nitpick comments:
In `@Test/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects`+TestsOnly.swift:
- Line 94: Update the comment above the exposed member to describe its current
purpose as a testing seam for sending an OBJECT ProtocolMessage, and remove the
outdated references to the SDK’s early days and making it private later.
In `@Test/AblyLiveObjectsTesting/LiveObjectMutableState`+TestsOnly.swift:
- Around line 14-18: Update the tests-only initializer’s siteTimeserials
parameter to be non-optional with an empty-dictionary default, then assign it
directly to self.siteTimeserials and remove the nil-coalescing fallback.
Preserve the existing initializer behavior for callers that omit the parameter
or provide an explicit dictionary.
In
`@Test/UTS/integration/standard/objects/helpers/ObjectsIntegrationHelpers.swift`:
- Around line 60-71: Update counterInstanceId so the non-liveCounter branch no
longer throws HTTPError; define and throw a small purpose-built local error for
this type-mismatch failure, or rely solely on `#require` to unwind after
Issue.record. Preserve the existing diagnostic message and successful counter.id
return path.
In `@Test/UTS/integration/standard/rest/PresenceTests.swift`:
- Around line 25-28: Add private restClient and realtimeOptions helpers to the
PresenceTests extension, encapsulating the repeated REST and realtime
ARTClientOptions setup shown in the tests. Replace each duplicated setup block
with the appropriate helper call, preserving useBinaryProtocol, optional
clientId, host values, and autoConnect behavior.
In `@Test/UTS/integration/standard/rest/PublishTests.swift`:
- Around line 128-145: Simplify test_RSL1l1_publish_params_with_forceNack by
removing the unused useBinaryProtocol argument and its protocol
parameterization, leaving a single non-async, non-throwing test that records the
deviation once. Preserve the existing Issue.record message and test enablement
condition.
In `@Test/UTS/unit/objects/InternalLiveCounterApiTests.swift`:
- Around line 72-102: Remove the redundant RTLC12e1_increment_non_finite_throws
test, move its native-test porting note to
RTLC12e1_increment_invalid_amounts_table, and retain the existing code and
status assertions in the table test, including the .nan case.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f13a09da-2db6-4567-b136-1da5058d1c6c
📒 Files selected for processing (88)
.claude/skills/uts-to-swift/SKILL.md.claude/skills/uts-to-swift/references/objects-mapping.md.claude/skills/uts-to-swift/scripts/resolve_uts.py.claude/skills/uts-to-swift/uts-package-mapping.json.github/workflows/liveobjects.yamlLiveObjects/CHANGELOG.mdLiveObjects/CLAUDE.mdLiveObjects/Sources/AblyLiveObjects/Internal/CoreSDK.swiftLiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swiftLiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swiftLiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swiftLiveObjects/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swiftLiveObjects/Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swiftLiveObjects/Sources/AblyLiveObjects/Internal/ObjectsPool.swiftLiveObjects/Sources/AblyLiveObjects/Path Based API/Public/Channel+Object.swiftLiveObjects/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObject.swiftLiveObjects/Sources/AblyLiveObjects/Utility/Errors.swiftLiveObjects/Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/DefaultInstanceTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/DefaultInternalPluginTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/DefaultPathObjectTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swiftLiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/ObjectDiffHelpersTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/ObjectLifetimesTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/ObjectsPoolTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/ParentReferencesTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/PathObjectSubscriptionTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/PublicRealtimeObjectTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/SyncObjectsPoolTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/TestsOnlySeamsTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/UTS/README.mdLiveObjects/Tests/AblyLiveObjectsTests/WireObjectMessageSizeTests.swiftMakefilePackage.swiftScripts/check-liveobjects-test-seams.shTest/AblyLiveObjectsTesting/ARTRealtimeChannel+TestsOnly.swiftTest/AblyLiveObjectsTesting/AblyLiveObjectsTesting.swiftTest/AblyLiveObjectsTesting/Assertions.swiftTest/AblyLiveObjectsTesting/InternalDefaultLiveCounter+TestsOnly.swiftTest/AblyLiveObjectsTesting/InternalDefaultLiveMap+TestsOnly.swiftTest/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects+TestsOnly.swiftTest/AblyLiveObjectsTesting/LiveObjectMutableState+TestsOnly.swiftTest/AblyLiveObjectsTesting/MockCoreSDK.swiftTest/AblyLiveObjectsTesting/MockLiveMapObjectsPoolDelegate.swiftTest/AblyLiveObjectsTesting/MockRealtimeObjects.swiftTest/AblyLiveObjectsTesting/MockSimpleClock.swiftTest/AblyLiveObjectsTesting/ObjectCreationHelpers+TestsOnly.swiftTest/AblyLiveObjectsTesting/ObjectsPool+TestsOnly.swiftTest/AblyLiveObjectsTesting/PublicDefaultRealtimeObject+TestsOnly.swiftTest/AblyLiveObjectsTesting/README.mdTest/AblyLiveObjectsTesting/Subscriber.swiftTest/AblyLiveObjectsTesting/TestFactories.swiftTest/AblyLiveObjectsTesting/TestLogger.swiftTest/AblyLiveObjectsTesting/UTSTestPoolFactories.swiftTest/UTS/deviations.mdTest/UTS/integration/proxy/objects/ObjectsFaultsTests.swiftTest/UTS/integration/standard/objects/ObjectsGcTests.swiftTest/UTS/integration/standard/objects/ObjectsLifecycleTests.swiftTest/UTS/integration/standard/objects/ObjectsSyncTests.swiftTest/UTS/integration/standard/objects/helpers/ObjectsIntegrationHelpers.swiftTest/UTS/integration/standard/objects/helpers/ObjectsRestProvisioning.swiftTest/UTS/integration/standard/rest/HistoryTests.swiftTest/UTS/integration/standard/rest/PresenceTests.swiftTest/UTS/integration/standard/rest/PublishTests.swiftTest/UTS/unit/objects/InstanceTests.swiftTest/UTS/unit/objects/InternalLiveCounterApiTests.swiftTest/UTS/unit/objects/InternalLiveCounterTests.swiftTest/UTS/unit/objects/InternalLiveMapApiTests.swiftTest/UTS/unit/objects/InternalLiveMapParentReferencesTests.swiftTest/UTS/unit/objects/InternalLiveMapTests.swiftTest/UTS/unit/objects/LiveObjectSubscribeTests.swiftTest/UTS/unit/objects/ObjectIdTests.swiftTest/UTS/unit/objects/ObjectsPoolTests.swiftTest/UTS/unit/objects/ObjectsUTSHelpers.swiftTest/UTS/unit/objects/ParentReferencesTests.swiftTest/UTS/unit/objects/PathObjectMutationsTests.swiftTest/UTS/unit/objects/PathObjectSubscribeTests.swiftTest/UTS/unit/objects/PathObjectTests.swiftTest/UTS/unit/objects/PublicObjectMessageTests.swiftTest/UTS/unit/objects/README.mdTest/UTS/unit/objects/RealtimeObjectTests.swiftTest/UTS/unit/objects/ValueTypesTests.swiftTest/UTS/unit/objects/deviations.md
💤 Files with no reviewable changes (1)
- LiveObjects/Tests/AblyLiveObjectsTests/UTS/README.md
Addresses CodeRabbit review feedback on #2237: the note refers to the plugin's historical releases page, so link directly to /releases rather than the repository root.
The target branch's commit 36b57c6 moved the LiveObjects 'objects' UTS unit ports out of AblyLiveObjectsTests and into the UTS target (Test/UTS/unit/objects/), and added the shared AblyLiveObjectsTesting support target. Correct the test-target table and CI notes, which still described the pre-restructure layout.
docs: document LiveObjects versioning, distribution and test targets; fix UTS integration build on iOS/tvOS
clearOnDetachedEmitsNoUpdateEvents constructs Subscriber<...>, whose parameter-pack generics require iOS 17 / tvOS 17, but it was the one Subscriber-using test missing the @available(iOS 17.0.0, tvOS 17.0.0, *) annotation its siblings carry. BuildTool compiles the iOS/tvOS test bundles at the plugin floor of 14.0, so the gap failed the "Xcode, iOS/tvOS (Xcode 16.4)" jobs at build-for-testing; macOS passed only because xcodebuild raises the macOS bundle floor to 14 on its own. A mechanical sweep confirmed this was the only unguarded Subscriber use. Also documents the Test/UTS and Test/AblyLiveObjectsTesting targets in the root CLAUDE.md test-structure section.
…kflows Remove liveobjects.yaml's build-and-test-uts job (and its aggregation-gate entry): both of its purposes were already covered elsewhere — - execution: integration-test.yaml's Fastlane lanes run the whole UTS target on iOS, tvOS and macOS via Test/Ably.xctestplan (including the LiveObjects objects unit tier, the sandbox integration tier and the macOS-only proxy tier); - warnings-as-errors compilation: the build-and-test-spm job compiles every test target in the package under the flag, UTS included. It was also a flake source, running the network-bound sandbox/proxy suites on every PR in duplicate. So that this topology is discoverable from any workflow a developer opens, add orientation comments across the family: where UTS tests execute and why (integration-test.yaml), why liveobjects.yaml has no UTS job, what check-spm.yaml does and doesn't cover, why the plugin is absent from check-pod.yaml (SPM-only), where LiveObjects DocC is built vs the core Jazzy docs (docs.yml), and a job-level comment for every previously uncommented liveobjects.yaml job (matrices, Xcode test/release builds, coverage's UnitTests-vs-AllTests plan asymmetry, example app, DocC). Also drop integration-test.yaml's stale note about replicating changes to integration-test-*.yaml siblings (none exist) and update CONTRIBUTING.md's CI section to match.
There was a problem hiding this comment.
Pull request overview
This PR enables LiveObjects UTS coverage by (1) moving the objects unit-tier UTS suites into the shared UTS target, (2) adding new objects integration suites that run against the Ably nonprod sandbox, and (3) introducing a dedicated AblyLiveObjectsTesting support target to keep test seams out of shipped LiveObjects sources (enforced via a new guard script run in CI and make lint).
Changes:
- Added LiveObjects objects integration suites (
ObjectsSyncTests,ObjectsLifecycleTests,ObjectsGcTests) plus REST provisioning + helper wiring. - Introduced
AblyLiveObjectsTestingSPM target and migratedtestsOnly_seams out ofLiveObjects/Sourcesinto test-support extensions, with a guard script to prevent regressions. - Relocated/renamed objects unit-tier UTS ports into
Test/UTS/unit/objects/and updated CI/docs/tooling to reflect the new layout.
Reviewed changes
Copilot reviewed 96 out of 96 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Test/UTS/unit/objects/ValueTypesTests.swift | Renames suite + updates UTS provenance/comments. |
| Test/UTS/unit/objects/RealtimeObjectTests.swift | Renames suite + imports AblyLiveObjectsTesting for internal seams. |
| Test/UTS/unit/objects/README.md | Documents objects unit-tier UTS layout/conventions in UTS target. |
| Test/UTS/unit/objects/PublicObjectMessageTests.swift | Renames suite + updates UTS provenance/comments. |
| Test/UTS/unit/objects/PathObjectSubscribeTests.swift | Renames suite + imports AblyLiveObjectsTesting. |
| Test/UTS/unit/objects/PathObjectMutationsTests.swift | Renames suite + updates UTS test-ID tags. |
| Test/UTS/unit/objects/ParentReferencesTests.swift | Renames suite + imports AblyLiveObjectsTesting; updates UTS tags. |
| Test/UTS/unit/objects/ObjectsUTSHelpers.swift | Updates helper commentary for renamed suites; imports testing target. |
| Test/UTS/unit/objects/ObjectsPoolTests.swift | Renames suite + imports AblyLiveObjectsTesting; updates internal references. |
| Test/UTS/unit/objects/ObjectIdTests.swift | Renames suite + imports AblyLiveObjectsTesting; updates tags. |
| Test/UTS/unit/objects/LiveObjectSubscribeTests.swift | Renames suite + imports AblyLiveObjectsTesting. |
| Test/UTS/unit/objects/InternalLiveMapParentReferencesTests.swift | Renames suite + imports AblyLiveObjectsTesting; updates internal references. |
| Test/UTS/unit/objects/InternalLiveMapApiTests.swift | Renames suite + updates UTS provenance/comments. |
| Test/UTS/unit/objects/InternalLiveCounterApiTests.swift | Renames suite + adds statusCode assertions for invalid increment amounts. |
| Test/UTS/unit/objects/InstanceTests.swift | Renames suite + imports AblyLiveObjectsTesting. |
| Test/UTS/integration/standard/objects/ObjectsSyncTests.swift | Adds direct-sandbox objects sync integration coverage. |
| Test/UTS/integration/standard/objects/ObjectsLifecycleTests.swift | Adds end-to-end lifecycle/mutation propagation integration coverage. |
| Test/UTS/integration/standard/objects/ObjectsGcTests.swift | Adds tombstone/recreate integration coverage (GC sweep remains unit-tier). |
| Test/UTS/integration/standard/objects/helpers/ObjectsRestProvisioning.swift | Adds REST provisioning helper for objects fixtures (V2 REST shape). |
| Test/UTS/integration/standard/objects/helpers/ObjectsIntegrationHelpers.swift | Adds shared client/channel wiring + typed value readers for integration suites. |
| Test/UTS/deviations.md | Appends deviations + application record for enabling these suites. |
| Test/AblyLiveObjectsTesting/UTSTestPoolFactories.swift | Adds availability annotations to align with LiveObjects platform floor. |
| Test/AblyLiveObjectsTesting/TestLogger.swift | Adds availability annotations for LiveObjects-compatible builds. |
| Test/AblyLiveObjectsTesting/TestFactories.swift | Adds availability annotations for LiveObjects-compatible builds. |
| Test/AblyLiveObjectsTesting/Subscriber.swift | Expands availability to macOS 14 to match parameter-pack requirement. |
| Test/AblyLiveObjectsTesting/README.md | Documents purpose + seam-migration rule + residual allowlist. |
| Test/AblyLiveObjectsTesting/PublicDefaultRealtimeObject+TestsOnly.swift | Adds test-only accessors for PublicDefaultRealtimeObject. |
| Test/AblyLiveObjectsTesting/ObjectsPool+TestsOnly.swift | Adds test-only init/setters (and Entry helpers) for ObjectsPool. |
| Test/AblyLiveObjectsTesting/ObjectCreationHelpers+TestsOnly.swift | Exposes object-ID creation helper for tests without shipping seams. |
| Test/AblyLiveObjectsTesting/MockSimpleClock.swift | Adds availability annotations. |
| Test/AblyLiveObjectsTesting/MockRealtimeObjects.swift | Adds availability annotations. |
| Test/AblyLiveObjectsTesting/MockLiveMapObjectsPoolDelegate.swift | Adds availability annotations. |
| Test/AblyLiveObjectsTesting/MockCoreSDK.swift | Adds availability annotations. |
| Test/AblyLiveObjectsTesting/LiveObjectMutableState+TestsOnly.swift | Adds test-only initializer to avoid shipping testsOnly_ init. |
| Test/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects+TestsOnly.swift | Adds test-only accessors and helpers for engine state/control. |
| Test/AblyLiveObjectsTesting/InternalDefaultLiveMap+TestsOnly.swift | Migrates testsOnly_ seams for map internals out of shipped sources. |
| Test/AblyLiveObjectsTesting/InternalDefaultLiveCounter+TestsOnly.swift | Migrates testsOnly_ seams for counter internals out of shipped sources. |
| Test/AblyLiveObjectsTesting/Assertions.swift | Adds availability annotation to helper fatalError. |
| Test/AblyLiveObjectsTesting/ARTRealtimeChannel+TestsOnly.swift | Exposes non-type-erased object seam for tests without shipping accessors. |
| Test/AblyLiveObjectsTesting/AblyLiveObjectsTesting.swift | Adds module anchor file for the new test-support target. |
| Scripts/check-liveobjects-test-seams.sh | Adds guardrail script to prevent new shipped testsOnly_ seams. |
| Package.swift | Adds AblyLiveObjectsTesting target + wires it into test targets; adds LiveObjects deps to UTS. |
| Makefile | Runs the seams guard script as part of make lint. |
| LiveObjects/Tests/AblyLiveObjectsTests/WireObjectMessageSizeTests.swift | Switches to using AblyLiveObjectsTesting seams. |
| LiveObjects/Tests/AblyLiveObjectsTests/TestsOnlySeamsTests.swift | Switches to using AblyLiveObjectsTesting seams. |
| LiveObjects/Tests/AblyLiveObjectsTests/SyncObjectsPoolTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/PublicRealtimeObjectTests.swift | Updates imports; removes duplicated spec coverage; adjusts one error assertion. |
| LiveObjects/Tests/AblyLiveObjectsTests/PathObjectSubscriptionTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/ParentReferencesTests.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/ObjectsPoolTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/ObjectLifetimesTests.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/ObjectDiffHelpersTests.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift | Updates imports; removes duplicated spec coverage; adds availability on one test. |
| LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift | Updates imports; removes duplicated spec coverage; minor cleanup. |
| LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/Helpers/ClientHelper.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/DefaultPathObjectTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/DefaultInternalPluginTests.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/DefaultInstanceTests.swift | Updates imports; removes duplicated spec coverage. |
| LiveObjects/Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift | Updates imports to use AblyLiveObjectsTesting. |
| LiveObjects/Tests/AblyLiveObjectsTests/UTS/README.md | Removes outdated/misleading UTS-unit documentation from plugin test target. |
| LiveObjects/Sources/AblyLiveObjects/Utility/Errors.swift | Removes shipped testsOnly_ error accessor and clarifies comment. |
| LiveObjects/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObject.swift | Makes members internal for AblyLiveObjectsTesting; removes shipped testsOnly_ accessors. |
| LiveObjects/Sources/AblyLiveObjects/Path Based API/Public/Channel+Object.swift | Makes seam internal for AblyLiveObjectsTesting; removes shipped testsOnly_ accessor. |
| LiveObjects/Sources/AblyLiveObjects/Internal/ObjectsPool.swift | Removes shipped testsOnly_ seams; relaxes access for test-support target. |
| LiveObjects/Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift | Makes object-ID creator internal for test-support target; removes shipped testsOnly_. |
| LiveObjects/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift | Removes shipped testsOnly_ initializer from production sources. |
| LiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift | Removes shipped testsOnly_ seams; relaxes access for test-support target. |
| LiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift | Removes shipped testsOnly_ seams; relaxes access for test-support target. |
| LiveObjects/Sources/AblyLiveObjects/Internal/CoreSDK.swift | Documents remaining sanctioned testsOnly_ residuals in production. |
| LiveObjects/CONTRIBUTING.md | Clarifies plugin versioning/distribution relationship to ably-cocoa releases. |
| LiveObjects/CLAUDE.md | Notes that objects UTS suites live under Test/UTS/unit/objects/ now. |
| LiveObjects/CHANGELOG.md | Adds Unreleased notes summarizing implementation/testing progress. |
| fastlane/Fastfile | Raises test build deployment targets for UTS (needed due to LiveObjects floor). |
| CLAUDE.md | Updates repo-level structure notes for UTS objects + new testing target. |
| .github/workflows/liveobjects.yaml | Adds test-seams check; scopes release build to shipped target; updates commentary. |
| .github/workflows/integration-test.yaml | Adds documentation clarifying UTS execution responsibilities in CI. |
| .github/workflows/docs.yml | Clarifies core SDK docs vs LiveObjects DocC docs responsibility. |
| .github/workflows/check-spm.yaml | Clarifies compile-only nature and CI split for tests. |
| .github/workflows/check-pod.yaml | Clarifies LiveObjects is SPM-only and intentionally absent from pod/carthage packaging. |
| .claude/skills/uts-to-swift/uts-package-mapping.json | Documents resolver behavior + adds dormant // override semantics. |
| .claude/skills/uts-to-swift/scripts/resolve_uts.py | Implements // override + documents class-name derivation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add non-reporting history/presence-history helpers and use them inside every pollUntil predicate (HistoryTests, PublishTests, PresenceTests, ChannelHistoryTests — 11 sites): a transient error during polling now retries instead of permanently failing the test; final reads keep the reporting variants. (CodeRabbit, extended to two suites it didn't flag.) - Remove the unused ObjectsPool.Entry tombstone accessors (Copilot); verified unused by compile proof and receiver type audit. - README (AblyLiveObjectsTesting): clarify the D3 dumb-accessor rule — mechanical shape-preserving constructs (enum-case dispatch, element-wise forwarding, continuation bridging) are not "logic" — and record testsOnly_publish as a lead-approved D3 exception with rationale (composes the production RTO15d validator + CoreSDK.nosync_publish, deliberately without the RTO20 apply stage). Rewrite its stale "early days of the SDK" comment accordingly. (Copilot + CodeRabbit.) - Throw a purpose-built ObjectsHelperError instead of HTTPError for the type-mismatch failure in counterInstanceId (CodeRabbit nitpick). - Make the tests-only siteTimeserials init parameter non-optional with an empty-dictionary default and drop the dead nil-coalescing (CodeRabbit nitpick). Verified: swift build --build-tests green; TestsOnlySeamsTests + LiveObjectMutableStateTests pass (21 tests); make lint (EditorConfig + seams guardrail) green.
|
Re the six CodeRabbit nitpicks (posted in the review body, so answering here) — three applied in fadb670, three declined: Applied:
Declined:
|
…jects-uts-integration-tests Brings in the PR #2234 review fixes (comment-policy sweep, citation corrections, the nosync_onChannelRelease/nosync_resetDataToZeroValued renames, the subscription-register let refactor, the SyncCursor revert to throws, the CCR3b size fix, Errors numericCode single-sourcing) and the CI fixes. Conflict resolutions: - Seam extraction wins: the testsOnly_ members stay in Test/AblyLiveObjectsTesting (not Sources); the register-refactor signature change is ported into the extracted testsOnly_applyObjectMessages seam. - Wave-1 dedup deletions win: the dispose-twin tests and the noop emit test stay deleted; the base's comment/citation fixes are applied to the surviving tests (nosync_onChannelRelease doc, RTLO4b4c3a retag). - Leaked-tag cleanups reconciled (UTS/README.md stays deleted; deviations.md files keep the moved content, tags gone). - testsOnly_underlyingLiveObjectsError re-homed in AblyLiveObjectsTesting (the reverted SyncCursorTests need it; the userInfo key is raised to internal with the usual intent comment). Verified: swift build --build-tests green; native unit suite, UTS unit sample, SyncCursor/seams/mutable-state/PluginAPI suites all pass; EditorConfig + seams guardrail green.
c745f40
into
feature/liveobjects-implementation
There was a problem hiding this comment.
🧹 Nitpick comments (2)
LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (2)
1349-1349: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winRestore duplicate
MAP_CREATEcoverage.Line 1349 removes the test that verifies a second create is discarded after the initial value is merged. This guard protects idempotent operation application. Without the test, a regression can merge the initial value twice and change map state incorrectly. Keep an equivalent assertion through the new test seam.
The removed test is identified in the supplied line-range change details.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift` at line 1349, Restore duplicate MAP_CREATE coverage in MapCreateOperationTests by adding an equivalent test through the new test seam. Verify that after the initial value is merged, applying a second create is discarded and does not alter the map state, preserving idempotent operation application.
315-315: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winKeep the RTLM6i omission regression test.
Line 315 removes coverage for a replacement state that omits
clearTimeserial.InternalDefaultLiveMap.replaceDataassignsclearTimeserial = state.map?.clearTimeserial, so this transition clears stale state. Restore the case or add an equivalent test in the new test-support layout.The production assignment is in
LiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift` at line 315, Restore or add the RTLM6i regression test in the InternalDefaultLiveMap tests for replacing state that omits clearTimeserial. Verify that replaceData clears the previously stored clearTimeserial value when state.map?.clearTimeserial is absent, while preserving the existing RTLM6h coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift`:
- Line 1349: Restore duplicate MAP_CREATE coverage in MapCreateOperationTests by
adding an equivalent test through the new test seam. Verify that after the
initial value is merged, applying a second create is discarded and does not
alter the map state, preserving idempotent operation application.
- Line 315: Restore or add the RTLM6i regression test in the
InternalDefaultLiveMap tests for replacing state that omits clearTimeserial.
Verify that replaceData clears the previously stored clearTimeserial value when
state.map?.clearTimeserial is absent, while preserving the existing RTLM6h
coverage.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 73723c01-f466-4b53-a21d-1c906e89963a
📒 Files selected for processing (21)
LiveObjects/Sources/AblyLiveObjects/Internal/CoreSDK.swiftLiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swiftLiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swiftLiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swiftLiveObjects/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swiftLiveObjects/Sources/AblyLiveObjects/Internal/ObjectsPool.swiftLiveObjects/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObject.swiftLiveObjects/Sources/AblyLiveObjects/Utility/Errors.swiftLiveObjects/Tests/AblyLiveObjectsTests/DefaultPathObjectTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/ParentReferencesTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/PublicRealtimeObjectTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/SyncCursorTests.swiftLiveObjects/Tests/AblyLiveObjectsTests/TestsOnlySeamsTests.swiftTest/AblyLiveObjectsTesting/ARTErrorInfo+TestsOnly.swiftTest/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects+TestsOnly.swiftTest/AblyLiveObjectsTesting/MockRealtimeObjects.swiftTest/UTS/deviations.mdTest/UTS/unit/objects/ObjectsUTSHelpers.swift
💤 Files with no reviewable changes (1)
- Test/UTS/deviations.md
🚧 Files skipped from review as they are similar to previous changes (16)
- LiveObjects/Tests/AblyLiveObjectsTests/ParentReferencesTests.swift
- LiveObjects/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift
- Test/UTS/unit/objects/ObjectsUTSHelpers.swift
- Test/AblyLiveObjectsTesting/MockRealtimeObjects.swift
- LiveObjects/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift
- LiveObjects/Tests/AblyLiveObjectsTests/TestsOnlySeamsTests.swift
- LiveObjects/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
- LiveObjects/Sources/AblyLiveObjects/Internal/CoreSDK.swift
- LiveObjects/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObject.swift
- LiveObjects/Tests/AblyLiveObjectsTests/DefaultPathObjectTests.swift
- LiveObjects/Sources/AblyLiveObjects/Utility/Errors.swift
- LiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
- LiveObjects/Tests/AblyLiveObjectsTests/PublicRealtimeObjectTests.swift
- LiveObjects/Sources/AblyLiveObjects/Internal/ObjectsPool.swift
- Test/AblyLiveObjectsTesting/InternalDefaultRealtimeObjects+TestsOnly.swift
- LiveObjects/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift
…atch) - ObjectsUTSSeededRealtimeObjects now echoes each captured publishAndApply operation back onto its existing pool entry (a reduced RTO20 ACK echo), so PathObjectMutationsTests asserts the spec's post-apply value reads verbatim for primitive writes; the deviation record is narrowed to the *_CREATE blueprint cases. The echo is asynchronous like the real ACK: the write APIs call publishAndApply while holding the written object's state mutex, so a synchronous echo violates exclusivity. - Remove the channelName defaults from InternalDefaultRealtimeObjects (init + MutableState); production always supplies the name, and every test construction site now passes it explicitly. - Reword the testsOnly_getFullPaths seam docs (counter + map) to describe the accessor rather than the pool DFS rationale that doesn't apply. - Correct stale test_-prefixed method references in the objects UTS deviations record (the Swift Testing methods carry no prefix). Verified: swift build --build-tests green; full UTS target 330 tests passed (incl. sandbox integration; one documented RSL1l1 skip); native unit tier TEST SUCCEEDED; EditorConfig + seams guardrail green.
Summary
This PR enables the UTS integration test suites for LiveObjects, originally translated from the UTS integration specs in #2226. When that PR was authored, the path-based API was a compile-only skeleton, so its suites carried a
.disabled("Compile-only until the implementation lands")trait. The implementation has now landed on the base branch (feature/liveobjects-implementation), and these tests run — and pass — exactly as originally written, with zero test adaptations.Results
All suites verified against the real (nonprod) Ably sandbox:
ObjectsSyncTestsObjectsLifecycleTestsObjectsGcTestsObjectsFaultsTestsHistoryTests/PresenceTests/PublishTestsEach
@Testruns both JSON and msgpack protocol variants. The proxy tier self-provisions theuts-proxybinary (checksum-verified GitHub release download).What's included
Test/UTS/integration/standard/objects/— the sync, lifecycle, and GC suites plus their helpers (ObjectsIntegrationHelpers,ObjectsRestProvisioning).Test/UTS/integration/proxy/objects/— the fault-injection suite (ObjectsFaultsTests: sync interruption, buffering across faults, detach/reattach, publish-ack loss).Test/UTS/integration/standard/rest/— the History/Presence/Publish suites from the same source PR.Package.swift— adds theAblyLiveObjectsdependency to theUTStest target (required by the objects suites).Test/UTS/deviations.md— appended records: theRSL1l1skip gate and the application record for this test-enablement pass..claude/skills/uts-to-swift/— skill routing updated so futureobjectsUTS ports land in the correct targets (unit →LiveObjects/Tests/AblyLiveObjectsTests/UTS/; integration/proxy →Test/UTS/integration/…), plus the refreshed objects mapping reference.Relationship to the base branch
These tests are the acceptance evidence for the implementation work on
feature/liveobjects-implementation. Three defects they exposed were fixed there (not here — this PR contains no library source changes):deiniton the internal queue tripped a dispatch precondition (SIGTRAP during ARC-driven teardown).get()did not implicitly attach the channel (RTL33b) — every integration spec's setup relies on it.siteCodewas never delivered to channels created after CONNECTED, silently disabling RTO20 local echo.The suites in this PR now pass with those fixes in place, unmodified from their spec translations.
Notes for reviewers
uts/objects/integration/in the specification repo; the test bodies are line-by-line translations (deviations, where unavoidable, are recorded inTest/UTS/deviations.md).uts-proxyrelease binary.swift test --filter ObjectsSyncTests(etc.) from the repo root, aftergit submodule update --init --recursive.Summary by CodeRabbit
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores