Skip to content

[tests] Use local servers for networking tests - #12022

Merged
simonrozsival merged 10 commits into
mainfrom
android-change-networking-tests
Jul 10, 2026
Merged

simonrozsival merged 10 commits into
mainfrom
android-change-networking-tests

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Summary

  • Replace httpbin.org redirect/decompression coverage with local loopback HTTP endpoints
  • Replace badssl.com self-signed/hostname-mismatch coverage with local self-signed HTTPS servers
  • Update LinkDesc HttpClient regression to post to a local HttpListener

Validation

  • make all
  • ./dotnet-local.sh build -t:Install -c Debug tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj -p:Device=R58Y30HZ65V -p:IncludeCategories=SSL
  • (cd tests/Mono.Android-Tests/Mono.Android-Tests && ../../../dotnet-local.sh test Mono.Android.NET-Tests.csproj --no-build -c Debug --report-trx --results-directory ../../../bin/TestDebug/TestResults -p:Device=R58Y30HZ65V -p:IncludeCategories=SSL) — 25 passed
  • ./dotnet-local.sh test bin/TestDebug/MSBuildDeviceIntegration/net10.0/MSBuildDeviceIntegration.dll --filter "FullyQualifiedName~InstallAndRunTests.CustomLinkDescriptionPreserve" — 4 skipped (test is currently ignored for all runtime variants)

Replace httpbin.org and badssl.com dependencies in networking tests with local loopback HTTP/HTTPS servers, including self-signed TLS coverage. Update the LinkDesc HttpClient regression to post to a local listener.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 8, 2026 16:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates networking-related tests to stop depending on external internet endpoints (httpbin.org/badssl.com) by introducing local loopback HTTP/HTTPS test servers and switching existing redirect/decompression/SSL-validation tests to use them. This improves test reliability in constrained or offline environments and reduces external flakiness.

Changes:

  • Added reusable local HTTP/HTTPS test server helpers for Mono.Android.NET-Tests.
  • Migrated AndroidMessageHandler redirect/decompression and invalid-certificate tests to use local servers instead of external hosts.
  • Updated the LinkDesc HttpClient regression app/test to POST to a local HttpListener endpoint and adjusted the manifest to allow cleartext traffic + INTERNET permission.
Show a summary per file
File Description
tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs Enables cleartext + INTERNET permission for the LinkDesc regression app so it can talk to local HTTP endpoints.
tests/MSBuildDeviceIntegration/Resources/LinkDescTest/HttpClientTest.cs Replaces external POST target with a local HttpListener-based loopback server.
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/LocalTestServers.cs Introduces local HTTP and HTTPS server helpers for test scenarios (compression, redirects, self-signed certs).
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs Switches decompression, redirect, and SSL callback tests to local servers.
tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidHandlerTestBase.cs Updates redirect tests to use local loopback servers.
tests/Mono.Android-Tests/Mono.Android-Tests/System.Net/SslTest.cs Removes httpbin from the external URL list to reduce dependency on that service.
tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj Adds the new LocalTestServers.cs to the test project build.

Copilot's findings

  • Files reviewed: 7/7 changed files
  • Comments generated: 4

