Skip to content

Commit 798b585

Browse files
rmarinhoCopilot
andcommitted
Simplify port API: keep only AdbPortSpec overloads
Remove string and int convenience overloads per @jonathanpeppers review. The strongly-typed AdbPortSpec is now the only API surface for ReversePortAsync and RemoveReversePortAsync. Removed ValidatePort helper and RS0026/RS0027 suppressions (no longer needed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 00dc5ff commit 798b585

4 files changed

Lines changed: 18 additions & 163 deletions

File tree

src/Xamarin.Android.Tools.AndroidSdk/PublicAPI/net10.0/PublicAPI.Unshipped.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,4 @@ static Xamarin.Android.Tools.AdbPortSpec.TryParse(string! socketSpec) -> Xamarin
200200
virtual Xamarin.Android.Tools.AdbRunner.ListReversePortsAsync(string! serial, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Xamarin.Android.Tools.AdbPortRule!>!>!
201201
virtual Xamarin.Android.Tools.AdbRunner.RemoveAllReversePortsAsync(string! serial, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
202202
virtual Xamarin.Android.Tools.AdbRunner.RemoveReversePortAsync(string! serial, Xamarin.Android.Tools.AdbPortSpec! remote, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
203-
virtual Xamarin.Android.Tools.AdbRunner.RemoveReversePortAsync(string! serial, int remotePort, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
204-
virtual Xamarin.Android.Tools.AdbRunner.RemoveReversePortAsync(string! serial, string! remote, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
205203
virtual Xamarin.Android.Tools.AdbRunner.ReversePortAsync(string! serial, Xamarin.Android.Tools.AdbPortSpec! remote, Xamarin.Android.Tools.AdbPortSpec! local, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
206-
virtual Xamarin.Android.Tools.AdbRunner.ReversePortAsync(string! serial, int remotePort, int localPort, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
207-
virtual Xamarin.Android.Tools.AdbRunner.ReversePortAsync(string! serial, string! remote, string! local, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!

src/Xamarin.Android.Tools.AndroidSdk/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,4 @@ static Xamarin.Android.Tools.AdbPortSpec.TryParse(string! socketSpec) -> Xamarin
200200
virtual Xamarin.Android.Tools.AdbRunner.ListReversePortsAsync(string! serial, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Xamarin.Android.Tools.AdbPortRule!>!>!
201201
virtual Xamarin.Android.Tools.AdbRunner.RemoveAllReversePortsAsync(string! serial, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
202202
virtual Xamarin.Android.Tools.AdbRunner.RemoveReversePortAsync(string! serial, Xamarin.Android.Tools.AdbPortSpec! remote, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
203-
virtual Xamarin.Android.Tools.AdbRunner.RemoveReversePortAsync(string! serial, int remotePort, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
204-
virtual Xamarin.Android.Tools.AdbRunner.RemoveReversePortAsync(string! serial, string! remote, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
205203
virtual Xamarin.Android.Tools.AdbRunner.ReversePortAsync(string! serial, Xamarin.Android.Tools.AdbPortSpec! remote, Xamarin.Android.Tools.AdbPortSpec! local, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
206-
virtual Xamarin.Android.Tools.AdbRunner.ReversePortAsync(string! serial, int remotePort, int localPort, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!
207-
virtual Xamarin.Android.Tools.AdbRunner.ReversePortAsync(string! serial, string! remote, string! local, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task!

src/Xamarin.Android.Tools.AndroidSdk/Runners/AdbRunner.cs

Lines changed: 13 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -244,99 +244,48 @@ public async Task StopEmulatorAsync (string serial, CancellationToken cancellati
244244
return null;
245245
}
246246

247-
#pragma warning disable RS0026, RS0027 // Multiple overloads with optional parameters are intentional for API convenience
248247
/// <summary>
249-
/// Sets up reverse port forwarding from the device to the host via
250-
/// 'adb -s &lt;serial&gt; reverse &lt;remote&gt; &lt;local&gt;'.
251-
/// Supports any socket spec accepted by adb (tcp:PORT, localabstract:NAME, etc.).
252-
/// This is the core overload; the typed and int convenience overloads delegate here.
248+
/// Sets up reverse port forwarding via 'adb -s &lt;serial&gt; reverse &lt;remote&gt; &lt;local&gt;'.
253249
/// </summary>
254250
/// <param name="serial">Device serial number.</param>
255-
/// <param name="remote">Remote (device-side) socket spec, e.g. "tcp:5000" or "localabstract:foo".</param>
256-
/// <param name="local">Local (host-side) socket spec, e.g. "tcp:5000".</param>
251+
/// <param name="remote">Remote (device-side) port spec.</param>
252+
/// <param name="local">Local (host-side) port spec.</param>
257253
/// <param name="cancellationToken">Cancellation token.</param>
258-
public virtual async Task ReversePortAsync (string serial, string remote, string local, CancellationToken cancellationToken = default)
254+
public virtual async Task ReversePortAsync (string serial, AdbPortSpec remote, AdbPortSpec local, CancellationToken cancellationToken = default)
259255
{
260256
if (string.IsNullOrWhiteSpace (serial))
261257
throw new ArgumentException ("Serial must not be empty.", nameof (serial));
262-
if (string.IsNullOrWhiteSpace (remote))
263-
throw new ArgumentException ("Remote socket spec must not be empty.", nameof (remote));
264-
if (string.IsNullOrWhiteSpace (local))
265-
throw new ArgumentException ("Local socket spec must not be empty.", nameof (local));
266-
267-
var psi = ProcessUtils.CreateProcessStartInfo (adbPath, "-s", serial, "reverse", remote, local);
268-
using var stderr = new StringWriter ();
269-
var exitCode = await ProcessUtils.StartProcess (psi, null, stderr, cancellationToken, environmentVariables).ConfigureAwait (false);
270-
ProcessUtils.ThrowIfFailed (exitCode, $"adb -s {serial} reverse {remote} {local}", stderr);
271-
}
272-
273-
/// <summary>
274-
/// Typed overload: sets up reverse port forwarding using <see cref="AdbPortSpec"/> values.
275-
/// </summary>
276-
public virtual Task ReversePortAsync (string serial, AdbPortSpec remote, AdbPortSpec local, CancellationToken cancellationToken = default)
277-
{
278258
if (remote is null)
279259
throw new ArgumentNullException (nameof (remote));
280260
if (local is null)
281261
throw new ArgumentNullException (nameof (local));
282-
return ReversePortAsync (serial, remote.ToSocketSpec (), local.ToSocketSpec (), cancellationToken);
283-
}
284262

285-
/// <summary>
286-
/// TCP convenience overload: sets up reverse port forwarding via
287-
/// 'adb -s &lt;serial&gt; reverse tcp:&lt;remotePort&gt; tcp:&lt;localPort&gt;'.
288-
/// </summary>
289-
public virtual Task ReversePortAsync (string serial, int remotePort, int localPort, CancellationToken cancellationToken = default)
290-
{
291-
ValidatePort (remotePort, nameof (remotePort));
292-
ValidatePort (localPort, nameof (localPort));
293-
return ReversePortAsync (serial, new AdbPortSpec (AdbProtocol.Tcp, remotePort), new AdbPortSpec (AdbProtocol.Tcp, localPort), cancellationToken);
263+
var psi = ProcessUtils.CreateProcessStartInfo (adbPath, "-s", serial, "reverse", remote.ToSocketSpec (), local.ToSocketSpec ());
264+
using var stderr = new StringWriter ();
265+
var exitCode = await ProcessUtils.StartProcess (psi, null, stderr, cancellationToken, environmentVariables).ConfigureAwait (false);
266+
ProcessUtils.ThrowIfFailed (exitCode, $"adb -s {serial} reverse {remote} {local}", stderr);
294267
}
295-
#pragma warning restore RS0026, RS0027
296268

297-
#pragma warning disable RS0026, RS0027 // Multiple overloads with optional parameters are intentional for API convenience
298269
/// <summary>
299270
/// Removes a specific reverse port forwarding rule via
300271
/// 'adb -s &lt;serial&gt; reverse --remove &lt;remote&gt;'.
301-
/// Supports any socket spec accepted by adb.
302272
/// </summary>
303273
/// <param name="serial">Device serial number.</param>
304-
/// <param name="remote">Remote (device-side) socket spec to remove, e.g. "tcp:5000".</param>
274+
/// <param name="remote">Remote (device-side) port spec to remove.</param>
305275
/// <param name="cancellationToken">Cancellation token.</param>
306-
public virtual async Task RemoveReversePortAsync (string serial, string remote, CancellationToken cancellationToken = default)
276+
public virtual async Task RemoveReversePortAsync (string serial, AdbPortSpec remote, CancellationToken cancellationToken = default)
307277
{
308278
if (string.IsNullOrWhiteSpace (serial))
309279
throw new ArgumentException ("Serial must not be empty.", nameof (serial));
310-
if (string.IsNullOrWhiteSpace (remote))
311-
throw new ArgumentException ("Remote socket spec must not be empty.", nameof (remote));
280+
if (remote is null)
281+
throw new ArgumentNullException (nameof (remote));
312282

313-
var psi = ProcessUtils.CreateProcessStartInfo (adbPath, "-s", serial, "reverse", "--remove", remote);
283+
var psi = ProcessUtils.CreateProcessStartInfo (adbPath, "-s", serial, "reverse", "--remove", remote.ToSocketSpec ());
314284
using var stderr = new StringWriter ();
315285
var exitCode = await ProcessUtils.StartProcess (psi, null, stderr, cancellationToken, environmentVariables).ConfigureAwait (false);
316286
ProcessUtils.ThrowIfFailed (exitCode, $"adb -s {serial} reverse --remove {remote}", stderr);
317287
}
318288

319-
/// <summary>
320-
/// Typed overload: removes a specific reverse port forwarding rule using <see cref="AdbPortSpec"/>.
321-
/// </summary>
322-
public virtual Task RemoveReversePortAsync (string serial, AdbPortSpec remote, CancellationToken cancellationToken = default)
323-
{
324-
if (remote is null)
325-
throw new ArgumentNullException (nameof (remote));
326-
return RemoveReversePortAsync (serial, remote.ToSocketSpec (), cancellationToken);
327-
}
328-
329-
/// <summary>
330-
/// TCP convenience overload: removes a specific reverse port forwarding rule via
331-
/// 'adb -s &lt;serial&gt; reverse --remove tcp:&lt;remotePort&gt;'.
332-
/// </summary>
333-
public virtual Task RemoveReversePortAsync (string serial, int remotePort, CancellationToken cancellationToken = default)
334-
{
335-
ValidatePort (remotePort, nameof (remotePort));
336-
return RemoveReversePortAsync (serial, new AdbPortSpec (AdbProtocol.Tcp, remotePort), cancellationToken);
337-
}
338-
#pragma warning restore RS0026, RS0027
339-
340289
/// <summary>
341290
/// Removes all reverse port forwarding rules via
342291
/// 'adb -s &lt;serial&gt; reverse --remove-all'.
@@ -400,12 +349,6 @@ internal static IReadOnlyList<AdbPortRule> ParseReverseListOutput (IEnumerable<s
400349
return rules;
401350
}
402351

403-
static void ValidatePort (int port, string paramName)
404-
{
405-
if (port <= 0 || port > 65535)
406-
throw new ArgumentOutOfRangeException (paramName, port, "Port must be between 1 and 65535.");
407-
}
408-
409352
/// <summary>
410353
/// Parses the output lines from 'adb devices -l'.
411354
/// Accepts an <see cref="IEnumerable{T}"/> to avoid allocating a joined string.

tests/Xamarin.Android.Tools.AndroidSdk-Tests/AdbRunnerTests.cs

Lines changed: 5 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,71 +1001,19 @@ public void ReversePortAsync_EmptySerial_ThrowsArgumentException ()
10011001
{
10021002
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
10031003
Assert.ThrowsAsync<System.ArgumentException> (
1004-
async () => await runner.ReversePortAsync ("", 5000, 5000));
1004+
async () => await runner.ReversePortAsync ("", new AdbPortSpec (AdbProtocol.Tcp, 5000), new AdbPortSpec (AdbProtocol.Tcp, 5000)));
10051005
}
10061006

10071007
[Test]
1008-
public void ReversePortAsync_ZeroRemotePort_ThrowsArgumentOutOfRange ()
1009-
{
1010-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1011-
Assert.ThrowsAsync<System.ArgumentOutOfRangeException> (
1012-
async () => await runner.ReversePortAsync ("emulator-5554", 0, 5000));
1013-
}
1014-
1015-
[Test]
1016-
public void ReversePortAsync_NegativeLocalPort_ThrowsArgumentOutOfRange ()
1017-
{
1018-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1019-
Assert.ThrowsAsync<System.ArgumentOutOfRangeException> (
1020-
async () => await runner.ReversePortAsync ("emulator-5554", 5000, -1));
1021-
}
1022-
1023-
[Test]
1024-
public void ReversePortAsync_PortAbove65535_ThrowsArgumentOutOfRange ()
1025-
{
1026-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1027-
Assert.ThrowsAsync<System.ArgumentOutOfRangeException> (
1028-
async () => await runner.ReversePortAsync ("emulator-5554", 70000, 5000));
1029-
}
1030-
1031-
// --- ReversePortAsync string overload validation tests ---
1032-
1033-
[Test]
1034-
public void ReversePortAsync_String_EmptySerial_ThrowsArgumentException ()
1035-
{
1036-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1037-
Assert.ThrowsAsync<System.ArgumentException> (
1038-
async () => await runner.ReversePortAsync ("", "tcp:5000", "tcp:5000"));
1039-
}
1040-
1041-
[Test]
1042-
public void ReversePortAsync_String_EmptyRemote_ThrowsArgumentException ()
1043-
{
1044-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1045-
Assert.ThrowsAsync<System.ArgumentException> (
1046-
async () => await runner.ReversePortAsync ("emulator-5554", "", "tcp:5000"));
1047-
}
1048-
1049-
[Test]
1050-
public void ReversePortAsync_String_EmptyLocal_ThrowsArgumentException ()
1051-
{
1052-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1053-
Assert.ThrowsAsync<System.ArgumentException> (
1054-
async () => await runner.ReversePortAsync ("emulator-5554", "tcp:5000", ""));
1055-
}
1056-
1057-
// --- ReversePortAsync AdbPortSpec overload validation tests ---
1058-
1059-
[Test]
1060-
public void ReversePortAsync_AdbPortSpec_NullRemote_ThrowsArgumentNull ()
1008+
public void ReversePortAsync_NullRemote_ThrowsArgumentNull ()
10611009
{
10621010
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
10631011
Assert.ThrowsAsync<System.ArgumentNullException> (
10641012
async () => await runner.ReversePortAsync ("emulator-5554", (AdbPortSpec) null!, new AdbPortSpec (AdbProtocol.Tcp, 5000)));
10651013
}
10661014

10671015
[Test]
1068-
public void ReversePortAsync_AdbPortSpec_NullLocal_ThrowsArgumentNull ()
1016+
public void ReversePortAsync_NullLocal_ThrowsArgumentNull ()
10691017
{
10701018
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
10711019
Assert.ThrowsAsync<System.ArgumentNullException> (
@@ -1079,39 +1027,11 @@ public void RemoveReversePortAsync_EmptySerial_ThrowsArgumentException ()
10791027
{
10801028
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
10811029
Assert.ThrowsAsync<System.ArgumentException> (
1082-
async () => await runner.RemoveReversePortAsync ("", 5000));
1083-
}
1084-
1085-
[Test]
1086-
public void RemoveReversePortAsync_ZeroPort_ThrowsArgumentOutOfRange ()
1087-
{
1088-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1089-
Assert.ThrowsAsync<System.ArgumentOutOfRangeException> (
1090-
async () => await runner.RemoveReversePortAsync ("emulator-5554", 0));
1030+
async () => await runner.RemoveReversePortAsync ("", new AdbPortSpec (AdbProtocol.Tcp, 5000)));
10911031
}
10921032

1093-
// --- RemoveReversePortAsync string overload validation tests ---
1094-
1095-
[Test]
1096-
public void RemoveReversePortAsync_String_EmptySerial_ThrowsArgumentException ()
1097-
{
1098-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1099-
Assert.ThrowsAsync<System.ArgumentException> (
1100-
async () => await runner.RemoveReversePortAsync ("", "tcp:5000"));
1101-
}
1102-
1103-
[Test]
1104-
public void RemoveReversePortAsync_String_EmptyRemote_ThrowsArgumentException ()
1105-
{
1106-
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
1107-
Assert.ThrowsAsync<System.ArgumentException> (
1108-
async () => await runner.RemoveReversePortAsync ("emulator-5554", ""));
1109-
}
1110-
1111-
// --- RemoveReversePortAsync AdbPortSpec overload validation tests ---
1112-
11131033
[Test]
1114-
public void RemoveReversePortAsync_AdbPortSpec_NullRemote_ThrowsArgumentNull ()
1034+
public void RemoveReversePortAsync_NullRemote_ThrowsArgumentNull ()
11151035
{
11161036
var runner = new AdbRunner ("/fake/sdk/platform-tools/adb");
11171037
Assert.ThrowsAsync<System.ArgumentNullException> (

0 commit comments

Comments
 (0)