Skip to content

MSTest Integration tests #1148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8ea1237
Merge remote-tracking branch 'refs/remotes/origin/develop'
drieseng Oct 15, 2017
0f08b85
Prepare for 2016.1.0 RTW.
drieseng Oct 15, 2017
fc114fb
Merge remote-tracking branch 'remotes/origin/develop'
drieseng May 3, 2020
23168f4
Merge remote-tracking branch 'remotes/origin/develop'
drieseng May 3, 2020
4583da5
Remove CWLs.
drieseng May 3, 2020
4eef090
Merge branch 'develop'
drieseng May 3, 2020
cca8255
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 1, 2020
66e24e7
Sponsoring (#691)
drieseng Jun 7, 2020
66cf838
Prepare for 2020.0.0-beta1
drieseng Jun 1, 2020
356b22a
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 7, 2020
61c09ff
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 7, 2020
d8fbae3
Update name of Sandcastle Help File Builder environment variable.
drieseng Jun 7, 2020
e9979a6
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 7, 2020
32f2615
Fix path to source file.
drieseng Jun 7, 2020
bf651ca
Remove local-use file.
drieseng Jun 7, 2020
9b21a46
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 7, 2020
1068694
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 7, 2020
5942469
Merge remote-tracking branch 'remotes/origin/develop'
drieseng Jun 7, 2020
84b9281
Merge branch 'develop'
drieseng Dec 30, 2020
8737fdb
Merge branch 'develop'
drieseng Dec 31, 2020
853ec99
Prepare for 2020.0.0 release.
drieseng Dec 31, 2020
2c99132
Merge branch 'develop'
drieseng Dec 31, 2020
f480937
Merge branch 'develop'
drieseng Dec 31, 2020
a06522c
Merge branch 'develop'
drieseng Jan 24, 2021
acda143
Prepare for 2020.0.1 release
drieseng Jan 24, 2021
4cdedf6
Use cryptographically secure random number generator.
drieseng May 29, 2022
69a42d3
Integration tests
WojciechNagorski Jun 29, 2023
6f567ec
Remove todos
WojciechNagorski Jun 29, 2023
77b27e5
Merge branch 'master' of https://github.com/sshnet/SSH.NET into integ…
WojciechNagorski Aug 26, 2023
82dc77a
Use correct SSH.NET
WojciechNagorski Aug 30, 2023
bfef6aa
Merge branch 'develop' of https://github.com/sshnet/SSH.NET into inte…
WojciechNagorski Aug 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/Renci.SshNet.IntegrationTests/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[*.cs]

#### SYSLIB diagnostics ####

# SYSLIB1045: Use 'GeneratedRegexAttribute' to generate the regular expression implementation at compile-time
#
# TODO: Remove this when https://github.com/sshnet/SSH.NET/issues/1131 is implemented.
dotnet_diagnostic.SYSLIB1045.severity = none

### StyleCop Analyzers rules ###

#### .NET Compiler Platform analysers rules ####

# IDE0007: Use var instead of explicit type
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0007
dotnet_diagnostic.IDE0007.severity = suggestion

# IDE0028: Use collection initializers
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0028
dotnet_diagnostic.IDE0028.severity = suggestion

# IDE0058: Remove unnecessary expression value
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0058
dotnet_diagnostic.IDE0058.severity = suggestion

# IDE0059: Remove unnecessary value assignment
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0059
dotnet_diagnostic.IDE0059.severity = suggestion

# IDE0230: Use UTF-8 string literal
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0230
dotnet_diagnostic.IDE0230.severity = suggestion
49 changes: 49 additions & 0 deletions src/Renci.SshNet.IntegrationTests/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FROM alpine:latest

COPY --chown=root:root server/ssh /etc/ssh/
COPY --chown=root:root server/script /opt/sshnet
COPY user/sshnet /home/sshnet/.ssh

RUN apk update && apk upgrade --no-cache && \
apk add --no-cache syslog-ng && \
# install and configure sshd
apk add --no-cache openssh && \
# install openssh-server-pam to allow for keyboard-interactive authentication
apk add --no-cache openssh-server-pam && \
dos2unix /etc/ssh/* && \
chmod 400 /etc/ssh/ssh*key && \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
sed -i 's/#LogLevel\s*INFO/LogLevel DEBUG3/' /etc/ssh/sshd_config && \
echo 'PubkeyAcceptedAlgorithms ssh-rsa' >> /etc/ssh/sshd_config && \
chmod 646 /etc/ssh/sshd_config && \
# install and configure sudo
apk add --no-cache sudo && \
addgroup sudo && \
# allow root to run any command
echo 'root ALL=(ALL) ALL' > /etc/sudoers && \
# allow everyone in the 'sudo' group to run any command without a password
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \
# add user to run most of the integration tests
adduser -D sshnet && \
passwd -u sshnet && \
echo 'sshnet:ssh4ever' | chpasswd && \
dos2unix /home/sshnet/.ssh/* && \
chown -R sshnet:sshnet /home/sshnet && \
chmod -R 700 /home/sshnet/.ssh && \
chmod -R 644 /home/sshnet/.ssh/authorized_keys && \
# add user to administer container (update configs, restart sshd)
adduser -D sshnetadm && \
passwd -u sshnetadm && \
echo 'sshnetadm:ssh4ever' | chpasswd && \
addgroup sshnetadm sudo && \
dos2unix /opt/sshnet/* && \
# install shadow package; we use chage command in this package to expire/unexpire password of the sshnet user
apk add --no-cache shadow && \
# allow us to use telnet command; we use this in the remote port forwarding tests
apk --no-cache add busybox-extras && \
# install full-fledged ps command
apk add --no-cache procps

EXPOSE 22 22

ENTRYPOINT ["/opt/sshnet/start.sh"]
47 changes: 47 additions & 0 deletions src/Renci.SshNet.IntegrationTests/IntegrationTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<!--
Even though we're not interested in producing XML docs for test projects, we have to enable this in order to have the .NET Compiler
Platform analyzers produce the IDE0005 (Remove unnecessary import) diagnostic.

To avoid warnings for missing XML docs, we add CS1591 (Missing XML comment for publicly visible type or member) to the NoWarn property.

We can stop producing XML docs for test projects (and remove the NoWarn for CS1591) once the following issue is fixed:
https://github.com/dotnet/roslyn/issues/41640.
-->
<NoWarn>$(NoWarn);CS1591</NoWarn>

</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="Testcontainers" Version="3.4.0" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Renci.SshNet\Renci.SshNet.csproj">
<Aliases>LocalSshNet</Aliases>
</ProjectReference>
</ItemGroup>

<ItemGroup>
<None Update="app.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions src/Renci.SshNet.IntegrationTests/ScpClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace IntegrationTests
{
/// <summary>
/// The SCP client integration tests
/// </summary>
[TestClass]
public class ScpClientTests : IntegrationTestBase, IDisposable
{
private readonly ScpClient _scpClient;

public ScpClientTests()
{
_scpClient = new ScpClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
_scpClient.Connect();
}

[TestMethod]

public void Upload_And_Download_FileStream()
{
var file = $"/tmp/{Guid.NewGuid()}.txt";
var fileContent = "File content !@#$%^&*()_+{}:,./<>[];'\\|";

using var uploadStream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent));
_scpClient.Upload(uploadStream, file);

using var downloadStream = new MemoryStream();
_scpClient.Download(file, downloadStream);

var result = Encoding.UTF8.GetString(downloadStream.ToArray());

Assert.AreEqual(fileContent, result);
}

public void Dispose()
{
_scpClient.Disconnect();
_scpClient.Dispose();
}
}
}
100 changes: 100 additions & 0 deletions src/Renci.SshNet.IntegrationTests/SftpClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
namespace IntegrationTests
{
/// <summary>
/// The SFTP client integration tests
/// </summary>
[TestClass]
public class SftpClientTests : IntegrationTestBase, IDisposable
{
private readonly SftpClient _sftpClient;

public SftpClientTests()
{
_sftpClient = new SftpClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
_sftpClient.Connect();
}

[TestMethod]
public void Create_directory_with_contents_and_list_it()
{
var testDirectory = "/home/sshnet/sshnet-test";
var testFileName = "test-file.txt";
var testFilePath = $"{testDirectory}/{testFileName}";
var testContent = "file content";

// Create new directory and check if it exists
_sftpClient.CreateDirectory(testDirectory);
Assert.IsTrue(_sftpClient.Exists(testDirectory));

// Upload file and check if it exists
using var fileStream = new MemoryStream(Encoding.UTF8.GetBytes(testContent));
_sftpClient.UploadFile(fileStream, testFilePath);
Assert.IsTrue(_sftpClient.Exists(testFilePath));

// Check if ListDirectory works
var files = _sftpClient.ListDirectory(testDirectory);

_sftpClient.DeleteFile(testFilePath);
_sftpClient.DeleteDirectory(testDirectory);

var builder = new StringBuilder();
foreach (var file in files)
{
builder.AppendLine($"{file.FullName} {file.IsRegularFile} {file.IsDirectory}");
}

Assert.AreEqual(@"/home/sshnet/sshnet-test/. False True
/home/sshnet/sshnet-test/.. False True
/home/sshnet/sshnet-test/test-file.txt True False
", builder.ToString());
}

[TestMethod]
public async Task Create_directory_with_contents_and_list_it_async()
{
var testDirectory = "/home/sshnet/sshnet-test";
var testFileName = "test-file.txt";
var testFilePath = $"{testDirectory}/{testFileName}";
var testContent = "file content";

// Create new directory and check if it exists
_sftpClient.CreateDirectory(testDirectory);
Assert.IsTrue(_sftpClient.Exists(testDirectory));

// Upload file and check if it exists
using var fileStream = new MemoryStream(Encoding.UTF8.GetBytes(testContent));
_sftpClient.UploadFile(fileStream, testFilePath);
Assert.IsTrue(_sftpClient.Exists(testFilePath));

// Check if ListDirectory works
var files = await _sftpClient.ListDirectoryAsync(testDirectory, CancellationToken.None);

_sftpClient.DeleteFile(testFilePath);
_sftpClient.DeleteDirectory(testDirectory);

var builder = new StringBuilder();
foreach (var file in files)
{
builder.AppendLine($"{file.FullName} {file.IsRegularFile} {file.IsDirectory}");
}

Assert.AreEqual(@"/home/sshnet/sshnet-test/. False True
/home/sshnet/sshnet-test/.. False True
/home/sshnet/sshnet-test/test-file.txt True False
", builder.ToString());
}

[TestMethod]
[ExpectedException(typeof(SftpPermissionDeniedException), "Permission denied")]
public void Test_Sftp_ListDirectory_Permission_Denied()
{
_sftpClient.ListDirectory("/root");
}

public void Dispose()
{
_sftpClient.Disconnect();
_sftpClient.Dispose();
}
}
}
32 changes: 32 additions & 0 deletions src/Renci.SshNet.IntegrationTests/SshClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace IntegrationTests
{
/// <summary>
/// The SSH client integration tests
/// </summary>
[TestClass]
public class SshClientTests : IntegrationTestBase, IDisposable
{
private readonly SshClient _sshClient;

public SshClientTests()
{
_sshClient = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
_sshClient.Connect();
}

[TestMethod]
public void Echo_Command_with_all_characters()
{
var builder = new StringBuilder();
var response = _sshClient.RunCommand("echo $'test !@#$%^&*()_+{}:,./<>[];\\|'");

Assert.AreEqual("test !@#$%^&*()_+{}:,./<>[];\\|\n", response.Result);
}

public void Dispose()
{
_sshClient.Disconnect();
_sshClient.Dispose();
}
}
}
19 changes: 19 additions & 0 deletions src/Renci.SshNet.IntegrationTests/TestInitializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace IntegrationTests
{
[TestClass]
public class TestInitializer
{
[AssemblyInitialize]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "MSTests requires context parameter")]
public static async Task Initialize(TestContext context)
{
await InfrastructureFixture.Instance.InitializeAsync();
}

[AssemblyCleanup]
public static async Task Cleanup()
{
await InfrastructureFixture.Instance.DisposeAsync();
}
}
}
Loading