Skip to content

Commit 7c82a28

Browse files
IgorMilavecdrieseng
authored andcommitted
Add unit tests for task-based asynchronous API (#906)
* Fix runtime and culture dependant tests. * Set C# 7.3 in Tests.csproj to limit intellisense's suggestions under different targets * Add SftpClientTest.*Async * Add SftpFileStreamTest_OpenAsync_* * Add SftpFileStreamTest_WriteAsync_* * Add SftpFileStreamTest_ReadAsync_* * Align AppVeyor script with Test project target frameworks
1 parent cce44d3 commit 7c82a28

File tree

42 files changed

+3379
-68
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3379
-68
lines changed

appveyor.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ build:
99

1010
test_script:
1111
- cmd: >-
12-
vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net40\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning"
12+
vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net35\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning"
1313
14-
vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net35\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning"
14+
vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net472\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning"

src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NegativeOne.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public void IsConnectedOnSessionShouldBeInvokedOnce()
9494
}
9595

9696
[TestMethod]
97-
public void SendMessageOnSessionShouldBeInvokedThreeTimes()
97+
public void SendMessageOnSessionShouldBeInvokedOneTime()
9898
{
9999
// allow keep-alive to be sent once
100100
Thread.Sleep(100);

src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ public void Create_ByteArrayAndIndentLevel_IndentLevelLessThanZero()
3737
catch (ArgumentOutOfRangeException ex)
3838
{
3939
Assert.IsNull(ex.InnerException);
40+
#if NETFRAMEWORK
4041
Assert.AreEqual(string.Format("Cannot be less than zero.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message);
42+
#else
43+
Assert.AreEqual(string.Format("Cannot be less than zero. (Parameter '{1}')", Environment.NewLine, ex.ParamName), ex.Message);
44+
#endif
4145
Assert.AreEqual("indentLevel", ex.ParamName);
4246
}
4347
}

src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ protected override void SetupMocks()
5454
.Setup(p => p.SendExecRequest(string.Format("scp -prf {0}", _transformedPath)))
5555
.Returns(false);
5656
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
57+
#if NET35
5758
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
58-
59-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
60-
// an interface, we need to expect this call as well
61-
_pipeStreamMock.Setup(p => p.Close());
59+
#else
60+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
61+
#endif
6262
}
6363

6464
protected override void Arrange()
@@ -106,7 +106,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
106106
[TestMethod]
107107
public void DisposeOnPipeStreamShouldBeInvokedOnce()
108108
{
109+
#if NET35
109110
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
111+
#else
112+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
113+
#endif
110114
}
111115

112116
[TestMethod]

src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ protected override void SetupMocks()
5353
_channelSessionMock.InSequence(sequence)
5454
.Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _transformedPath))).Returns(false);
5555
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
56+
#if NET35
5657
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
57-
58-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
59-
// an interface, we need to expect this call as well
60-
_pipeStreamMock.Setup(p => p.Close());
58+
#else
59+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
60+
#endif
6161
}
6262

6363
protected override void Arrange()
@@ -105,7 +105,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
105105
[TestMethod]
106106
public void DisposeOnPipeStreamShouldBeInvokedOnce()
107107
{
108+
#if NET35
108109
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
110+
#else
111+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
112+
#endif
109113
}
110114

111115
[TestMethod]

src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ protected override void SetupMocks()
5454
.Setup(p => p.SendExecRequest(string.Format("scp -f {0}", _transformedPath)))
5555
.Returns(false);
5656
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
57+
#if NET35
5758
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
58-
59-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
60-
// an interface, we need to expect this call as well
61-
_pipeStreamMock.Setup(p => p.Close());
59+
#else
60+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
61+
#endif
6262
}
6363

6464
protected override void Arrange()
@@ -116,7 +116,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
116116
[TestMethod]
117117
public void DisposeOnPipeStreamShouldBeInvokedOnce()
118118
{
119+
#if NET35
119120
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
121+
#else
122+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
123+
#endif
120124
}
121125

122126
[TestMethod]

src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ protected override void SetupMocks()
5353
.Setup(p => p.SendExecRequest(string.Format("scp -r -p -d -t {0}", _transformedPath)))
5454
.Returns(false);
5555
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
56+
#if NET35
5657
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
57-
58-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
59-
// an interface, we need to expect this call as well
60-
_pipeStreamMock.Setup(p => p.Close());
58+
#else
59+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
60+
#endif
6161
}
6262

6363
protected override void Arrange()
@@ -105,7 +105,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
105105
[TestMethod]
106106
public void DisposeOnPipeStreamShouldBeInvokedOnce()
107107
{
108+
#if NET35
108109
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
110+
#else
111+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
112+
#endif
109113
}
110114

111115
[TestMethod]

src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ protected override void SetupMocks()
5959
.Setup(p => p.SendExecRequest(string.Format("scp -t -d {0}", _transformedPath)))
6060
.Returns(false);
6161
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
62+
#if NET35
6263
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
63-
64-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
65-
// an interface, we need to expect this call as well
66-
_pipeStreamMock.Setup(p => p.Close());
67-
}
64+
#else
65+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
66+
#endif
67+
}
6868

