Skip to content

Commit b56b985

Browse files
committed
Read to end when ExecuteServerCommand without receiver
Rename ExecuteServerCommand which return IEnumerable to ExecuteServerEnumerable
1 parent 5e785ff commit b56b985

File tree

12 files changed

+140
-67
lines changed

12 files changed

+140
-67
lines changed

.gitignore

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## Ignore Visual Studio temporary files, build results, and
22
## files generated by popular Visual Studio add-ons.
33
##
4-
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
4+
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
55

66
# User-specific files
77
*.rsuser
@@ -29,14 +29,11 @@ x86/
2929
bld/
3030
[Bb]in/
3131
[Oo]bj/
32-
[Oo]ut/
3332
[Ll]og/
3433
#[Ll]ogs/
3534

3635
# Visual Studio 2015/2017 cache/options directory
3736
.vs/
38-
# JetBrains Rider options directory
39-
.idea/
4037
# Uncomment if you have tasks that create the project's static files in wwwroot
4138
#wwwroot/
4239

@@ -85,6 +82,8 @@ StyleCopReport.xml
8582
*.pgc
8683
*.pgd
8784
*.rsp
85+
# but not Directory.Build.rsp, as it configures directory-level build defaults
86+
!Directory.Build.rsp
8887
*.sbr
8988
*.tlb
9089
*.tli
@@ -93,6 +92,7 @@ StyleCopReport.xml
9392
*.tmp_proj
9493
*_wpftmp.csproj
9594
*.log
95+
*.tlog
9696
*.vspscc
9797
*.vssscc
9898
.builds
@@ -296,6 +296,17 @@ node_modules/
296296
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
297297
*.vbw
298298

299+
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
300+
*.vbp
301+
302+
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
303+
*.dsw
304+
*.dsp
305+
306+
# Visual Studio 6 technical files
307+
*.ncb
308+
*.aps
309+
299310
# Visual Studio LightSwitch build output
300311
**/*.HTMLClient/GeneratedArtifacts
301312
**/*.DesktopClient/GeneratedArtifacts
@@ -352,6 +363,9 @@ ASALocalRun/
352363
# Local History for Visual Studio
353364
.localhistory/
354365

366+
# Visual Studio History (VSHistory) files
367+
.vshistory/
368+
355369
# BeatPulse healthcheck temp database
356370
healthchecksdb
357371

@@ -363,3 +377,24 @@ MigrationBackup/
363377