simonrozsival and others added 8 commits July 8, 2026 22:14
Bind local HTTP listeners to loopback, dispose LinkDesc HTTP resources, backdate self-signed certificates further, and assert policy errors in the HTTPS redirect callback test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Share local test server exception handling and shutdown logic, and add intent-level helpers for redirect and OK responses to remove repeated listener setup in networking tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add local HTTP test-server endpoint helpers for the networking tests and LinkDesc HttpClient regression. Scope the generated app's cleartext allowance to localhost via network security config instead of enabling app-wide cleartext traffic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use declaration-style using statements in the local HTTP test helpers and redirect tests to reduce nesting. Opt the generated LinkTestLib project into C# 8 so its embedded helper can use using declarations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the extra LocalHttpTestServer wrapper from Mono.Android networking tests. LocalTestServer now owns shared lifecycle/error handling, LocalHttpServer owns HTTP listener behavior and test endpoints, and LocalHttpsServer remains the HTTPS/self-signed transport helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the Mono.Android HttpListener-based LocalHttpServer with a TCP-based request parser/router shared by LocalHttpsServer. HTTPS now exposes the same /ok and /redirect-to endpoints as HTTP, with TLS layered via SslStream. Rename the generated LinkDesc helper to LinkDescHttpServer to avoid confusion with the Mono.Android helpers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use BaseAddress with httpbin-style relative redirect endpoints in networking tests, name the HTTPS certificate host argument, and rename the generated LinkDesc helper back to LocalHttpServer with a /post endpoint.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the duplicate LinkDesc local HTTP server and compile the shared Mono.Android LocalTestServers helper into the generated LinkTestLib project. Make the shared helper netstandard2.0-compatible for the LinkDesc library while keeping HTTPS/Brotli support for the Mono.Android tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival added flaky-tests ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). labels Jul 9, 2026
@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

✅ Android PR Reviewer completed successfully!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Code Review — ⚠️ Needs Changes

Nice cleanup. Replacing httpbin.org / badssl.com with in-process loopback servers removes a real source of external-network flakiness, and LocalTestServers.cs is well thought through:

  • Per-response Connection: close correctly forces a fresh TLS handshake, which is what keeps ServerCertificateCustomValidationCallback_Redirects asserting callbackCounter == 2.
  • Handler exceptions are captured off the accept loop and surfaced via AssertNoUnhandledExceptions(), and dispose-time IOException/ObjectDisposedException are correctly ignored once the handler completed.
  • Self-signed cert generation with SANs and the HTTPS host pinned to localhost (matching the cert) is a sensible design.

CI: ✅ All dotnet-android checks are green on bd7911c. mergeable_state: blocked reflects the pending maintainer review, not a CI failure.

Findings (see inline):

  • ⚠️ 1 warning — LinkDesc network_security_config.xml whitelists cleartext for localhost, but LocalHttpServer uses 127.0.0.1; the LinkDesc HttpClientTest will hit Cleartext ... not permitted once CustomLinkDescriptionPreserve is un-ignored.
  • 💡 2 suggestions — port-selection race in GetAvailablePort() (re-introduces a flaky window); reduced fidelity of NoServerCertificateCustomValidationCallback_ThrowsWhenThereIsCertificateHostnameMismatch.

Worth double-checking before merge: the two tests that actually exercise the loopback servers end-to-end aren't part of the green CI legs — CustomLinkDescriptionPreserve is ignored for all runtime variants (per the PR description), and the SSL-category AndroidMessageHandlerTests run on a physical device rather than the emulator legs. So the green checks above don't fully validate the new cleartext/loopback paths.

Prioritized: the network-security-config vs. server-host mismatch is the one to fix; the other two are optional.

Generated by Android PR Reviewer for #12022 · 209.6 AIC · ⌖ 27.5 AIC · ⊞ 6.8K
Comment /review to run again

