Add integration tests for the API clients
This commit is contained in:
parent
2fb3546b76
commit
3a3b6f840e
10 changed files with 188 additions and 4 deletions
|
@ -4,9 +4,20 @@ stages:
|
|||
- test
|
||||
- release
|
||||
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
DOCKER_CERT_PATH: "/certs/client"
|
||||
DOCKER_TLS_VERIFY: 0
|
||||
DOCKER_HOST: 'tcp://docker:2375'
|
||||
|
||||
test:
|
||||
stage: test
|
||||
services:
|
||||
- docker:dind
|
||||
variables:
|
||||
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/docker
|
||||
script:
|
||||
- curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.4.tgz | tar -xzv -C /usr/local/
|
||||
- dotnet tool restore
|
||||
- dotnet nuke Test
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "INetMock.Client.Test", "tes
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{37738E95-E68E-4242-B7D7-9591605D8E33}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "INetMock.Client.IntegrationTest", "tests\INetMock.Client.IntegrationTest\INetMock.Client.IntegrationTest.csproj", "{D12E0C79-2E27-4FDB-94E7-402EBA267F72}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -39,9 +41,14 @@ Global
|
|||
{66DAC329-57DE-4218-9880-84E65E91E623}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{66DAC329-57DE-4218-9880-84E65E91E623}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{66DAC329-57DE-4218-9880-84E65E91E623}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D12E0C79-2E27-4FDB-94E7-402EBA267F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D12E0C79-2E27-4FDB-94E7-402EBA267F72}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D12E0C79-2E27-4FDB-94E7-402EBA267F72}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D12E0C79-2E27-4FDB-94E7-402EBA267F72}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{4B1CFFB0-23B5-4238-BFCC-4155F459FF8E} = {07100561-E3C0-4B95-92E1-D2D3BA12C3A6}
|
||||
{66DAC329-57DE-4218-9880-84E65E91E623} = {4FF6267B-A7EC-4277-98EA-39155A82C886}
|
||||
{D12E0C79-2E27-4FDB-94E7-402EBA267F72} = {4FF6267B-A7EC-4277-98EA-39155A82C886}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
3
assets/integration-tests.dockerfile
Normal file
3
assets/integration-tests.dockerfile
Normal file
|
@ -0,0 +1,3 @@
|
|||
FROM registry.gitlab.com/inetmock/inetmock:latest
|
||||
|
||||
USER root
|
|
@ -1,3 +1,4 @@
|
|||
using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
using Nuke.Common;
|
||||
using Nuke.Common.CI;
|
||||
|
@ -7,6 +8,7 @@ using Nuke.Common.Git;
|
|||
using Nuke.Common.IO;
|
||||
using Nuke.Common.ProjectModel;
|
||||
using Nuke.Common.Tooling;
|
||||
using Nuke.Common.Tools.Docker;
|
||||
using Nuke.Common.Tools.DotNet;
|
||||
using Nuke.Common.Tools.GitVersion;
|
||||
using Nuke.Common.Utilities.Collections;
|
||||
|
@ -79,8 +81,14 @@ class Build : NukeBuild
|
|||
.EnableNoRestore());
|
||||
});
|
||||
|
||||
Target IntegrationTestImage => _ => _
|
||||
.Executes(() => DockerTasks.DockerBuild(s => s
|
||||
.SetFile(Path.Join("assets", "integration-tests.dockerfile"))
|
||||
.SetTag("inetmock-root")
|
||||
.SetPath(".")));
|
||||
|
||||
Target Test => _ => _
|
||||
.DependsOn(Compile)
|
||||
.DependsOn(Compile, IntegrationTestImage)
|
||||
.Executes(() => DotNetTest(s => s
|
||||
.SetProjectFile(Solution)
|
||||
.SetConfiguration(Configuration)
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using INetMock.Client.Audit.Serialization;
|
||||
using INetMock.Client.Grpc;
|
||||
using INetMock.Client.Rpc;
|
||||
|
||||
namespace INetMock.Client.Audit.Client
|
||||
|
@ -18,7 +19,7 @@ namespace INetMock.Client.Audit.Client
|
|||
}
|
||||
|
||||
public AuditApiClient(Uri address, GrpcChannelOptions? options = null) : this(
|
||||
GrpcChannel.ForAddress(address, options ?? new GrpcChannelOptions()))
|
||||
ChannelFactory.ForAddress(address, options ?? new GrpcChannelOptions()))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
40
src/INetMock.Client/Grpc/ChannelFactory.cs
Normal file
40
src/INetMock.Client/Grpc/ChannelFactory.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Sockets;
|
||||
using Grpc.Net.Client;
|
||||
|
||||
namespace INetMock.Client.Grpc
|
||||
{
|
||||
internal static class ChannelFactory
|
||||
{
|
||||
internal static GrpcChannel ForAddress(Uri uri, GrpcChannelOptions options) =>
|
||||
uri.Scheme.ToLowerInvariant() switch
|
||||
{
|
||||
"unix" => ForUnixSocket(uri.AbsolutePath, options),
|
||||
_ => GrpcChannel.ForAddress(uri, options)
|
||||
};
|
||||
|
||||
private static GrpcChannel ForUnixSocket(string path, GrpcChannelOptions options)
|
||||
{
|
||||
var endpoint = new UnixDomainSocketEndPoint(path);
|
||||
options.HttpHandler = new SocketsHttpHandler
|
||||
{
|
||||
ConnectCallback = async (_, cancellationToken) =>
|
||||
{
|
||||
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
|
||||
try
|
||||
{
|
||||
await socket.ConnectAsync(endpoint, cancellationToken).ConfigureAwait(false);
|
||||
return new NetworkStream(socket, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
socket.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
return GrpcChannel.ForAddress("http://localhost", options);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||
using Google.Protobuf.WellKnownTypes;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using INetMock.Client.Grpc;
|
||||
using INetMock.Client.Rpc;
|
||||
|
||||
namespace INetMock.Client.PCAP.Client
|
||||
|
@ -21,7 +22,7 @@ namespace INetMock.Client.PCAP.Client
|
|||
}
|
||||
|
||||
public PcapApiClient(Uri address, GrpcChannelOptions? options = null)
|
||||
: this(GrpcChannel.ForAddress(address, options ?? new GrpcChannelOptions()))
|
||||
: this(ChannelFactory.ForAddress(address, options ?? new GrpcChannelOptions()))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ namespace INetMock.Client.PCAP.Client
|
|||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return new Subscription(key.Substring(0, splitIndex), key.Substring(splitIndex), key);
|
||||
return new Subscription(key.Substring(splitIndex+1), key.Substring(0, splitIndex), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNet.Testcontainers" Version="1.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\INetMock.Client\INetMock.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using DotNet.Testcontainers.Containers.Builders;
|
||||
using DotNet.Testcontainers.Containers.Modules;
|
||||
using DotNet.Testcontainers.Containers.WaitStrategies;
|
||||
using Xunit;
|
||||
|
||||
namespace INetMock.Client.IntegrationTest
|
||||
{
|
||||
public class INetMockServerFixture : IAsyncLifetime
|
||||
{
|
||||
private readonly TestcontainersContainer _inetmockContainer;
|
||||
|
||||
public INetMockServerFixture()
|
||||
{
|
||||
_inetmockContainer = new TestcontainersBuilder<TestcontainersContainer>()
|
||||
.WithImage("inetmock-root:latest")
|
||||
.WithCommand("serve")
|
||||
.WithPortBinding(80, true)
|
||||
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(80))
|
||||
.WithDockerEndpoint(Environment.GetEnvironmentVariable("DOCKER_HOST") ?? "unix:///var/run/docker.sock")
|
||||
.WithMount(Path.GetTempPath(), "/var/run/inetmock")
|
||||
.WithCleanUp(true)
|
||||
.Build();
|
||||
}
|
||||
|
||||
public Uri SocketPath => new ($"unix://{Path.Join(Path.GetTempPath(), "inetmock.sock")}", UriKind.Absolute);
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await _inetmockContainer.StartAsync();
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await _inetmockContainer.StopAsync();
|
||||
await _inetmockContainer.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using INetMock.Client.PCAP;
|
||||
using INetMock.Client.PCAP.Client;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace INetMock.Client.IntegrationTest.PCAP.Client
|
||||
{
|
||||
public class PcapApiClientTests : IClassFixture<INetMockServerFixture>
|
||||
{
|
||||
private readonly ITestOutputHelper _outputHelper;
|
||||
private readonly IPcapApiClient _apiClient;
|
||||
|
||||
public PcapApiClientTests(ITestOutputHelper testOutputHelper, INetMockServerFixture inetmockFixture)
|
||||
{
|
||||
_outputHelper = testOutputHelper;
|
||||
_apiClient = new PcapApiClient(inetmockFixture.SocketPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ListAvailableDevicesAsync_RunningContainer_AtLeastLoopbackDevice()
|
||||
{
|
||||
var devs = await _apiClient.ListAvailableDevicesAsync();
|
||||
|
||||
Assert.Contains(devs, device => device.Name.Equals("lo"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ListActiveRecordingsAsync_NoRecordingsRunning_EmptyResult()
|
||||
{
|
||||
var recordings = await _apiClient.ListActiveRecordingsAsync();
|
||||
|
||||
Assert.Empty(recordings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void StartPcapFileRecordingAsync_RecordLoopbackInterface_RunningRecording()
|
||||
{
|
||||
const string targetPath = "/tmp/lo_record.pcap";
|
||||
await _apiClient.StartPcapFileRecordingAsync(new("lo", targetPath));
|
||||
|
||||
var subscriptions = await _apiClient.ListActiveRecordingsAsync();
|
||||
Assert.Contains(subscriptions, subscription => subscription.Device.Equals("lo") && subscription.ConsumerName.Equals(targetPath));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue