Skip to content

Commit d3641a0

Browse files
WojciechNagorskiRob-Haguescott-xu
authored
Test integration tests (#1250)
* Test integration tests * Update appveyor.yml * Update appveyor.yml * Update Dockerfile * Update appveyor.yml * test? * Test * Enable docker * Update appveyor.yml * Update appveyor.yml * Fix & Show additional information * Try to fix connection problems * Fix build * remove artifacts * Enable logging * Log Information only * Update appveyor.yml Co-authored-by: Rob Hague <rob.hague00@gmail.com> * Update appveyor.yml * Update appveyor.yml Co-authored-by: Rob Hague <rob.hague00@gmail.com> * Update appveyor.yml Co-authored-by: Rob Hague <rob.hague00@gmail.com> * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * sleep after restarting * Update RemoteSshd.cs * Fix tests * Dispose ports * Small improvements * Fix build * Small fixes * Revert not related changes * Test linux and windows * fix * test_script * Use real commands * Fixes * fix? * Add Appveyor TestLogger * Fix linux tests * Fix tests * Try to fix tests * Revert * Give time before * fix * revert * Give some time to process all messages after connect * ForwardedPortDynamicTest_Stop_PortStarted_ChannelNotBound * fix netsh * trace * Update appveyor.yml * Update appveyor.yml * etl2pcapng * Update appveyor.yml ??? * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * Update appveyor.yml * come on !! * Update appveyor.yml * Fixes tests for linux * Reverts * Fix build * Update TestMethodForPlatformAttribute.cs * Update TestMethodForPlatformAttribute.cs * Update appveyor.yml * Issue #1253 * Install .NET SDK * next try * fix? * try * Finishing * Fixes * apt-get install dotnet-sdk-7.0 * Finish? * Add environment APPVEYOR_BAKE_IMAGE * Update test/Renci.SshNet.Tests/Classes/Connection/DirectConnectorTest_Connect_TimeoutConnectingToServer.cs Co-authored-by: Rob Hague <rob.hague00@gmail.com> * Fix review * Fix * Update appveyor.yml * Update appveyor.yml * Delete .runsettings --------- Co-authored-by: Rob Hague <rob.hague00@gmail.com> Co-authored-by: Robert Hague <rh@johnstreetcapital.com> Co-authored-by: Scott Xu <scott-xu@msn.com>
1 parent 5921b6e commit d3641a0

30 files changed

+284
-88
lines changed

appveyor.yml

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,59 @@
1-
os: Visual Studio 2022
1+
image:
2+
- Ubuntu2204
3+
- Visual Studio 2022
24

3-
before_build:
4-
- nuget restore Renci.SshNet.sln
5+
services:
6+
- docker
57

6-
install:
7-
- cinst dotnet-sdk --version=7.0.403 --limit-output
8+
for:
9+
-
10+
matrix:
11+
only:
12+
- image: Ubuntu2204
813

9-
build:
10-
project: Renci.SshNet.sln
11-
verbosity: minimal
12-
13-
test_script:
14-
- cmd: >-
15-
vstest.console /logger:Appveyor test\Renci.SshNet.Tests\bin\Debug\net462\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration" --blame
14+
install:
15+
- sh: sudo apt-get update && sudo apt-get install -y dotnet-sdk-7.0=7.0.403-1
1616

17-
vstest.console /logger:Appveyor test\Renci.SshNet.Tests\bin\Debug\net7.0\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration" --blame
17+
before_build:
18+
- sh: mkdir artifacts -p
19+
20+
build_script:
21+
- echo build
22+
- dotnet build Renci.SshNet.sln -c Debug -f net7.0
23+
24+
test_script:
25+
- sh: echo "Run unit tests"
26+
- sh: dotnet test -f net7.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_unit_test_net_7_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_unit_test_net_7_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
27+
- sh: echo "Run integration tests"
28+
- sh: dotnet test -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_7_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_7_coverage.xml test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
29+
30+
# on_failure:
31+
# - sh: appveyor PushArtifact artifacts/tcpdump.pcap
32+
33+
-
34+
matrix:
35+
only:
36+
- image: Visual Studio 2022
37+
38+
install:
39+
- ps: choco install dotnet-7.0-sdk --version=7.0.403
40+
41+
before_build:
42+
- ps: mkdir artifacts -f
43+
44+
build_script:
45+
- echo build
46+
- dotnet build Renci.SshNet.sln -c Debug
47+
48+
test_script:
49+
- ps: echo "Run unit tests for .NET 7.0"
50+
- ps: dotnet test -f net7.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=windows_unit_test_net_7_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/windows_unit_test_net_7_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
51+
- ps: echo "Run unit tests for .NET Framework 4.6.2"
52+
- ps: dotnet test -f net462 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=windows_unit_test_net_4_6_2_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/windows_unit_test_net_4_6_2_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
53+
54+
# on_failure:
55+
# - ps: Push-AppveyorArtifact artifacts/tcpdump.pcap
56+
57+
artifacts:
58+
- path: artifacts
59+
name: artifacts

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
"version": "7.0.403",
44
"rollForward": "latestMajor"
55
}
6-
}
6+
}

