From bd8eb7cc60530538c0b42d7085dcd14ce66d6fbf Mon Sep 17 00:00:00 2001
From: Pavel Gross
Date: Wed, 19 Feb 2025 10:55:57 +0300
Subject: [PATCH] [#33] Client: Add extended life tests
Signed-off-by: Pavel Gross
---
README.md | 2 +-
src/FrostFS.SDK.Client/FrostFSClient.cs | 31 +-
.../Interfaces/IFrostFSClient.cs | 3 +
.../Mappers/Netmap/PlacementPolicy.cs | 6 +-
.../Mappers/Netmap/Replica.cs | 13 +-
.../Mappers/Object/ObjectAttributeMapper.cs | 5 -
.../Models/Netmap/FrostFsFilter.cs | 20 +-
.../Models/Netmap/FrostFsPlacementPolicy.cs | 10 +
.../Models/Netmap/FrostFsSelector.cs | 18 +-
.../Models/Object/FrostFsAttributePair.cs | 30 +-
src/FrostFS.SDK.Client/Pool/Pool.cs | 9 +-
.../Services/ContainerServiceProvider.cs | 2 +-
.../Client/ContainerTests/ContainerTests.cs | 283 ++++++
.../Smoke/Client/MiscTests/InterceptorTest.cs | 37 +
.../Smoke/Client/NetworkTests/NetworkTests.cs | 111 +++
.../Smoke/Client/ObjectTests/ObjectTests.cs | 337 +++++++
.../Smoke/Client/SessionTests/SessionTests.cs | 21 +
.../Multithread/MultiThreadTestsBase.cs | 0
.../Multithread/MultithreadPoolSmokeTests.cs | 47 +-
.../MultithreadSmokeClientTests.cs | 44 +-
.../Smoke/{ => PoolTests}/PoolSmokeTests.cs | 28 +-
.../Smoke/SmokeClientTests.cs | 829 ------------------
src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs | 108 ++-
src/FrostFS.SDK.Tests/Unit/ContainerTest.cs | 2 +-
24 files changed, 1020 insertions(+), 976 deletions(-)
create mode 100644 src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs
create mode 100644 src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs
create mode 100644 src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs
create mode 100644 src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs
create mode 100644 src/FrostFS.SDK.Tests/Smoke/Client/SessionTests/SessionTests.cs
rename src/FrostFS.SDK.Tests/{ => Smoke/PoolTests}/Multithread/MultiThreadTestsBase.cs (100%)
rename src/FrostFS.SDK.Tests/{ => Smoke/PoolTests}/Multithread/MultithreadPoolSmokeTests.cs (92%)
rename src/FrostFS.SDK.Tests/{ => Smoke/PoolTests}/Multithread/MultithreadSmokeClientTests.cs (94%)
rename src/FrostFS.SDK.Tests/Smoke/{ => PoolTests}/PoolSmokeTests.cs (95%)
delete mode 100644 src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs
diff --git a/README.md b/README.md
index eccf0a2..add47ea 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ var placementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1));
var createContainerParam = new PrmContainerCreate(
new FrostFsContainerInfo(BasicAcl.PublicRW, new FrostFsPlacementPolicy(true, new FrostFsReplica(1))));
-var containerId = await client.CreateContainerAsync(createContainerParam);
+var containerId = await client.PutContainerAsync(createContainerParam);
using var fileStream = File.OpenRead(@"C:\Users\Paul\Pictures\cat.jpeg");
diff --git a/src/FrostFS.SDK.Client/FrostFSClient.cs b/src/FrostFS.SDK.Client/FrostFSClient.cs
index 27017fe..83f917e 100644
--- a/src/FrostFS.SDK.Client/FrostFSClient.cs
+++ b/src/FrostFS.SDK.Client/FrostFSClient.cs
@@ -212,9 +212,15 @@ public class FrostFSClient : IFrostFSClient
return GetContainerService().ListContainersAsync(args, ctx);
}
+ [Obsolete("Use PutContainerAsync method")]
public Task CreateContainerAsync(PrmContainerCreate args, CallContext ctx)
{
- return GetContainerService().CreateContainerAsync(args, ctx);
+ return GetContainerService().PutContainerAsync(args, ctx);
+ }
+
+ public Task PutContainerAsync(PrmContainerCreate args, CallContext ctx)
+ {
+ return GetContainerService().PutContainerAsync(args, ctx);
}
public Task DeleteContainerAsync(PrmContainerDelete args, CallContext ctx)
@@ -314,18 +320,6 @@ public class FrostFSClient : IFrostFSClient
}
#endregion
- private async void CheckFrostFsVersionSupport(CallContext ctx)
- {
- var service = GetNetmapService();
- var localNodeInfo = await service.GetLocalNodeInfoAsync(ctx).ConfigureAwait(false);
-
- if (!localNodeInfo.Version.IsSupported(ClientCtx.Version))
- {
- var msg = $"FrostFS {localNodeInfo.Version} is not supported.";
- throw new FrostFsException(msg);
- }
- }
-
private CallInvoker? CreateInvoker()
{
CallInvoker? callInvoker = null;
@@ -361,7 +355,7 @@ public class FrostFSClient : IFrostFSClient
{
var invoker = CreateInvoker();
- NetmapServiceClient = NetmapServiceClient ?? (
+ NetmapServiceClient ??= (
invoker != null
? new NetmapServiceClient(invoker)
: new NetmapServiceClient(ClientCtx.Channel));
@@ -378,7 +372,7 @@ public class FrostFSClient : IFrostFSClient
{
var invoker = CreateInvoker();
- SessionServiceClient = SessionServiceClient ?? (
+ SessionServiceClient ??= (
invoker != null
? new SessionServiceClient(invoker)
: new SessionServiceClient(ClientCtx.Channel));
@@ -387,7 +381,6 @@ public class FrostFSClient : IFrostFSClient
}
return SessionServiceProvider;
-
}
private ApeManagerServiceProvider GetApeManagerService()
@@ -396,7 +389,7 @@ public class FrostFSClient : IFrostFSClient
{
var invoker = CreateInvoker();
- ApeManagerServiceClient = ApeManagerServiceClient ?? (
+ ApeManagerServiceClient ??= (
invoker != null
? new APEManagerServiceClient(invoker)
: new APEManagerServiceClient(ClientCtx.Channel));
@@ -413,7 +406,7 @@ public class FrostFSClient : IFrostFSClient
{
var invoker = CreateInvoker();
- AccountingServiceClient = AccountingServiceClient ?? (
+ AccountingServiceClient ??= (
invoker != null
? new AccountingServiceClient(invoker)
: new AccountingServiceClient(ClientCtx.Channel));
@@ -430,7 +423,7 @@ public class FrostFSClient : IFrostFSClient
{
var invoker = CreateInvoker();
- ContainerServiceClient = ContainerServiceClient ?? (
+ ContainerServiceClient ??= (
invoker != null
? new ContainerServiceClient(invoker)
: new ContainerServiceClient(ClientCtx.Channel));
diff --git a/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs b/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs
index cce7364..594cc63 100644
--- a/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs
+++ b/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs
@@ -33,8 +33,11 @@ public interface IFrostFSClient
IAsyncEnumerable ListContainersAsync(PrmContainerGetAll args, CallContext ctx);
+ [Obsolete("Use PutContainerAsync method")]
Task CreateContainerAsync(PrmContainerCreate args, CallContext ctx);
+ Task PutContainerAsync(PrmContainerCreate args, CallContext ctx);
+
Task DeleteContainerAsync(PrmContainerDelete args, CallContext ctx);
#endregion
diff --git a/src/FrostFS.SDK.Client/Mappers/Netmap/PlacementPolicy.cs b/src/FrostFS.SDK.Client/Mappers/Netmap/PlacementPolicy.cs
index 30410aa..ee1c8a4 100644
--- a/src/FrostFS.SDK.Client/Mappers/Netmap/PlacementPolicy.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Netmap/PlacementPolicy.cs
@@ -17,9 +17,9 @@ public static class PlacementPolicyMapper
return new FrostFsPlacementPolicy(
placementPolicy.Unique,
placementPolicy.ContainerBackupFactor,
- new System.Collections.ObjectModel.Collection(placementPolicy.Selectors.Select(selector => selector.ToModel()).ToList()),
- new System.Collections.ObjectModel.Collection(placementPolicy.Filters.Select(filter => filter.ToModel()).ToList()),
- placementPolicy.Replicas.Select(replica => replica.ToModel()).ToArray()
+ [.. placementPolicy.Selectors.Select(s => s.ToModel())],
+ [.. placementPolicy.Filters.Select(f => f.ToModel())],
+ [.. placementPolicy.Replicas.Select(r => r.ToModel())]
);
}
}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Client/Mappers/Netmap/Replica.cs b/src/FrostFS.SDK.Client/Mappers/Netmap/Replica.cs
index bc415e1..cd7a0b7 100644
--- a/src/FrostFS.SDK.Client/Mappers/Netmap/Replica.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Netmap/Replica.cs
@@ -50,13 +50,15 @@ public static class PolicyMapper
throw new ArgumentNullException(nameof(selector));
}
- return new FrostFsSelector(selector.Name)
+ var model = new FrostFsSelector(selector.Name)
{
Count = selector.Count,
Clause = (int)selector.Clause,
Attribute = selector.Attribute,
Filter = selector.Filter
};
+
+ return model;
}
public static Filter ToMessage(this FrostFsFilter filter)
@@ -86,6 +88,13 @@ public static class PolicyMapper
throw new ArgumentNullException(nameof(filter));
}
- return new FrostFsFilter(filter.Name, filter.Key, (int)filter.Op, filter.Value, filter.Filters.Select(f => f.ToModel()).ToArray());
+ var model = new FrostFsFilter(
+ filter.Name,
+ filter.Key,
+ (int)filter.Op,
+ filter.Value,
+ [.. filter.Filters.Select(f => f.ToModel())]);
+
+ return model;
}
}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Client/Mappers/Object/ObjectAttributeMapper.cs b/src/FrostFS.SDK.Client/Mappers/Object/ObjectAttributeMapper.cs
index cfec8fd..a28100e 100644
--- a/src/FrostFS.SDK.Client/Mappers/Object/ObjectAttributeMapper.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Object/ObjectAttributeMapper.cs
@@ -8,11 +8,6 @@ public static class ObjectAttributeMapper
{
public static Header.Types.Attribute ToMessage(this FrostFsAttributePair attribute)
{
- if (attribute is null)
- {
- throw new ArgumentNullException(nameof(attribute));
- }
-
return new Header.Types.Attribute
{
Key = attribute.Key,
diff --git a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsFilter.cs b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsFilter.cs
index ebd3c20..11ee079 100644
--- a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsFilter.cs
+++ b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsFilter.cs
@@ -1,4 +1,7 @@
-namespace FrostFS.SDK;
+using System.Linq;
+using FrostFS.Netmap;
+
+namespace FrostFS.SDK;
public class FrostFsFilter(string name, string key, int operation, string value, FrostFsFilter[] filters) : IFrostFsFilter
{
@@ -7,4 +10,19 @@ public class FrostFsFilter(string name, string key, int operation, string value,
public int Operation { get; } = operation;
public string Value { get; } = value;
public FrostFsFilter[] Filters { get; } = filters;
+
+ internal Filter GetMessage()
+ {
+ var filter = new Filter()
+ {
+ Name = Name,
+ Key = Key,
+ Op = (Operation)Operation,
+ Value = Value,
+ };
+
+ filter.Filters.AddRange(Filters.Select(f => f.GetMessage()));
+
+ return filter;
+ }
}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs
index 184514b..abfce6c 100644
--- a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs
+++ b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs
@@ -51,6 +51,16 @@ public struct FrostFsPlacementPolicy(bool unique,
ContainerBackupFactor = BackupFactor
};
+ if (Selectors != null && Selectors.Count > 0)
+ {
+ policy.Selectors.AddRange(Selectors.Select(s => s.GetMessage()));
+ }
+
+ if (Filters != null && Filters.Count > 0)
+ {
+ policy.Filters.AddRange(Filters.Select(s => s.ToMessage()));
+ }
+
foreach (var replica in Replicas)
{
policy.Replicas.Add(replica.ToMessage());
diff --git a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsSelector.cs b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsSelector.cs
index 3369d6c..c058967 100644
--- a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsSelector.cs
+++ b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsSelector.cs
@@ -1,10 +1,24 @@
-namespace FrostFS.SDK;
+using FrostFS.Netmap;
+
+namespace FrostFS.SDK;
public class FrostFsSelector(string name)
{
- public string Name { get; set; } = name;
+ public string Name { get; } = name;
public uint Count { get; set; }
public int Clause { get; set; }
public string? Attribute { get; set; }
public string? Filter { get; set; }
+
+ internal Selector GetMessage()
+ {
+ return new Selector()
+ {
+ Name = Name,
+ Clause = (Clause)Clause,
+ Count = Count,
+ Filter = Filter ?? string.Empty,
+ Attribute = Attribute ?? string.Empty,
+ };
+ }
}
diff --git a/src/FrostFS.SDK.Client/Models/Object/FrostFsAttributePair.cs b/src/FrostFS.SDK.Client/Models/Object/FrostFsAttributePair.cs
index 64d865f..9db7898 100644
--- a/src/FrostFS.SDK.Client/Models/Object/FrostFsAttributePair.cs
+++ b/src/FrostFS.SDK.Client/Models/Object/FrostFsAttributePair.cs
@@ -1,8 +1,36 @@
namespace FrostFS.SDK;
-public class FrostFsAttributePair(string key, string value)
+public struct FrostFsAttributePair(string key, string value) : System.IEquatable
{
public string Key { get; set; } = key;
public string Value { get; set; } = value;
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null || obj is not FrostFsAttributePair)
+ return false;
+
+ return Equals((FrostFsAttributePair)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Key.GetHashCode() ^ Value.GetHashCode();
+ }
+
+ public static bool operator ==(FrostFsAttributePair left, FrostFsAttributePair right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(FrostFsAttributePair left, FrostFsAttributePair right)
+ {
+ return !(left == right);
+ }
+
+ public bool Equals(FrostFsAttributePair other)
+ {
+ return GetHashCode().Equals(other.GetHashCode());
+ }
}
diff --git a/src/FrostFS.SDK.Client/Pool/Pool.cs b/src/FrostFS.SDK.Client/Pool/Pool.cs
index 3abfe60..f0b7a6e 100644
--- a/src/FrostFS.SDK.Client/Pool/Pool.cs
+++ b/src/FrostFS.SDK.Client/Pool/Pool.cs
@@ -568,10 +568,17 @@ public partial class Pool : IFrostFSClient
return client.Client!.ListContainersAsync(args, ctx);
}
+ [Obsolete("Use PutContainerAsync method")]
public async Task CreateContainerAsync(PrmContainerCreate args, CallContext ctx)
{
var client = Connection();
- return await client.Client!.CreateContainerAsync(args, ctx).ConfigureAwait(false);
+ return await client.Client!.PutContainerAsync(args, ctx).ConfigureAwait(false);
+ }
+
+ public async Task PutContainerAsync(PrmContainerCreate args, CallContext ctx)
+ {
+ var client = Connection();
+ return await client.Client!.PutContainerAsync(args, ctx).ConfigureAwait(false);
}
public async Task DeleteContainerAsync(PrmContainerDelete args, CallContext ctx)
diff --git a/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs b/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs
index ca76e08..d7ba34c 100644
--- a/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs
+++ b/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs
@@ -71,7 +71,7 @@ internal sealed class ContainerServiceProvider(ContainerService.ContainerService
}
}
- internal async Task CreateContainerAsync(PrmContainerCreate args, CallContext ctx)
+ internal async Task PutContainerAsync(PrmContainerCreate args, CallContext ctx)
{
var grpcContainer = args.Container.GetContainer();
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs
new file mode 100644
index 0000000..37a8c13
--- /dev/null
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs
@@ -0,0 +1,283 @@
+using System.Collections.Concurrent;
+using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
+using FrostFS.SDK.Client;
+using Grpc.Core;
+
+namespace FrostFS.SDK.Tests.Smoke;
+
+[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
+[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
+public class ContainerTests : SmokeTestsBase
+{
+ [Fact]
+ public async void FailCreateContainerByTimeoutTest()
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ try
+ {
+ _ = await CreateContainer(client,
+ ctx: new CallContext(TimeSpan.FromMilliseconds(1)),
+ token: null,
+ unique: true,
+ backupFactor: 1,
+ selectors: [],
+ filter: [],
+ containerAttributes: [new("testKey1", "testValue1")],
+ new FrostFsReplica(1));
+
+ Assert.Fail("Exception is expected");
+ }
+ catch (RpcException ex)
+ {
+ Assert.Equal(StatusCode.DeadlineExceeded, ex.Status.StatusCode);
+ }
+ }
+
+ [Fact]
+ public async void CreateContainerTest1()
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+ await Cleanup(client);
+
+ client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ FrostFsContainerId containerId = await CreateContainer(client,
+ ctx: default,
+ token: null,
+ unique: true,
+ backupFactor: 1,
+ selectors: [],
+ filter: [],
+ containerAttributes: [new ("testKey1", "testValue1")],
+ new FrostFsReplica(3));
+
+ Assert.NotNull(containerId);
+
+ var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
+
+ Assert.NotNull(container);
+
+ Assert.NotNull(container.Attributes);
+ Assert.Equal(2, container.Attributes.Count);
+ Assert.Equal("testKey1", container.Attributes[0].Key);
+ Assert.Equal("testValue1", container.Attributes[0].Value);
+ Assert.Equal("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", container.Attributes[1].Key);
+ Assert.Equal("true", container.Attributes[1].Value);
+
+ Assert.True(container.PlacementPolicy.HasValue);
+
+ Assert.Equal(1u, container.PlacementPolicy.Value.BackupFactor);
+ Assert.True(container.PlacementPolicy.Value.Unique);
+ Assert.Empty(container.PlacementPolicy.Value.Selectors);
+ Assert.Empty(container.PlacementPolicy.Value.Filters);
+
+ Assert.Single(container.PlacementPolicy.Value.Replicas);
+ Assert.Equal(3, container.PlacementPolicy.Value.Replicas[0].Count);
+ Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcParityCount);
+ Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcDataCount);
+ Assert.Equal("", container.PlacementPolicy.Value.Replicas[0].Selector);
+
+ Assert.Equal(OwnerId!.ToString(), container.Owner!.Value);
+
+ Assert.NotNull(container.Version);
+
+ Assert.Equal(Version!.Major, container.Version.Major);
+ Assert.Equal(Version.Minor, container.Version.Minor);
+ }
+
+ [Fact]
+ public async void CreateContainerTest2()
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ await Cleanup(client);
+
+ client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ Collection filters = [
+ new ("filter1", "filterKey1", 1, "testValue1", []),
+ new ("filter2", "filterKey2", 2, "testValue2", [new ("subFilter2", "subFilterKey2", 3, "testValue3",[])])
+ ];
+
+ Collection selectors = [
+ new ("selector1") {
+ Count = 1,
+ Clause = 1,
+ Attribute = "attribute1",
+ Filter = "filter1"
+ },
+ new ("selector2") {
+ Count = 2,
+ Clause = 2,
+ Attribute = "attribute2",
+ Filter = "filter2"
+ },
+ ];
+
+ FrostFsContainerId containerId = await CreateContainer(client,
+ ctx: default,
+ token: null,
+ unique: false,
+ backupFactor: 2,
+ selectors,
+ filter: filters,
+ containerAttributes: [],
+ new FrostFsReplica(1));
+
+ Assert.NotNull(containerId);
+
+ var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
+
+ Assert.NotNull(container);
+
+ Assert.NotNull(container.Attributes);
+ Assert.Single(container.Attributes);
+ Assert.Equal("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", container.Attributes[0].Key);
+ Assert.Equal("true", container.Attributes[0].Value);
+
+ Assert.True(container.PlacementPolicy.HasValue);
+
+ Assert.Equal(2u, container.PlacementPolicy.Value.BackupFactor);
+ Assert.False(container.PlacementPolicy.Value.Unique);
+
+ Assert.NotEmpty(container.PlacementPolicy.Value.Selectors);
+
+ Assert.Equal(2, container.PlacementPolicy.Value.Selectors.Count);
+
+ var selector1 = container.PlacementPolicy.Value.Selectors[0];
+ Assert.Equal("selector1", selector1.Name);
+ Assert.Equal(1, selector1.Clause);
+ Assert.Equal(1u, selector1.Count);
+ Assert.Equal("attribute1", selector1.Attribute);
+ Assert.Equal("filter1", selector1.Filter);
+
+ var selector2 = container.PlacementPolicy.Value.Selectors[1];
+ Assert.Equal("selector2", selector2.Name);
+ Assert.Equal(2, selector2.Clause);
+ Assert.Equal(2u, selector2.Count);
+ Assert.Equal("attribute2", selector2.Attribute);
+ Assert.Equal("filter2", selector2.Filter);
+
+ Assert.NotEmpty(container.PlacementPolicy.Value.Filters);
+
+ Assert.Equal(2, container.PlacementPolicy.Value.Filters.Count);
+
+ var filter1 = container.PlacementPolicy.Value.Filters[0];
+ Assert.Equal("filter1", filter1.Name);
+ Assert.Equal("filterKey1", filter1.Key);
+ Assert.Equal("testValue1", filter1.Value);
+ Assert.Equal(1, filter1.Operation);
+ Assert.Empty(filter1.Filters);
+
+ var filter2 = container.PlacementPolicy.Value.Filters[1];
+ Assert.Equal("filter2", filter2.Name);
+ Assert.Equal("filterKey2", filter2.Key);
+ Assert.Equal("testValue2", filter2.Value);
+ Assert.Equal(2, filter2.Operation);
+ Assert.NotEmpty(filter2.Filters);
+
+ Assert.Single(filter2.Filters);
+
+ var subFilter = filter2.Filters.First();
+ Assert.Equal("subFilter2", subFilter.Name);
+ Assert.Equal("subFilterKey2", subFilter.Key);
+ Assert.Equal("testValue3", subFilter.Value);
+ Assert.Equal(3, subFilter.Operation);
+ Assert.Empty(subFilter.Filters);
+
+ Assert.Single(container.PlacementPolicy.Value.Replicas);
+ Assert.Equal(1, container.PlacementPolicy.Value.Replicas[0].Count);
+ Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcParityCount);
+ Assert.Equal(0u, container.PlacementPolicy.Value.Replicas[0].EcDataCount);
+ Assert.Equal("", container.PlacementPolicy.Value.Replicas[0].Selector);
+
+ Assert.Equal(OwnerId!.ToString(), container.Owner!.Value);
+
+ Assert.NotNull(container.Version);
+
+ Assert.Equal(Version!.Major, container.Version.Major);
+ Assert.Equal(Version.Minor, container.Version.Minor);
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(10)]
+ public async void ListAndDeleteContainersTest(int countainerCount)
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ await Cleanup(client);
+
+ var tasks = new Task[countainerCount];
+
+ var createdContainers = new ConcurrentDictionary();
+
+ for (int i = 0; i < countainerCount; i++)
+ {
+ int index = i;
+ tasks[i] = Task.Run(async () =>
+ {
+ FrostFsContainerId containerId = await CreateContainer(client,
+ ctx: default,
+ token: null,
+ unique: true,
+ backupFactor: 1,
+ selectors: [],
+ filter: [],
+ containerAttributes: [new($"testKey{index}", $"testValue{index}")],
+ new FrostFsReplica(3));
+
+ createdContainers.TryAdd(containerId.ToString(), index);
+ });
+ }
+
+ #pragma warning disable xUnit1031 // Timeout is used
+ if (!Task.WaitAll(tasks, 20000))
+ {
+ Assert.Fail("cannot create containers");
+ }
+ #pragma warning restore xUnit1031
+
+ var containers = client.ListContainersAsync(new PrmContainerGetAll(), default);
+
+ var receivedContainers = new List();
+ await foreach (var cntr in containers)
+ {
+ receivedContainers.Add(cntr.ToString());
+ }
+
+ Assert.Equal(countainerCount, receivedContainers.Count);
+
+ foreach (var cntrId in receivedContainers)
+ {
+ if (!createdContainers.TryGetValue(cntrId, out var index))
+ {
+ Assert.Fail("Cannot find corresponding container");
+ }
+
+ FrostFsContainerId container = new(cntrId);
+ var containerInfo = await client.GetContainerAsync(new PrmContainerGet(container), default);
+
+ Assert.NotNull(containerInfo);
+ Assert.NotNull(containerInfo.Attributes);
+
+ Assert.Contains(new FrostFsAttributePair($"testKey{index}", $"testValue{index}"), containerInfo.Attributes);
+ }
+
+ tasks = new Task[countainerCount];
+
+ for (int i = 0; i < receivedContainers.Count; i++)
+ {
+ tasks[i] = client.DeleteContainerAsync(new PrmContainerDelete(new FrostFsContainerId(receivedContainers[i]), lightWait), default);
+ }
+
+ await Task.WhenAll(tasks);
+
+ await foreach (var _ in client.ListContainersAsync(default, default))
+ {
+ Assert.Fail("Containers exist");
+ }
+ }
+}
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs b/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs
new file mode 100644
index 0000000..c3df8e5
--- /dev/null
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs
@@ -0,0 +1,37 @@
+using FrostFS.SDK.Client;
+using FrostFS.SDK.SmokeTests;
+
+namespace FrostFS.SDK.Tests.Smoke;
+
+public class InterceptorTests() : SmokeTestsBase
+{
+ [Fact]
+ public async void NodeInfoCallbackAndInterceptorTest()
+ {
+ bool callbackInvoked = false;
+ bool interceptorInvoked = false;
+
+ var options = ClientOptions;
+ options.Value.Callback = (cs) =>
+ {
+ callbackInvoked = true;
+ Assert.True(cs.ElapsedMicroSeconds > 0);
+ };
+
+ options.Value.Interceptors.Add(new CallbackInterceptor(s => interceptorInvoked = true));
+
+ var client = FrostFSClient.GetInstance(options, GrpcChannel);
+
+ var result = await client.GetNodeInfoAsync(default);
+
+ Assert.True(callbackInvoked);
+ Assert.True(interceptorInvoked);
+
+ Assert.Equal(2, result.Version.Major);
+ Assert.Equal(13, result.Version.Minor);
+ Assert.Equal(NodeState.Online, result.State);
+ Assert.Equal(33, result.PublicKey.Length);
+ Assert.NotNull(result.Addresses);
+ Assert.True(result.Attributes.Count > 0);
+ }
+}
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs
new file mode 100644
index 0000000..f1fce3c
--- /dev/null
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs
@@ -0,0 +1,111 @@
+using System.Diagnostics.CodeAnalysis;
+using FrostFS.SDK.Client;
+using FrostFS.SDK.SmokeTests;
+
+namespace FrostFS.SDK.Tests.Smoke;
+
+[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
+[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
+public class SmokeClientTests : SmokeTestsBase
+{
+ [Fact]
+ public async void AccountTest()
+ {
+ var test = lightWait.Timeout;
+
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ var result = await client.GetBalanceAsync(default);
+
+ Assert.NotNull(result);
+ Assert.True(result.Value == 0);
+ }
+
+ [Fact]
+ public async void NodeInfoTest()
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ var result = await client.GetNodeInfoAsync(default);
+
+ Assert.Equal(2, result.Version.Major);
+ Assert.Equal(13, result.Version.Minor);
+ Assert.Equal(NodeState.Online, result.State);
+ Assert.Equal(33, result.PublicKey.Length);
+ Assert.Equal(2, result.Addresses.Count);
+ Assert.Equal(11, result.Attributes.Count);
+ }
+
+ [Fact]
+ public async void NodeInfoStatisticsTest()
+ {
+ var options = ClientOptions;
+
+ var callbackContent = string.Empty;
+ options.Value.Callback = (cs) => callbackContent = $"{cs.MethodName} took {cs.ElapsedMicroSeconds} microseconds";
+
+ var client = FrostFSClient.GetInstance(options, GrpcChannel);
+
+ var result = await client.GetNodeInfoAsync(default);
+
+ Assert.NotEmpty(callbackContent);
+ }
+
+ [Fact]
+ public async void NetworkSettingsTest()
+ {
+ var options = ClientOptions;
+ var client = FrostFSClient.GetInstance(options, GrpcChannel);
+
+ var result = await client.GetNetworkSettingsAsync(default);
+
+ Assert.NotNull(result);
+
+ Assert.True(0u < result.Epoch);
+ Assert.True(result.HomomorphicHashingDisabled);
+ Assert.True(result.MaintenanceModeAllowed);
+ Assert.True(0u < result.MagicNumber);
+
+ Assert.Equal(0u, result.AuditFee);
+ Assert.Equal(0u, result.BasicIncomeRate);
+ Assert.Equal(0u, result.ContainerAliasFee);
+ Assert.Equal(0u, result.ContainerFee);
+ Assert.Equal(75u, result.EpochDuration);
+ Assert.Equal(10_000_000_000u, result.InnerRingCandidateFee);
+ Assert.Equal(12u, result.MaxECDataCount);
+ Assert.Equal(4u, result.MaxECParityCount);
+ Assert.Equal(5242880u, result.MaxObjectSize);
+ Assert.Equal(8000u, result.MsPerBlock);
+ Assert.Equal(100_000_000u, result.WithdrawFee);
+ }
+
+ [Fact]
+ public async void NodeInfoCallbackAndInterceptorTest()
+ {
+ bool callbackInvoked = false;
+ bool interceptorInvoked = false;
+
+ var options = ClientOptions;
+ options.Value.Callback = (cs) =>
+ {
+ callbackInvoked = true;
+ Assert.True(cs.ElapsedMicroSeconds > 0);
+ };
+
+ options.Value.Interceptors.Add(new CallbackInterceptor(s => interceptorInvoked = true));
+
+ var client = FrostFSClient.GetInstance(options, GrpcChannel);
+
+ var result = await client.GetNodeInfoAsync(default);
+
+ Assert.True(callbackInvoked);
+ Assert.True(interceptorInvoked);
+
+ Assert.Equal(2, result.Version.Major);
+ Assert.Equal(13, result.Version.Minor);
+ Assert.Equal(NodeState.Online, result.State);
+ Assert.Equal(33, result.PublicKey.Length);
+ Assert.NotNull(result.Addresses);
+ Assert.True(result.Attributes.Count > 0);
+ }
+}
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs
new file mode 100644
index 0000000..98e32f7
--- /dev/null
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs
@@ -0,0 +1,337 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Security.Cryptography;
+using FrostFS.SDK.Client;
+using FrostFS.SDK.Client.Interfaces;
+using FrostFS.SDK.Cryptography;
+using Xunit.Abstractions;
+
+namespace FrostFS.SDK.Tests.Smoke;
+
+[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
+[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
+public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
+{
+ private readonly ITestOutputHelper _testOutputHelper = testOutputHelper;
+
+ const string clientCut = "clientCut";
+ const string serverCut = "serverCut";
+ const string singleObject = "singleObject";
+
+ [Theory]
+ [InlineData(true, 1, 1)]
+ [InlineData(false, 1, 1)]
+ [InlineData(true, 1, 3)]
+ [InlineData(false, 1, 3)]
+ [InlineData(true, 2, 3)]
+ [InlineData(false, 2, 3)]
+ [InlineData(true, 2, 1)]
+ [InlineData(false, 2, 1)]
+ public async void FullScenario(bool unique, uint backupFactor, int replicas)
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+ _testOutputHelper.WriteLine("client created");
+
+ await Cleanup(client);
+ _testOutputHelper.WriteLine("existing containers removed");
+
+ FrostFsContainerId containerId = await CreateContainer(client,
+ ctx: default,
+ token: null,
+ unique: unique,
+ backupFactor: backupFactor,
+ selectors: [],
+ filter: [],
+ containerAttributes: [],
+ new FrostFsReplica(replicas));
+
+ Assert.NotNull(containerId);
+ _testOutputHelper.WriteLine("container created");
+
+ await AddObjectRules(client, containerId);
+ _testOutputHelper.WriteLine("rules added");
+
+ await RunSuite(client, containerId);
+ }
+
+ private async Task RunSuite(IFrostFSClient client, FrostFsContainerId containerId)
+ {
+ int[] objectSizes = [1, 257, 6 * 1024, 20 * 1024];
+
+ string[] objectTypes = [clientCut, serverCut, singleObject];
+
+ foreach (var objectSize in objectSizes)
+ {
+ _testOutputHelper.WriteLine($"test set for object size {objectSize}");
+
+ var bytes = GetRandomBytes(objectSize);
+ var hash = SHA256.HashData(bytes);
+
+ FrostFsObjectId objectId;
+ foreach (var type in objectTypes)
+ {
+ switch (type)
+ {
+ case serverCut:
+ objectId = await CreateObjectServerCut(client, containerId, bytes);
+ break;
+ case clientCut:
+ objectId = await CreateObjectClientCut(client, containerId, bytes);
+ break;
+ case singleObject:
+ if (objectSize > 1 * 1024 * 1024)
+ continue;
+ objectId = await PutSingleObject(client, containerId, bytes);
+
+ break;
+ default:
+ throw new ArgumentException("unexpected object type");
+ }
+
+ Assert.NotNull(objectId);
+
+ _testOutputHelper.WriteLine($"\tobject created");
+
+ await ValidateContent(client, containerId, hash, objectId);
+ _testOutputHelper.WriteLine($"\tcontent validated");
+
+ await ValidateFilters(client, containerId, objectId, null, (ulong)bytes.Length);
+ _testOutputHelper.WriteLine($"\tfilters validated");
+
+ // if (type != clientCut)
+ // {
+ // await ValidatePatch(client, containerId, bytes, objectId);
+ // _testOutputHelper.WriteLine($"\tpatch validated");
+ // }
+
+ await ValidateRange(client, containerId, bytes, objectId);
+ _testOutputHelper.WriteLine($"\trange validated");
+
+ await ValidateRangeHash(client, containerId, bytes, objectId);
+ _testOutputHelper.WriteLine($"\trange hash validated");
+
+ await RemoveObject(client, containerId, objectId);
+ _testOutputHelper.WriteLine($"\tobject removed");
+ }
+ }
+ }
+
+ private static async Task ValidateRangeHash(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes, FrostFsObjectId objectId)
+ {
+ if (bytes.Length < 200)
+ return;
+
+ var rangeParam = new PrmRangeHashGet(containerId, objectId, [new FrostFsRange(100, 64)], bytes);
+
+ var hashes = await client.GetRangeHashAsync(rangeParam, default);
+
+ foreach (var h in hashes)
+ {
+ var x = h[..32].ToArray();
+ Assert.NotNull(x);
+ Assert.True(x.Length > 0);
+ }
+ }
+
+ private async Task ValidateRange(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes, FrostFsObjectId objectId)
+ {
+ if (bytes.Length < 200)
+ return;
+
+ await CheckRange(client, containerId, bytes, objectId, new FrostFsRange(0, 50));
+ await CheckRange(client, containerId, bytes, objectId, new FrostFsRange(50, 100));
+
+ await CheckRange(client, containerId, bytes, objectId, new FrostFsRange((ulong)bytes.Length-100, 100));
+
+ if (bytes.Length >= 6200)
+ await CheckRange(client, containerId, bytes, objectId, new FrostFsRange(6000, 100));
+ }
+
+ private async Task CheckRange(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes, FrostFsObjectId objectId, FrostFsRange range)
+ {
+ var rangeParam = new PrmRangeGet(containerId, objectId, range);
+
+ var rangeReader = await client.GetRangeAsync(rangeParam, default);
+
+ var rangeBytes = new byte[rangeParam.Range.Length];
+ MemoryStream ms = new(rangeBytes);
+
+ ReadOnlyMemory? chunk;
+ while ((chunk = await rangeReader!.ReadChunk()) != null)
+ {
+ ms.Write(chunk.Value.Span);
+ }
+
+ Assert.Equal(SHA256.HashData(bytes.AsSpan().Slice((int)range.Offset, (int)range.Length)), SHA256.HashData(rangeBytes));
+
+ _testOutputHelper.WriteLine($"\t\trange {range.Offset};{range.Length} validated");
+ }
+
+ private static async Task ValidatePatch(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes, FrostFsObjectId objectId)
+ {
+ if (bytes.Length < 1024 + 64)
+ return;
+
+ var patch = new byte[1024];
+ for (int i = 0; i < patch.Length; i++)
+ {
+ patch[i] = 32;
+ }
+
+ var range = new FrostFsRange(64, (ulong)patch.Length);
+
+ var patchParams = new PrmObjectPatch(
+ new FrostFsAddress(containerId, objectId),
+ payload: new MemoryStream(patch),
+ maxChunkLength: 1024,
+ range: range);
+
+ var newIbjId = await client.PatchObjectAsync(patchParams, default);
+
+ var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, newIbjId), default);
+
+ var downloadedBytes = new byte[@object.Header.PayloadLength];
+ MemoryStream ms = new(downloadedBytes);
+
+ ReadOnlyMemory? chunk;
+ while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
+ {
+ ms.Write(chunk.Value.Span);
+ }
+
+ for (int i = 0; i < (int)range.Offset; i++)
+ Assert.Equal(downloadedBytes[i], bytes[i]);
+
+ var rangeEnd = range.Offset + range.Length;
+
+ for (int i = (int)range.Offset; i < (int)rangeEnd; i++)
+ Assert.Equal(downloadedBytes[i], patch[i - (int)range.Offset]);
+
+ for (int i = (int)rangeEnd; i < bytes.Length; i++)
+ Assert.Equal(downloadedBytes[i], bytes[i]);
+ }
+
+
+ private async Task ValidateFilters(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId, SplitId? splitId, ulong length)
+ {
+ var ecdsaKey = keyString.LoadWif();
+
+ var networkInfo = await client.GetNetmapSnapshotAsync(default);
+
+ await CheckFilter(client, containerId, new FilterByContainerId(FrostFsMatchType.Equals, containerId));
+
+ await CheckFilter(client, containerId, new FilterByOwnerId(FrostFsMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey)));
+
+ if (splitId != null)
+ {
+ await CheckFilter(client, containerId, new FilterBySplitId(FrostFsMatchType.Equals, splitId));
+ }
+
+ await CheckFilter(client, containerId, new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test"));
+
+ await CheckFilter(client, containerId, new FilterByObjectId(FrostFsMatchType.Equals, objectId));
+
+ await CheckFilter(client, containerId, new FilterByVersion(FrostFsMatchType.Equals, networkInfo.NodeInfoCollection[0].Version));
+
+ await CheckFilter(client, containerId, new FilterByEpoch(FrostFsMatchType.Equals, networkInfo.Epoch));
+
+ await CheckFilter(client, containerId, new FilterByPayloadLength(FrostFsMatchType.Equals, length));
+
+ // var checkSum = CheckSum.CreateCheckSum(hash);
+ // await CheckFilter(client, containerId, new FilterByPayloadHash(FrostFsMatchType.Equals, checkSum));
+
+ await CheckFilter(client, containerId, new FilterByPhysicallyStored());
+ }
+
+ private static async Task RemoveObject(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId)
+ {
+ await client.DeleteObjectAsync(new PrmObjectDelete(containerId, objectId), default);
+
+ try
+ {
+ _ = await client.GetObjectAsync(
+ new PrmObjectGet(containerId, objectId),
+ default);
+
+ Assert.Fail("Exception is expected here");
+ }
+ catch (FrostFsResponseException ex)
+ {
+ Assert.Equal("object already removed", ex.Status!.Message);
+ }
+ }
+
+ private static async Task ValidateContent(IFrostFSClient client, FrostFsContainerId containerId, byte[] hash, FrostFsObjectId objectId)
+ {
+ var @object = await client.GetObjectAsync(
+ new PrmObjectGet(containerId, objectId),
+ default);
+
+ var downloadedBytes = new byte[@object.Header.PayloadLength];
+ MemoryStream ms = new(downloadedBytes);
+
+ ReadOnlyMemory? chunk = null;
+ while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
+ {
+ ms.Write(chunk.Value.Span);
+ }
+
+ Assert.Equal(hash, SHA256.HashData(downloadedBytes));
+ }
+
+ private static async Task CreateObjectServerCut(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes)
+ {
+ var header = new FrostFsObjectHeader(
+ containerId: containerId,
+ type: FrostFsObjectType.Regular,
+ [new FrostFsAttributePair("fileName", "test")]);
+
+ var param = new PrmObjectPut(header);
+
+ var objectWriter = await client.PutObjectAsync(param, default).ConfigureAwait(true);
+
+ await objectWriter.WriteAsync(bytes);
+ return await objectWriter.CompleteAsync();
+ }
+
+ private static async Task CreateObjectClientCut(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes)
+ {
+ var header = new FrostFsObjectHeader(
+ containerId: containerId,
+ type: FrostFsObjectType.Regular,
+ [new FrostFsAttributePair("fileName", "test")]);
+
+ var param = new PrmObjectClientCutPut(header, payload: new MemoryStream(bytes));
+
+ return await client.PutClientCutObjectAsync(param, default).ConfigureAwait(true);
+ }
+
+ private static async Task PutSingleObject(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes)
+ {
+ var header = new FrostFsObjectHeader(
+ containerId: containerId,
+ type: FrostFsObjectType.Regular,
+ [new FrostFsAttributePair("fileName", "test")]);
+
+
+ var obj = new FrostFsObject(header) { SingleObjectPayload = bytes };
+
+ var param = new PrmSingleObjectPut(obj);
+
+ return await client.PutSingleObjectAsync(param, default).ConfigureAwait(true);
+ }
+
+ private static async Task CheckFilter(IFrostFSClient client, FrostFsContainerId containerId, IObjectFilter filter)
+ {
+ var resultObjectsCount = 0;
+
+ PrmObjectSearch searchParam = new(containerId, null, [], filter);
+
+ await foreach (var objId in client.SearchObjectsAsync(searchParam, default))
+ {
+ resultObjectsCount++;
+ var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objId), default);
+ }
+
+ Assert.True(0 < resultObjectsCount, $"Filter for {filter.Key} doesn't work");
+ }
+}
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/SessionTests/SessionTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/SessionTests/SessionTests.cs
new file mode 100644
index 0000000..ab14d8e
--- /dev/null
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/SessionTests/SessionTests.cs
@@ -0,0 +1,21 @@
+using System.Diagnostics.CodeAnalysis;
+using FrostFS.SDK.Client;
+
+namespace FrostFS.SDK.Tests.Smoke;
+
+[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
+[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
+public class SessionTests : SmokeTestsBase
+{
+ [Fact]
+ public async void GetSessionTest()
+ {
+ var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
+
+ var token = await client.CreateSessionAsync(new(100), default);
+
+ Assert.NotNull(token);
+ Assert.NotEqual(Guid.Empty, token.Id);
+ Assert.Equal(33, token.SessionKey.Length);
+ }
+}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Tests/Multithread/MultiThreadTestsBase.cs b/src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultiThreadTestsBase.cs
similarity index 100%
rename from src/FrostFS.SDK.Tests/Multithread/MultiThreadTestsBase.cs
rename to src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultiThreadTestsBase.cs
diff --git a/src/FrostFS.SDK.Tests/Multithread/MultithreadPoolSmokeTests.cs b/src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultithreadPoolSmokeTests.cs
similarity index 92%
rename from src/FrostFS.SDK.Tests/Multithread/MultithreadPoolSmokeTests.cs
rename to src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultithreadPoolSmokeTests.cs
index 4cb7e4d..194ef98 100644
--- a/src/FrostFS.SDK.Tests/Multithread/MultithreadPoolSmokeTests.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultithreadPoolSmokeTests.cs
@@ -4,16 +4,12 @@ using System.Security.Cryptography;
using FrostFS.SDK.Client;
using FrostFS.SDK.Cryptography;
-using Microsoft.Extensions.Options;
-
namespace FrostFS.SDK.Tests.Smoke;
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
public class MultithreadPoolSmokeTests : SmokeTestsBase
{
- private static readonly PrmWait lightWait = new(100, 1);
-
private InitParameters GetDefaultParams()
{
return new InitParameters((url) => Grpc.Net.Client.GrpcChannel.ForAddress(new Uri(url)))
@@ -170,7 +166,7 @@ public class MultithreadPoolSmokeTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["key1", "value1"]);
- var containerId = await pool.CreateContainerAsync(createContainerParam, default);
+ var containerId = await pool.PutContainerAsync(createContainerParam, default);
var bytes = GetRandomBytes(1024);
@@ -219,7 +215,7 @@ public class MultithreadPoolSmokeTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
lightWait);
- var containerId = await pool.CreateContainerAsync(createContainerParam, default);
+ var containerId = await pool.PutContainerAsync(createContainerParam, default);
var bytes = new byte[] { 1, 2, 3 };
@@ -315,7 +311,7 @@ public class MultithreadPoolSmokeTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["testKey", "testValue"]);
- var createdContainer = await pool.CreateContainerAsync(createContainerParam, default);
+ var createdContainer = await pool.PutContainerAsync(createContainerParam, default);
var container = await pool.GetContainerAsync(new PrmContainerGet(createdContainer), default);
Assert.NotNull(container);
@@ -399,7 +395,7 @@ public class MultithreadPoolSmokeTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
PrmWait.DefaultParams);
- var container = await pool.CreateContainerAsync(createContainerParam, ctx);
+ var container = await pool.PutContainerAsync(createContainerParam, ctx);
var containerInfo = await pool.GetContainerAsync(new PrmContainerGet(container), ctx);
Assert.NotNull(containerInfo);
@@ -482,7 +478,7 @@ public class MultithreadPoolSmokeTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
lightWait);
- var containerId = await pool.CreateContainerAsync(createContainerParam, default);
+ var containerId = await pool.PutContainerAsync(createContainerParam, default);
var ctx = new CallContext(TimeSpan.FromSeconds(10));
@@ -545,37 +541,4 @@ public class MultithreadPoolSmokeTests : SmokeTestsBase
Assert.Fail($"Container {cid.GetValue()} exist");
}
}
-
- private static byte[] GetRandomBytes(int size)
- {
- Random rnd = new();
- var bytes = new byte[size];
- rnd.NextBytes(bytes);
- return bytes;
- }
-
- private static IOptions GetSingleOwnerOptions(string key, string url)
- {
- return Options.Create(new ClientSettings
- {
- Key = key,
- Host = url
- });
- }
-
- private static IOptions GetOptions(string url)
- {
- return Options.Create(new ClientSettings
- {
- Host = url
- });
- }
-
- static async Task Cleanup(Pool pool)
- {
- await foreach (var cid in pool.ListContainersAsync(default, default))
- {
- await pool.DeleteContainerAsync(new PrmContainerDelete(cid, lightWait), default).ConfigureAwait(true);
- }
- }
}
diff --git a/src/FrostFS.SDK.Tests/Multithread/MultithreadSmokeClientTests.cs b/src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultithreadSmokeClientTests.cs
similarity index 94%
rename from src/FrostFS.SDK.Tests/Multithread/MultithreadSmokeClientTests.cs
rename to src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultithreadSmokeClientTests.cs
index b239e58..32aeb2e 100644
--- a/src/FrostFS.SDK.Tests/Multithread/MultithreadSmokeClientTests.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/PoolTests/Multithread/MultithreadSmokeClientTests.cs
@@ -14,8 +14,6 @@ namespace FrostFS.SDK.Tests.Smoke;
[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
public class MultithreadSmokeClientTests : SmokeTestsBase
{
- private static readonly PrmWait lightWait = new(100, 1);
-
[Fact]
public async void AccountTest()
{
@@ -103,7 +101,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["key1", "value1"]);
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
+ var containerId = await client.PutContainerAsync(createContainerParam, default);
var bytes = GetRandomBytes(1024);
@@ -147,7 +145,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
lightWait);
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
+ var containerId = await client.PutContainerAsync(createContainerParam, default);
var bytes = new byte[] { 1, 2, 3 };
@@ -241,7 +239,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["testKey", "testValue"]);
- var createdContainer = await client.CreateContainerAsync(createContainerParam, ctx);
+ var createdContainer = await client.PutContainerAsync(createContainerParam, ctx);
var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer), default);
Assert.NotNull(container);
@@ -312,7 +310,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["testKey", "testValue"]);
- var createdContainer = await client.CreateContainerAsync(createContainerParam, default);
+ var createdContainer = await client.PutContainerAsync(createContainerParam, default);
var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer), default);
Assert.NotNull(container);
@@ -392,7 +390,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["testKey", "testValue"]);
- var createdContainer = await client.CreateContainerAsync(createContainerParam, default);
+ var createdContainer = await client.PutContainerAsync(createContainerParam, default);
var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer), default);
Assert.NotNull(container);
@@ -446,7 +444,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["testKey", "testValue"]);
- var createdContainer = await client.CreateContainerAsync(createContainerParam, default);
+ var createdContainer = await client.PutContainerAsync(createContainerParam, default);
var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer), default);
Assert.NotNull(container);
@@ -502,7 +500,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
PrmWait.DefaultParams);
- var container = await client.CreateContainerAsync(createContainerParam, ctx);
+ var container = await client.PutContainerAsync(createContainerParam, ctx);
var containerInfo = await client.GetContainerAsync(new PrmContainerGet(container), ctx);
Assert.NotNull(containerInfo);
@@ -583,7 +581,7 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
lightWait);
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
+ var containerId = await client.PutContainerAsync(createContainerParam, default);
var ctx = new CallContext(TimeSpan.FromSeconds(10));
@@ -685,30 +683,4 @@ public class MultithreadSmokeClientTests : SmokeTestsBase
Assert.Single(result.Addresses);
Assert.Equal(9, result.Attributes.Count);
}
-
- private static byte[] GetRandomBytes(int size)
- {
- Random rnd = new();
- var bytes = new byte[size];
- rnd.NextBytes(bytes);
- return bytes;
- }
-
- private static IOptions GetClientOptions(string key, string url)
- {
- return Options.Create(new ClientSettings
- {
- Key = key,
- Host = url
- });
- }
-
-
- static async Task Cleanup(IFrostFSClient client)
- {
- await foreach (var cid in client.ListContainersAsync(default, default))
- {
- await client.DeleteContainerAsync(new PrmContainerDelete(cid, lightWait), default);
- }
- }
}
diff --git a/src/FrostFS.SDK.Tests/Smoke/PoolSmokeTests.cs b/src/FrostFS.SDK.Tests/Smoke/PoolTests/PoolSmokeTests.cs
similarity index 95%
rename from src/FrostFS.SDK.Tests/Smoke/PoolSmokeTests.cs
rename to src/FrostFS.SDK.Tests/Smoke/PoolTests/PoolSmokeTests.cs
index 94b2c8b..9e7ea80 100644
--- a/src/FrostFS.SDK.Tests/Smoke/PoolSmokeTests.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/PoolTests/PoolSmokeTests.cs
@@ -10,8 +10,6 @@ namespace FrostFS.SDK.Tests.Smoke;
[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
public class PoolSmokeTests : SmokeTestsBase
{
- private static readonly PrmWait lightWait = new(100, 1);
-
private InitParameters GetDefaultParams()
{
return new InitParameters((url) => Grpc.Net.Client.GrpcChannel.ForAddress(new Uri(url)))
@@ -168,7 +166,7 @@ public class PoolSmokeTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["key1", "value1"]);
- var containerId = await pool.CreateContainerAsync(createContainerParam, default);
+ var containerId = await pool.PutContainerAsync(createContainerParam, default);
var bytes = GetRandomBytes(1024);
@@ -217,7 +215,7 @@ public class PoolSmokeTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
lightWait);
- var containerId = await pool.CreateContainerAsync(createContainerParam, default);
+ var containerId = await pool.PutContainerAsync(createContainerParam, default);
var bytes = new byte[] { 1, 2, 3 };
@@ -315,7 +313,7 @@ public class PoolSmokeTests : SmokeTestsBase
PrmWait.DefaultParams,
xheaders: ["testKey", "testValue"]);
- var createdContainer = await pool.CreateContainerAsync(createContainerParam, ctx);
+ var createdContainer = await pool.PutContainerAsync(createContainerParam, ctx);
var container = await pool.GetContainerAsync(new PrmContainerGet(createdContainer), default);
Assert.NotNull(container);
@@ -399,7 +397,7 @@ public class PoolSmokeTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
PrmWait.DefaultParams);
- var container = await pool.CreateContainerAsync(createContainerParam, ctx);
+ var container = await pool.PutContainerAsync(createContainerParam, ctx);
var containerInfo = await pool.GetContainerAsync(new PrmContainerGet(container), ctx);
Assert.NotNull(containerInfo);
@@ -483,7 +481,7 @@ public class PoolSmokeTests : SmokeTestsBase
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1))),
lightWait);
- var containerId = await pool.CreateContainerAsync(createContainerParam, default);
+ var containerId = await pool.PutContainerAsync(createContainerParam, default);
var ctx = new CallContext(TimeSpan.FromSeconds(10));
@@ -545,20 +543,4 @@ public class PoolSmokeTests : SmokeTestsBase
Assert.Fail($"Container {cid.GetValue()} exist");
}
}
-
- private static byte[] GetRandomBytes(int size)
- {
- Random rnd = new();
- var bytes = new byte[size];
- rnd.NextBytes(bytes);
- return bytes;
- }
-
- static async Task Cleanup(Pool pool)
- {
- await foreach (var cid in pool.ListContainersAsync(default, default))
- {
- await pool.DeleteContainerAsync(new PrmContainerDelete(cid, lightWait), default).ConfigureAwait(true);
- }
- }
}
diff --git a/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs b/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs
deleted file mode 100644
index 3dac829..0000000
--- a/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs
+++ /dev/null
@@ -1,829 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Security.Cryptography;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
-using FrostFS.Refs;
-using FrostFS.SDK.Client;
-using FrostFS.SDK.Client.Interfaces;
-using FrostFS.SDK.Cryptography;
-using FrostFS.SDK.SmokeTests;
-using FrostFS.Session;
-using Google.Protobuf;
-using Microsoft.Extensions.Options;
-
-namespace FrostFS.SDK.Tests.Smoke;
-
-[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
-[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
-public class SmokeClientTests : SmokeTestsBase
-{
- private static readonly PrmWait lightWait = new(100, 1);
-
- [Fact]
- public async void AccountTest()
- {
- var test = lightWait.Timeout;
-
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- var result = await client.GetBalanceAsync(default);
-
- Assert.NotNull(result);
- Assert.True(result.Value == 0);
- }
-
- [Fact]
- public async void NodeInfoTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- var result = await client.GetNodeInfoAsync(default);
-
- Assert.Equal(2, result.Version.Major);
- Assert.Equal(13, result.Version.Minor);
- Assert.Equal(NodeState.Online, result.State);
- Assert.Equal(33, result.PublicKey.Length);
- // Assert.Single(result.Addresses);
- // Assert.Equal(9, result.Attributes.Count);
- }
-
- [Fact]
- public async void NodeInfoStatisticsTest()
- {
- var options = ClientOptions;
-
- var callbackContent = string.Empty;
- options.Value.Callback = (cs) => callbackContent = $"{cs.MethodName} took {cs.ElapsedMicroSeconds} microseconds";
-
- var client = FrostFSClient.GetInstance(options, GrpcChannel);
-
- var result = await client.GetNodeInfoAsync(default);
-
- Assert.NotEmpty(callbackContent);
- }
-
- [Fact]
- public async void GetSessionTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- var token = await client.CreateSessionAsync(new(100), default);
-
- Assert.NotNull(token);
- Assert.NotEqual(Guid.Empty, token.Id);
- Assert.Equal(33, token.SessionKey.Length);
- }
-
- [Fact]
- public async void CreateObjectWithSessionToken()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- await Cleanup(client);
-
- var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue), default);
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams,
- xheaders: ["key1", "value1"]);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
-
- await AddObjectRules(client, containerId);
-
- var bytes = GetRandomBytes(1024);
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")]),
- sessionToken: token);
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId), default)
- .ConfigureAwait(true);
-
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk().ConfigureAwait(true)) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
-
- await Cleanup(client).ConfigureAwait(true);
- }
-
- [Fact]
- public async void FilterTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- await Cleanup(client);
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- lightWait);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
-
- await AddObjectRules(client, containerId);
-
- var bytes = new byte[] { 1, 2, 3 };
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")],
- new FrostFsSplit()));
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var ecdsaKey = keyString.LoadWif();
-
- var networkInfo = await client.GetNetmapSnapshotAsync(default);
-
- await CheckFilter(client, containerId, new FilterByContainerId(FrostFsMatchType.Equals, containerId));
-
- await CheckFilter(client, containerId, new FilterByOwnerId(FrostFsMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey)));
-
- await CheckFilter(client, containerId, new FilterBySplitId(FrostFsMatchType.Equals, param.Header!.Split!.SplitId));
-
- await CheckFilter(client, containerId, new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test"));
-
- await CheckFilter(client, containerId, new FilterByObjectId(FrostFsMatchType.Equals, objectId));
-
- await CheckFilter(client, containerId, new FilterByVersion(FrostFsMatchType.Equals, networkInfo.NodeInfoCollection[0].Version));
-
- await CheckFilter(client, containerId, new FilterByEpoch(FrostFsMatchType.Equals, networkInfo.Epoch));
-
- await CheckFilter(client, containerId, new FilterByPayloadLength(FrostFsMatchType.Equals, 3));
-
- var checkSum = CheckSum.CreateCheckSum(bytes);
-
- // await CheckFilter(client, containerId, new FilterByPayloadHash(FrostFsMatchType.Equals, checkSum));
-
- await CheckFilter(client, containerId, new FilterByPhysicallyStored());
- }
-
- private static async Task CheckFilter(IFrostFSClient client, FrostFsContainerId containerId, IObjectFilter filter)
- {
- var resultObjectsCount = 0;
-
- PrmObjectSearch searchParam = new(containerId, null, [], filter);
-
- await foreach (var objId in client.SearchObjectsAsync(searchParam, default))
- {
- resultObjectsCount++;
- var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objId), default);
- }
-
- Assert.True(0 < resultObjectsCount, $"Filter for {filter.Key} doesn't work");
- }
-
- [Theory]
- [InlineData(1)]
- [InlineData(3 * 1024 * 1024)] // exactly one chunk size - 3MB
- [InlineData(6 * 1024 * 1024 + 100)]
- public async void SimpleScenarioTest(int objectSize)
- {
- bool callbackInvoked = false;
-
- var options = ClientOptions;
-
- options.Value.Callback = new((cs) =>
- {
- callbackInvoked = true;
- Assert.True(cs.ElapsedMicroSeconds > 0);
- });
-
- var client = FrostFSClient.GetInstance(options, GrpcChannel);
-
- await Cleanup(client);
-
- var ctx = new CallContext(TimeSpan.FromSeconds(20));
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams,
- xheaders: ["testKey", "testValue"]);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, ctx);
-
- var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
- Assert.NotNull(container);
- Assert.True(callbackInvoked);
-
- await AddObjectRules(client, containerId);
-
- var bytes = GetRandomBytes(objectSize);
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")]));
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var filter1 = new FilterByOwnerId(FrostFsMatchType.Equals, OwnerId!);
- await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId, null, [], filter1), default))
- {
- var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId, false), default);
- }
-
- var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
-
- bool hasObject = false;
- await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId, null, [], filter), default))
- {
- hasObject = true;
-
- var res = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId), default);
-
- var objHeader = res.HeaderInfo;
- Assert.NotNull(objHeader);
- Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
- Assert.NotNull(objHeader.Attributes);
- Assert.Single(objHeader.Attributes);
- Assert.Equal("fileName", objHeader.Attributes.First().Key);
- Assert.Equal("test", objHeader.Attributes.First().Value);
- }
-
- Assert.True(hasObject);
-
- var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId), default);
-
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
- }
-
- [Theory]
- [InlineData(1)]
- [InlineData(500 * 1024)]
- [InlineData(3 * 1024 * 1024)]
- public async void PutSingleObjectTest(int objectSize)
- {
- var options = ClientOptions;
-
- var client = FrostFSClient.GetInstance(options, GrpcChannel);
-
- await Cleanup(client);
-
- var ctx = new CallContext();
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams,
- xheaders: ["testKey1", "testValue1"]);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, ctx);
-
- var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
- Assert.NotNull(container);
-
- await AddObjectRules(client, containerId);
-
- var bytes = GetRandomBytes(objectSize);
-
- var header = new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName1", "test1")]);
-
- var obj = new FrostFsObject(header) { SingleObjectPayload = bytes };
-
- var param = new PrmSingleObjectPut(obj);
-
- var objectId = await client.PutSingleObjectAsync(param, default).ConfigureAwait(true);
-
- var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName1", "test1");
-
- bool hasObject = false;
- await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId, null, [], filter), default))
- {
- hasObject = true;
-
- var res = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId), default);
-
- var objHeader = res.HeaderInfo;
- Assert.NotNull(objHeader);
- Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
- Assert.NotNull(objHeader.Attributes);
- Assert.Single(objHeader.Attributes);
- Assert.Equal("fileName1", objHeader.Attributes.First().Key);
- Assert.Equal("test1", objHeader.Attributes.First().Value);
- }
-
- Assert.True(hasObject);
-
- var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId), default);
-
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
-
- await Cleanup(client);
-
- await foreach (var _ in client.ListContainersAsync(default, default))
- {
- Assert.Fail("Containers exist");
- }
- }
-
- [Fact]
- public async void CleanupTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- await Cleanup(client);
- }
-
- [Fact]
- public async void PatchTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- await Cleanup(client);
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams,
- xheaders: ["testKey", "testValue"]);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
-
- var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
- Assert.NotNull(container);
-
- await AddObjectRules(client, containerId);
-
- var bytes = new byte[1024];
- for (int i = 0; i < 1024; i++)
- {
- bytes[i] = 31;
- }
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")]));
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var patch = new byte[256];
- for (int i = 0; i < patch.Length; i++)
- {
- patch[i] = 32;
- }
-
- var range = new FrostFsRange(64, (ulong)patch.Length);
-
- var patchParams = new PrmObjectPatch(
- new FrostFsAddress(containerId, objectId),
- payload: new MemoryStream(patch),
- maxChunkLength: 256,
- range: range);
-
- var newIbjId = await client.PatchObjectAsync(patchParams, default);
-
- var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, newIbjId), default);
-
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- for (int i = 0; i < (int)range.Offset; i++)
- Assert.Equal(downloadedBytes[i], bytes[i]);
-
- var rangeEnd = range.Offset + range.Length;
-
- for (int i = (int)range.Offset; i < (int)rangeEnd; i++)
- Assert.Equal(downloadedBytes[i], patch[i - (int)range.Offset]);
-
- for (int i = (int)rangeEnd; i < bytes.Length; i++)
- Assert.Equal(downloadedBytes[i], bytes[i]);
-
- await Cleanup(client);
-
- await foreach (var _ in client.ListContainersAsync(default, default))
- {
- Assert.Fail("Containers exist");
- }
- }
-
- [Fact]
- public async void RangeTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- await Cleanup(client);
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams,
- xheaders: ["testKey", "testValue"]);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
-
- var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
- Assert.NotNull(container);
-
- await AddObjectRules(client, containerId);
-
- var bytes = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- bytes[i] = (byte)i;
- }
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular));
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var rangeParam = new PrmRangeGet(containerId, objectId, new FrostFsRange(50, 100));
-
- var rangeReader = await client.GetRangeAsync(rangeParam, default);
-
- var downloadedBytes = new byte[rangeParam.Range.Length];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk;
- while ((chunk = await rangeReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- Assert.Equal(SHA256.HashData(bytes.AsSpan().Slice(50, 100)), SHA256.HashData(downloadedBytes));
- }
-
- [Fact]
- public async void RangeHashTest()
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- await Cleanup(client);
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams,
- xheaders: ["testKey", "testValue"]);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
-
- var container = await client.GetContainerAsync(new PrmContainerGet(containerId), default);
- Assert.NotNull(container);
-
- await AddObjectRules(client, containerId);
-
- var bytes = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- bytes[i] = (byte)i;
- }
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular));
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var rangeParam = new PrmRangeHashGet(containerId, objectId, [new FrostFsRange(100, 64)], bytes);
-
- var hashes = await client.GetRangeHashAsync(rangeParam, default);
-
- foreach (var hash in hashes)
- {
- var x = hash[..32].ToArray();
- Assert.NotNull(x);
- Assert.True(x.Length > 0);
- }
- }
-
- [Theory]
- [InlineData(1)]
- [InlineData(3 * 1024 * 1024)] // exactly one chunk size - 3MB
- [InlineData(6 * 1024 * 1024 + 100)]
- public async void SimpleScenarioWithSessionTest(int objectSize)
- {
- var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
-
- var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue), default);
-
- await Cleanup(client);
-
- var ctx = new CallContext(TimeSpan.FromSeconds(20));
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- PrmWait.DefaultParams);
-
- var container = await client.CreateContainerAsync(createContainerParam, ctx);
-
- var containerInfo = await client.GetContainerAsync(new PrmContainerGet(container), ctx);
- Assert.NotNull(containerInfo);
-
- await AddObjectRules(client, container);
-
- var bytes = GetRandomBytes(objectSize);
-
- var param = new PrmObjectPut(
- new FrostFsObjectHeader(
- containerId: container,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")]),
- sessionToken: token);
-
- var stream = await client.PutObjectAsync(param, default).ConfigureAwait(true);
-
- await stream.WriteAsync(bytes.AsMemory());
- var objectId = await stream.CompleteAsync();
-
- var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
-
- bool hasObject = false;
- await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(container, token, [], filter), default))
- {
- hasObject = true;
-
- var res = await client.GetObjectHeadAsync(new PrmObjectHeadGet(container, objectId, false, token), default);
-
- var objHeader = res.HeaderInfo;
- Assert.NotNull(objHeader);
- Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
- Assert.NotNull(objHeader.Attributes);
- Assert.Single(objHeader.Attributes);
- Assert.Equal("fileName", objHeader.Attributes.First().Key);
- Assert.Equal("test", objHeader.Attributes.First().Value);
- }
-
- Assert.True(hasObject);
-
- var @object = await client.GetObjectAsync(new PrmObjectGet(container, objectId, token), default);
-
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
-
- await Cleanup(client);
-
- await foreach (var _ in client.ListContainersAsync(default, default))
- {
- Assert.Fail("Containers exist");
- }
- }
-
- [Fact]
- public async void ClientCutScenarioTest()
- {
- var options = ClientOptions;
- options.Value.Interceptors.Add(new CallbackInterceptor());
-
- var client = FrostFSClient.GetInstance(options, GrpcChannel);
-
- await Cleanup(client);
-
- int[] replicas = [3]; //1
-
- foreach (var rep in replicas)
- {
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(
- new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(rep)),
- [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]),
- lightWait);
-
- var containerId = await client.CreateContainerAsync(createContainerParam, default);
-
- var ctx = new CallContext(TimeSpan.FromSeconds(10));
-
- var container = await client.GetContainerAsync(new PrmContainerGet(containerId), ctx);
-
- Assert.NotNull(container);
-
- await AddObjectRules(client, containerId);
-
- var mb = 1024 * 1024;
-
- int[] objectSizes = [1, 1024, 64 * mb + 1]; //64 * mb, 64 * mb - 1, , 2 * 64 * mb + 256];
-
- foreach (var objectSize in objectSizes)
- {
- byte[] bytes = GetRandomBytes(objectSize);
-
- var param = new PrmObjectClientCutPut(
- new FrostFsObjectHeader(
- containerId: containerId,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")]),
- payload: new MemoryStream(bytes));
-
- var objectId = await client.PutClientCutObjectAsync(param, default).ConfigureAwait(true);
-
- var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId), default);
-
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
-
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
-
- Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
- }
- }
- }
-
- [Fact]
- public async void NodeInfoCallbackAndInterceptorTest()
- {
- bool callbackInvoked = false;
- bool interceptorInvoked = false;
-
- var options = ClientOptions;
- options.Value.Callback = (cs) =>
- {
- callbackInvoked = true;
- Assert.True(cs.ElapsedMicroSeconds > 0);
- };
-
- options.Value.Interceptors.Add(new CallbackInterceptor(s => interceptorInvoked = true));
-
- var client = FrostFSClient.GetInstance(options, GrpcChannel);
-
- var result = await client.GetNodeInfoAsync(default);
-
- Assert.True(callbackInvoked);
- Assert.True(interceptorInvoked);
-
- Assert.Equal(2, result.Version.Major);
- Assert.Equal(13, result.Version.Minor);
- Assert.Equal(NodeState.Online, result.State);
- Assert.Equal(33, result.PublicKey.Length);
- Assert.NotNull(result.Addresses);
- Assert.True(result.Attributes.Count > 0);
- }
-
- private static byte[] GetRandomBytes(int size)
- {
- Random rnd = new();
- var bytes = new byte[size];
- rnd.NextBytes(bytes);
- return bytes;
- }
-
- private static IOptions GetClientOptions(string key, string url)
- {
- return Options.Create(new ClientSettings
- {
- Key = key,
- Host = url
- });
- }
-
- static async Task Cleanup(IFrostFSClient client)
- {
- await foreach (var cid in client.ListContainersAsync(default, default))
- {
- await client.DeleteContainerAsync(new PrmContainerDelete(cid, lightWait), default);
- }
- }
-
- private static async Task AddContainerRules(IFrostFSClient client, FrostFsContainerId containerId)
- {
- var addChainPrm = new PrmApeChainAdd(
- new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()),
- new FrostFsChain
- {
- ID = Encoding.ASCII.GetBytes("chain-id-test1"),
- Rules = [
- new FrostFsRule
- {
- Status = RuleStatus.Allow,
- Actions = new Actions(inverted: false, names: ["*"]),
- Resources = new Resource (inverted: false, names: [$"native:container/*"]),
- Any = false,
- Conditions = []
- }
- ],
- MatchType = RuleMatchType.DenyPriority
- }
- );
-
- await client.AddChainAsync(addChainPrm, default);
-
- var listChainPrm = new PrmApeChainList(new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()));
-
- while (true)
- {
- await Task.Delay(1000);
- var chains = await client.ListChainAsync(listChainPrm, default);
-
- if (chains.Length > 0)
- break;
- }
-
- await Task.Delay(8000);
- }
-
- private static async Task AddObjectRules(IFrostFSClient client, FrostFsContainerId containerId)
- {
- var addChainPrm = new PrmApeChainAdd(
- new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()),
- new FrostFsChain
- {
- ID = Encoding.ASCII.GetBytes("chain-id-test"),
- Rules = [
- new FrostFsRule
- {
- Status = RuleStatus.Allow,
- Actions = new Actions(inverted: false, names: ["*"]),
- Resources = new Resource (inverted: false, names: [$"native:object/*"]),
- Any = false,
- Conditions = []
- }
- ],
- MatchType = RuleMatchType.DenyPriority
- }
- );
-
- await client.AddChainAsync(addChainPrm, default);
-
- await Task.Delay(8000);
- }
-}
diff --git a/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs b/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs
index a524a82..ac76a54 100644
--- a/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs
@@ -1,28 +1,34 @@
-using System.Security.Cryptography;
-
+using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Security.Cryptography;
+using System.Security.Principal;
+using System.Text;
using FrostFS.SDK.Client;
+using FrostFS.SDK.Client.Interfaces;
using FrostFS.SDK.Cryptography;
using Grpc.Core;
using Microsoft.Extensions.Options;
+using Xunit.Abstractions;
namespace FrostFS.SDK.Tests.Smoke;
+[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
+[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
public abstract class SmokeTestsBase
{
// cluster Ori
- internal readonly string url = "http://10.78.128.207:8080";
- internal readonly string keyString = "L4JWLdedUd4b21sriRHtCPGkjG2Mryz2AWLiVqTBSNyxxyAUcc7s";
-
+ // internal readonly string url = "http://10.78.128.207:8080";
+ // internal readonly string keyString = "L4JWLdedUd4b21sriRHtCPGkjG2Mryz2AWLiVqTBSNyxxyAUcc7s";
// cluster
- // internal readonly string url = "http://10.78.128.190:8080";
- // internal readonly string keyString = "L47c3bunc6bJd7uEAfPUae2VkyupFR9nizoH6jfPonzQxijqH2Ba";
+ internal readonly string url = "http://10.78.128.190:8080";
+ internal readonly string keyString = "L47c3bunc6bJd7uEAfPUae2VkyupFR9nizoH6jfPonzQxijqH2Ba";
// WSL2
- //internal readonly string url = "http://172.29.238.97:8080";
- //internal readonly string keyString = "KzPXA6669m2pf18XmUdoR8MnP1pi1PMmefiFujStVFnv7WR5SRmK";
+ // internal readonly string url = "http://172.29.238.97:8080";
+ // internal readonly string keyString = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq"; // "KzPXA6669m2pf18XmUdoR8MnP1pi1PMmefiFujStVFnv7WR5SRmK";
//"KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
@@ -44,4 +50,88 @@ public abstract class SmokeTestsBase
protected static Func GrpcChannel => (url) => Grpc.Net.Client.GrpcChannel.ForAddress(new Uri(url));
protected IOptions ClientOptions => Options.Create(new ClientSettings { Key = keyString, Host = url });
+
+ protected static readonly PrmWait lightWait = new(100, 1);
+
+ protected static byte[] GetRandomBytes(int size)
+ {
+ Random rnd = new();
+ var bytes = new byte[size];
+ rnd.NextBytes(bytes);
+ return bytes;
+ }
+
+ protected static async Task CreateContainer(IFrostFSClient client,
+ CallContext ctx,
+ FrostFsSessionToken? token,
+ bool unique,
+ uint backupFactor,
+ Collection selectors,
+ Collection filter,
+ Collection containerAttributes,
+ params FrostFsReplica[] replicas)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+
+ var networkSettings = await client.GetNetworkSettingsAsync(ctx);
+
+ var attributes = containerAttributes ?? [];
+
+ if (networkSettings.HomomorphicHashingDisabled)
+ attributes.Add(new("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true"));
+
+ var containerInfo = new FrostFsContainerInfo(
+ new FrostFsPlacementPolicy(unique, backupFactor, selectors, filter, replicas),
+ [.. attributes]);
+
+ var createContainerParam = new PrmContainerCreate(
+ containerInfo,
+ PrmWait.DefaultParams,
+ token,
+ xheaders: ["key1", "value1"]);
+
+ return await client.PutContainerAsync(createContainerParam, ctx);
+ }
+
+ protected static async Task Cleanup(IFrostFSClient client)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+
+ var tasks = new List();
+ await foreach (var cid in client.ListContainersAsync(default, default))
+ {
+ tasks.Add(client.DeleteContainerAsync(new PrmContainerDelete(cid, lightWait), default));
+ }
+
+ await Task.WhenAll(tasks);
+ }
+
+ protected static async Task AddObjectRules(IFrostFSClient client, FrostFsContainerId containerId)
+ {
+ ArgumentNullException.ThrowIfNull(client);
+ ArgumentNullException.ThrowIfNull(containerId);
+
+ var addChainPrm = new PrmApeChainAdd(
+ new FrostFsChainTarget(FrostFsTargetType.Container, containerId.GetValue()),
+ new FrostFsChain
+ {
+ ID = Encoding.ASCII.GetBytes("chain-id-test"),
+ Rules = [
+ new FrostFsRule
+ {
+ Status = RuleStatus.Allow,
+ Actions = new Actions(inverted: false, names: ["*"]),
+ Resources = new Resource (inverted: false, names: [$"native:object/*"]),
+ Any = false,
+ Conditions = []
+ }
+ ],
+ MatchType = RuleMatchType.DenyPriority
+ }
+ );
+
+ await client.AddChainAsync(addChainPrm, default);
+
+ await Task.Delay(8000);
+ }
}
diff --git a/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs b/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs
index 2088b4b..db1e193 100644
--- a/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs
+++ b/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs
@@ -16,7 +16,7 @@ public class ContainerTest : ContainerTestsBase
{
var param = new PrmContainerCreate(new FrostFsContainerInfo(Mocker.PlacementPolicy), PrmWait.DefaultParams);
- var result = await GetClient().CreateContainerAsync(param, default);
+ var result = await GetClient().PutContainerAsync(param, default);
Assert.NotNull(result);
Assert.NotNull(result.GetValue());
--
2.45.3