6969
protected override void Arrange()
7070
{
@@ -122,7 +122,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
122122
[TestMethod]
123123
public void DisposeOnPipeStreamShouldBeInvokedOnce()
124124
{
125+
#if NET35
125126
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
127+
#else
128+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
129+
#endif
126130
}
127131

128132
[TestMethod]

src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ protected override void SetupMocks()
8484
p => p.SendData(It.Is<byte[]>(b => b.SequenceEqual(new byte[] {0}))));
8585
_pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
8686
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
87+
#if NET35
8788
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
88-
89-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
90-
// an interface, we need to expect this call as well
91-
_pipeStreamMock.Setup(p => p.Close());
89+
#else
90+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
91+
#endif
9292
}
9393

9494
protected override void Arrange()
@@ -134,7 +134,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
134134
[TestMethod]
135135
public void DisposeOnPipeStreamShouldBeInvokedOnce()
136136
{
137+
#if NET35
137138
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
139+
#else
140+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
141+
#endif
138142
}
139143

140144
[TestMethod]

src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ protected override void SetupMocks()
5757
.Setup(p => p.SendExecRequest(string.Format("scp -t -d {0}", _transformedPath)))
5858
.Returns(false);
5959
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
60+
#if NET35
6061
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
61-
62-
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
63-
// an interface, we need to expect this call as well
64-
_pipeStreamMock.Setup(p => p.Close());
62+
#else
63+
_pipeStreamMock.InSequence(sequence).Setup(p => p.Close());
64+
#endif
6565
}
6666

6767
protected override void Arrange()
@@ -119,7 +119,11 @@ public void DisposeOnChannelShouldBeInvokedOnce()
119119
[TestMethod]
120120
public void DisposeOnPipeStreamShouldBeInvokedOnce()
121121
{
122+
#if NET35
122123
_pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
124+
#else
125+
_pipeStreamMock.Verify(p => p.Close(), Times.Once);
126+
#endif
123127
}
124128

125129
[TestMethod]
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#if FEATURE_TAP
2+
using System;
3+
using System.Threading.Tasks;
4+
using Microsoft.VisualStudio.TestTools.UnitTesting;
5+
using Moq;
6+
using Renci.SshNet.Sftp;
7+
8+
namespace Renci.SshNet.Tests.Classes.Sftp
9+
{
10+
public abstract class SftpFileStreamAsyncTestBase
11+
{
12+
internal Mock<ISftpSession> SftpSessionMock;
13+
protected MockSequence MockSequence;
14+
15+
protected virtual Task ArrangeAsync()
16+
{
17+
SetupData();
18+
CreateMocks();
19+
SetupMocks();
20+
return Task.CompletedTask;
21+
}
22+
23+
protected virtual void SetupData()
24+
{
25+
MockSequence = new MockSequence();
26+
}
27+
28+
protected abstract void SetupMocks();
29+
30+
private void CreateMocks()
31+
{
32+
SftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
33+
}
34+
35+
[TestInitialize]
36+
public async Task SetUpAsync()
37+
{
38+
await ArrangeAsync();
39+
await ActAsync();
40+
}
41+
42+
protected abstract Task ActAsync();
43+
44+
protected byte[] GenerateRandom(int length)
45+
{
46+
return GenerateRandom(length, new Random());
47+
}
48+
49+
protected byte[] GenerateRandom(int length, Random random)
50+
{
51+
var buffer = new byte[length];
52+
random.NextBytes(buffer);
53+
return buffer;
54+
}
55+
56+
protected byte[] GenerateRandom(uint length)
57+
{
58+
return GenerateRandom(length, new Random());
59+
}
60+
61+
protected byte[] GenerateRandom(uint length, Random random)
62+
{
63+
var buffer = new byte[length];
64+
random.NextBytes(buffer);
65+
return buffer;
66+
}
67+
}
68+
}
69+
#endif
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#if FEATURE_TAP
2+
using System;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
using Microsoft.VisualStudio.TestTools.UnitTesting;
6+
using Renci.SshNet.Sftp;
7+
8+
namespace Renci.SshNet.Tests.Classes.Sftp
9+
{
10+
[TestClass]
11+
public class SftpFileStreamTest_OpenAsync_FileAccessInvalid : SftpFileStreamAsyncTestBase
12+
{
13+
private Random _random;
14+
private string _path;
15+
private FileMode _fileMode;
16+
private FileAccess _fileAccess;
17+
private int _bufferSize;
18+
private ArgumentOutOfRangeException _actualException;
19+
20+
protected override void SetupData()
21+
{
22+
base.SetupData();
23+
24+
_random = new Random();
25+
_path = _random.Next().ToString();
26+
_fileMode = FileMode.Open;
27+
_fileAccess = 0;
28+
_bufferSize = _random.Next(5, 1000);
29+
}
30+
31+
protected override void SetupMocks()
32+
{
33+
}
34+
35+
protected override async Task ActAsync()
36+
{
37+
try
38+
{
39+
await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default);
40+
Assert.Fail();
41+
}
42+
catch (ArgumentOutOfRangeException ex)
43+
{
44+
_actualException = ex;
45+
}
46+
}
47+
48+
[TestMethod]
49+
public void CtorShouldHaveThrownArgumentException()
50+
{
51+
Assert.IsNotNull(_actualException);
52+
Assert.IsNull(_actualException.InnerException);
53+
Assert.AreEqual("access", _actualException.ParamName);
54+
}
55+
}
56+
}
57+
#endif

0 commit comments

Comments
 (0)