Adding Live backend tests
These tests are not unit tests but actual backup tests to backends (both cloud and self hosted containers).
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
name: Backend Live Tests
|
||||
'on':
|
||||
- push
|
||||
- pull_request
|
||||
jobs:
|
||||
check_secrets:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
s3_secrets_available: '${{ steps.check_s3.outputs.available }}'
|
||||
dropbox_secrets_available: '${{ steps.check_dropbox.outputs.available }}'
|
||||
azure_secrets_available: '${{ steps.check_azure.outputs.available }}'
|
||||
steps:
|
||||
- id: check_s3
|
||||
name: Check S3 secrets
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Starting S3 secrets check..."
|
||||
if [[ -n "${{ secrets.TESTCREDENTIAL_S3_BUCKETNAME }}" ]] && \
|
||||
[[ -n "${{ secrets.TESTCREDENTIAL_S3_KEY }}" ]] && \
|
||||
[[ -n "${{ secrets.TESTCREDENTIAL_S3_REGION }}" ]] && \
|
||||
[[ -n "${{ secrets.TESTCREDENTIAL_S3_SECRET }}" ]]; then
|
||||
echo "All S3 secrets found"
|
||||
echo "available=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Missing some S3 secrets"
|
||||
echo "available=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "S3 check completed"
|
||||
- id: check_dropbox
|
||||
name: Check Dropbox secrets
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Starting Dropbox secrets check..."
|
||||
if [[ -n "${{ secrets.TESTCREDENTIAL_DROPBOX_FOLDER }}" ]] && \
|
||||
[[ -n "${{ secrets.TESTCREDENTIAL_DROPBOX_TOKEN }}" ]]; then
|
||||
echo "All Dropbox secrets found"
|
||||
echo "available=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Missing some Dropbox secrets"
|
||||
echo "available=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "Dropbox check completed"
|
||||
- id: check_azure
|
||||
name: Check Azure secrets
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Starting Azure secrets check..."
|
||||
if [[ -n "${{ secrets.TESTCREDENTIAL_AZURE_ACCOUNTNAME }}" ]] && \
|
||||
[[ -n "${{ secrets.TESTCREDENTIAL_AZURE_ACCESSKEY }}" ]] && \
|
||||
[[ -n "${{ secrets.TESTCREDENTIAL_AZURE_CONTAINERNAME }}" ]]; then
|
||||
echo "All Azure secrets found"
|
||||
echo "available=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Missing some Azure secrets"
|
||||
echo "available=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "Azure check completed"
|
||||
- name: Debug Output
|
||||
shell: bash
|
||||
run: |
|
||||
echo "S3 Available: ${{ steps.check_s3.outputs.available }}"
|
||||
echo "Dropbox Available: ${{ steps.check_dropbox.outputs.available }}"
|
||||
|
||||
|
||||
test_ftp:
|
||||
name: FTP Tests
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore NuGet dependencies
|
||||
run: >-
|
||||
dotnet restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Build project
|
||||
run: >-
|
||||
dotnet build --no-restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Setup Testcontainers Cloud Client
|
||||
uses: atomicjar/testcontainers-cloud-setup-action@v1
|
||||
with:
|
||||
token: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
- name: Run FTP tests
|
||||
env:
|
||||
TC_CLOUD_TOKEN: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
run: >-
|
||||
dotnet test --no-build --filter="ClassName~FtpTests"
|
||||
--logger:"console;verbosity=detailed"
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
test_s3:
|
||||
needs: check_secrets
|
||||
if: needs.check_secrets.outputs.s3_secrets_available == 'true'
|
||||
name: S3 Tests
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore NuGet dependencies
|
||||
run: >-
|
||||
dotnet restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Build project
|
||||
run: >-
|
||||
dotnet build --no-restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Run S3 tests
|
||||
env:
|
||||
TC_CLOUD_TOKEN: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
TESTCREDENTIAL_S3_BUCKETNAME: '${{ secrets.TESTCREDENTIAL_S3_BUCKETNAME }}'
|
||||
TESTCREDENTIAL_S3_KEY: '${{ secrets.TESTCREDENTIAL_S3_KEY }}'
|
||||
TESTCREDENTIAL_S3_REGION: '${{ secrets.TESTCREDENTIAL_S3_REGION }}'
|
||||
TESTCREDENTIAL_S3_SECRET: '${{ secrets.TESTCREDENTIAL_S3_SECRET }}'
|
||||
run: >-
|
||||
dotnet test --no-build --filter="ClassName~S3Tests"
|
||||
--logger:"console;verbosity=detailed"
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
test_azure:
|
||||
needs: check_secrets
|
||||
if: needs.check_secrets.outputs.azure_secrets_available == 'true'
|
||||
name: Azure Tests
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore NuGet dependencies
|
||||
run: >-
|
||||
dotnet restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Build project
|
||||
run: >-
|
||||
dotnet build --no-restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Run Azure tests
|
||||
env:
|
||||
TESTCREDENTIAL_AZURE_ACCOUNTNAME: '${{ secrets.TESTCREDENTIAL_AZURE_ACCOUNTNAME }}'
|
||||
TESTCREDENTIAL_AZURE_ACCESSKEY: '${{ secrets.TESTCREDENTIAL_AZURE_ACCESSKEY }}'
|
||||
TESTCREDENTIAL_AZURE_CONTAINERNAME: '${{ secrets.TESTCREDENTIAL_AZURE_CONTAINERNAME }}'
|
||||
run: >-
|
||||
dotnet test --no-build --filter="ClassName~AzureTests"
|
||||
--logger:"console;verbosity=detailed"
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
|
||||
test_webdav:
|
||||
name: Webdav Tests
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore NuGet dependencies
|
||||
run: >-
|
||||
dotnet restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Build project
|
||||
run: >-
|
||||
dotnet build --no-restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Setup Testcontainers Cloud Client
|
||||
uses: atomicjar/testcontainers-cloud-setup-action@v1
|
||||
with:
|
||||
token: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
- name: Run Webdav tests
|
||||
env:
|
||||
TC_CLOUD_TOKEN: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
run: >-
|
||||
dotnet test --no-build --filter="ClassName~WebDavTests"
|
||||
--logger:"console;verbosity=detailed"
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
test_dropbox:
|
||||
needs: check_secrets
|
||||
if: needs.check_secrets.outputs.dropbox_secrets_available == 'true'
|
||||
name: DropBox Tests
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
max-parallel: 1
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore NuGet dependencies
|
||||
run: >-
|
||||
dotnet restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Build project
|
||||
run: >-
|
||||
dotnet build --no-restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Run Dropbox tests
|
||||
env:
|
||||
TC_CLOUD_TOKEN: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
TESTCREDENTIAL_DROPBOX_FOLDER: '${{ secrets.TESTCREDENTIAL_DROPBOX_FOLDER }}'
|
||||
TESTCREDENTIAL_DROPBOX_TOKEN: '${{ secrets.TESTCREDENTIAL_DROPBOX_TOKEN }}'
|
||||
run: >-
|
||||
dotnet test --no-build --filter="ClassName~DropBoxTests"
|
||||
--logger:"console;verbosity=detailed"
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
test_ssh:
|
||||
name: SSH Tests
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore NuGet dependencies
|
||||
run: >-
|
||||
dotnet restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Build project
|
||||
run: >-
|
||||
dotnet build --no-restore
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
- name: Setup Testcontainers Cloud Client
|
||||
uses: atomicjar/testcontainers-cloud-setup-action@v1
|
||||
with:
|
||||
token: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
- name: Run SSH tests
|
||||
env:
|
||||
TC_CLOUD_TOKEN: '${{ secrets.TC_CLOUD_TOKEN }}'
|
||||
run: >-
|
||||
dotnet test --no-build --filter="ClassName~SshTests"
|
||||
--logger:"console;verbosity=detailed"
|
||||
LiveTests/Duplicati.Backend.Tests/Duplicati.Backend.Tests.sln
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Azure;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for Dropbox backend
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class AzureTests : BaseTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Dropbox test. There are no adicional parameters to be set or tested.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public Task TestAzureBlob()
|
||||
{
|
||||
CheckRequiredEnvironment(["TESTCREDENTIAL_AZURE_ACCOUNTNAME","TESTCREDENTIAL_AZURE_ACCESSKEY","TESTCREDENTIAL_AZURE_CONTAINERNAME"
|
||||
]);
|
||||
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[]
|
||||
{
|
||||
$"azure://{Environment.GetEnvironmentVariable("TESTCREDENTIAL_AZURE_CONTAINERNAME")}?auth-username={Environment.GetEnvironmentVariable("TESTCREDENTIAL_AZURE_ACCOUNTNAME")}&auth-password={Uri.EscapeDataString(Environment.GetEnvironmentVariable("TESTCREDENTIAL_AZURE_ACCESSKEY")!)}"
|
||||
}.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0) Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Base;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for tests that require a running SFTPGo instance which will
|
||||
/// be used to test the FTP, Webdav & SSH backends.
|
||||
///
|
||||
/// It handles the creation of the necessary configuration files and certificates
|
||||
/// </summary>
|
||||
public class BaseSftpgoTest : BaseTest
|
||||
{
|
||||
protected static readonly string TEST_USER_NAME = "testuser";
|
||||
protected static readonly string TEST_USER_PASSWORD = "testpassword";
|
||||
protected static readonly string CERTIFICATE_FILE = "fullchain.pem";
|
||||
protected static readonly string CERTIFICATE_PRIVATE_KEY_FILE = "privkey.pem";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a josn file with the configuration for the SFTPGo instance
|
||||
/// </summary>
|
||||
/// <param name="directoryInfo">directory in which to create the file</param>
|
||||
protected void CreateUsersFile(DirectoryInfo directoryInfo)
|
||||
{
|
||||
var sftpgoConfig = "{\"users\":[{\"id\":1,\"status\":1,\"username\":\"testuser\",\"password\":\"$2a$10$BTqu.odQz6jLQAi70KbQJOYBcRHpbhP4uxqcfFXZalq4zUsQZGj/6\",\"has_password\":true,\"home_dir\":\"/srv/sftpgo/data/testuser\",\"uid\":0,\"gid\":0,\"max_sessions\":0,\"quota_size\":0,\"quota_files\":0,\"permissions\":{\"/\":[\"*\"]},\"upload_data_transfer\":0,\"download_data_transfer\":0,\"total_data_transfer\":0,\"created_at\":1729521839754,\"updated_at\":1729521839754,\"last_password_change\":1729521839754,\"filters\":{\"hooks\":{\"external_auth_disabled\":false,\"pre_login_disabled\":false,\"check_password_disabled\":false},\"totp_config\":{\"secret\":{}}},\"filesystem\":{\"provider\":0,\"osconfig\":{},\"s3config\":{\"access_secret\":{}},\"gcsconfig\":{\"credentials\":{}},\"azblobconfig\":{\"account_key\":{},\"sas_url\":{}},\"cryptconfig\":{\"passphrase\":{}},\"sftpconfig\":{\"password\":{},\"private_key\":{},\"key_passphrase\":{}},\"httpconfig\":{\"password\":{},\"api_key\":{}}}}],\"groups\":[],\"folders\":[],\"admins\":[{\"id\":1,\"status\":1,\"username\":\"admin\",\"password\":\"$2a$10$HJGY10EuEPPajgut3OMTte5NXqbn1RXMTzy8BUA639a6qzinOjIx6\",\"permissions\":[\"*\"],\"filters\":{\"require_two_factor\":false,\"totp_config\":{\"secret\":{}},\"preferences\":{}},\"created_at\":1729521817148,\"updated_at\":1729521817148,\"last_login\":1729521817152}],\"api_keys\":[],\"shares\":[],\"event_actions\":[],\"event_rules\":[],\"roles\":[],\"ip_lists\":[],\"configs\":{},\"version\":16}";
|
||||
|
||||
using var usersFile = File.Create(Path.Combine(directoryInfo.FullName, "users.json"));
|
||||
|
||||
using var userFileWritter = new StreamWriter(usersFile);
|
||||
|
||||
userFileWritter.WriteLine(sftpgoConfig);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a self signed certificate to be used on WebDav and SFTP connections.
|
||||
///
|
||||
/// Its created on a temporary directory and the private key and public key are saved in PEM format.
|
||||
///
|
||||
/// It is up to the caller to delete the files albeit its in the OS temporary directory.
|
||||
/// </summary>
|
||||
/// <returns>Returns the directory in which certificate was created</returns>
|
||||
protected DirectoryInfo CreateHttpsCertificates()
|
||||
{
|
||||
using var rsa = RSA.Create(2048);
|
||||
|
||||
var request = new CertificateRequest(
|
||||
$"CN=TestCertificateForWebdav",
|
||||
rsa,
|
||||
HashAlgorithmName.SHA256,
|
||||
RSASignaturePadding.Pkcs1);
|
||||
|
||||
request.CertificateExtensions.Add(
|
||||
new X509KeyUsageExtension(
|
||||
X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature,
|
||||
false));
|
||||
|
||||
request.CertificateExtensions.Add(
|
||||
new X509EnhancedKeyUsageExtension(
|
||||
[new Oid("1.3.6.1.5.5.7.3.1")], false));
|
||||
|
||||
var certificate = request.CreateSelfSigned(
|
||||
DateTimeOffset.Now.AddDays(-1),
|
||||
DateTimeOffset.Now.AddDays(30));
|
||||
|
||||
if (OperatingSystem.IsWindows()) certificate.FriendlyName = "Test Certificate";
|
||||
|
||||
var directoryInfo = Directory.CreateTempSubdirectory("TemporaryCertificates");
|
||||
|
||||
using var privateKeyFile = File.Create(Path.Combine(directoryInfo.FullName, CERTIFICATE_PRIVATE_KEY_FILE));
|
||||
using var publicKeyFile = File.Create(Path.Combine(directoryInfo.FullName, CERTIFICATE_FILE));
|
||||
|
||||
using var privateKeyWriter = new StreamWriter(privateKeyFile);
|
||||
using var publicKeyWriter = new StreamWriter(publicKeyFile);
|
||||
privateKeyWriter.WriteLine(certificate.GetRSAPrivateKey()!.ExportRSAPrivateKeyPem());
|
||||
publicKeyWriter.WriteLine(certificate.ExportCertificatePem());
|
||||
|
||||
return directoryInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Duplicati.Backend.Tests.Base;
|
||||
|
||||
public class BaseTest
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the environment variables are set and if not fails with detailed about the missing variables
|
||||
/// </summary>
|
||||
/// <param name="requiredEnvironmentVariables">Array of variables to be checked</param>
|
||||
protected void CheckRequiredEnvironment(string[] requiredEnvironmentVariables)
|
||||
{
|
||||
var missingVariables = requiredEnvironmentVariables
|
||||
.Where(variable => string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(variable)))
|
||||
.ToList();
|
||||
|
||||
if (missingVariables.Any()) Assert.Fail($"Required environment variables not set: {string.Join(", ", missingVariables)}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Base;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests to check if the TestContainers is available
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class PreliminaryTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task TestContainersEngineReady()
|
||||
{
|
||||
using var dockerClientConfiguration =
|
||||
TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration(ResourceReaper
|
||||
.DefaultSessionId);
|
||||
|
||||
using var dockerClient = dockerClientConfiguration.CreateClient();
|
||||
|
||||
var versionResponse = await dockerClient.System.GetSystemInfoAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!(versionResponse.ServerVersion.Contains("Testcontainers Desktop") ||
|
||||
versionResponse.ServerVersion.Contains("testcontainers cloud")))
|
||||
{
|
||||
Assert.Fail("Testcontainers engine not found");
|
||||
}
|
||||
|
||||
Console.WriteLine($"Engine configured: {versionResponse.ServerVersion}");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Dropbox;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for Dropbox backend
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class DropBoxTests : BaseTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Dropbox test. There are no adicional parameters to be set or tested.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public Task TestDropBox()
|
||||
{
|
||||
CheckRequiredEnvironment(["TESTCREDENTIAL_DROPBOX_FOLDER","TESTCREDENTIAL_DROPBOX_TOKEN"]);
|
||||
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[]
|
||||
{
|
||||
$"dropbox://{Environment.GetEnvironmentVariable("TESTCREDENTIAL_DROPBOX_FOLDER")}/?authid={Environment.GetEnvironmentVariable("TESTCREDENTIAL_DROPBOX_TOKEN")}"
|
||||
}.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0) Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Description>Commandline implementation of Duplicati</Description>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2"/>
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10"/>
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10"/>
|
||||
<PackageReference Include="Testcontainers" Version="3.4.0"/>
|
||||
<PackageReference Include="TestContainers.Container.Abstractions" Version="1.5.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Duplicati\CommandLine\BackendTester\Duplicati.CommandLine.BackendTester.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Backend.Tests", "Duplicati.Backend.Tests.csproj", "{6D888116-3424-4DE4-8AE3-D01A44A3EE38}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.BackendTester", "..\..\Duplicati\CommandLine\BackendTester\Duplicati.CommandLine.BackendTester.csproj", "{41756E86-799B-4142-9948-D9D94054BA15}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6D888116-3424-4DE4-8AE3-D01A44A3EE38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6D888116-3424-4DE4-8AE3-D01A44A3EE38}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6D888116-3424-4DE4-8AE3-D01A44A3EE38}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6D888116-3424-4DE4-8AE3-D01A44A3EE38}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{41756E86-799B-4142-9948-D9D94054BA15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{41756E86-799B-4142-9948-D9D94054BA15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{41756E86-799B-4142-9948-D9D94054BA15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{41756E86-799B-4142-9948-D9D94054BA15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.FTP;
|
||||
|
||||
/// <summary>
|
||||
/// FTP Tests
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class FtpTests : BaseSftpgoTest
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Test a simple FTP connection, no SSL
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TestMethod]
|
||||
public async Task TestSimpleFtp()
|
||||
{
|
||||
var outputConsumer = new OutputConsumer();
|
||||
var filePermissions = UnixFileModes.UserRead | UnixFileModes.UserWrite | UnixFileModes.UserExecute |
|
||||
UnixFileModes.GroupRead | UnixFileModes.GroupWrite | UnixFileModes.GroupExecute |
|
||||
UnixFileModes.OtherRead | UnixFileModes.OtherWrite | UnixFileModes.OtherExecute;
|
||||
|
||||
var temporaryKeysDir = CreateHttpsCertificates();
|
||||
|
||||
CreateUsersFile(temporaryKeysDir);
|
||||
|
||||
var container = new ContainerBuilder()
|
||||
.WithImage("drakkan/sftpgo")
|
||||
.WithEnvironment("SFTPGO_LOG_LEVEL", "debug")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_FROM", "/var/lib/sftpgo/users.json")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_CLEAN", "0")
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__PORT", "2121")
|
||||
.WithEnvironment("SFTPGO_FTPD__PASSIVE_PORT_RANGE__END", "21000")
|
||||
.WithEnvironment("SFTPGO_FTPD__PASSIVE_PORT_RANGE__START", "20000")
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__ACTIVE_CONNECTIONS_SECURITY", "1")
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__CERTIFICATE_FILE", CERTIFICATE_FILE)
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__CERTIFICATE_KEY_FILE", CERTIFICATE_PRIVATE_KEY_FILE)
|
||||
.WithResourceMapping(temporaryKeysDir, "/var/lib/sftpgo/", filePermissions)
|
||||
.WithPortBinding(2121, 2121)
|
||||
|
||||
.WithOutputConsumer(outputConsumer);
|
||||
|
||||
container = Enumerable.Range(20000, 1000)
|
||||
.Aggregate(container, (current, port) => current.WithPortBinding(port, port));
|
||||
|
||||
var builtContainer = container
|
||||
.WithOutputConsumer(outputConsumer)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Starting container");
|
||||
await builtContainer.StartAsync();
|
||||
|
||||
// Once started we will already cleanup temporary directory
|
||||
temporaryKeysDir.Delete(true);
|
||||
|
||||
Console.WriteLine("Waiting X seconds");
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
|
||||
// Running this ignoring the certificate
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[]
|
||||
{
|
||||
$"ftp://{TEST_USER_NAME}:{TEST_USER_PASSWORD}@localhost:2121/",
|
||||
}.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0)
|
||||
{
|
||||
Console.WriteLine(await outputConsumer.GetStreamsOutput());
|
||||
Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
}
|
||||
|
||||
await builtContainer.StopAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test FTP connection with SSL/TLS
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TestMethod]
|
||||
public async Task TestFtpSsl()
|
||||
{
|
||||
var outputConsumer = new OutputConsumer();
|
||||
var filePermissions = UnixFileModes.UserRead | UnixFileModes.UserWrite | UnixFileModes.UserExecute |
|
||||
UnixFileModes.GroupRead | UnixFileModes.GroupWrite | UnixFileModes.GroupExecute |
|
||||
UnixFileModes.OtherRead | UnixFileModes.OtherWrite | UnixFileModes.OtherExecute;
|
||||
|
||||
var temporaryKeysDir = CreateHttpsCertificates();
|
||||
|
||||
CreateUsersFile(temporaryKeysDir);
|
||||
|
||||
var container = new ContainerBuilder()
|
||||
.WithImage("drakkan/sftpgo")
|
||||
.WithEnvironment("SFTPGO_LOG_LEVEL", "debug")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_FROM", "/var/lib/sftpgo/users.json")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_CLEAN", "0")
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__PORT", "2121")
|
||||
.WithEnvironment("SFTPGO_FTPD__PASSIVE_PORT_RANGE__END", "23000")
|
||||
.WithEnvironment("SFTPGO_FTPD__PASSIVE_PORT_RANGE__START", "22000")
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__ACTIVE_CONNECTIONS_SECURITY", "1")
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__CERTIFICATE_FILE", CERTIFICATE_FILE)
|
||||
.WithEnvironment("SFTPGO_FTPD__BINDINGS__0__CERTIFICATE_KEY_FILE", CERTIFICATE_PRIVATE_KEY_FILE)
|
||||
.WithResourceMapping(temporaryKeysDir, "/var/lib/sftpgo/", filePermissions)
|
||||
.WithPortBinding(2122, 2121)
|
||||
|
||||
.WithOutputConsumer(outputConsumer);
|
||||
|
||||
container = Enumerable.Range(22000, 1000)
|
||||
.Aggregate(container, (current, port) => current.WithPortBinding(port, port));
|
||||
|
||||
var builtContainer = container
|
||||
.WithOutputConsumer(outputConsumer)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Starting container");
|
||||
await builtContainer.StartAsync();
|
||||
|
||||
// Once started we will already cleanup temporary directory
|
||||
temporaryKeysDir.Delete(true);
|
||||
|
||||
Console.WriteLine("Waiting X seconds");
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
|
||||
// Running this ignoring the certificate
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
["ftp://testuser:testpassword@localhost:2122/", "use-ssl=true"]);
|
||||
|
||||
if (exitCode != 0)
|
||||
{
|
||||
Console.WriteLine(await outputConsumer.GetStreamsOutput());
|
||||
Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
}
|
||||
|
||||
await builtContainer.StopAsync();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
global using System.Security.Cryptography;
|
||||
global using System.Security.Cryptography.X509Certificates;
|
||||
global using System.Text;
|
||||
global using DotNet.Testcontainers.Builders;
|
||||
global using DotNet.Testcontainers.Configurations;
|
||||
global using DotNet.Testcontainers.Containers;
|
||||
global using Duplicati.Backend.Tests.Base;
|
||||
global using Duplicati.Backend.Tests.Utility;
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Google_Drive;
|
||||
|
||||
/// <summary>
|
||||
/// Google Drive tests
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class GoogleDriveTests : BaseTest
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
public Task TestGoogleDriveSimple()
|
||||
{
|
||||
CheckRequiredEnvironment(["TESTCREDENTIAL_GOOGLEDRIVE_TOKEN","TESTCREDENTIAL_GOOGLEDRIVE_FOLDER"]);
|
||||
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[]
|
||||
{
|
||||
$"googledrive:///{Environment.GetEnvironmentVariable("TESTCREDENTIAL_GOOGLEDRIVE_FOLDER")}?authid={Environment.GetEnvironmentVariable("TESTCREDENTIAL_GOOGLEDRIVE_TOKEN")}",
|
||||
|
||||
}.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0) Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
|
||||
return Task.CompletedTask;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Glboal parameters to be used on all tests
|
||||
/// </summary>
|
||||
public static class Parameters
|
||||
{
|
||||
// Standard parameters for the backend tester
|
||||
public static string[] GlobalTestParameters =>
|
||||
[
|
||||
"--auto-clean",
|
||||
"--auto-create-folder",
|
||||
"--extended-chars=_-",
|
||||
"--force",
|
||||
$"--max-file-size={Environment.GetEnvironmentVariable("MAX_FILE_SIZE") ?? "1000kb"}",
|
||||
$"--number-of-files={Environment.GetEnvironmentVariable("NUMBER_OF_FILES") ?? "20"}"
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
# Environment variables for tests
|
||||
|
||||
On github actions these are mapped 1:1 to secrets, even the non password fields are stored in secrets.
|
||||
|
||||
Tests like FTP, SSH and Webdav are self-contained, they do not require any environment variable.
|
||||
|
||||
## General
|
||||
|
||||
These control the size and number of files generated.
|
||||
|
||||
```
|
||||
MAX_FILE_SIZE default is 1000kb
|
||||
NUMBER_OF_FILES default is 20
|
||||
```
|
||||
|
||||
## Google Drive:
|
||||
|
||||
Google Drive credentials are mapped to the following environment variables:
|
||||
|
||||
```
|
||||
TESTCREDENTIAL_GOOGLEDRIVE_FOLDER
|
||||
TESTCREDENTIAL_GOOGLEDRIVE_TOKEN
|
||||
```
|
||||
## S3
|
||||
|
||||
S3 credentials are mapped to the following environment variables:
|
||||
|
||||
Attention: **AWS TESTCREDENTIAL_S3_SECRET is URI escaped automatically, supply the raw value.**
|
||||
|
||||
```
|
||||
TESTCREDENTIAL_S3_KEY
|
||||
TESTCREDENTIAL_S3_SECRET
|
||||
TESTCREDENTIAL_S3_BUCKETNAME
|
||||
TESTCREDENTIAL_S3_REGION
|
||||
```
|
||||
|
||||
## Dropbox
|
||||
|
||||
Dropbox credentials are mapped to the following environment variables:
|
||||
|
||||
```
|
||||
TESTCREDENTIAL_DROPBOX_FOLDER
|
||||
TESTCREDENTIAL_DROPBOX_TOKEN
|
||||
```
|
||||
|
||||
## Azure Blob
|
||||
|
||||
Attention: **TESTCREDENTIAL_AZURE_ACCESSKEY is URI escaped automatically, supply the raw value.**
|
||||
|
||||
|
||||
```
|
||||
TESTCREDENTIAL_AZURE_ACCOUNTNAME
|
||||
TESTCREDENTIAL_AZURE_ACCESSKEY
|
||||
TESTCREDENTIAL_AZURE_CONTAINERNAME
|
||||
```
|
||||
|
||||
## Running the tests
|
||||
|
||||
[TestContainers](https://testcontainers.org/) is a pre-requisite for SSH, FTP and Webdav tests. It is not required for the other tests.
|
||||
|
||||
Set the environment variables as described above, then run the tests using the following commands:
|
||||
|
||||
Minimal Verbosity:
|
||||
|
||||
`dotnet test Duplicati.Backend.Tests.sln --logger:"console;verbosity=normal"`
|
||||
|
||||
Running with full verbosity (useful if tests are failing):
|
||||
|
||||
`dotnet test Duplicati.Backend.Tests.sln --logger:"console;verbosity=detailed"`
|
||||
|
||||
Running specific tests:
|
||||
|
||||
`dotnet test Duplicati.Backend.Tests.sln --logger:"console;verbosity=detailed" --filter="Name=TestDropBox"`
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.S3;
|
||||
|
||||
/// <summary>
|
||||
/// S3 Tests
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class S3Tests : BaseTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform tests using AWS Client
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TestMethod]
|
||||
public Task TestS3WithAwsClient()
|
||||
{
|
||||
return TestS3WithClient("aws");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform tests using Minio Client
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TestMethod]
|
||||
public Task TestS3WithMinioClient()
|
||||
{
|
||||
return TestS3WithClient("minio");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs tests with selected client. The S3 tests don't have any additional parameters to be set or tested.
|
||||
/// </summary>
|
||||
/// <param name="client">client to be used, either aws or minio</param>
|
||||
/// <returns></returns>
|
||||
private Task TestS3WithClient(string client)
|
||||
{
|
||||
CheckRequiredEnvironment([
|
||||
"TESTCREDENTIAL_S3_KEY",
|
||||
"TESTCREDENTIAL_S3_SECRET",
|
||||
"TESTCREDENTIAL_S3_BUCKETNAME",
|
||||
"TESTCREDENTIAL_S3_REGION"
|
||||
]);
|
||||
|
||||
Console.WriteLine( $"s3://{Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_BUCKETNAME")}/?s3-location-constraint={Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_REGION")}&s3-storage-class=&s3-client={client}&auth-username={Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_KEY")}&auth-password={Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_SECRET")}");
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[]
|
||||
{
|
||||
$"s3://{Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_BUCKETNAME")}/?s3-location-constraint={Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_REGION")}&s3-storage-class=&s3-client={client}&auth-username={Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_KEY")}&auth-password={Uri.EscapeDataString(Environment.GetEnvironmentVariable("TESTCREDENTIAL_S3_SECRET")!)}"
|
||||
}.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0) Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.SSH;
|
||||
|
||||
/// <summary>
|
||||
/// SSH Tests
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class SshTests : BaseSftpgoTest
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Tests connecting to SSH using password authentication
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task TestSSHWithPassword()
|
||||
{
|
||||
|
||||
var outputConsumer = new OutputConsumer();
|
||||
var filePermissions = UnixFileModes.UserRead | UnixFileModes.UserWrite | UnixFileModes.UserExecute |
|
||||
UnixFileModes.GroupRead | UnixFileModes.GroupWrite | UnixFileModes.GroupExecute |
|
||||
UnixFileModes.OtherRead | UnixFileModes.OtherWrite | UnixFileModes.OtherExecute;
|
||||
|
||||
var temporaryKeysDir = CreateHttpsCertificates();
|
||||
|
||||
CreateUsersFile(temporaryKeysDir);
|
||||
|
||||
var container = new ContainerBuilder()
|
||||
.WithImage("drakkan/sftpgo")
|
||||
.WithEnvironment("SFTPGO_LOG_LEVEL", "debug")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_FROM", "/var/lib/sftpgo/users.json")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_CLEAN", "0")
|
||||
.WithEnvironment("SFTPGO_SFTPD__BINDINGS__0__PORT", "3333")
|
||||
.WithPortBinding(3000, 3333)
|
||||
.WithResourceMapping(temporaryKeysDir, "/var/lib/sftpgo/", filePermissions)
|
||||
.WithOutputConsumer(outputConsumer)
|
||||
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(3333))
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Starting container");
|
||||
await container.StartAsync();
|
||||
|
||||
// Once started we will already cleanup temporary directory
|
||||
temporaryKeysDir.Delete(true);
|
||||
|
||||
Console.WriteLine("Waiting X seconds");
|
||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
|
||||
// Console.WriteLine($"TCP Connect testing, @::1 is open = { await IsPortOpenAsync("::1",3000) }");
|
||||
// Console.WriteLine($"TCP Connect testing, @localhost is open = { await IsPortOpenAsync("localhost",3000) }");
|
||||
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[]
|
||||
{
|
||||
$"ssh://{TEST_USER_NAME}:{TEST_USER_PASSWORD}@127.0.0.1:3000",
|
||||
"--ssh-accept-any-fingerprints"
|
||||
}.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0)
|
||||
{
|
||||
Console.WriteLine(await outputConsumer.GetStreamsOutput());
|
||||
Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
}
|
||||
|
||||
await container.StopAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Utility;
|
||||
public class OutputConsumer : IOutputConsumer
|
||||
{
|
||||
private readonly MemoryStream _stdout = new();
|
||||
private readonly MemoryStream _stderr = new();
|
||||
|
||||
public bool Enabled => true;
|
||||
|
||||
public Stream Stdout => _stdout;
|
||||
|
||||
public Stream Stderr => _stderr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_stdout.Dispose();
|
||||
_stderr.Dispose();
|
||||
}
|
||||
|
||||
public async Task<string> GetStreamsOutput()
|
||||
{
|
||||
var output = new StringBuilder();
|
||||
|
||||
_stdout.Position = 0;
|
||||
using (var reader = new StreamReader(_stdout, leaveOpen: true))
|
||||
{
|
||||
output.AppendLine("STDOUT:");
|
||||
output.AppendLine(await reader.ReadToEndAsync());
|
||||
}
|
||||
|
||||
_stderr.Position = 0;
|
||||
using (var reader = new StreamReader(_stderr, leaveOpen: true))
|
||||
{
|
||||
output.AppendLine("STDERR:");
|
||||
output.AppendLine(await reader.ReadToEndAsync());
|
||||
}
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace Duplicati.Backend.Tests.Webdav;
|
||||
|
||||
[TestClass]
|
||||
public sealed class WebDavTests : BaseSftpgoTest
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
public async Task TestWebdavHttps()
|
||||
{
|
||||
var outputConsumer = new OutputConsumer();
|
||||
var filePermissions = UnixFileModes.UserRead | UnixFileModes.UserWrite | UnixFileModes.UserExecute |
|
||||
UnixFileModes.GroupRead | UnixFileModes.GroupWrite | UnixFileModes.GroupExecute |
|
||||
UnixFileModes.OtherRead | UnixFileModes.OtherWrite | UnixFileModes.OtherExecute;
|
||||
|
||||
var temporaryKeysDir = CreateHttpsCertificates();
|
||||
|
||||
CreateUsersFile(temporaryKeysDir);
|
||||
|
||||
var container = new ContainerBuilder()
|
||||
.WithImage("drakkan/sftpgo")
|
||||
.WithEnvironment("SFTPGO_LOG_LEVEL", "debug")
|
||||
.WithEnvironment("SFTPGO_WEBDAVD__BINDINGS__0__ENABLE_HTTPS", "1")
|
||||
.WithEnvironment("SFTPGO_WEBDAVD__BINDINGS__0__PORT", "8090")
|
||||
.WithEnvironment("SFTPGO_WEBDAVD__BINDINGS__0__CERTIFICATE_FILE", "fullchain.pem")
|
||||
.WithEnvironment("SFTPGO_WEBDAVD__BINDINGS__0__CERTIFICATE_KEY_FILE", "privkey.pem")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_FROM", "/var/lib/sftpgo/users.json")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_CLEAN", "0")
|
||||
.WithResourceMapping(temporaryKeysDir, "/var/lib/sftpgo/", filePermissions)
|
||||
.WithPortBinding(8090, 8090)
|
||||
.WithOutputConsumer(outputConsumer)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Starting container");
|
||||
await container.StartAsync();
|
||||
|
||||
// Once started we will already cleanup temporary directory
|
||||
temporaryKeysDir.Delete(true);
|
||||
|
||||
Console.WriteLine("Waiting X seconds");
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
|
||||
// Print logs
|
||||
Console.WriteLine("Fetching logs...");
|
||||
var containerStartupLogs = await outputConsumer.GetStreamsOutput();
|
||||
Console.WriteLine(containerStartupLogs);
|
||||
|
||||
// Running this ignoring the certificate
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[] { $"webdavs://{TEST_USER_NAME}:{TEST_USER_PASSWORD}@localhost:8090/", "--accept-any-ssl-certificate=true" }.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode != 0)
|
||||
{
|
||||
Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
}
|
||||
|
||||
// Running not ignoring the certificate, should return non-zero exit code
|
||||
exitCode = CommandLine.BackendTester.Program.Main(
|
||||
new[] { $"webdavs://{TEST_USER_NAME}:{TEST_USER_PASSWORD}@localhost:8090/", "--accept-any-ssl-certificate=false" }.Concat(Parameters.GlobalTestParameters).ToArray());
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
Assert.Fail("BackendTester is returning zero when it should return non-zero exit code, check logs for details");
|
||||
}
|
||||
|
||||
Console.WriteLine("Stopping container");
|
||||
await container.StopAsync();
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task TestWebdavHttp()
|
||||
{
|
||||
var outputConsumer = new OutputConsumer();
|
||||
var filePermissions = UnixFileModes.UserRead | UnixFileModes.UserWrite | UnixFileModes.UserExecute |
|
||||
UnixFileModes.GroupRead | UnixFileModes.GroupWrite | UnixFileModes.GroupExecute |
|
||||
UnixFileModes.OtherRead | UnixFileModes.OtherWrite | UnixFileModes.OtherExecute;
|
||||
|
||||
var temporaryKeysDir = CreateHttpsCertificates();
|
||||
|
||||
CreateUsersFile(temporaryKeysDir);
|
||||
|
||||
var container = new ContainerBuilder()
|
||||
.WithImage("drakkan/sftpgo")
|
||||
.WithEnvironment("SFTPGO_LOG_LEVEL", "debug")
|
||||
.WithEnvironment("SFTPGO_WEBDAVD__BINDINGS__0__PORT", "8090")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_FROM", "/var/lib/sftpgo/users.json")
|
||||
.WithEnvironment("SFTPGO_LOADDATA_CLEAN", "0")
|
||||
.WithResourceMapping(temporaryKeysDir, "/var/lib/sftpgo/", filePermissions)
|
||||
.WithPortBinding(8091, 8090)
|
||||
.WithOutputConsumer(outputConsumer)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Starting container");
|
||||
await container.StartAsync();
|
||||
|
||||
// Once started we will already cleanup temporary directory
|
||||
temporaryKeysDir.Delete(true);
|
||||
|
||||
Console.WriteLine("Waiting X seconds");
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
|
||||
// Print logs
|
||||
Console.WriteLine("Fetching logs...");
|
||||
var containerStartupLogs = await outputConsumer.GetStreamsOutput();
|
||||
Console.WriteLine(containerStartupLogs);
|
||||
|
||||
// Running this ignoring the certificate
|
||||
var exitCode = CommandLine.BackendTester.Program.Main(
|
||||
["webdav://testuser:testpassword@localhost:8091/"]);
|
||||
|
||||
if (exitCode != 0)
|
||||
{
|
||||
Assert.Fail("BackendTester is returning non-zero exit code, check logs for details");
|
||||
}
|
||||
|
||||
Console.WriteLine("Stopping container");
|
||||
await container.StopAsync();
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user