Repository navigation
ci(bindings): run the Kotlin and Swift wire-contract tests on the shipped Binding Sets - #2937
Conversation
…pped Binding Sets The proxy crate ships a Kotlin and a Swift wire-contract test beside its golden pins, and neither ran anywhere: zingo-mobile wired the Kotlin one into its own unit suite from the submodule, and the Swift one waited on #2504. Step 1 of #2930 moves both into zingolib, since each tests a Binding Set that zingolib publishes. The Android binding build gains a test source set over the Kotlin test, JUnit 4 as a test dependency, and the golden directory as a system property. The package job of binding-layer-android.yaml runs it after bundling the AAR, against the Kotlin Binding Set the AAR ships. A test-only Swift package beside the Swift test depends on the ZingoBindings package by path, the test imports that module, and its golden path gains the directory it was missing. The iOS workflow runs it under xcodebuild on an available simulator, because the XCFrameworks hold iOS slices only. The glossary gains Binding Set, Binding Layer Endpoint and Bundle Pin, and restates Prebuilt Bundle to the packaged form that #2833 publishes, so that the records of #2930 have a target for those terms. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
juanky201271
left a comment
There was a problem hiding this comment.
The Kotlin half holds: the test only uses allocationSize/write/read over a ByteBuffer, so it never touches UniffiLib and needs no host library. Two things on the Swift step, which the PR says no Mac has run, and one on docs.
Docs this PR leaves stale: contract-tests/README.md still says the app's Gradle unit suite runs the Kotlin test and that the Swift one joins the step-7 packaging (#2504); the headers of GoldenWireContractTest.kt ("zingo-mobile's test suite wires it in") and GoldenWireContractTests.swift say the same. zingolib runs both now; the README should name binding-layer-android.yaml and binding-layer-ios.yaml.
…contract test The contract-tests package declares no products, so SwiftPM generates a single scheme named after the package, ZingoBindingsContractTests-Package. The step asked for GoldenWireContractTests, which is the test target, and xcodebuild would have refused it on the first nightly run. The simulator picker took the first device of the first runtime in the JSON, so a watchOS or tvOS device could win, and an empty list ended in a Python traceback. The step now filters with jq for an available iPhone on an iOS runtime and fails with a device listing when none exists. The tail that trimmed the xcodebuild log also hid the compile and link errors above the trailer. The step passes -quiet instead, which keeps the full set of errors, warnings and test results and drops the rest. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…S plan The workbench now owns the contract-tests package as constants beside the shipped package: its directory, its manifest, its package name, and the relative path by which it reaches bindings/swift. A pin test reads the manifest and asserts each constant against it, and resolves the relative path back to the shipped package's directory, so a move of either package fails in tools/workbench before it fails in a nightly. The iOS plan of build-binding-layer ends with a new XcodeTest step. The step first checks that the plan's output directory is the directory the shipped manifest reads, so the test never compiles against stale frameworks. It then lists the available simulators, picks the first iPhone on an iOS runtime with a pure function that a fixture listing covers, and runs the package's one scheme with -quiet. The iOS workflow calls the builder alone, so a local run proves what CI proves. The README and both test headers now say where each suite runs: the Kotlin test in the Gradle library's unit suite, which the Android workflow's package job runs, and the Swift test at the end of the iOS plan. That package job runs one Gradle invocation for the AAR and the test. The Gradle script derives the proxy crate from zingolibRoot instead of a second relative path, and normalizes the golden directory. The glossary's Binding Layer entry and the Android workflow's comments say Binding Sets where they said bindings. A .gitignore beside the contract manifest keeps SwiftPM's .build and .swiftpm out of the crate, and cargo honours it when packaging. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ong iOS output before the build, and require the executed test count The simulator picker takes the iOS deployment target as its floor and skips every runtime below it, prefers a booted iPhone, and returns the device's udid beside its name. The xcodebuild destination names the device by id, which is unambiguous across runtimes, where a bare name is not. The check that the iOS output directory is the one the Swift contract test's package reads moves from the last step of the plan into build, before any step runs, and compares the paths lexically. The old check canonicalized a directory that does not exist in the case it guards against, so it reported a resolve error in place of its own message, and only after the whole iOS build. The step keeps the working directory and the scheme alone, and the plan test no longer asserts a mismatch under a name that claims agreement. xcodebuild runs without -quiet, its output is captured and echoed, and the builder parses the last "Executed N tests" line and requires N to equal the suite's size, which a unit test pins to the number of test methods in the Swift file. A scheme that discovers no test can no longer pass. The host working-directory check now guards captured commands as well as streamed ones, through one helper, so an absent directory is named before the program. The Swift test drops the ZINGO_GOLDEN_DIR override, which xcodebuild never forwards to a simulator test host, and the README states the absolute golden path the Gradle script sets. The android workflow's header is rewrapped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
juanky201271
left a comment
There was a problem hiding this comment.
All three addressed, thanks. The Kotlin step compiles and runs in the package job.
I dispatched ci-nightly on this branch and the Swift step fails at link time: ~37 undefined SystemConfiguration symbols from hickory_resolver / system_configuration in libzingo_nym_proxy_ffi.a (job). The shipped bindings/swift/Package.swift doesn't link the framework; zingo-mobile only works because its pbxproj links it by hand. linkerSettings: [.linkedFramework("SystemConfiguration")] on the ZingoBindings target should fix it. Good catch by the test, but as is this breaks the iOS job of the nightly and /publish.
nit: xcodebuild warned "Using the first of multiple matching destinations". The parser already has the UDID, so -destination "platform=iOS Simulator,id=<udid>" avoids that.
The Swift wire-contract test fails at link time with undefined SystemConfiguration symbols. The static library libzingo_nym_proxy_ffi.a carries hickory_resolver's system_configuration crate, which calls into that framework. The shipped bindings/swift/Package.swift linked no framework, so every consumer had to link it by hand, as zingo-mobile's pbxproj does. The ZingoBindings target now declares the framework in its linker settings. The workbench pin test asserts the setting through a named constant, so the manifest cannot drop it unnoticed. This serves step 1 of zingolib#2930. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for dispatching the nightly. The link failure is real, and 87c401f does not fix it. 85b499d adds The destination nit is already in 87c401f. The nightly you dispatched ran at ac55e65. The step now passes 87c401f also closes eight items from a pass over ac55e65:
No Mac has run the Swift step since 87c401f. The iOS job on 85b499d is the proof. |
…tination xcodebuild still warned that it was using the first of multiple matching destinations after the step named the simulator by udid. The arm64 and the x86_64 entries of one simulator share that udid, so the udid alone matches both. The destination now ends with arch=arm64, which matches one entry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fix(bindings): close the review findings that followed PR #2937
Step 1 of #2930. Each piece here adds coverage in zingolib. Nothing is deleted.
What was already true
zingo-ffi/libis a root-workspace member, sotest.yamlruns the wallet crate tests on every PR. The netutils job runs the proxy crate tests and the live mixnet start. The testa_mixnet_refusal_maps_to_the_owned_mixnet_markerhas pinned the mixnet marker since a67de8d. Step 1 therefore reduces to the two wire-contract tests and the glossary.The Kotlin wire-contract test
The Android binding build gains a test source set over
contract-tests/kotlin, JUnit 4.13.2 as a test dependency, and the golden directory as thezingo.golden.dirsystem property. The package job ofbinding-layer-android.yamlrunstestReleaseUnitTestafter it bundles the AAR. The test then compiles against the Kotlin Binding Set that the AAR ships, so no host library is needed.The Swift wire-contract test
The Swift test has never run anywhere. A test-only package at
contract-tests/Package.swiftdepends on theZingoBindingspackage by path, so the shippedPackage.swiftgains no test target. The test now imports that module. Its golden path was one directory short, and it gains the missing component. The iOS workflow runs the test underxcodebuildon an available simulator, because the XCFrameworks hold iOS slices only.The glossary
zingolib/CONTEXT.mdgains Binding Set, Binding Layer Endpoint and Bundle Pin. It restates Prebuilt Bundle to the packaged form that #2833 publishes. Ruling 9 of #2930 refers to these terms.Verified
Not verified here
JUnit is a new Gradle test dependency. The test file imports it.
Refs #2930.
🤖 Generated with Claude Code