diff --git a/Directory.Packages.props b/Directory.Packages.props
index 039256594..34c2c98ea 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -57,6 +57,7 @@
+
diff --git a/Testcontainers.sln b/Testcontainers.sln
index 9595905ed..46bb2474b 100644
--- a/Testcontainers.sln
+++ b/Testcontainers.sln
@@ -85,6 +85,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.PostgreSql",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.PubSub", "src\Testcontainers.PubSub\Testcontainers.PubSub.csproj", "{E6642255-667D-476B-B584-089AA5E6C0B1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Qdrant", "src\Testcontainers.Qdrant\Testcontainers.Qdrant.csproj", "{7C98973D-53D7-49F9-BDFE-E3268F402584}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.RabbitMq", "src\Testcontainers.RabbitMq\Testcontainers.RabbitMq.csproj", "{A6D480BC-FDE8-4B92-A2A6-FF16BEE486AE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.RavenDb", "src\Testcontainers.RavenDb\Testcontainers.RavenDb.csproj", "{F6394475-D6F1-46E2-81BF-4BA78A40B878}"
@@ -179,6 +181,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.PostgreSql.T
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.PubSub.Tests", "tests\Testcontainers.PubSub.Tests\Testcontainers.PubSub.Tests.csproj", "{0F86BCE8-62E1-4BFC-AA84-63C7514C90AC}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Qdrant.Tests", "tests\Testcontainers.Qdrant.Tests\Testcontainers.Qdrant.Tests.csproj", "{9DCE3E7F-B341-4AD0-BAAA-C3B91EB91B0D}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.RabbitMq.Tests", "tests\Testcontainers.RabbitMq.Tests\Testcontainers.RabbitMq.Tests.csproj", "{19564567-1736-4626-B406-17E4E02F18B2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.RavenDb.Tests", "tests\Testcontainers.RavenDb.Tests\Testcontainers.RavenDb.Tests.csproj", "{D53726B6-5447-47E6-B881-A44EFF6E5534}"
@@ -348,6 +352,10 @@ Global
{E6642255-667D-476B-B584-089AA5E6C0B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6642255-667D-476B-B584-089AA5E6C0B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6642255-667D-476B-B584-089AA5E6C0B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7C98973D-53D7-49F9-BDFE-E3268F402584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7C98973D-53D7-49F9-BDFE-E3268F402584}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7C98973D-53D7-49F9-BDFE-E3268F402584}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7C98973D-53D7-49F9-BDFE-E3268F402584}.Release|Any CPU.Build.0 = Release|Any CPU
{A6D480BC-FDE8-4B92-A2A6-FF16BEE486AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6D480BC-FDE8-4B92-A2A6-FF16BEE486AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6D480BC-FDE8-4B92-A2A6-FF16BEE486AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -536,6 +544,10 @@ Global
{0F86BCE8-62E1-4BFC-AA84-63C7514C90AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F86BCE8-62E1-4BFC-AA84-63C7514C90AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F86BCE8-62E1-4BFC-AA84-63C7514C90AC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9DCE3E7F-B341-4AD0-BAAA-C3B91EB91B0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9DCE3E7F-B341-4AD0-BAAA-C3B91EB91B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9DCE3E7F-B341-4AD0-BAAA-C3B91EB91B0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9DCE3E7F-B341-4AD0-BAAA-C3B91EB91B0D}.Release|Any CPU.Build.0 = Release|Any CPU
{19564567-1736-4626-B406-17E4E02F18B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19564567-1736-4626-B406-17E4E02F18B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19564567-1736-4626-B406-17E4E02F18B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -606,6 +618,7 @@ Global
{464F1120-A0DA-462B-B9E8-45176D883625} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{8AB91636-9055-4900-A72A-7CFFACDFDBF0} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{E6642255-667D-476B-B584-089AA5E6C0B1} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
+ {7C98973D-53D7-49F9-BDFE-E3268F402584} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{A6D480BC-FDE8-4B92-A2A6-FF16BEE486AE} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{F6394475-D6F1-46E2-81BF-4BA78A40B878} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{BFDA179A-40EB-4CEB-B8E9-0DF32C65E2C5} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
@@ -653,6 +666,7 @@ Global
{3E55CBE8-AFE8-426D-9470-49D63CD1051C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{56D0DCA5-567F-4B3B-8B79-CB108F8EB8A6} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{0F86BCE8-62E1-4BFC-AA84-63C7514C90AC} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+ {9DCE3E7F-B341-4AD0-BAAA-C3B91EB91B0D} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{19564567-1736-4626-B406-17E4E02F18B2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{D53726B6-5447-47E6-B881-A44EFF6E5534} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{31EE94A0-E721-4073-B6F1-DD912D004DEF} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
diff --git a/src/Testcontainers.Qdrant/.editorconfig b/src/Testcontainers.Qdrant/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/src/Testcontainers.Qdrant/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/src/Testcontainers.Qdrant/QdrantBuilder.cs b/src/Testcontainers.Qdrant/QdrantBuilder.cs
new file mode 100644
index 000000000..07e388c88
--- /dev/null
+++ b/src/Testcontainers.Qdrant/QdrantBuilder.cs
@@ -0,0 +1,94 @@
+namespace Testcontainers.Qdrant;
+
+///
+[PublicAPI]
+public sealed class QdrantBuilder : ContainerBuilder
+{
+ public const string QdrantImage = "qdrant/qdrant:v1.8.3";
+
+ public const ushort QdrantHttpPort = 6333;
+
+ public const ushort QdrantGrpcPort = 6334;
+
+ public const string QdrantTlsCertFilePath = "/qdrant/tls/cert.pem";
+
+ public const string QdrantTlsKeyFilePath = "/qdrant/tls/key.pem";
+
+ public QdrantBuilder() : this(new QdrantConfiguration()) =>
+ DockerResourceConfiguration = Init().DockerResourceConfiguration;
+
+ private QdrantBuilder(QdrantConfiguration dockerResourceConfiguration) : base(dockerResourceConfiguration) =>
+ DockerResourceConfiguration = dockerResourceConfiguration;
+
+ ///
+ /// The API key used to secure the instance. A certificate and private key should also be
+ /// provided to to enable Transport Layer Security (TLS).
+ ///
+ /// The API key
+ public QdrantBuilder WithApiKey(string apiKey) =>
+ Merge(DockerResourceConfiguration, new QdrantConfiguration(apiKey: apiKey))
+ .WithEnvironment("QDRANT__SERVICE__API_KEY", apiKey);
+
+ ///
+ /// A certificate and private key to enable Transport Layer Security (TLS).
+ ///
+ /// A public certificate in PEM format
+ /// A private key for the certificate in PEM format
+ public QdrantBuilder WithCertificate(string certificate, string privateKey)
+ {
+ return Merge(DockerResourceConfiguration, new QdrantConfiguration(certificate: certificate, privateKey: privateKey))
+ .WithEnvironment("QDRANT__SERVICE__ENABLE_TLS", "1")
+ .WithResourceMapping(Encoding.UTF8.GetBytes(certificate), QdrantTlsCertFilePath)
+ .WithEnvironment("QDRANT__TLS__CERT", QdrantTlsCertFilePath)
+ .WithResourceMapping(Encoding.UTF8.GetBytes(privateKey), QdrantTlsKeyFilePath)
+ .WithEnvironment("QDRANT__TLS__KEY", QdrantTlsKeyFilePath);
+ }
+
+ ///
+ public override QdrantContainer Build()
+ {
+ Validate();
+
+ var waitStrategy = Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request =>
+ {
+ var httpWaitStrategy = request.ForPort(QdrantHttpPort).ForPath("/readyz");
+
+ // allow any certificate defined to pass validation
+ if (DockerResourceConfiguration.Certificate is not null)
+ {
+ httpWaitStrategy.UsingTls()
+ .UsingHttpMessageHandler(new HttpClientHandler
+ {
+ ServerCertificateCustomValidationCallback = (_, _, _, _) => true
+ });
+ }
+
+ return httpWaitStrategy;
+ });
+
+ var qdrantBuilder = DockerResourceConfiguration.WaitStrategies.Count() > 1 ? this : WithWaitStrategy(waitStrategy);
+ return new QdrantContainer(qdrantBuilder.DockerResourceConfiguration);
+ }
+
+ ///
+ protected override QdrantBuilder Init() =>
+ base.Init()
+ .WithImage(QdrantImage)
+ .WithPortBinding(QdrantHttpPort, true)
+ .WithPortBinding(QdrantGrpcPort, true);
+
+ ///
+ protected override QdrantBuilder Clone(IResourceConfiguration resourceConfiguration) =>
+ Merge(DockerResourceConfiguration, new QdrantConfiguration(resourceConfiguration));
+
+ ///
+ protected override QdrantBuilder Merge(QdrantConfiguration oldValue, QdrantConfiguration newValue) =>
+ new(new QdrantConfiguration(oldValue, newValue));
+
+ ///
+ protected override QdrantConfiguration DockerResourceConfiguration { get; }
+
+ ///
+ protected override QdrantBuilder Clone(IContainerConfiguration resourceConfiguration) =>
+ Merge(DockerResourceConfiguration, new QdrantConfiguration(resourceConfiguration));
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Qdrant/QdrantConfiguration.cs b/src/Testcontainers.Qdrant/QdrantConfiguration.cs
new file mode 100644
index 000000000..1f80db5f4
--- /dev/null
+++ b/src/Testcontainers.Qdrant/QdrantConfiguration.cs
@@ -0,0 +1,71 @@
+namespace Testcontainers.Qdrant;
+
+///
+[PublicAPI]
+public sealed class QdrantConfiguration : ContainerConfiguration
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public QdrantConfiguration(string apiKey = null, string certificate = null, string privateKey = null)
+ {
+ ApiKey = apiKey;
+ Certificate = certificate;
+ PrivateKey = privateKey;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public QdrantConfiguration(IResourceConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public QdrantConfiguration(IContainerConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public QdrantConfiguration(QdrantConfiguration resourceConfiguration)
+ : this(new QdrantConfiguration(), resourceConfiguration)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old Docker resource configuration.
+ /// The new Docker resource configuration.
+ public QdrantConfiguration(QdrantConfiguration oldValue, QdrantConfiguration newValue)
+ : base(oldValue, newValue)
+ {
+ ApiKey = BuildConfiguration.Combine(oldValue.ApiKey, newValue.ApiKey);
+ Certificate = BuildConfiguration.Combine(oldValue.Certificate, newValue.Certificate);
+ PrivateKey = BuildConfiguration.Combine(oldValue.PrivateKey, newValue.PrivateKey);
+ }
+
+ ///
+ /// Gets the API key used to secure Qdrant.
+ ///
+ public string ApiKey { get; }
+
+ ///
+ /// Gets the certificate used to configure Transport Layer Security. Certificate must be in PEM format.
+ ///
+ public string Certificate { get; }
+
+ ///
+ /// Gets the private key used to configure Transport Layer Security. Private key must be in PEM format.
+ ///
+ public string PrivateKey { get; }
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Qdrant/QdrantContainer.cs b/src/Testcontainers.Qdrant/QdrantContainer.cs
new file mode 100644
index 000000000..0851188c5
--- /dev/null
+++ b/src/Testcontainers.Qdrant/QdrantContainer.cs
@@ -0,0 +1,33 @@
+namespace Testcontainers.Qdrant;
+
+///
+[PublicAPI]
+public sealed class QdrantContainer : DockerContainer
+{
+ private readonly QdrantConfiguration _configuration;
+
+ public QdrantContainer(QdrantConfiguration configuration) : base(configuration)
+ {
+ _configuration = configuration;
+ }
+
+ ///
+ /// Gets the connection string for connecting to Qdrant REST APIs
+ ///
+ public string GetHttpConnectionString()
+ {
+ var scheme = _configuration.Certificate != null ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
+ var endpoint = new UriBuilder(scheme, Hostname, GetMappedPublicPort(QdrantBuilder.QdrantHttpPort));
+ return endpoint.ToString();
+ }
+
+ ///
+ /// Gets the connection string for connecting to Qdrant gRPC APIs
+ ///
+ public string GetGrpcConnectionString()
+ {
+ var scheme = _configuration.Certificate != null ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
+ var endpoint = new UriBuilder(scheme, Hostname, GetMappedPublicPort(QdrantBuilder.QdrantGrpcPort));
+ return endpoint.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/Testcontainers.Qdrant/Testcontainers.Qdrant.csproj b/src/Testcontainers.Qdrant/Testcontainers.Qdrant.csproj
new file mode 100644
index 000000000..51735310a
--- /dev/null
+++ b/src/Testcontainers.Qdrant/Testcontainers.Qdrant.csproj
@@ -0,0 +1,12 @@
+
+
+ net6.0;net8.0;netstandard2.0;netstandard2.1;net462
+ latest
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Testcontainers.Qdrant/Usings.cs b/src/Testcontainers.Qdrant/Usings.cs
new file mode 100644
index 000000000..b2b9653ef
--- /dev/null
+++ b/src/Testcontainers.Qdrant/Usings.cs
@@ -0,0 +1,9 @@
+global using System;
+global using System.Linq;
+global using System.Net.Http;
+global using System.Text;
+global using Docker.DotNet.Models;
+global using DotNet.Testcontainers.Builders;
+global using DotNet.Testcontainers.Configurations;
+global using DotNet.Testcontainers.Containers;
+global using JetBrains.Annotations;
\ No newline at end of file
diff --git a/tests/Testcontainers.Qdrant.Tests/.editorconfig b/tests/Testcontainers.Qdrant.Tests/.editorconfig
new file mode 100644
index 000000000..6f066619d
--- /dev/null
+++ b/tests/Testcontainers.Qdrant.Tests/.editorconfig
@@ -0,0 +1 @@
+root = true
\ No newline at end of file
diff --git a/tests/Testcontainers.Qdrant.Tests/PemCertificate.cs b/tests/Testcontainers.Qdrant.Tests/PemCertificate.cs
new file mode 100644
index 000000000..661052e05
--- /dev/null
+++ b/tests/Testcontainers.Qdrant.Tests/PemCertificate.cs
@@ -0,0 +1,24 @@
+namespace Testcontainers.Qdrant;
+
+public record PemCertificate(string Certificate, string PrivateKey, string Thumbprint)
+{
+ public static PemCertificate Create(string commonName)
+ {
+ using var key = RSA.Create(2048);
+ var utcNow = DateTimeOffset.UtcNow;
+ var request = new CertificateRequest(
+ $"CN={commonName}",
+ key,
+ HashAlgorithmName.SHA256,
+ RSASignaturePadding.Pkcs1)
+ {
+ CertificateExtensions = { new X509BasicConstraintsExtension(false, false, 0, true) },
+ };
+
+ var certificate = request.CreateSelfSigned(utcNow, utcNow.AddYears(1));
+ return new PemCertificate(
+ certificate.ExportCertificatePem(),
+ certificate.GetRSAPrivateKey().ExportPkcs8PrivateKeyPem(),
+ certificate.GetCertHashString(HashAlgorithmName.SHA256));
+ }
+}
\ No newline at end of file
diff --git a/tests/Testcontainers.Qdrant.Tests/QdrantContainerApiKeyCertificateTest.cs b/tests/Testcontainers.Qdrant.Tests/QdrantContainerApiKeyCertificateTest.cs
new file mode 100644
index 000000000..f6b62e1a7
--- /dev/null
+++ b/tests/Testcontainers.Qdrant.Tests/QdrantContainerApiKeyCertificateTest.cs
@@ -0,0 +1,100 @@
+namespace Testcontainers.Qdrant;
+
+public sealed class QdrantContainerApiKeyCertificateTest : IAsyncLifetime
+{
+ private const string Host = "Testcontainers";
+ private const string ApiKey = "password!";
+ private static readonly PemCertificate Cert = PemCertificate.Create(Host);
+
+ private readonly QdrantContainer _qdrantContainer = new QdrantBuilder()
+ .WithApiKey(ApiKey)
+ .WithCertificate(Cert.Certificate, Cert.PrivateKey)
+ .Build();
+
+ public Task InitializeAsync()
+ {
+ return _qdrantContainer.StartAsync();
+ }
+
+ public Task DisposeAsync()
+ {
+ return _qdrantContainer.DisposeAsync().AsTask();
+ }
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task ListCollectionsReturnsValidResponse()
+ {
+ var httpMessageHandler = new HttpClientHandler
+ {
+ ServerCertificateCustomValidationCallback =
+ CertificateValidation.Thumbprint(Cert.Thumbprint),
+ };
+
+ var channel = GrpcChannel.ForAddress(
+ _qdrantContainer.GetGrpcConnectionString(),
+ new GrpcChannelOptions
+ {
+ HttpClient = new HttpClient(httpMessageHandler)
+ {
+ DefaultRequestHeaders = { Host = Host },
+ },
+ });
+ var callInvoker = channel.Intercept(metadata =>
+ {
+ metadata.Add("api-key", ApiKey);
+ return metadata;
+ });
+
+ var grpcClient = new QdrantGrpcClient(callInvoker);
+ var client = new QdrantClient(grpcClient);
+ var response = await client.ListCollectionsAsync();
+
+ Assert.Empty(response);
+ }
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task ListCollectionsWithoutApiKeyReturnsInvalidResponse()
+ {
+ var httpMessageHandler = new HttpClientHandler
+ {
+ ServerCertificateCustomValidationCallback =
+ CertificateValidation.Thumbprint(Cert.Thumbprint)
+ };
+
+ var channel = GrpcChannel.ForAddress(
+ _qdrantContainer.GetGrpcConnectionString(),
+ new GrpcChannelOptions
+ {
+ HttpClient = new HttpClient(httpMessageHandler)
+ {
+ DefaultRequestHeaders = { Host = Host },
+ },
+ });
+
+ var grpcClient = new QdrantGrpcClient(channel);
+ var client = new QdrantClient(grpcClient);
+
+ var exception = await Assert.ThrowsAsync(async () =>
+ await client.ListCollectionsAsync());
+
+ Assert.Equal(StatusCode.PermissionDenied, exception.Status.StatusCode);
+ }
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task ListCollectionsWithoutCertificateValidationReturnsInvalidResponse()
+ {
+ var client = new HttpClient
+ {
+ BaseAddress = new Uri(_qdrantContainer.GetHttpConnectionString()),
+ DefaultRequestHeaders = { Host = Host },
+ };
+
+ client.DefaultRequestHeaders.Add("api-key", ApiKey);
+
+ // The SSL connection could not be established
+ await Assert.ThrowsAsync(() => client.GetAsync("/collections"));
+ }
+}
\ No newline at end of file
diff --git a/tests/Testcontainers.Qdrant.Tests/QdrantContainerTest.cs b/tests/Testcontainers.Qdrant.Tests/QdrantContainerTest.cs
new file mode 100644
index 000000000..87e3815e3
--- /dev/null
+++ b/tests/Testcontainers.Qdrant.Tests/QdrantContainerTest.cs
@@ -0,0 +1,40 @@
+namespace Testcontainers.Qdrant;
+
+public sealed class QdrantContainerTest : IAsyncLifetime
+{
+ private readonly QdrantContainer _qdrantContainer = new QdrantBuilder().Build();
+
+ public Task InitializeAsync()
+ {
+ return _qdrantContainer.StartAsync();
+ }
+
+ public Task DisposeAsync()
+ {
+ return _qdrantContainer.DisposeAsync().AsTask();
+ }
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task PingReturnsValidResponse()
+ {
+ var client = new HttpClient
+ {
+ BaseAddress = new Uri(_qdrantContainer.GetHttpConnectionString()),
+ };
+
+ var response = await client.GetAsync("/");
+ Assert.True(response.IsSuccessStatusCode);
+ }
+
+ [Fact]
+ [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
+ public async Task ListCollectionsReturnsValidResponse()
+ {
+ var uri = new Uri(_qdrantContainer.GetGrpcConnectionString());
+ var client = new QdrantClient(uri.Host, uri.Port);
+
+ var response = await client.ListCollectionsAsync();
+ Assert.Empty(response);
+ }
+}
\ No newline at end of file
diff --git a/tests/Testcontainers.Qdrant.Tests/Testcontainers.Qdrant.Tests.csproj b/tests/Testcontainers.Qdrant.Tests/Testcontainers.Qdrant.Tests.csproj
new file mode 100644
index 000000000..e20447fc9
--- /dev/null
+++ b/tests/Testcontainers.Qdrant.Tests/Testcontainers.Qdrant.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+ net8.0
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Testcontainers.Qdrant.Tests/Usings.cs b/tests/Testcontainers.Qdrant.Tests/Usings.cs
new file mode 100644
index 000000000..abf2356ac
--- /dev/null
+++ b/tests/Testcontainers.Qdrant.Tests/Usings.cs
@@ -0,0 +1,12 @@
+global using System;
+global using System.Net.Http;
+global using System.Security.Cryptography;
+global using System.Security.Cryptography.X509Certificates;
+global using System.Threading.Tasks;
+global using DotNet.Testcontainers.Commons;
+global using Grpc.Core;
+global using Grpc.Core.Interceptors;
+global using Grpc.Net.Client;
+global using Qdrant.Client;
+global using Qdrant.Client.Grpc;
+global using Xunit;
\ No newline at end of file