test(android): prototype integration tests - #14905
Draft
thomaseizinger wants to merge 6 commits into
Draft
Conversation
Adds a seam for opening connlib sessions so the service's event loop can be driven without a portal, and three sketches of what integration coverage could look like: instrumented tests on the service, an instrumented test on the session screen, and Robolectric tests for managed configuration and connect-on-start.
The tunnel runs as a systemExempted foreground service, which the platform refuses to start unless the app holds VPN consent; without it the first startForeground threw and took the instrumentation process down with it. Robolectric only dispatches a broadcast when the main looper is advanced, so the boot test never reached BootReceiver.
A started service outlives the test that started it, so the next test could end up driving a service wired up from an object graph that no longer exists: its fake session factory was one no test could see. The fake now outlives the graph and each test stops whatever the previous one left running. Timeouts also say which wait expired and what the service was doing, since an emulator in CI offers no other way to tell.
Stopping the service was not enough to get rid of it: its event loop was still waiting on a fake session that never ended, so it never stopped itself. Ending those sessions first does, and the managed configuration a test writes now reaches a service that may predate it.
The service was surviving with started=false and one client: something held a binding that was never released, and a bound service is destroyed for nobody. The tests bind and unbind themselves now, which is the only way to be sure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Everything worth covering on Android sits behind one call:
TunnelServicebuilds a connlibSessionitself, so its event loop, its state flows and its teardown are unreachable to a test with no portal.SessionFactoryis the seam that changes: the service asks for a session instead of constructing one, and the real factory is a Hilt provider that does what the service used to do inline.With that in place, three sketches of what coverage could look like, deliberately shallow and meant to be compared rather than merged as-is:
openleaving nothing running, and a managed token and device name reaching connlib.SessionActivity, and a disconnect closes the screen.RestrictionsManagerthroughMainActivityinto the repository, and the connect-on-start decision. No emulator, so these run in the unit-test job.Both instrumented suites run in the
connectedDebugAndroidTestjob that already exists and has had nothing to run.The service also had to stop starting connlib's telemetry client in builds stamped
FIREZONE_NO_TELEMETRY, which the Kotlin side already honours: otherwise the emulator would report to Sentry on every CI run, which is exactly what that flag is set to prevent.TunnelServicestill reaches connlib directly for logging and telemetry, which is why the JVM tests stay away from it; only the session is behind a seam.