From 2e56c139465c601c5c5bdb5a27696dcce376b511 Mon Sep 17 00:00:00 2001 From: Pavel Gross Date: Mon, 17 Feb 2025 16:01:41 +0300 Subject: [PATCH] [#31] Client: fix for session Signed-off-by: Pavel Gross --- src/FrostFS.SDK.Client/CllientKey.cs | 2 +- src/FrostFS.SDK.Client/FrostFSClient.cs | 2 +- .../Models/Netmap/FrostFsPlacementPolicy.cs | 3 +- .../Models/Object/FrostFsObject.cs | 3 +- .../Models/Session/FrostFsSessionToken.cs | 15 +- src/FrostFS.SDK.Client/ObjectWriter.cs | 2 + .../Services/ObjectServiceProvider.cs | 84 +++--- .../Tools/RequestConstructor.cs | 5 +- .../Smoke/SmokeClientTests.cs | 268 +++++++++++------- src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs | 9 +- 10 files changed, 247 insertions(+), 146 deletions(-) diff --git a/src/FrostFS.SDK.Client/CllientKey.cs b/src/FrostFS.SDK.Client/CllientKey.cs index da02b02..7a7943b 100644 --- a/src/FrostFS.SDK.Client/CllientKey.cs +++ b/src/FrostFS.SDK.Client/CllientKey.cs @@ -12,7 +12,7 @@ public class ClientKey(ECDsa key) internal ByteString PublicKeyProto { get; } = ByteString.CopyFrom(key.PublicKey()); - internal string PublicKey { get; } = key.PublicKey().ToString(); + internal string PublicKey { get; } = Base58.Encode(key.PublicKey()); internal FrostFsOwner Owner { get; } = new FrostFsOwner(key.PublicKey().PublicKeyToAddress()); } diff --git a/src/FrostFS.SDK.Client/FrostFSClient.cs b/src/FrostFS.SDK.Client/FrostFSClient.cs index eea24fc..27017fe 100644 --- a/src/FrostFS.SDK.Client/FrostFSClient.cs +++ b/src/FrostFS.SDK.Client/FrostFSClient.cs @@ -447,7 +447,7 @@ public class FrostFSClient : IFrostFSClient { var invoker = CreateInvoker(); - ObjectServiceClient = ObjectServiceClient ?? ( + ObjectServiceClient ??= ( invoker != null ? new ObjectServiceClient(invoker) : new ObjectServiceClient(ClientCtx.Channel)); diff --git a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs index 6ca8ab9..184514b 100644 --- a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs +++ b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsPlacementPolicy.cs @@ -47,7 +47,8 @@ public struct FrostFsPlacementPolicy(bool unique, Filters = { }, Selectors = { }, Replicas = { }, - Unique = Unique + Unique = Unique, + ContainerBackupFactor = BackupFactor }; foreach (var replica in Replicas) diff --git a/src/FrostFS.SDK.Client/Models/Object/FrostFsObject.cs b/src/FrostFS.SDK.Client/Models/Object/FrostFsObject.cs index f366b9e..dfd2a22 100644 --- a/src/FrostFS.SDK.Client/Models/Object/FrostFsObject.cs +++ b/src/FrostFS.SDK.Client/Models/Object/FrostFsObject.cs @@ -45,9 +45,10 @@ public class FrostFsObject /// Reader for received data public IObjectReader? ObjectReader { get; set; } - internal byte[] SingleObjectPayload + public byte[] SingleObjectPayload { get { return bytes ?? []; } + set { bytes = value; } } /// diff --git a/src/FrostFS.SDK.Client/Models/Session/FrostFsSessionToken.cs b/src/FrostFS.SDK.Client/Models/Session/FrostFsSessionToken.cs index 54f0615..5f675ae 100644 --- a/src/FrostFS.SDK.Client/Models/Session/FrostFsSessionToken.cs +++ b/src/FrostFS.SDK.Client/Models/Session/FrostFsSessionToken.cs @@ -1,5 +1,5 @@ using System; - +using System.Diagnostics; using FrostFS.Refs; using FrostFS.SDK.Client; @@ -36,7 +36,9 @@ public class FrostFsSessionToken get { if (_id == Guid.Empty) + { _id = ProtoId.ToUuid(); + } return _id; } @@ -47,7 +49,9 @@ public class FrostFsSessionToken get { if (_sessionKey.IsEmpty) + { _sessionKey = ProtoSessionKey.Memory; + } return _sessionKey; } @@ -69,12 +73,15 @@ public class FrostFsSessionToken sessionToken.Body.Container = new() { Verb = verb }; if (containerId != null) + { sessionToken.Body.Container.ContainerId = containerId; + } else + { sessionToken.Body.Container.Wildcard = true; + } sessionToken.Body.SessionKey = key.PublicKeyProto; - sessionToken.Signature = key.ECDsaKey.SignMessagePart(sessionToken.Body); return sessionToken; @@ -100,7 +107,9 @@ public class FrostFsSessionToken ObjectSessionContext.Types.Target target = new() { Container = address.ContainerId }; if (address.ObjectId != null) + { target.Objects.Add(address.ObjectId); + } sessionToken.Body.Object = new() { @@ -108,8 +117,6 @@ public class FrostFsSessionToken Verb = verb }; - sessionToken.Body.SessionKey = key.PublicKeyProto; - sessionToken.Signature = key.ECDsaKey.SignMessagePart(sessionToken.Body); return sessionToken; diff --git a/src/FrostFS.SDK.Client/ObjectWriter.cs b/src/FrostFS.SDK.Client/ObjectWriter.cs index 4fad9c9..5683740 100644 --- a/src/FrostFS.SDK.Client/ObjectWriter.cs +++ b/src/FrostFS.SDK.Client/ObjectWriter.cs @@ -32,6 +32,8 @@ namespace FrostFS.SDK.Client } }; + chunkRequest.AddMetaHeader(args.XHeaders); + chunkRequest.Sign(this.ctx.Key.ECDsaKey); await streamer.Write(chunkRequest).ConfigureAwait(false); diff --git a/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs b/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs index 3125547..1011b69 100644 --- a/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs +++ b/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs @@ -10,7 +10,6 @@ using FrostFS.Refs; using FrostFS.SDK.Client; using FrostFS.SDK.Client.Interfaces; using FrostFS.SDK.Client.Mappers.GRPC; -using FrostFS.SDK.Cryptography; using FrostFS.Session; using Google.Protobuf; @@ -278,7 +277,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false); var protoToken = sessionToken.CreateObjectTokenContext( - new Address { ContainerId = grpcObject.Header.ContainerId, ObjectId = grpcObject.ObjectId }, + new Address { ContainerId = grpcObject.Header.ContainerId }, ObjectSessionContext.Types.Verb.Put, ClientContext.Key); @@ -297,7 +296,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl { var chunkSize = args.MaxChunkLength; Stream payload = args.Payload ?? throw new ArgumentNullException(nameof(args), "Stream parameter is null"); - + var call = client.Patch(null, ctx.GetDeadline(), ctx.CancellationToken); byte[]? chunkBuffer = null; @@ -306,31 +305,15 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl // common chunkBuffer = ArrayPool.Shared.Rent(chunkSize); + bool isFirstChunk = true; + ulong currentPos = args.Range.Offset; + var address = new Address { ObjectId = args.Address.ObjectId, ContainerId = args.Address.ContainerId }; - var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false); - - var protoToken = sessionToken.CreateObjectTokenContext( - address, - ObjectSessionContext.Types.Verb.Patch, - ClientContext.Key); - - var request = new PatchRequest() - { - Body = new() - { - Address = address, - ReplaceAttributes = args.ReplaceAttributes, - } - }; - - bool isFirstChunk = true; - ulong currentPos = args.Range.Offset; - while (true) { var bytesCount = await payload.ReadAsync(chunkBuffer, 0, chunkSize, ctx.CancellationToken).ConfigureAwait(false); @@ -340,41 +323,62 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl break; } - if (isFirstChunk && args.NewAttributes != null && args.NewAttributes.Length > 0) + var request = new PatchRequest() { - foreach (var attr in args.NewAttributes) + Body = new() { - request.Body.NewAttributes.Add(attr.ToMessage()); + Address = address, + Patch = new PatchRequest.Types.Body.Types.Patch + { + Chunk = ByteString.CopyFrom(chunkBuffer, 0, bytesCount), + SourceRange = new Object.Range { Offset = currentPos, Length = (ulong)bytesCount } + } } - } - - request.Body.Patch = new PatchRequest.Types.Body.Types.Patch - { - Chunk = ByteString.CopyFrom(chunkBuffer, 0, bytesCount), - SourceRange = new Object.Range { Offset = currentPos, Length = (ulong)bytesCount } }; - currentPos += (ulong)bytesCount; + if (isFirstChunk) + { + var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false); - request.AddMetaHeader(args.XHeaders, protoToken); + var protoToken = sessionToken.CreateObjectTokenContext( + address, + ObjectSessionContext.Types.Verb.Patch, + ClientContext.Key); + + request.AddMetaHeader(args.XHeaders, protoToken); + + if (args.NewAttributes != null && args.NewAttributes.Length > 0) + { + foreach (var attr in args.NewAttributes) + { + request.Body.NewAttributes.Add(attr.ToMessage()); + request.Body.ReplaceAttributes = args.ReplaceAttributes; + } + } + + isFirstChunk = false; + } + else + { + request.AddMetaHeader(args.XHeaders); + } request.Sign(ClientContext.Key.ECDsaKey); await call.RequestStream.WriteAsync(request).ConfigureAwait(false); - isFirstChunk = false; + currentPos += (ulong)bytesCount; } } finally { - await call.RequestStream.CompleteAsync().ConfigureAwait(false); - if (chunkBuffer != null) { ArrayPool.Shared.Return(chunkBuffer); } } + await call.RequestStream.CompleteAsync().ConfigureAwait(false); var response = await call.ResponseAsync.ConfigureAwait(false); Verifier.CheckResponse(response); @@ -513,7 +517,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl { // send chunks limited to default or user's settings var bufferSize = objectLimitSize > 0 ? - (int)Math.Min(objectLimitSize - sentBytes, chunkSize) + Math.Min(objectLimitSize - sentBytes, chunkSize) : chunkSize; var bytesCount = await payload.ReadAsync(chunkBuffer, 0, bufferSize, ctx.CancellationToken).ConfigureAwait(false); @@ -531,6 +535,8 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl } }; + chunkRequest.AddMetaHeader(args.XHeaders); + chunkRequest.Sign(ClientContext.Key.ECDsaKey); await stream.Write(chunkRequest).ConfigureAwait(false); @@ -571,8 +577,6 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl ObjectTools.SetSplitValues(grpcHeader, header.Split, ClientContext.Owner, ClientContext.Version, ClientContext.Key); } - var oid = new ObjectID { Value = grpcHeader.Sha256() }; - var initRequest = new PutRequest { Body = new PutRequest.Types.Body @@ -587,7 +591,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false); var protoToken = sessionToken.CreateObjectTokenContext( - new Address { ContainerId = grpcHeader.ContainerId, ObjectId = oid }, + new Address { ContainerId = grpcHeader.ContainerId }, ObjectSessionContext.Types.Verb.Put, ClientContext.Key); diff --git a/src/FrostFS.SDK.Client/Tools/RequestConstructor.cs b/src/FrostFS.SDK.Client/Tools/RequestConstructor.cs index 00a3916..102eeb5 100644 --- a/src/FrostFS.SDK.Client/Tools/RequestConstructor.cs +++ b/src/FrostFS.SDK.Client/Tools/RequestConstructor.cs @@ -18,7 +18,10 @@ public static class RequestConstructor if (request.MetaHeader is not null) return; - request.MetaHeader = MetaHeader.Default().ToMessage(); + var metaHeader = MetaHeader.Default(); + metaHeader.Ttl = 2; + + request.MetaHeader = metaHeader.ToMessage(); if (sessionToken != null) request.MetaHeader.SessionToken = sessionToken; diff --git a/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs b/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs index e1b0c8d..3dac829 100644 --- a/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs +++ b/src/FrostFS.SDK.Tests/Smoke/SmokeClientTests.cs @@ -7,6 +7,7 @@ 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; @@ -21,6 +22,8 @@ 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); @@ -66,8 +69,6 @@ public class SmokeClientTests : SmokeTestsBase var token = await client.CreateSessionAsync(new(100), default); - var ownerHash = Base58.Decode(OwnerId!.Value); - Assert.NotNull(token); Assert.NotEqual(Guid.Empty, token.Id); Assert.Equal(33, token.SessionKey.Length); @@ -84,7 +85,7 @@ public class SmokeClientTests : SmokeTestsBase var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)), [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), PrmWait.DefaultParams, xheaders: ["key1", "value1"]); @@ -133,7 +134,7 @@ public class SmokeClientTests : SmokeTestsBase var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)), [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), lightWait); @@ -221,7 +222,7 @@ public class SmokeClientTests : SmokeTestsBase var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)), [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), PrmWait.DefaultParams, xheaders: ["testKey", "testValue"]); @@ -285,6 +286,81 @@ public class SmokeClientTests : SmokeTestsBase } 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); @@ -294,6 +370,14 @@ public class SmokeClientTests : SmokeTestsBase } } + [Fact] + public async void CleanupTest() + { + var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel); + + await Cleanup(client); + } + [Fact] public async void PatchTest() { @@ -387,7 +471,7 @@ public class SmokeClientTests : SmokeTestsBase var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)), [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), PrmWait.DefaultParams, xheaders: ["testKey", "testValue"]); @@ -429,13 +513,6 @@ public class SmokeClientTests : SmokeTestsBase } Assert.Equal(SHA256.HashData(bytes.AsSpan().Slice(50, 100)), SHA256.HashData(downloadedBytes)); - - await Cleanup(client); - - await foreach (var _ in client.ListContainersAsync(default, default)) - { - Assert.Fail("Containers exist"); - } } [Fact] @@ -447,7 +524,7 @@ public class SmokeClientTests : SmokeTestsBase var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)), [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), PrmWait.DefaultParams, xheaders: ["testKey", "testValue"]); @@ -482,13 +559,8 @@ public class SmokeClientTests : SmokeTestsBase foreach (var hash in hashes) { var x = hash[..32].ToArray(); - } - - await Cleanup(client); - - await foreach (var _ in client.ListContainersAsync(default, default)) - { - Assert.Fail("Containers exist"); + Assert.NotNull(x); + Assert.True(x.Length > 0); } } @@ -499,7 +571,7 @@ public class SmokeClientTests : SmokeTestsBase public async void SimpleScenarioWithSessionTest(int objectSize) { var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel); - //Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0)) + var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue), default); await Cleanup(client); @@ -508,7 +580,7 @@ public class SmokeClientTests : SmokeTestsBase var createContainerParam = new PrmContainerCreate( new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(3)), [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), PrmWait.DefaultParams); @@ -574,14 +646,8 @@ public class SmokeClientTests : SmokeTestsBase } } - [Theory] - [InlineData(1)] - [InlineData(64 * 1024 * 1024)] // exactly 1 block size - 64MB - [InlineData(64 * 1024 * 1024 - 1)] - [InlineData(64 * 1024 * 1024 + 1)] - [InlineData(2 * 64 * 1024 * 1024 + 256)] - [InlineData(200)] - public async void ClientCutScenarioTest(int objectSize) + [Fact] + public async void ClientCutScenarioTest() { var options = ClientOptions; options.Value.Interceptors.Add(new CallbackInterceptor()); @@ -590,71 +656,57 @@ public class SmokeClientTests : SmokeTestsBase await Cleanup(client); - var createContainerParam = new PrmContainerCreate( - new FrostFsContainerInfo( - new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(1)), - [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), - lightWait); + int[] replicas = [3]; //1 - 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); - - 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 filter1 = new FilterByOwnerId(FrostFsMatchType.Equals, OwnerId!); - await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(containerId, null, [], filter1), default)) + foreach (var rep in replicas) { - var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId, false), default); - } + var createContainerParam = new PrmContainerCreate( + new FrostFsContainerInfo( + new FrostFsPlacementPolicy(true, 1, [], [], new FrostFsReplica(rep)), + [new FrostFsAttributePair("__SYSTEM__DISABLE_HOMOMORPHIC_HASHING", "true")]), + lightWait); - var @object = await client.GetObjectAsync(new PrmObjectGet(containerId, objectId), default); + var containerId = await client.CreateContainerAsync(createContainerParam, default); - var downloadedBytes = new byte[@object.Header.PayloadLength]; - MemoryStream ms = new(downloadedBytes); + var ctx = new CallContext(TimeSpan.FromSeconds(10)); - ReadOnlyMemory? chunk = null; - while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) - { - ms.Write(chunk.Value.Span); - } + var container = await client.GetContainerAsync(new PrmContainerGet(containerId), ctx); - Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes)); + Assert.NotNull(container); - await CheckFilter(client, containerId, new FilterByRootObject()); + await AddObjectRules(client, containerId); + + var mb = 1024 * 1024; - await Cleanup(client); + int[] objectSizes = [1, 1024, 64 * mb + 1]; //64 * mb, 64 * mb - 1, , 2 * 64 * mb + 256]; - var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)); - - IAsyncEnumerator? enumerator = null; - do - { - if (deadline <= DateTime.UtcNow) + foreach (var objectSize in objectSizes) { - Assert.Fail("Containers exist"); - break; - } + byte[] bytes = GetRandomBytes(objectSize); - enumerator = client.ListContainersAsync(default, default).GetAsyncEnumerator(); - await Task.Delay(500); + 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)); + } } - while (await enumerator!.MoveNextAsync()); } [Fact] @@ -712,6 +764,43 @@ public class SmokeClientTests : SmokeTestsBase } } + 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( @@ -735,17 +824,6 @@ public class SmokeClientTests : SmokeTestsBase 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); } } diff --git a/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs b/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs index 95e353a..a524a82 100644 --- a/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs +++ b/src/FrostFS.SDK.Tests/Smoke/SmokeTestsBase.cs @@ -11,9 +11,14 @@ namespace FrostFS.SDK.Tests.Smoke; public abstract class SmokeTestsBase { + // cluster Ori + 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"; -- 2.45.3