diff --git a/src/FrostFS.SDK.Client/AssemblyInfo.cs b/src/FrostFS.SDK.Client/AssemblyInfo.cs
index 4d87f8c..4fa6cd9 100644
--- a/src/FrostFS.SDK.Client/AssemblyInfo.cs
+++ b/src/FrostFS.SDK.Client/AssemblyInfo.cs
@@ -8,7 +8,7 @@ using System.Runtime.CompilerServices;
"e15ab287e6239c98d5dfa91615bd77485d523a3a3f65a4e5028454cedd5ac4d9eca6da18b81985"+
"ac6905d33cc64b5a2587050c16f67b71ef8889dbd3c90ef7cc0b06bbbe09886601d195f5db179a"+
"3c2a25b1")]
-[assembly: AssemblyFileVersion("1.0.6.0")]
+[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyProduct("FrostFS.SDK.Client")]
[assembly: AssemblyTitle("FrostFS.SDK.Client")]
-[assembly: AssemblyVersion("1.0.6")]
+[assembly: AssemblyVersion("1.0.7")]
diff --git a/src/FrostFS.SDK.Client/FrostFS.SDK.Client.csproj b/src/FrostFS.SDK.Client/FrostFS.SDK.Client.csproj
index 037a2f4..88e20c6 100644
--- a/src/FrostFS.SDK.Client/FrostFS.SDK.Client.csproj
+++ b/src/FrostFS.SDK.Client/FrostFS.SDK.Client.csproj
@@ -6,7 +6,7 @@
enable
AllEnabledByDefault
FrostFS.SDK.Client
- 1.0.6
+ 1.0.7
C# SDK for FrostFS gRPC native protocol
diff --git a/src/FrostFS.SDK.Client/Mappers/MetaHeader.cs b/src/FrostFS.SDK.Client/Mappers/MetaHeader.cs
index e4ab8a2..b3fa5e3 100644
--- a/src/FrostFS.SDK.Client/Mappers/MetaHeader.cs
+++ b/src/FrostFS.SDK.Client/Mappers/MetaHeader.cs
@@ -16,8 +16,8 @@ public static class MetaHeaderMapper
return new RequestMetaHeader
{
Version = metaHeader.Version.ToMessage(),
- Epoch = (uint)metaHeader.Epoch,
- Ttl = (uint)metaHeader.Ttl
+ Epoch = metaHeader.Epoch,
+ Ttl = metaHeader.Ttl
};
}
}
\ 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 00ad4a3..4fa2edd 100644
--- a/src/FrostFS.SDK.Client/Mappers/Netmap/Replica.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Netmap/Replica.cs
@@ -11,7 +11,7 @@ public static class PolicyMapper
{
return new Replica
{
- Count = (uint)replica.Count,
+ Count = replica.Count,
Selector = replica.Selector,
EcDataCount = replica.EcDataCount,
EcParityCount = replica.EcParityCount
@@ -25,7 +25,7 @@ public static class PolicyMapper
throw new ArgumentNullException(nameof(replica));
}
- return new FrostFsReplica((int)replica.Count, replica.Selector)
+ return new FrostFsReplica(replica.Count, replica.Selector)
{
EcDataCount = replica.EcDataCount,
EcParityCount = replica.EcParityCount
diff --git a/src/FrostFS.SDK.Client/Mappers/Version.cs b/src/FrostFS.SDK.Client/Mappers/Version.cs
index a66df6e..af8738d 100644
--- a/src/FrostFS.SDK.Client/Mappers/Version.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Version.cs
@@ -18,7 +18,7 @@ public static class VersionMapper
throw new System.ArgumentNullException(nameof(model));
}
- var key = model.Major << 16 + model.Minor;
+ var key = (int)model.Major << 16 + (int)model.Minor;
if (!_cacheMessages.ContainsKey(key))
{
@@ -28,8 +28,8 @@ public static class VersionMapper
_spinlock.Enter(ref lockTaken);
var message = new Version
{
- Major = (uint)model.Major,
- Minor = (uint)model.Minor
+ Major = model.Major,
+ Minor = model.Minor
};
_cacheMessages.Add(key, message);
@@ -64,7 +64,7 @@ public static class VersionMapper
try
{
_spinlock.Enter(ref lockTaken);
- var model = new FrostFsVersion((int)message.Major, (int)message.Minor);
+ var model = new FrostFsVersion(message.Major, message.Minor);
_cacheModels.Add(key, model);
return model;
diff --git a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsReplica.cs b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsReplica.cs
index 5ace048..82e2240 100644
--- a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsReplica.cs
+++ b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsReplica.cs
@@ -4,12 +4,12 @@ namespace FrostFS.SDK;
public struct FrostFsReplica : IEquatable
{
- public int Count { get; set; }
+ public uint Count { get; set; }
public string Selector { get; set; }
public uint EcDataCount { get; set; }
public uint EcParityCount { get; set; }
- public FrostFsReplica(int count, string? selector = null)
+ public FrostFsReplica(uint count, string? selector = null)
{
selector ??= string.Empty;
@@ -31,12 +31,12 @@ public struct FrostFsReplica : IEquatable
public readonly uint CountNodes()
{
- return Count != 0 ? (uint)Count : EcDataCount + EcParityCount;
+ return Count != 0 ? Count : EcDataCount + EcParityCount;
}
public override readonly int GetHashCode()
{
- return (Count + Selector.GetHashCode()) ^ (int)EcDataCount ^ (int)EcParityCount;
+ return Count.GetHashCode() ^ Selector.GetHashCode() ^ (int)EcDataCount ^ (int)EcParityCount;
}
public static bool operator ==(FrostFsReplica left, FrostFsReplica right)
diff --git a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsVersion.cs b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsVersion.cs
index 81e642d..9ed9522 100644
--- a/src/FrostFS.SDK.Client/Models/Netmap/FrostFsVersion.cs
+++ b/src/FrostFS.SDK.Client/Models/Netmap/FrostFsVersion.cs
@@ -3,12 +3,12 @@ using FrostFS.SDK.Client.Mappers.GRPC;
namespace FrostFS.SDK;
-public class FrostFsVersion(int major, int minor)
+public class FrostFsVersion(uint major, uint minor)
{
private Version? version;
- public int Major { get; set; } = major;
- public int Minor { get; set; } = minor;
+ public uint Major { get; set; } = major;
+ public uint Minor { get; set; } = minor;
internal Version VersionID
{
diff --git a/src/FrostFS.SDK.Client/Models/Response/MetaHeader.cs b/src/FrostFS.SDK.Client/Models/Response/MetaHeader.cs
index 36dad09..547b2b5 100644
--- a/src/FrostFS.SDK.Client/Models/Response/MetaHeader.cs
+++ b/src/FrostFS.SDK.Client/Models/Response/MetaHeader.cs
@@ -1,10 +1,10 @@
namespace FrostFS.SDK;
-public class MetaHeader(FrostFsVersion version, int epoch, int ttl)
+public class MetaHeader(FrostFsVersion version, ulong epoch, uint ttl)
{
public FrostFsVersion Version { get; set; } = version;
- public int Epoch { get; set; } = epoch;
- public int Ttl { get; set; } = ttl;
+ public ulong Epoch { get; set; } = epoch;
+ public uint Ttl { get; set; } = ttl;
public static MetaHeader Default()
{
diff --git a/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs b/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs
index a8b748f..b3c1f50 100644
--- a/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs
+++ b/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs
@@ -295,86 +295,88 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
internal async Task PatchObjectAsync(PrmObjectPatch args, CallContext ctx)
{
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;
- try
+ var address = new Address
{
- chunkBuffer = ArrayPool.Shared.Rent(chunkSize);
+ ObjectId = args.Address.ObjectId,
+ ContainerId = args.Address.ContainerId
+ };
- bool isFirstChunk = true;
- ulong currentPos = args.Range.Offset;
-
- var address = new Address
+ if (args.Payload != null && args.Payload.Length > 0)
+ {
+ byte[]? chunkBuffer = null;
+ try
{
- ObjectId = args.Address.ObjectId,
- ContainerId = args.Address.ContainerId
- };
+ chunkBuffer = ArrayPool.Shared.Rent(chunkSize);
- while (true)
- {
- var bytesCount = await payload.ReadAsync(chunkBuffer, 0, chunkSize, ctx.CancellationToken).ConfigureAwait(false);
+ bool isFirstChunk = true;
+ ulong currentPos = args.Range.Offset;
- if (bytesCount == 0)
+ while (true)
{
- break;
- }
+ var bytesCount = await args.Payload.ReadAsync(chunkBuffer, 0, chunkSize, ctx.CancellationToken).ConfigureAwait(false);
- var request = new PatchRequest()
- {
- Body = new()
+ if (bytesCount == 0)
{
- Address = address,
- Patch = new PatchRequest.Types.Body.Types.Patch
+ break;
+ }
+
+ PatchRequest request;
+
+ if (isFirstChunk)
+ {
+ request = await CreateFirstRequest(args, ctx, address).ConfigureAwait(false);
+
+ request.Body.Patch = new PatchRequest.Types.Body.Types.Patch
{
Chunk = UnsafeByteOperations.UnsafeWrap(chunkBuffer.AsMemory(0, bytesCount)),
SourceRange = new Range { Offset = currentPos, Length = (ulong)bytesCount }
- }
+ };
+
+ isFirstChunk = false;
}
- };
-
- if (isFirstChunk)
- {
- var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false);
-
- var protoToken = sessionToken.CreateObjectTokenContext(
- address,
- ObjectSessionContext.Types.Verb.Patch,
- ClientContext.Key);
-
- request.AddMetaHeader(args.XHeaders, protoToken);
-
- if (args.NewAttributes != null && args.NewAttributes.Length > 0)
+ else
{
- foreach (var attr in args.NewAttributes)
+ request = new PatchRequest()
{
- request.Body.NewAttributes.Add(attr.ToMessage());
- request.Body.ReplaceAttributes = args.ReplaceAttributes;
- }
+ Body = new()
+ {
+ Address = address,
+ Patch = new PatchRequest.Types.Body.Types.Patch
+ {
+ Chunk = UnsafeByteOperations.UnsafeWrap(chunkBuffer.AsMemory(0, bytesCount)),
+ SourceRange = new Range { Offset = currentPos, Length = (ulong)bytesCount }
+ }
+ }
+ };
+
+ request.AddMetaHeader(args.XHeaders);
}
- isFirstChunk = false;
+ request.Sign(ClientContext.Key);
+
+ await call.RequestStream.WriteAsync(request).ConfigureAwait(false);
+
+ currentPos += (ulong)bytesCount;
}
- else
+ }
+ finally
+ {
+ if (chunkBuffer != null)
{
- request.AddMetaHeader(args.XHeaders);
+ ArrayPool.Shared.Return(chunkBuffer);
}
-
- request.Sign(ClientContext.Key);
-
- await call.RequestStream.WriteAsync(request).ConfigureAwait(false);
-
- currentPos += (ulong)bytesCount;
}
}
- finally
+ else if (args.NewAttributes != null && args.NewAttributes.Length > 0)
{
- if (chunkBuffer != null)
- {
- ArrayPool.Shared.Return(chunkBuffer);
- }
+ PatchRequest request = await CreateFirstRequest(args, ctx, address).ConfigureAwait(false);
+
+ request.Sign(ClientContext.Key);
+
+ await call.RequestStream.WriteAsync(request).ConfigureAwait(false);
}
await call.RequestStream.CompleteAsync().ConfigureAwait(false);
@@ -383,9 +385,36 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
Verifier.CheckResponse(response);
return response.Body.ObjectId.ToModel();
+
+ async Task CreateFirstRequest(PrmObjectPatch args, CallContext ctx, Address address)
+ {
+ var body = new PatchRequest.Types.Body() { Address = address };
+
+ if (args.NewAttributes != null)
+ {
+ body.ReplaceAttributes = args.ReplaceAttributes;
+
+ foreach (var attr in args.NewAttributes!)
+ {
+ body.NewAttributes.Add(attr.ToMessage());
+ }
+ }
+
+ var request = new PatchRequest() { Body = body };
+
+ var sessionToken = args.SessionToken ?? await GetDefaultSession(args, ctx).ConfigureAwait(false);
+
+ var protoToken = sessionToken.CreateObjectTokenContext(
+ address,
+ ObjectSessionContext.Types.Verb.Patch,
+ ClientContext.Key);
+
+ request.AddMetaHeader(args.XHeaders, protoToken);
+ return request;
+ }
}
- internal async Task PutClientCutObjectAsync(PrmObjectClientCutPut args, CallContext ctx)
+ internal async Task PutClientCutObjectAsync(PrmObjectClientCutPut args, CallContext ctx)
{
if (args.Payload == null)
throw new ArgumentException(nameof(args.Payload));
@@ -431,9 +460,9 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
var objectsCount = fullLength > 0 ? (int)(fullLength / (ulong)partSize) + restPart : 0;
progressInfo ??= new UploadProgressInfo(Guid.NewGuid(), objectsCount);
-
+
var remain = fullLength;
-
+
byte[]? buffer = null;
bool isRentBuffer = false;
@@ -443,7 +472,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
{
if (args.CustomBuffer.Length < chunkSize)
throw new ArgumentException($"Buffer size is too small. At least {chunkSize} required");
-
+
buffer = args.CustomBuffer;
}
else
@@ -457,7 +486,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
while (remain > 0)
{
- var bytesToWrite = Math.Min((ulong)partSize, remain);
+ var bytesToWrite = Math.Min((ulong)partSize, remain);
var isLastPart = remain <= (ulong)partSize;
// When the last part of the object is uploaded, all metadata for the object must be added
@@ -502,7 +531,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
var part = new ObjectPartInfo(offset, uploaded, objectId);
offset += uploaded;
progressInfo.AddPart(part);
-
+
remain -= bytesToWrite;
if (isLastPart)
@@ -582,16 +611,16 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
var restPart = (fullLength % (ulong)partSize) > 0 ? 1 : 0;
var objectsCount = fullLength > 0 ? (int)(fullLength / (ulong)partSize) + restPart : 0;
+ progressInfo ??= new UploadProgressInfo(Guid.NewGuid(), objectsCount);
+
// if the object fits one part, it can be loaded as non-complex object, but if it is not upload resuming
- if (objectsCount == 1 && progressInfo != null && progressInfo.GetLast().Length == 0)
+ if (objectsCount == 1 && progressInfo.GetLast().Length == 0)
{
args.PutObjectContext.MaxObjectSizeCache = partSize;
args.PutObjectContext.FullLength = fullLength;
var singlePartResult = await PutMultipartStreamObjectAsync(args, default).ConfigureAwait(false);
return singlePartResult.ObjectId;
}
-
- progressInfo ??= new UploadProgressInfo(Guid.NewGuid(), objectsCount);
var remain = fullLength;
@@ -659,8 +688,10 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
offset += size;
if (i < objectsCount)
+ {
continue;
-
+ }
+
// Once all parts of the object are uploaded, they must be linked into a single entity
var linkObject = new FrostFsLinkObject(args.Header.ContainerId, progressInfo.SplitId, parentHeader!, [.. progressInfo.GetParts().Select(p => p.ObjectId)]);
diff --git a/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs b/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs
index cff5cc1..64bc8e9 100644
--- a/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs
+++ b/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs
@@ -1,7 +1,7 @@
using System.Reflection;
[assembly: AssemblyCompany("TrueCloudLab")]
-[assembly: AssemblyFileVersion("1.0.6.0")]
+[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyProduct("FrostFS.SDK.Cryptography")]
[assembly: AssemblyTitle("FrostFS.SDK.Cryptography")]
-[assembly: AssemblyVersion("1.0.6.0")]
+[assembly: AssemblyVersion("1.0.7.0")]
diff --git a/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj b/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj
index 20e0a83..faeabb1 100644
--- a/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj
+++ b/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj
@@ -5,7 +5,7 @@
12.0
enable
FrostFS.SDK.Cryptography
- 1.0.6
+ 1.0.7
Cryptography tools for C# SDK
diff --git a/src/FrostFS.SDK.Protos/AssemblyInfo.cs b/src/FrostFS.SDK.Protos/AssemblyInfo.cs
index f16be42..d7fab05 100644
--- a/src/FrostFS.SDK.Protos/AssemblyInfo.cs
+++ b/src/FrostFS.SDK.Protos/AssemblyInfo.cs
@@ -1,7 +1,7 @@
using System.Reflection;
[assembly: AssemblyCompany("TrueCloudLab")]
-[assembly: AssemblyFileVersion("1.0.6.0")]
+[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyProduct("FrostFS.SDK.Protos")]
[assembly: AssemblyTitle("FrostFS.SDK.Protos")]
-[assembly: AssemblyVersion("1.0.6.0")]
+[assembly: AssemblyVersion("1.0.7.0")]
diff --git a/src/FrostFS.SDK.Protos/FrostFS.SDK.Protos.csproj b/src/FrostFS.SDK.Protos/FrostFS.SDK.Protos.csproj
index b6bc876..222acd1 100644
--- a/src/FrostFS.SDK.Protos/FrostFS.SDK.Protos.csproj
+++ b/src/FrostFS.SDK.Protos/FrostFS.SDK.Protos.csproj
@@ -5,7 +5,7 @@
12.0
enable
FrostFS.SDK.Protos
- 1.0.6
+ 1.0.7
Protobuf client for C# SDK
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs
index 04a8b2c..f1032db 100644
--- a/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/ContainerTests/ContainerTests.cs
@@ -77,7 +77,7 @@ public class ContainerTests : SmokeTestsBase
Assert.Empty(container.PlacementPolicy.Value.Filters);
Assert.Single(container.PlacementPolicy.Value.Replicas);
- Assert.Equal(3, container.PlacementPolicy.Value.Replicas[0].Count);
+ Assert.Equal(3u, 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);
@@ -191,7 +191,7 @@ public class ContainerTests : SmokeTestsBase
Assert.Empty(subFilter.Filters);
Assert.Single(container.PlacementPolicy.Value.Replicas);
- Assert.Equal(1, container.PlacementPolicy.Value.Replicas[0].Count);
+ Assert.Equal(1u, 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);
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs b/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs
index 664d522..9d2fd63 100644
--- a/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/MiscTests/InterceptorTest.cs
@@ -29,8 +29,8 @@ public class InterceptorTests() : SmokeTestsBase
Assert.True(callbackInvoked);
Assert.True(interceptorInvoked);
- Assert.Equal(2, result.Version.Major);
- Assert.Equal(13, result.Version.Minor);
+ Assert.Equal(2u, result.Version.Major);
+ Assert.Equal(13u, result.Version.Minor);
Assert.Equal(NodeState.Online, result.State);
Assert.Equal(33, result.PublicKey.Length);
Assert.NotNull(result.Addresses);
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs
index a3d25af..229531a 100644
--- a/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/NetworkTests/NetworkTests.cs
@@ -28,8 +28,8 @@ public class SmokeClientTests : SmokeTestsBase
var result = await client.GetNodeInfoAsync(default);
- Assert.Equal(2, result.Version.Major);
- Assert.Equal(13, result.Version.Minor);
+ Assert.Equal(2u, result.Version.Major);
+ Assert.Equal(13u, result.Version.Minor);
Assert.Equal(NodeState.Online, result.State);
Assert.Equal(33, result.PublicKey.Length);
Assert.Single(result.Addresses);
@@ -103,8 +103,8 @@ public class SmokeClientTests : SmokeTestsBase
Assert.True(callbackInvoked);
Assert.True(interceptorInvoked);
- Assert.Equal(2, result.Version.Major);
- Assert.Equal(13, result.Version.Minor);
+ Assert.Equal(2u, result.Version.Major);
+ Assert.Equal(13u, result.Version.Minor);
Assert.Equal(NodeState.Online, result.State);
Assert.Equal(33, result.PublicKey.Length);
Assert.NotNull(result.Addresses);
diff --git a/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs b/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs
index a0f501f..473b076 100644
--- a/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs
+++ b/src/FrostFS.SDK.Tests/Smoke/Client/ObjectTests/ObjectTests.cs
@@ -26,7 +26,7 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
[InlineData(false, 2, 3)]
[InlineData(true, 2, 1)]
[InlineData(false, 2, 1)]
- public async void FullScenario(bool unique, uint backupFactor, int replicas)
+ public async void FullScenario(bool unique, uint backupFactor, uint replicas)
{
var client = FrostFSClient.GetInstance(ClientOptions, GrpcChannel);
_testOutputHelper.WriteLine("client created");
@@ -121,9 +121,16 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
await ValidateFilters(client, containerId, objectId, null, (ulong)bytes.Length);
_testOutputHelper.WriteLine($"\tfilters validated");
- if (type != clientCut)
+ if (type != clientCut && bytes.Length > 1024 + 64 && bytes.Length < 20 * 1024 * 1024)
{
- await ValidatePatch(client, containerId, bytes, objectId);
+ // patch payload only
+ await ValidatePatch(client, containerId, bytes, true, objectId, [], false);
+
+ // patch attributes only
+ await ValidatePatch(client, containerId, bytes, false, objectId, [new("a1", "v1"), new("a2", "v2")], false);
+
+ // patch payload and attributes
+ await ValidatePatch(client, containerId, bytes, true, objectId, [new("a3", "v3"), new("a4", "v4")], true);
_testOutputHelper.WriteLine($"\tpatch validated");
}
@@ -199,51 +206,73 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
_testOutputHelper.WriteLine($"\t\trange {range.Offset};{range.Length} validated");
}
- private static async Task ValidatePatch(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes, FrostFsObjectId objectId)
+ private static async Task ValidatePatch(
+ IFrostFSClient client,
+ FrostFsContainerId containerId,
+ byte[] bytes,
+ bool patchPayload,
+ FrostFsObjectId objectId,
+ FrostFsAttributePair[] attributes,
+ bool replaceAttributes)
{
- if (bytes.Length < 1024 + 64 || bytes.Length > 5900)
- return;
-
- var patch = new byte[1024];
- for (int i = 0; i < patch.Length; i++)
+ byte[]? patch = null;
+ FrostFsRange range = new();
+ if (patchPayload)
{
- patch[i] = 32;
- }
+ patch = new byte[1024];
+ for (int i = 0; i < patch.Length; i++)
+ {
+ patch[i] = 32;
+ }
- var range = new FrostFsRange(64, (ulong)patch.Length);
+ range = new FrostFsRange(64, (ulong)patch.Length);
+ }
var patchParams = new PrmObjectPatch(
new FrostFsAddress(containerId, objectId),
- payload: new MemoryStream(patch),
+ payload: new MemoryStream(patch ?? []),
maxChunkLength: 1024,
- range: range);
+ range: range,
+ replaceAttributes: replaceAttributes,
+ newAttributes: attributes);
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)
+ if (patchPayload)
{
- ms.Write(chunk.Value.Span);
+ 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]);
}
- 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]);
+ if (attributes != null && attributes.Length > 0)
+ {
+ foreach (var newAttr in attributes)
+ {
+ var i = @object!.Header!.Attributes!.Count(p => p.Key == newAttr.Key && p.Value == newAttr.Value);
+ Assert.Equal(1, i);
+ }
+ }
}
-
private async Task ValidateFilters(IFrostFSClient client, FrostFsContainerId containerId, FrostFsObjectId objectId, SplitId? splitId, ulong length)
{
var ecdsaKey = keyString.LoadWif();
@@ -318,7 +347,7 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
Assert.NotNull(objHeader);
Assert.Equal(containerId.GetValue(), objHeader.ContainerId.GetValue());
-
+
Assert.Equal(expected.HeaderInfo!.OwnerId!.Value, objHeader.OwnerId!.Value);
Assert.Equal(expected.HeaderInfo.Version!.Major, objHeader.Version!.Major);
Assert.Equal(expected.HeaderInfo.Version!.Minor, objHeader.Version!.Minor);
@@ -338,7 +367,6 @@ public class ObjectTests(ITestOutputHelper testOutputHelper) : SmokeTestsBase
Assert.Null(objHeader.Split);
}
-
private static async Task CreateObjectServerCut(IFrostFSClient client, FrostFsContainerId containerId, byte[] bytes)
{
var header = new FrostFsObjectHeader(
diff --git a/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs b/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs
index e713b4a..ce1d06c 100644
--- a/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs
+++ b/src/FrostFS.SDK.Tests/Unit/ContainerTest.cs
@@ -14,7 +14,7 @@ public class ContainerTest : ContainerTestsBase
[Theory]
[InlineData(1, "test", 0, 0)]
- public void ReplicaToMessagelTest(int count, string selector, uint ecDataCount, uint ecParityCount)
+ public void ReplicaToMessagelTest(uint count, string selector, uint ecDataCount, uint ecParityCount)
{
FrostFsReplica replica = new()
{
@@ -26,7 +26,7 @@ public class ContainerTest : ContainerTestsBase
Replica message = replica.ToMessage();
- Assert.Equal((uint)count, message.Count);
+ Assert.Equal(count, message.Count);
Assert.Equal(selector, message.Selector);
Assert.Equal(ecDataCount, message.EcDataCount);
Assert.Equal(ecParityCount, message.EcParityCount);
diff --git a/src/FrostFS.SDK.Tests/Unit/PlacementPolicyTests.cs b/src/FrostFS.SDK.Tests/Unit/PlacementPolicyTests.cs
index 9957c63..46f7a3d 100644
--- a/src/FrostFS.SDK.Tests/Unit/PlacementPolicyTests.cs
+++ b/src/FrostFS.SDK.Tests/Unit/PlacementPolicyTests.cs
@@ -69,13 +69,13 @@ public class PlacementPolicyTests : NetworkTestsBase
var rep0 = result.Replicas[0];
Assert.Equal(2u, rep0.EcDataCount);
Assert.Equal(3u, rep0.EcParityCount);
- Assert.Equal(4, rep0.Count);
+ Assert.Equal(4u, rep0.Count);
Assert.Equal("selector1", rep0.Selector);
var rep1 = result.Replicas[1];
Assert.Equal(5u, rep1.EcDataCount);
Assert.Equal(6u, rep1.EcParityCount);
- Assert.Equal(7, rep1.Count);
+ Assert.Equal(7u, rep1.Count);
Assert.Equal("selector2", rep1.Selector);
var f0 = result.Filters[0];
@@ -126,7 +126,7 @@ public class PlacementPolicyTests : NetworkTestsBase
FrostFsReplica model = replica.ToModel();
- Assert.Equal(count, (uint)model.Count);
+ Assert.Equal(count, model.Count);
Assert.Equal(selector, model.Selector);
Assert.Equal(ecDataCount, model.EcDataCount);
Assert.Equal(ecParityCount, model.EcParityCount);
@@ -140,7 +140,7 @@ public class PlacementPolicyTests : NetworkTestsBase
[InlineData(1, " ", 2, 3)]
[InlineData(10, "!", 0, 0)]
[InlineData(1, "123", 0, 0)]
- public void ReplicaToMessagelTest(int count, string selector, uint ecDataCount, uint ecParityCount)
+ public void ReplicaToMessagelTest(uint count, string selector, uint ecDataCount, uint ecParityCount)
{
FrostFsReplica replica = new ()
{
@@ -152,7 +152,7 @@ public class PlacementPolicyTests : NetworkTestsBase
Replica message = replica.ToMessage();
- Assert.Equal((uint)count, message.Count);
+ Assert.Equal(count, message.Count);
Assert.Equal(selector, message.Selector);
Assert.Equal(ecDataCount, message.EcDataCount);
Assert.Equal(ecParityCount, message.EcParityCount);
@@ -235,11 +235,11 @@ public class PlacementPolicyTests : NetworkTestsBase
Assert.Single(message.Filters);
- var subfilter = message.Filters[0];
- Assert.Equal(name, subfilter.Name);
- Assert.Equal(key, subfilter.Key);
- Assert.Equal(operation, (int)subfilter.Op);
- Assert.Equal(value, subfilter.Value);
+ var grpcFilter = message.Filters[0];
+ Assert.Equal(name, grpcFilter.Name);
+ Assert.Equal(key, grpcFilter.Key);
+ Assert.Equal(operation, (int)grpcFilter.Op);
+ Assert.Equal(value, grpcFilter.Value);
}
[Fact]
@@ -265,11 +265,11 @@ public class PlacementPolicyTests : NetworkTestsBase
for (int i = 0; i < 3; i++)
{
- var subfilter = message.Filters[i];
- Assert.Equal(names[i], subfilter.Name);
- Assert.Equal(keys[i], subfilter.Key);
- Assert.Equal(operations[i], (int)subfilter.Op);
- Assert.Equal(values[i], subfilter.Value);
+ var grpcFilter = message.Filters[i];
+ Assert.Equal(names[i], grpcFilter.Name);
+ Assert.Equal(keys[i], grpcFilter.Key);
+ Assert.Equal(operations[i], (int)grpcFilter.Op);
+ Assert.Equal(values[i], grpcFilter.Value);
}
}
diff --git a/src/FrostFS.SDK.Tests/Unit/PlacementVectorTests.cs b/src/FrostFS.SDK.Tests/Unit/PlacementVectorTests.cs
index fdf7ffe..9833ae1 100644
--- a/src/FrostFS.SDK.Tests/Unit/PlacementVectorTests.cs
+++ b/src/FrostFS.SDK.Tests/Unit/PlacementVectorTests.cs
@@ -248,12 +248,12 @@ public class FilterDto
Key ?? string.Empty,
(int)Op,
Value ?? string.Empty,
- Filters != null ? Filters.Select(f => f.Filter).ToArray() : []);
+ Filters != null ? [.. Filters.Select(f => f.Filter)] : []);
}
public class ReplicaDto
{
- public int Count { get; set; }
+ public uint Count { get; set; }
public string? Selector { get; set; }
}