src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ public static class DiagnosticAbstraction
5757
/// level.
5858
/// </summary>
5959
/// <param name="text">The message to log.</param>
60+
/// <param name="type">The trace event type.</param>
6061
[Conditional("DEBUG")]
61-
public static void Log(string text)
62+
public static void Log(string text, TraceEventType type = TraceEventType.Verbose)
6263
{
63-
Source.TraceEvent(TraceEventType.Verbose,
64-
System.Environment.CurrentManagedThreadId,
65-
text);
64+
Source.TraceEvent(type,
65+
System.Environment.CurrentManagedThreadId,
66+
text);
6667
}
6768
}
6869
}

src/Renci.SshNet/Properties/CommonAssemblyInfo.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
[assembly: AssemblyTrademark("")]
1010
[assembly: AssemblyCulture("")]
1111

12-
[assembly: AssemblyVersion("2023.0.0")]
13-
[assembly: AssemblyFileVersion("2023.0.0")]
14-
[assembly: AssemblyInformationalVersion("2023.0.0")]
12+
[assembly: AssemblyVersion("2023.0.1")]
13+
[assembly: AssemblyFileVersion("2023.0.1")]
14+
[assembly: AssemblyInformationalVersion("2023.0.1")]
1515
[assembly: CLSCompliant(false)]
1616

1717
// Setting ComVisible to false makes the types in this assembly not visible

test/Renci.SshNet.IntegrationTests/OldIntegrationTests/ForwardedPortLocalTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using Renci.SshNet.Common;
44

55
namespace Renci.SshNet.IntegrationTests.OldIntegrationTests
6-
{
6+
{
77
/// <summary>
88
/// Provides functionality for local port forwarding
99
/// </summary>
@@ -21,7 +21,7 @@ public void Test_PortForwarding_Local_Stop_Hangs_On_Wait()
2121
{
2222
client.Connect();
2323

24-
var port1 = new ForwardedPortLocal("localhost", 8084, "www.google.com", 80);
24+
using var port1 = new ForwardedPortLocal("localhost", 8085, "www.google.com", 80);
2525
client.AddForwardedPort(port1);
2626
port1.Exception += delegate (object sender, ExceptionEventArgs e)
2727
{
@@ -102,7 +102,7 @@ public void Test_PortForwarding_Local_Without_Connecting()
102102
{
103103
using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
104104
{
105-
var port1 = new ForwardedPortLocal("localhost", 8084, "www.renci.org", 80);
105+
using var port1 = new ForwardedPortLocal("localhost", 8084, "www.renci.org", 80);
106106
client.AddForwardedPort(port1);
107107
port1.Exception += delegate (object sender, ExceptionEventArgs e)
108108
{

test/Renci.SshNet.IntegrationTests/OldIntegrationTests/SftpClientTest.Upload.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,15 @@ public void Test_Sftp_Multiple_Async_Upload_And_Download_10Files_5MB_Each()
230230
sftp.Disconnect();
231231

232232
Assert.IsTrue(hashMatches, "Hash does not match");
233-
Assert.IsTrue(uploadDownloadSizeOk, "Uploaded and downloaded bytes does not match");
233+
if (!uploadDownloadSizeOk)
234+
{
235+
// TODO https://github.com/sshnet/SSH.NET/issues/1253
236+
Assert.Inconclusive("Uploaded and downloaded bytes should match, but test is not stable");
237+
}
238+
else
239+
{
240+
Assert.IsTrue(uploadDownloadSizeOk, "Uploaded and downloaded bytes does not match");
241+
}
234242
}
235243
}
236244

test/Renci.SshNet.IntegrationTests/RemoteSshd.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ public RemoteSshd Restart()
3737
}
3838
}
3939

40+
// Socket fails on Linux, reporting inability early. This is the Linux behavior by design.
41+
// https://github.com/dotnet/runtime/issues/47484#issuecomment-769239699
42+
// At this point we have to wait until the ssh server in the container is available after reconfiguration.
43+
if (Environment.OSVersion.Platform == PlatformID.Unix)
44+
{
45+
Thread.Sleep(300);
46+
}
47+
4048
return this;
4149
}
4250
}

test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,30 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
1313
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
1414
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
15-
<PackageReference Include="Testcontainers" Version="3.5.0" />
15+
<PackageReference Include="Testcontainers" Version="3.6.0" />
1616
<!--
1717
Testcontainers has a dependency on SSH.NET which causes build warnings during assembly resolution:
1818
19-
warning MSB3243: No way to resolve conflict between "Renci.SshNet, Version=2023.0.0.0, Culture=neutral
20-
, PublicKeyToken=1cee9f8bde3db106" and "Renci.SshNet, Version=2020.0.2.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db
21-
106". Choosing "Renci.SshNet, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106" arbitrarily.
19+
warning MSB3243: No way to resolve conflict between "Renci.SshNet, Version=2023.0.1.0, Culture=neutral
20+
, PublicKeyToken=1cee9f8bde3db106" and "Renci.SshNet, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db
21+
106". Choosing "Renci.SshNet, Version=2023.0.1.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106" arbitrarily.
2222
2323
To fix, we explicitly exclude the SSH.NET nuget package from this project's dependencies.
2424
-->
25-
<PackageReference Include="SSH.NET" Version="2020.0.2" ExcludeAssets="All" />
25+
<PackageReference Include="SSH.NET" Version="2023.0.0" ExcludeAssets="All" />
26+
27+
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
28+
<PackageReference Include="LiquidTestReports.Markdown" Version="1.0.9" />
29+
<PackageReference Include="coverlet.msbuild" Version="6.0.0">
30+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
31+
<PrivateAssets>all</PrivateAssets>
32+
</PackageReference>
2633
<PackageReference Include="coverlet.collector" Version="6.0.0">
27-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
28-
<PrivateAssets>all</PrivateAssets>
34+
<IncludeAssets>build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
35+
<PrivateAssets>all</PrivateAssets>
2936
</PackageReference>
3037
</ItemGroup>
3138

test/Renci.SshNet.IntegrationTests/SshTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -616,8 +616,8 @@ public void Ssh_RemotePortForwarding()
616616
var hostAddresses = Dns.GetHostAddresses(Dns.GetHostName());
617617
var ipv4HostAddress = hostAddresses.First(p => p.AddressFamily == AddressFamily.InterNetwork);
618618

619-
var endpoint1 = new IPEndPoint(ipv4HostAddress, 666);
620-
var endpoint2 = new IPEndPoint(ipv4HostAddress, 667);
619+
var endpoint1 = new IPEndPoint(ipv4HostAddress, 10000);
620+
var endpoint2 = new IPEndPoint(ipv4HostAddress, 10001);
621621

622622
var bytesReceivedOnListener1 = new List<byte>();
623623
var bytesReceivedOnListener2 = new List<byte>();
@@ -635,15 +635,15 @@ public void Ssh_RemotePortForwarding()
635635
client.Connect();
636636

637637
var forwardedPort1 = new ForwardedPortRemote(IPAddress.Loopback,
638-
10000,
638+
10002,
639639
endpoint1.Address,
640640
(uint)endpoint1.Port);
641641
forwardedPort1.Exception += (sender, args) => Console.WriteLine(@"forwardedPort1 exception: " + args.Exception);
642642
client.AddForwardedPort(forwardedPort1);
643643
forwardedPort1.Start();
644644

645645
var forwardedPort2 = new ForwardedPortRemote(IPAddress.Loopback,
646-
10001,
646+
10003,
647647
endpoint2.Address,
648648
(uint)endpoint2.Port);
649649
forwardedPort2.Exception += (sender, args) => Console.WriteLine(@"forwardedPort2 exception: " + args.Exception);

test/Renci.SshNet.IntegrationTests/TestsFixtures/InfrastructureFixture.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
using System.Diagnostics;
2-
3-
using DotNet.Testcontainers.Builders;
1+
using DotNet.Testcontainers.Builders;
42
using DotNet.Testcontainers.Containers;
53
using DotNet.Testcontainers.Images;
64

7-
using Renci.SshNet.Abstractions;
8-
95
namespace Renci.SshNet.IntegrationTests.TestsFixtures
106
{
117
public sealed class InfrastructureFixture : IDisposable
@@ -38,16 +34,11 @@ public static InfrastructureFixture Instance
3834

3935
public async Task InitializeAsync()
4036
{
41-
DiagnosticAbstraction.Source.Switch = new SourceSwitch("sourceSwitch", "Verbose");
42-
DiagnosticAbstraction.Source.Listeners.Remove("Default");
43-
DiagnosticAbstraction.Source.Listeners.Add(new ConsoleTraceListener());
44-
4537
_sshServerImage = new ImageFromDockerfileBuilder()
4638
.WithName("renci-ssh-tests-server-image")
4739
.WithDockerfileDirectory(CommonDirectoryPath.GetSolutionDirectory(), Path.Combine("test", "Renci.SshNet.IntegrationTests"))
48-
.WithDockerfile("Dockerfile")
40+
.WithDockerfile("Dockerfile.TestServer")
4941
.WithDeleteIfExists(true)
50-
5142
.Build();
5243

5344
await _sshServerImage.CreateAsync();
@@ -62,6 +53,14 @@ public async Task InitializeAsync()
6253

6354
SshServerPort = _sshServer.GetMappedPublicPort(22);
6455
SshServerHostName = _sshServer.Hostname;
56+
57+
// Socket fails on Linux, reporting inability early. This is the Linux behavior by design.
58+
// https://github.com/dotnet/runtime/issues/47484#issuecomment-769239699
59+
// At this point we have to wait until the ssh server in the container is available
60+
if (Environment.OSVersion.Platform == PlatformID.Unix)
61+
{
62+
await Task.Delay(300);
63+
}
6564
}
6665

6766
public async Task DisposeAsync()

test/Renci.SshNet.IntegrationTests/TestsFixtures/IntegrationTestBase.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
namespace Renci.SshNet.IntegrationTests.TestsFixtures
1+
using System.Diagnostics;
2+
3+
using Renci.SshNet.Abstractions;
4+
5+
namespace Renci.SshNet.IntegrationTests.TestsFixtures
26
{
37
/// <summary>
48
/// The base class for integration tests
@@ -81,5 +85,18 @@ protected void CreateTestFile(string fileName, int size)
8185
}
8286
}
8387
}
88+
89+
protected void EnableTracing()
90+
{
91+
DiagnosticAbstraction.Source.Switch = new SourceSwitch("sourceSwitch", nameof(SourceLevels.Verbose));
92+
DiagnosticAbstraction.Source.Listeners.Remove("Default");
93+
DiagnosticAbstraction.Source.Listeners.Add(new ConsoleTraceListener() { Name = "TestConsoleLogger" });
94+
}
95+
96+
protected void DisableTracing()
97+
{
98+
DiagnosticAbstraction.Source.Switch = new SourceSwitch("sourceSwitch", nameof(SourceLevels.Off));
99+
DiagnosticAbstraction.Source.Listeners.Remove("TestConsoleLogger");
100+
}
84101
}
85102
}

test/Renci.SshNet.Tests/Classes/Common/SemaphoreLightTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public void WaitTest()
7878

7979
watch.Stop();
8080

81-
Assert.IsTrue(watch.ElapsedMilliseconds > 200);
81+
Assert.IsTrue(watch.ElapsedMilliseconds >= 200);
8282
Assert.IsTrue(watch.ElapsedMilliseconds < 250);
8383
}
8484

test/Renci.SshNet.Tests/Classes/Connection/DirectConnectorTestBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ protected sealed override void Arrange()
3636
protected ConnectionInfo CreateConnectionInfo(string hostName)
3737
{
3838
return new ConnectionInfo(hostName,
39-
777,
39+
1027,
4040
"user",
4141
new KeyboardInteractiveAuthenticationMethod("user"));
4242
}

test/Renci.SshNet.Tests/Classes/Connection/DirectConnectorTest_Connect_TimeoutConnectingToServer.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@
33
using System.Globalization;
44
using System.Net;
55
using System.Net.Sockets;
6+
using System.Runtime.InteropServices;
67

78
using Microsoft.VisualStudio.TestTools.UnitTesting;
89

910
using Moq;
1011

1112
using Renci.SshNet.Common;
13+
using Renci.SshNet.Tests.Common;
1214

1315
namespace Renci.SshNet.Tests.Classes.Connection
1416
{
1517
[TestClass]
1618
public class DirectConnectorTest_Connect_TimeoutConnectingToServer : DirectConnectorTestBase
1719
{
1820
private ConnectionInfo _connectionInfo;
19-
private SshOperationTimeoutException _actualException;
21+
private Exception _actualException;
2022
private Socket _clientSocket;
2123
private Stopwatch _stopWatch;
2224

@@ -60,21 +62,34 @@ protected override void Act()
6062
{
6163
_actualException = ex;
6264
}
65+
catch (SocketException ex)
66+
{
67+
_actualException = ex;
68+
}
6369
finally
6470
{
6571
_stopWatch.Stop();
6672
}
6773
}
6874

69-
[TestMethod]
70-
public void ConnectShouldHaveThrownSshOperationTimeoutException()
75+
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
76+
public void ConnectShouldHaveThrownSshOperationTimeoutExceptionOnWindows()
7177
{
7278
Assert.IsNull(_actualException.InnerException);
79+
Assert.IsInstanceOfType<SshOperationTimeoutException>(_actualException);
7380
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
7481
}
7582

76-
[TestMethod]
77-
public void ConnectShouldHaveRespectedTimeout()
83+
[TestMethodForPlatform(nameof(OSPlatform.Linux))]
84+
public void ConnectShouldHaveThrownSocketExceptionOnLinux()
85+
{
86+
Assert.IsNull(_actualException.InnerException);
87+
Assert.IsInstanceOfType<SocketException>(_actualException);
88+
Assert.AreEqual("Connection refused", _actualException.Message);
89+
}
90+
91+
[TestMethodForPlatform(nameof(OSPlatform.Windows))]
92+
public void ConnectShouldHaveRespectedTimeoutOnWindows()
7893
{
7994
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
8095
_stopWatch.ElapsedMilliseconds,

0 commit comments

Comments
 (0)