364378
# Fody - auto-generated XML schema
365379
FodyWeavers.xsd
380+
381+
# VS Code files for those working on multiple tools
382+
.vscode/*
383+
!.vscode/settings.json
384+
!.vscode/tasks.json
385+
!.vscode/launch.json
386+
!.vscode/extensions.json
387+
*.code-workspace
388+
389+
# Local History for Visual Studio Code
390+
.history/
391+
392+
# Windows Installer files from build outputs
393+
*.cab
394+
*.msi
395+
*.msix
396+
*.msm
397+
*.msp
398+
399+
# JetBrains Rider
400+
*.sln.iml

AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4+
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
45
<LangVersion>latest</LangVersion>
56
<NoWarn>$(NoWarn);CS1591</NoWarn>
67
</PropertyGroup>
@@ -19,13 +20,13 @@
1920
</Choose>
2021

2122
<ItemGroup>
22-
<PackageReference Include="coverlet.msbuild" Version="6.0.2" PrivateAssets="all">
23+
<PackageReference Include="coverlet.msbuild" Version="6.0.3" PrivateAssets="all">
2324
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2425
</PackageReference>
25-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
26+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
2627
<PackageReference Include="NSubstitute" Version="5.3.0" />
2728
<PackageReference Include="xunit" Version="2.9.2" />
28-
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" PrivateAssets="all">
29+
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0" PrivateAssets="all">
2930
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3031
</PackageReference>
3132
</ItemGroup>

AdvancedSharpAdbClient.Tests/Dummys/DummyAdbClient.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ public void ExecuteRemoteCommand(string command, DeviceData device) =>
2626
public void ExecuteRemoteCommand(string command, DeviceData device, IShellOutputReceiver receiver, Encoding encoding) =>
2727
ExecuteServerCommand("shell", command, receiver, encoding);
2828

29-
public IEnumerable<string> ExecuteRemoteCommand(string command, DeviceData device, Encoding encoding) =>
30-
ExecuteServerCommand("shell", command, encoding);
29+
public IEnumerable<string> ExecuteRemoteEnumerable(string command, DeviceData device, Encoding encoding) =>
30+
ExecuteServerEnumerable("shell", command, encoding);
3131

3232
public Task ExecuteRemoteCommandAsync(string command, DeviceData device, CancellationToken cancellationToken = default) =>
3333
ExecuteServerCommandAsync("shell", command, cancellationToken);
3434

3535
public Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver receiver, Encoding encoding, CancellationToken cancellationToken = default) =>
3636
ExecuteServerCommandAsync("shell", command, receiver, encoding, cancellationToken);
3737

38-
public IAsyncEnumerable<string> ExecuteRemoteCommandAsync(string command, DeviceData device, Encoding encoding, CancellationToken cancellationToken) =>
39-
ExecuteServerCommandAsync("shell", command, encoding, cancellationToken);
38+
public IAsyncEnumerable<string> ExecuteRemoteEnumerableAsync(string command, DeviceData device, Encoding encoding, CancellationToken cancellationToken) =>
39+
ExecuteServerEnumerableAsync("shell", command, encoding, cancellationToken);
4040

4141
public void ExecuteServerCommand(string target, string command)
4242
{
@@ -89,7 +89,7 @@ public void ExecuteServerCommand(string target, string command, IShellOutputRece
8989
public void ExecuteServerCommand(string target, string command, IAdbSocket socket, IShellOutputReceiver receiver, Encoding encoding) =>
9090
ExecuteServerCommand(target, command, receiver, encoding);
9191

92-
public IEnumerable<string> ExecuteServerCommand(string target, string command, Encoding encoding)
92+
public IEnumerable<string> ExecuteServerEnumerable(string target, string command, Encoding encoding)
9393
{
9494
StringBuilder requestBuilder = new();
9595
if (!StringExtensions.IsNullOrWhiteSpace(target))
@@ -115,8 +115,8 @@ public IEnumerable<string> ExecuteServerCommand(string target, string command, E
115115
}
116116
}
117117

118-
public IEnumerable<string> ExecuteServerCommand(string target, string command, IAdbSocket socket, Encoding encoding) =>
119-
ExecuteServerCommand(target, command, encoding);
118+
public IEnumerable<string> ExecuteServerEnumerable(string target, string command, IAdbSocket socket, Encoding encoding) =>
119+
ExecuteServerEnumerable(target, command, encoding);
120120

121121
public async Task ExecuteServerCommandAsync(string target, string command, CancellationToken cancellationToken = default)
122122
{
@@ -171,7 +171,7 @@ public async Task ExecuteServerCommandAsync(string target, string command, IShel
171171
public Task ExecuteServerCommandAsync(string target, string command, IAdbSocket socket, IShellOutputReceiver receiver, Encoding encoding, CancellationToken cancellationToken) =>
172172
ExecuteServerCommandAsync(target, command, receiver, encoding, cancellationToken);
173173

174-
public async IAsyncEnumerable<string> ExecuteServerCommandAsync(string target, string command, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken)
174+
public async IAsyncEnumerable<string> ExecuteServerEnumerableAsync(string target, string command, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken)
175175
{
176176
StringBuilder requestBuilder = new();
177177
if (!StringExtensions.IsNullOrWhiteSpace(target))
@@ -197,8 +197,8 @@ public async IAsyncEnumerable<string> ExecuteServerCommandAsync(string target, s
197197
}
198198
}
199199

200-
public IAsyncEnumerable<string> ExecuteServerCommandAsync(string target, string command, IAdbSocket socket, Encoding encoding, CancellationToken cancellationToken = default) =>
201-
ExecuteServerCommandAsync(target, command, socket, encoding, cancellationToken);
200+
public IAsyncEnumerable<string> ExecuteServerEnumerableAsync(string target, string command, IAdbSocket socket, Encoding encoding, CancellationToken cancellationToken = default) =>
201+
ExecuteServerEnumerableAsync(target, command, socket, encoding, cancellationToken);
202202

203203
#region Not Implemented
204204

AdvancedSharpAdbClient.Tests/Extensions/AdbClientExtensionsTests.Async.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public async Task ExecuteServerCommandAsyncTest()
4444
Assert.Equal(default, x.ArgAt<CancellationToken>(5));
4545
return Task.CompletedTask;
4646
});
47-
_ = client.ExecuteServerCommandAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<Encoding>(), Arg.Any<CancellationToken>())
47+
_ = client.ExecuteServerEnumerableAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<Encoding>(), Arg.Any<CancellationToken>())
4848
.Returns(x =>
4949
{
5050
Assert.Equal(target, x.ArgAt<string>(0));
@@ -53,7 +53,7 @@ public async Task ExecuteServerCommandAsyncTest()
5353
Assert.Equal(default, x.ArgAt<CancellationToken>(3));
5454
return result.AsEnumerableAsync(x.ArgAt<CancellationToken>(3));
5555
});
56-
_ = client.ExecuteServerCommandAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IAdbSocket>(), Arg.Any<Encoding>(), Arg.Any<CancellationToken>())
56+
_ = client.ExecuteServerEnumerableAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IAdbSocket>(), Arg.Any<Encoding>(), Arg.Any<CancellationToken>())
5757
.Returns(x =>
5858
{
5959
Assert.Equal(target, x.ArgAt<string>(0));
@@ -70,8 +70,8 @@ public async Task ExecuteServerCommandAsyncTest()
7070
await client.ExecuteServerCommandAsync(target, command, socket, predicate);
7171
await client.ExecuteServerCommandAsync(target, command, predicate, encoding);
7272
await client.ExecuteServerCommandAsync(target, command, socket, predicate, encoding);
73-
Assert.Equal(result, await AdbClientExtensions.ExecuteServerCommandAsync(client, target, command).ToListAsync());
74-
Assert.Equal(result, await AdbClientExtensions.ExecuteServerCommandAsync(client, target, command, socket).ToListAsync());
73+
Assert.Equal(result, await client.ExecuteServerEnumerableAsync(target, command).ToListAsync());
74+
Assert.Equal(result, await client.ExecuteServerEnumerableAsync(target, command, socket).ToListAsync());
7575
}
7676

7777
[Fact]
@@ -95,7 +95,7 @@ public async Task ExecuteRemoteCommandAsyncTest()
9595
Assert.Equal(default, x.ArgAt<CancellationToken>(4));
9696
return Task.CompletedTask;
9797
});
98-
_ = client.ExecuteRemoteCommandAsync(Arg.Any<string>(), device, Arg.Any<Encoding>(), Arg.Any<CancellationToken>())
98+
_ = client.ExecuteRemoteEnumerableAsync(Arg.Any<string>(), device, Arg.Any<Encoding>(), Arg.Any<CancellationToken>())
9999
.Returns(x =>
100100
{
101101
Assert.Equal(command, x.ArgAt<string>(0));
@@ -108,7 +108,7 @@ public async Task ExecuteRemoteCommandAsyncTest()
108108
await client.ExecuteRemoteCommandAsync(command, device, receiver);
109109
await client.ExecuteRemoteCommandAsync(command, device, predicate);
110110
await client.ExecuteRemoteCommandAsync(command, device, predicate, encoding);
111-
Assert.Equal(result, await AdbClientExtensions.ExecuteRemoteCommandAsync(client, command, device).ToListAsync());
111+
Assert.Equal(result, await client.ExecuteRemoteEnumerableAsync(command, device).ToListAsync());
112112
}
113113

114114
[Fact]

AdvancedSharpAdbClient.Tests/Extensions/AdbClientExtensionsTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ public void ExecuteServerCommandTest()
4141
Assert.Equal(receiver, x.ArgAt<IShellOutputReceiver>(3));
4242
Assert.Equal(encoding, x.ArgAt<Encoding>(4));
4343
});
44-
_ = client.ExecuteServerCommand(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<Encoding>())
44+
_ = client.ExecuteServerEnumerable(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<Encoding>())
4545
.Returns(x =>
4646
{
4747
Assert.Equal(target, x.ArgAt<string>(0));
4848
Assert.Equal(command, x.ArgAt<string>(1));
4949
Assert.Equal(encoding, x.ArgAt<Encoding>(2));
5050
return result;
5151
});
52-
_ = client.ExecuteServerCommand(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IAdbSocket>(), Arg.Any<Encoding>())
52+
_ = client.ExecuteServerEnumerable(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<IAdbSocket>(), Arg.Any<Encoding>())
5353
.Returns(x =>
5454
{
5555
Assert.Equal(target, x.ArgAt<string>(0));
@@ -65,8 +65,8 @@ public void ExecuteServerCommandTest()
6565
client.ExecuteServerCommand(target, command, socket, predicate);
6666
client.ExecuteServerCommand(target, command, predicate, encoding);
6767
client.ExecuteServerCommand(target, command, socket, predicate, encoding);
68-
Assert.Equal(result, AdbClientExtensions.ExecuteServerCommand(client, target, command));
69-
Assert.Equal(result, AdbClientExtensions.ExecuteServerCommand(client, target, command, socket));
68+
Assert.Equal(result, client.ExecuteServerEnumerable(target, command));
69+
Assert.Equal(result, client.ExecuteServerEnumerable(target, command, socket));
7070
}
7171

7272
[Fact]
@@ -88,7 +88,7 @@ public void ExecuteRemoteCommandTest()
8888
Assert.Equal(receiver, x.ArgAt<IShellOutputReceiver>(2));
8989
Assert.Equal(encoding, x.ArgAt<Encoding>(3));
9090
});
91-
_ = client.ExecuteRemoteCommand(Arg.Any<string>(), device, Arg.Any<Encoding>())
91+
_ = client.ExecuteRemoteEnumerable(Arg.Any<string>(), device, Arg.Any<Encoding>())
9292
.Returns(x =>
9393
{
9494
Assert.Equal(command, x.ArgAt<string>(0));
@@ -100,7 +100,7 @@ public void ExecuteRemoteCommandTest()
100100
client.ExecuteRemoteCommand(command, device, receiver);
101101
client.ExecuteRemoteCommand(command, device, predicate);
102102
client.ExecuteRemoteCommand(command, device, predicate, encoding);
103-
Assert.Equal(result, AdbClientExtensions.ExecuteRemoteCommand(client, command, device));
103+
Assert.Equal(result, client.ExecuteRemoteEnumerable(command, device));
104104
}
105105

106106
[Fact]

AdvancedSharpAdbClient/AdbClient.Async.cs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,29 @@ public virtual async Task ExecuteServerCommandAsync(string target, string comman
178178

179179
await socket.SendAdbRequestAsync(request.ToString(), cancellationToken);
180180
await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false);
181+
182+
try
183+
{
184+
using StreamReader reader = new(socket.GetShellStream());
185+
// Previously, we would loop while reader.Peek() >= 0. Turns out that this would
186+
// break too soon in certain cases (about every 10 loops, so it appears to be a timing
187+
// issue). Checking for reader.ReadLine() to return null appears to be much more robust
188+
// -- one of the integration test fetches output 1000 times and found no truncations.
189+
while (!cancellationToken.IsCancellationRequested)
190+
{
191+
if (await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false) == null) { break; }
192+
}
193+
}
194+
catch (Exception e)
195+
{
196+
// If a cancellation was requested, this main loop is interrupted with an exception
197+
// because the socket is closed. In that case, we don't need to throw a ShellCommandUnresponsiveException.
198+
// In all other cases, something went wrong, and we want to report it to the user.
199+
if (!cancellationToken.IsCancellationRequested)
200+
{
201+
throw new ShellCommandUnresponsiveException(e);
202+
}
203+
}
181204
}
182205

183206
/// <inheritdoc/>
@@ -258,18 +281,18 @@ public async Task ExecuteRemoteCommandAsync(string command, DeviceData device, I
258281

259282
#if COMP_NETSTANDARD2_1
260283
/// <inheritdoc/>
261-
public async IAsyncEnumerable<string> ExecuteServerCommandAsync(string target, string command, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default)
284+
public async IAsyncEnumerable<string> ExecuteServerEnumerableAsync(string target, string command, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default)
262285
{
263286
ExceptionExtensions.ThrowIfNull(encoding);
264287
using IAdbSocket socket = CreateAdbSocket();
265-
await foreach (string? line in ExecuteServerCommandAsync(target, command, socket, encoding, cancellationToken).ConfigureAwait(false))
288+
await foreach (string? line in ExecuteServerEnumerableAsync(target, command, socket, encoding, cancellationToken).ConfigureAwait(false))
266289
{
267290
yield return line;
268291
}
269292
}
270293

271294
/// <inheritdoc/>
272-
public virtual async IAsyncEnumerable<string> ExecuteServerCommandAsync(string target, string command, IAdbSocket socket, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default)
295+
public virtual async IAsyncEnumerable<string> ExecuteServerEnumerableAsync(string target, string command, IAdbSocket socket, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default)
273296
{
274297
ExceptionExtensions.ThrowIfNull(encoding);
275298

@@ -311,15 +334,15 @@ public virtual async IAsyncEnumerable<string> ExecuteServerCommandAsync(string t
311334
}
312335

313336
/// <inheritdoc/>
314-
public async IAsyncEnumerable<string> ExecuteRemoteCommandAsync(string command, DeviceData device, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default)
337+
public async IAsyncEnumerable<string> ExecuteRemoteEnumerableAsync(string command, DeviceData device, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default)
315338
{
316339
EnsureDevice(device);
317340
ExceptionExtensions.ThrowIfNull(encoding);
318341

319342
using IAdbSocket socket = CreateAdbSocket();
320343
await socket.SetDeviceAsync(device, cancellationToken);
321344

322-
await foreach (string? line in ExecuteServerCommandAsync("shell", command, socket, encoding, cancellationToken).ConfigureAwait(false))
345+
await foreach (string? line in ExecuteServerEnumerableAsync("shell", command, socket, encoding, cancellationToken).ConfigureAwait(false))
323346
{
324347
yield return line;
325348
}

0 commit comments

Comments
 (0)