Bind local test listeners directly to ephemeral ports and align the loopback cleartext configuration. Trust the local certificate before asserting a hostname mismatch so the test isolates name validation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9721cbaf-7e53-4fb0-b12c-6c9de7483f9d
@simonrozsival
simonrozsival enabled auto-merge (squash) July 10, 2026 07:09
@simonrozsival
simonrozsival merged commit bef2665 into main Jul 10, 2026
42 checks passed
@simonrozsival
simonrozsival deleted the android-change-networking-tests branch July 10, 2026 22:17
simonrozsival added a commit that referenced this pull request Jul 14, 2026
> Re-opened as a direct PR (supersedes #12098) so the `dotnet-android` pipeline runs automatically without `/azp run` approval.

### Context

Following up on #12022 (which migrated most on-device networking tests off live external URLs to the loopback `LocalHttpServer`/`LocalHttpsServer`) and #12058 (which handles `SslTest.HttpsShouldWork`), a few on-device tests were still reaching out to the public internet. Those requests made the tests flaky whenever the external endpoints were slow, rate-limited, or unavailable.

This migrates the remaining tests to local loopback servers.

### Tests migrated

| Test | Was hitting |
| ---- | ----------- |
| `SslTest.SslWithinTasksShouldWork` | `dotnet.microsoft.com` |
| `ProxyTest.QuoteInvalidQuoteUrlsShouldWork` | `msftconnecttest.com` |
| `AndroidMessageHandlerTests.ServerCertificateCustomValidationCallback_ApproveRequest` | `www.microsoft.com` |
| `AndroidMessageHandlerTests.ServerCertificateCustomValidationCallback_RejectRequest` | `www.microsoft.com` |
| `AndroidMessageHandlerTests.AndroidMessageHandlerSendsClientCertificate` | `corefx-net-tls.azurewebsites.net` |
| `AndroidMessageHandlerIntegrationTests.GetString_Many` | `google.com` |
| `HttpClientHandlerTestBase.Disposed` | `google.com` |
| `WebSocketTests.TestSocketConnection` | `echo.websocket.org` (was `[Ignore]`d) |

`ProxyTest` keeps its original point — an unescaped `|` in the query string (`?query&foo|bar`) — now exercised against the local `/ok` endpoint. `WebSocketTests` was previously disabled because the public echo server no longer exists; it is re-enabled against a local server.

### Test infrastructure (`LocalTestServers.cs`)

- **Client certificates (mutual TLS)**: `LocalHttpsServer.Start (requestClientCertificate: true)` now requests a client certificate during the TLS handshake, and a new `/echo-client-certificate` endpoint returns the certificate the server received (base64 DER). This replaces the external `EchoClientCertificate.ashx` endpoint.
- **`LocalWebSocketServer`**: a loopback WebSocket echo server that performs the upgrade handshake and echoes messages back (uses `WebSocket.CreateFromStream` after a manual `101 Switching Protocols` response).

### Notes

- `HttpsShouldWork` is intentionally left to #12058.
- The `http://10.255.255.1` cancellation/timeout tests deliberately use an unroutable address (not the public internet) and are unchanged.
- Cosmetic external hostnames that were never actually contacted (`CancelRequestViaProxy`'s base address behind a dead proxy, and `DisallowAutoRedirect`'s redirect target) were pointed at `localhost`.

The new server logic (HTTP, HTTPS, mutual-TLS echo, and WebSocket echo) was verified end-to-end against `HttpClient` and `ClientWebSocket` on desktop .NET.
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 10, 2026
@jonathanpeppers

Copy link
Copy Markdown
Member

/backport to release/10.0.1xx

@github-actions github-actions Bot unlocked this conversation Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0.1xx (link to workflow run)

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

@jonathanpeppers backporting to release/10.0.1xx failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git cherry-pick bef2665f349676bec98143a1285c97533236a75b

Auto-merging tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
CONFLICT (content): Merge conflict in tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
Auto-merging tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
CONFLICT (content): Merge conflict in tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
Auto-merging tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs
Auto-merging tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
CONFLICT (content): Merge conflict in tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
error: could not apply bef2665f3... [tests] Use local servers for networking tests (#12022)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"


$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch

Applying: [tests] Use local servers for networking tests
Using index info to reconstruct a base tree...
M	tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
M	tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
A	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidHandlerTestBase.cs
M	tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
Falling back to patching base and 3-way merge...
Auto-merging tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
Auto-merging tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
CONFLICT (content): Merge conflict in tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
Auto-merging tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs
CONFLICT (content): Merge conflict in tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs
Auto-merging tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
CONFLICT (content): Merge conflict in tests/Mono.Android-Tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidMessageHandlerTests.cs
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 [tests] Use local servers for networking tests
Error: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Nov 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

flaky-tests ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants