Skip to content

Testing tools: SDK harness on the iOS simulator, project on Unity 6.6 - #37

Merged
x401om merged 7 commits into
devfrom
feature/testing-tools
Nov 13, 2026
Merged

x401om merged 7 commits into
devfrom
feature/testing-tools

Conversation

@yauch-dev

Copy link
Copy Markdown
Collaborator

What

Two things, each its own commit.

SDK harness (Assets/SdkHarness/) — a player the agent drives from the command line against the real native SDK over the Pipeline command channel: harness_activate, harness_call (any public Adapty/AdaptyUI method by name, arguments as JSON, results of earlier calls reusable as $GetFlow), harness_events, harness_status. It answers the one question the desktop suite cannot: does the C# layer decode what the native SDK actually returns, on IL2CPP, after stripping. Build with harness_build, run from Xcode so the local StoreKit configuration is synced into the simulator and purchases stay local; the ios-storekit-purchase skill drives the purchase sheet by log lines. Everything is in Assets/SdkHarness/AGENTS.md.

A player with nothing in it but the pipeline runtime server and
AdaptySdkHarness, which exposes the public Adapty/AdaptyUI API as
harness_* commands: activate, call any method by name with JSON
arguments (returned models are passed back as $Method handles,
request-only models through their Builder), read the events the
listeners received. A UI Toolkit ledger on screen shows every request,
reply, late reply and event.

harness_build builds the scene for the simulator SDK and files
AdaptyDemo.storekit in the Xcode project and scheme; running it from
Xcode makes purchases local. The ios-storekit-purchase skill drives the
purchase sheet and alerts from the simulator's log. Recipe and limits in
Assets/SdkHarness/AGENTS.md.

Project on Unity 6.6, package floor 6.0.

Editor 6000.6.0f1 with its resaved project settings and package bumps
(pipeline 0.5.0-exp.1, project-auditor-rules, test-framework 1.8, ugui 2.6,
inputsystem 1.20). The package now declares unity 6000.0; the raise is
unreleased and noted under Unreleased in the changelog.

Follow-up

The Android lane of the harness and the bridge without the Java wrapper are in #36, stacked on this branch.

@yauch-dev
yauch-dev added this pull request to stack #38 September 11, 2026 19:20
@yauch-dev
yauch-dev requested a review from x401om September 11, 2026 19:20
@yauch-dev yauch-dev self-assigned this Sep 11, 2026
@StanislavMayorov
StanislavMayorov marked this pull request as draft September 30, 2026 10:19
@yauch-dev
yauch-dev force-pushed the feature/testing-tools branch from 658eae6 to a6de975 Compare October 27, 2026 18:38
@yauch-dev
yauch-dev marked this pull request as ready for review October 27, 2026 18:39
Editor 6000.6.0f1 with its resaved project settings and package bumps
(pipeline 0.5.0-exp.1, project-auditor-rules, test-framework 1.8, ugui 2.6,
inputsystem 1.20). The package now declares unity 6000.0; the raise is
unreleased and noted under Unreleased in the changelog.
A player with nothing in it but the pipeline runtime server and
AdaptySdkHarness, which exposes the public Adapty/AdaptyUI API as
harness_* commands: activate, call any method by name with JSON
arguments (returned models are passed back as $Method handles,
request-only models through their Builder), read the events the
listeners received. A UI Toolkit ledger on screen shows every request,
reply, late reply and event.

harness_build builds the scene for the simulator SDK and files
AdaptyDemo.storekit in the Xcode project and scheme; running it from
Xcode makes purchases local. The ios-storekit-purchase skill drives the
purchase sheet and alerts from the simulator's log. Recipe and limits in
Assets/SdkHarness/AGENTS.md.
IL2CPP on Unity 6 shares generics fully, so the Capture<T> the harness
makes by MakeGenericType runs for bool and enum payloads without an
instantiation compiled ahead of time. Checked on the simulator:
IsActivated, GetLogLevel and ShowDialog's action type all come back.
A link.xml under Assets/ goes into every player, so the one beside the
harness kept the whole SDK assembly in the demo and in StrippingBuild
too. SdkHarnessBuild now hands the linker its own list through
IUnityLinkerProcessor, and only while it builds the harness; any other
build gets an empty one.

The list keeps only what the harness reaches by reflection: Adapty's
and AdaptyUI's methods, AdaptyJson, and the request-side types it
builds from JSON or by member name. Response models and converters are
left to the linker, since their decoding after stripping is what the
harness is there to check. A full run on the simulator (activation
through the Builder, flows, products, profile, attribution, flow view,
dialog, purchase with parameters) decodes everything, and
StrippingBuild.IOS on High strips the SDK to 105 KB.
Complete and Run took their decisions apart, so a reply arriving right
at the budget could be reported both as the call's result and as a
late reply, or as neither. Both now decide under one lock.
@yauch-dev
yauch-dev force-pushed the feature/testing-tools branch from a6de975 to 5703a53 Compare October 28, 2026 15:33
@yauch-dev
yauch-dev removed this pull request from stack #38 October 28, 2026 15:36
@yauch-dev
yauch-dev changed the base branch from main to dev October 28, 2026 15:36
@yauch-dev
yauch-dev added this pull request to stack #40 October 28, 2026 15:36
…ly once

The exception path set its result outside the lock Run decides under,
so a call that threw after the wait had timed out (a flow pausing the
player loop on Android) was reported by neither side. Run also read the
result after leaving the lock, so a reply landing right after the
verdict went out both in the timed-out answer and as a late reply.
Both paths now complete through Complete, and Run takes the result with
its verdict.
harness_call took the first overload whose parameter names matched the
arguments. ShowDialog has two with the same names - one for a flow view,
one for a legacy onboarding view - so an onboarding handle always landed
on the flow overload and failed to bind before the SDK was called. Every
overload whose names match is now tried in turn and the first that binds
is called; when none binds, each one's reason is reported.
@x401om
x401om merged commit 570b5ce into dev Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants