parent
20586d8ada
commit
eebba7665b
13 changed files with 1094 additions and 233 deletions
|
@ -1,5 +1,3 @@
|
|||
using FrostFS.SDK;
|
||||
|
||||
namespace FrostFS.SDK.Client;
|
||||
|
||||
public readonly struct ObjectPartInfo(long offset, int length, FrostFsObjectId objectId) : System.IEquatable<ObjectPartInfo>
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace FrostFS.SDK;
|
|||
public class FrostFsResponseStatus(FrostFsStatusCode code, string? message = null, string? details = null)
|
||||
{
|
||||
public FrostFsStatusCode Code { get; set; } = code;
|
||||
|
||||
public string Message { get; set; } = message ?? string.Empty;
|
||||
|
||||
public string Details { get; set; } = details ?? string.Empty;
|
||||
|
|
|
@ -41,6 +41,8 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
|
|||
|
||||
public Collection<ByteString> RangeHashResponses { get; } = [];
|
||||
|
||||
public Action? Callback;
|
||||
|
||||
public override Mock<ObjectService.ObjectServiceClient> GetMock()
|
||||
{
|
||||
var mock = new Mock<ObjectService.ObjectServiceClient>();
|
||||
|
@ -165,9 +167,14 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
|
|||
It.IsAny<CancellationToken>()))
|
||||
.Returns((PutSingleRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
||||
{
|
||||
Callback?.Invoke();
|
||||
Verifier.CheckRequest(r);
|
||||
|
||||
PutSingleRequests.Add(r);
|
||||
var req = r.Clone();
|
||||
|
||||
// Clone method does not clone the payload but keeps a reference
|
||||
req.Body.Object.Payload = ByteString.CopyFrom(r.Body.Object.Payload.ToByteArray());
|
||||
PutSingleRequests.Add(req);
|
||||
|
||||
return new AsyncUnaryCall<PutSingleResponse>(
|
||||
Task.FromResult(putSingleResponse),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using FrostFS.Netmap;
|
||||
using FrostFS.SDK.Client;
|
||||
using FrostFS.SDK.Client.Mappers.GRPC;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
@ -10,6 +11,27 @@ namespace FrostFS.SDK.Tests.Unit;
|
|||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public class ContainerTest : ContainerTestsBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(1, "test", 0, 0)]
|
||||
|
||||
public void ReplicaToMessagelTest(int count, string selector, uint ecDataCount, uint ecParityCount)
|
||||
{
|
||||
FrostFsReplica replica = new()
|
||||
{
|
||||
Count = count,
|
||||
Selector = selector,
|
||||
EcDataCount = ecDataCount,
|
||||
EcParityCount = ecParityCount
|
||||
};
|
||||
|
||||
Replica message = replica.ToMessage();
|
||||
|
||||
Assert.Equal((uint)count, message.Count);
|
||||
Assert.Equal(selector, message.Selector);
|
||||
Assert.Equal(ecDataCount, message.EcDataCount);
|
||||
Assert.Equal(ecParityCount, message.EcParityCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void CreateContainerTest()
|
||||
{
|
||||
|
|
29
src/FrostFS.SDK.Tests/Unit/MetaheaderTests.cs
Normal file
29
src/FrostFS.SDK.Tests/Unit/MetaheaderTests.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using FrostFS.SDK.Client;
|
||||
using FrostFS.SDK.Client.Mappers.GRPC;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
public class MetaheaderTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(2, 13, 1, 1)]
|
||||
[InlineData(200, 0, 1000000, 8)]
|
||||
public void MetaheaderTest(int major, int minor, int epoch, int ttl)
|
||||
{
|
||||
MetaHeader metaHeader = new MetaHeader(
|
||||
new FrostFsVersion(
|
||||
major: 2,
|
||||
minor: 13
|
||||
),
|
||||
epoch: 0,
|
||||
ttl: 2
|
||||
);
|
||||
|
||||
var result = metaHeader.ToMessage();
|
||||
|
||||
Assert.Equal((ulong)metaHeader.Epoch, result.Epoch);
|
||||
Assert.Equal((ulong)metaHeader.Ttl, result.Ttl);
|
||||
Assert.Equal((ulong)metaHeader.Version.Major, result.Version.Major);
|
||||
Assert.Equal((ulong)metaHeader.Version.Minor, result.Version.Minor);
|
||||
}
|
||||
}
|
101
src/FrostFS.SDK.Tests/Unit/NetmapSnapshotTests.cs
Normal file
101
src/FrostFS.SDK.Tests/Unit/NetmapSnapshotTests.cs
Normal file
|
@ -0,0 +1,101 @@
|
|||
using FrostFS.Netmap;
|
||||
using FrostFS.SDK.Client;
|
||||
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
public class NetmapSnapshotTests : NetworkTestsBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
|
||||
public async void NetmapSnapshotTest(bool useContext)
|
||||
{
|
||||
var body = new NetmapSnapshotResponse.Types.Body
|
||||
{
|
||||
Netmap = new Netmap.Netmap { Epoch = 99 }
|
||||
};
|
||||
|
||||
var nodeInfo1 = new NodeInfo
|
||||
{
|
||||
State = NodeInfo.Types.State.Online,
|
||||
PublicKey = ByteString.CopyFrom([1, 2, 3])
|
||||
};
|
||||
|
||||
nodeInfo1.Addresses.Add("address1");
|
||||
nodeInfo1.Addresses.Add("address2");
|
||||
nodeInfo1.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key1", Value = "value1" });
|
||||
nodeInfo1.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key2", Value = "value2" });
|
||||
|
||||
var nodeInfo2 = new NodeInfo
|
||||
{
|
||||
State = NodeInfo.Types.State.Offline,
|
||||
PublicKey = ByteString.CopyFrom([3, 4, 5])
|
||||
};
|
||||
|
||||
nodeInfo2.Addresses.Add("address3");
|
||||
nodeInfo2.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key3", Value = "value3" });
|
||||
|
||||
body.Netmap.Nodes.Add(nodeInfo1);
|
||||
body.Netmap.Nodes.Add(nodeInfo2);
|
||||
|
||||
Mocker.NetmapSnapshotResponse = new NetmapSnapshotResponse { Body = body };
|
||||
|
||||
var ctx = useContext
|
||||
? new CallContext(TimeSpan.FromSeconds(20), Mocker.CancellationTokenSource.Token)
|
||||
: default;
|
||||
|
||||
var validTimeoutFrom = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
var result = await GetClient(DefaultSettings).GetNetmapSnapshotAsync(ctx);
|
||||
|
||||
var validTimeoutTo = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(99u, result.Epoch);
|
||||
Assert.Equal(2, result.NodeInfoCollection.Count);
|
||||
|
||||
var node1 = result.NodeInfoCollection[0];
|
||||
Assert.Equal(NodeState.Online, node1.State);
|
||||
Assert.Equal(2, node1.Addresses.Count);
|
||||
Assert.Equal("address1", node1.Addresses.ElementAt(0));
|
||||
Assert.Equal("address2", node1.Addresses.ElementAt(1));
|
||||
|
||||
Assert.Equal(2, node1.Attributes.Count);
|
||||
|
||||
Assert.Equal("key1", node1.Attributes.ElementAt(0).Key);
|
||||
Assert.Equal("value1", node1.Attributes.ElementAt(0).Value);
|
||||
Assert.Equal("key2", node1.Attributes.ElementAt(1).Key);
|
||||
Assert.Equal("value2", node1.Attributes.ElementAt(1).Value);
|
||||
|
||||
var node2 = result.NodeInfoCollection[1];
|
||||
Assert.Equal(NodeState.Offline, node2.State);
|
||||
Assert.Single(node2.Addresses);
|
||||
Assert.Equal("address3", node2.Addresses.ElementAt(0));
|
||||
|
||||
Assert.Single(node2.Attributes);
|
||||
|
||||
Assert.Equal("key3", node2.Attributes.ElementAt(0).Key);
|
||||
Assert.Equal("value3", node2.Attributes.ElementAt(0).Value);
|
||||
|
||||
if (useContext)
|
||||
{
|
||||
Assert.NotNull(Mocker.NetmapSnapshotRequest);
|
||||
Assert.Empty(Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders);
|
||||
|
||||
Assert.Equal(Mocker.CancellationTokenSource.Token, Mocker.CancellationToken);
|
||||
Assert.NotNull(Mocker.DateTime);
|
||||
Assert.True(Mocker.DateTime.Value >= validTimeoutFrom);
|
||||
Assert.True(Mocker.DateTime.Value <= validTimeoutTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(Mocker.NetmapSnapshotRequest);
|
||||
Assert.Empty(Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
}
|
||||
}
|
68
src/FrostFS.SDK.Tests/Unit/NetworkSettingsTests.cs
Normal file
68
src/FrostFS.SDK.Tests/Unit/NetworkSettingsTests.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using FrostFS.SDK.Client;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public class NetworkSettingsTests : NetworkTestsBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async void NetworkSettingsTest(bool useContext)
|
||||
{
|
||||
Mocker.Parameters.Add("AuditFee", [1]);
|
||||
Mocker.Parameters.Add("BasicIncomeRate", [2]);
|
||||
Mocker.Parameters.Add("ContainerFee", [3]);
|
||||
Mocker.Parameters.Add("ContainerAliasFee", [4]);
|
||||
Mocker.Parameters.Add("EpochDuration", [5]);
|
||||
Mocker.Parameters.Add("InnerRingCandidateFee", [6]);
|
||||
Mocker.Parameters.Add("MaxECDataCount", [7]);
|
||||
Mocker.Parameters.Add("MaxECParityCount", [8]);
|
||||
Mocker.Parameters.Add("MaxObjectSize", [9]);
|
||||
Mocker.Parameters.Add("WithdrawFee", [10]);
|
||||
Mocker.Parameters.Add("HomomorphicHashingDisabled", [1]);
|
||||
Mocker.Parameters.Add("MaintenanceModeAllowed", [1]);
|
||||
|
||||
var ctx = useContext
|
||||
? new CallContext(TimeSpan.FromSeconds(20), Mocker.CancellationTokenSource.Token)
|
||||
: default;
|
||||
|
||||
var validTimeoutFrom = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
var result = await GetClient(DefaultSettings).GetNetworkSettingsAsync(ctx);
|
||||
|
||||
var validTimeoutTo = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(Mocker.Parameters["AuditFee"], [(byte)result.AuditFee]);
|
||||
Assert.Equal(Mocker.Parameters["BasicIncomeRate"], [(byte)result.BasicIncomeRate]);
|
||||
Assert.Equal(Mocker.Parameters["ContainerFee"], [(byte)result.ContainerFee]);
|
||||
Assert.Equal(Mocker.Parameters["ContainerAliasFee"], [(byte)result.ContainerAliasFee]);
|
||||
Assert.Equal(Mocker.Parameters["EpochDuration"], [(byte)result.EpochDuration]);
|
||||
Assert.Equal(Mocker.Parameters["InnerRingCandidateFee"], [(byte)result.InnerRingCandidateFee]);
|
||||
Assert.Equal(Mocker.Parameters["MaxECDataCount"], [(byte)result.MaxECDataCount]);
|
||||
Assert.Equal(Mocker.Parameters["MaxECParityCount"], [(byte)result.MaxECParityCount]);
|
||||
Assert.Equal(Mocker.Parameters["MaxObjectSize"], [(byte)result.MaxObjectSize]);
|
||||
Assert.Equal(Mocker.Parameters["WithdrawFee"], [(byte)result.WithdrawFee]);
|
||||
|
||||
Assert.True(result.HomomorphicHashingDisabled);
|
||||
Assert.True(result.MaintenanceModeAllowed);
|
||||
|
||||
if (useContext)
|
||||
{
|
||||
Assert.Equal(Mocker.CancellationTokenSource.Token, Mocker.CancellationToken);
|
||||
Assert.NotNull(Mocker.DateTime);
|
||||
|
||||
Assert.True(Mocker.DateTime.Value >= validTimeoutFrom);
|
||||
Assert.True(Mocker.DateTime.Value <= validTimeoutTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(Mocker.NetworkInfoRequest);
|
||||
Assert.Empty(Mocker.NetworkInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using FrostFS.Netmap;
|
||||
using FrostFS.SDK.Client;
|
||||
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public class NetworkTest : NetworkTestsBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async void NetworkSettingsTest(bool useContext)
|
||||
{
|
||||
Mocker.Parameters.Add("AuditFee", [1]);
|
||||
Mocker.Parameters.Add("BasicIncomeRate", [2]);
|
||||
Mocker.Parameters.Add("ContainerFee", [3]);
|
||||
Mocker.Parameters.Add("ContainerAliasFee", [4]);
|
||||
Mocker.Parameters.Add("EpochDuration", [5]);
|
||||
Mocker.Parameters.Add("InnerRingCandidateFee", [6]);
|
||||
Mocker.Parameters.Add("MaxECDataCount", [7]);
|
||||
Mocker.Parameters.Add("MaxECParityCount", [8]);
|
||||
Mocker.Parameters.Add("MaxObjectSize", [9]);
|
||||
Mocker.Parameters.Add("WithdrawFee", [10]);
|
||||
Mocker.Parameters.Add("HomomorphicHashingDisabled", [1]);
|
||||
Mocker.Parameters.Add("MaintenanceModeAllowed", [1]);
|
||||
|
||||
var ctx = useContext
|
||||
? new CallContext(TimeSpan.FromSeconds(20), Mocker.CancellationTokenSource.Token)
|
||||
: default;
|
||||
|
||||
var validTimeoutFrom = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
var result = await GetClient(DefaultSettings).GetNetworkSettingsAsync(ctx);
|
||||
|
||||
var validTimeoutTo = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(Mocker.Parameters["AuditFee"], [(byte)result.AuditFee]);
|
||||
Assert.Equal(Mocker.Parameters["BasicIncomeRate"], [(byte)result.BasicIncomeRate]);
|
||||
Assert.Equal(Mocker.Parameters["ContainerFee"], [(byte)result.ContainerFee]);
|
||||
Assert.Equal(Mocker.Parameters["ContainerAliasFee"], [(byte)result.ContainerAliasFee]);
|
||||
Assert.Equal(Mocker.Parameters["EpochDuration"], [(byte)result.EpochDuration]);
|
||||
Assert.Equal(Mocker.Parameters["InnerRingCandidateFee"], [(byte)result.InnerRingCandidateFee]);
|
||||
Assert.Equal(Mocker.Parameters["MaxECDataCount"], [(byte)result.MaxECDataCount]);
|
||||
Assert.Equal(Mocker.Parameters["MaxECParityCount"], [(byte)result.MaxECParityCount]);
|
||||
Assert.Equal(Mocker.Parameters["MaxObjectSize"], [(byte)result.MaxObjectSize]);
|
||||
Assert.Equal(Mocker.Parameters["WithdrawFee"], [(byte)result.WithdrawFee]);
|
||||
|
||||
Assert.True(result.HomomorphicHashingDisabled);
|
||||
Assert.True(result.MaintenanceModeAllowed);
|
||||
|
||||
if (useContext)
|
||||
{
|
||||
Assert.Equal(Mocker.CancellationTokenSource.Token, Mocker.CancellationToken);
|
||||
Assert.NotNull(Mocker.DateTime);
|
||||
|
||||
Assert.True(Mocker.DateTime.Value >= validTimeoutFrom);
|
||||
Assert.True(Mocker.DateTime.Value <= validTimeoutTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(Mocker.NetworkInfoRequest);
|
||||
Assert.Empty(Mocker.NetworkInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
|
||||
public async void NetmapSnapshotTest(bool useContext)
|
||||
{
|
||||
var body = new NetmapSnapshotResponse.Types.Body
|
||||
{
|
||||
Netmap = new Netmap.Netmap { Epoch = 99 }
|
||||
};
|
||||
|
||||
var nodeInfo1 = new NodeInfo
|
||||
{
|
||||
State = NodeInfo.Types.State.Online,
|
||||
PublicKey = ByteString.CopyFrom([1, 2, 3])
|
||||
};
|
||||
|
||||
nodeInfo1.Addresses.Add("address1");
|
||||
nodeInfo1.Addresses.Add("address2");
|
||||
nodeInfo1.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key1", Value = "value1" });
|
||||
nodeInfo1.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key2", Value = "value2" });
|
||||
|
||||
var nodeInfo2 = new NodeInfo
|
||||
{
|
||||
State = NodeInfo.Types.State.Offline,
|
||||
PublicKey = ByteString.CopyFrom([3, 4, 5])
|
||||
};
|
||||
|
||||
nodeInfo2.Addresses.Add("address3");
|
||||
nodeInfo2.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key3", Value = "value3" });
|
||||
|
||||
body.Netmap.Nodes.Add(nodeInfo1);
|
||||
body.Netmap.Nodes.Add(nodeInfo2);
|
||||
|
||||
Mocker.NetmapSnapshotResponse = new NetmapSnapshotResponse { Body = body };
|
||||
|
||||
var ctx = useContext
|
||||
? new CallContext(TimeSpan.FromSeconds(20), Mocker.CancellationTokenSource.Token)
|
||||
: default;
|
||||
|
||||
var validTimeoutFrom = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
var result = await GetClient(DefaultSettings).GetNetmapSnapshotAsync(ctx);
|
||||
|
||||
var validTimeoutTo = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(99u, result.Epoch);
|
||||
Assert.Equal(2, result.NodeInfoCollection.Count);
|
||||
|
||||
var node1 = result.NodeInfoCollection[0];
|
||||
Assert.Equal(NodeState.Online, node1.State);
|
||||
Assert.Equal(2, node1.Addresses.Count);
|
||||
Assert.Equal("address1", node1.Addresses.ElementAt(0));
|
||||
Assert.Equal("address2", node1.Addresses.ElementAt(1));
|
||||
|
||||
Assert.Equal(2, node1.Attributes.Count);
|
||||
|
||||
Assert.Equal("key1", node1.Attributes.ElementAt(0).Key);
|
||||
Assert.Equal("value1", node1.Attributes.ElementAt(0).Value);
|
||||
Assert.Equal("key2", node1.Attributes.ElementAt(1).Key);
|
||||
Assert.Equal("value2", node1.Attributes.ElementAt(1).Value);
|
||||
|
||||
var node2 = result.NodeInfoCollection[1];
|
||||
Assert.Equal(NodeState.Offline, node2.State);
|
||||
Assert.Single(node2.Addresses);
|
||||
Assert.Equal("address3", node2.Addresses.ElementAt(0));
|
||||
|
||||
Assert.Single(node2.Attributes);
|
||||
|
||||
Assert.Equal("key3", node2.Attributes.ElementAt(0).Key);
|
||||
Assert.Equal("value3", node2.Attributes.ElementAt(0).Value);
|
||||
|
||||
if (useContext)
|
||||
{
|
||||
Assert.NotNull(Mocker.NetmapSnapshotRequest);
|
||||
Assert.Empty(Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders);
|
||||
|
||||
Assert.Equal(Mocker.CancellationTokenSource.Token, Mocker.CancellationToken);
|
||||
Assert.NotNull(Mocker.DateTime);
|
||||
Assert.True(Mocker.DateTime.Value >= validTimeoutFrom);
|
||||
Assert.True(Mocker.DateTime.Value <= validTimeoutTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(Mocker.NetmapSnapshotRequest);
|
||||
Assert.Empty(Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async void NodeInfoTest(bool useContext)
|
||||
{
|
||||
var body = new LocalNodeInfoResponse.Types.Body
|
||||
{
|
||||
NodeInfo = new NodeInfo()
|
||||
{
|
||||
State = NodeInfo.Types.State.Online,
|
||||
PublicKey = ByteString.CopyFrom([1, 2, 3])
|
||||
},
|
||||
Version = new Refs.Version { Major = 2, Minor = 12 }
|
||||
};
|
||||
|
||||
body.NodeInfo.Addresses.Add("address1");
|
||||
body.NodeInfo.Addresses.Add("address2");
|
||||
body.NodeInfo.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key1", Value = "value1" });
|
||||
body.NodeInfo.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key2", Value = "value2" });
|
||||
|
||||
Mocker.NodeInfoResponse = new LocalNodeInfoResponse { Body = body };
|
||||
|
||||
var ctx = useContext
|
||||
? new CallContext(TimeSpan.FromSeconds(20), Mocker.CancellationTokenSource.Token)
|
||||
: default;
|
||||
|
||||
var validTimeoutFrom = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
var result = await GetClient(DefaultSettings).GetNodeInfoAsync(ctx);
|
||||
|
||||
var validTimeoutTo = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(NodeState.Online, result.State);
|
||||
|
||||
Assert.Equal(2, result.Addresses.Count);
|
||||
Assert.Equal("address1", result.Addresses.ElementAt(0));
|
||||
Assert.Equal("address2", result.Addresses.ElementAt(1));
|
||||
|
||||
Assert.Equal(2, result.Attributes.Count);
|
||||
Assert.Equal("value1", result.Attributes["key1"]);
|
||||
Assert.Equal("value2", result.Attributes["key2"]);
|
||||
|
||||
Assert.NotNull(Mocker.LocalNodeInfoRequest);
|
||||
if (useContext)
|
||||
{
|
||||
Assert.Empty(Mocker.LocalNodeInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Equal(Mocker.CancellationTokenSource.Token, Mocker.CancellationToken);
|
||||
Assert.NotNull(Mocker.DateTime);
|
||||
|
||||
Assert.True(Mocker.DateTime.Value >= validTimeoutFrom);
|
||||
Assert.True(Mocker.DateTime.Value <= validTimeoutTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Empty(Mocker.LocalNodeInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
}
|
||||
}
|
69
src/FrostFS.SDK.Tests/Unit/NodeInfoTests.cs
Normal file
69
src/FrostFS.SDK.Tests/Unit/NodeInfoTests.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using FrostFS.Netmap;
|
||||
using FrostFS.SDK.Client;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
public class NodeInfoTests : NetworkTestsBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async void NodeInfoTest(bool useContext)
|
||||
{
|
||||
var body = new LocalNodeInfoResponse.Types.Body
|
||||
{
|
||||
NodeInfo = new NodeInfo()
|
||||
{
|
||||
State = NodeInfo.Types.State.Online,
|
||||
PublicKey = ByteString.CopyFrom([1, 2, 3])
|
||||
},
|
||||
Version = new Refs.Version { Major = 2, Minor = 12 }
|
||||
};
|
||||
|
||||
body.NodeInfo.Addresses.Add("address1");
|
||||
body.NodeInfo.Addresses.Add("address2");
|
||||
body.NodeInfo.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key1", Value = "value1" });
|
||||
body.NodeInfo.Attributes.Add(new NodeInfo.Types.Attribute { Key = "key2", Value = "value2" });
|
||||
|
||||
Mocker.NodeInfoResponse = new LocalNodeInfoResponse { Body = body };
|
||||
|
||||
var ctx = useContext
|
||||
? new CallContext(TimeSpan.FromSeconds(20), Mocker.CancellationTokenSource.Token)
|
||||
: default;
|
||||
|
||||
var validTimeoutFrom = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
var result = await GetClient(DefaultSettings).GetNodeInfoAsync(ctx);
|
||||
|
||||
var validTimeoutTo = DateTime.UtcNow.AddSeconds(20);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(NodeState.Online, result.State);
|
||||
|
||||
Assert.Equal(2, result.Addresses.Count);
|
||||
Assert.Equal("address1", result.Addresses.ElementAt(0));
|
||||
Assert.Equal("address2", result.Addresses.ElementAt(1));
|
||||
|
||||
Assert.Equal(2, result.Attributes.Count);
|
||||
Assert.Equal("value1", result.Attributes["key1"]);
|
||||
Assert.Equal("value2", result.Attributes["key2"]);
|
||||
|
||||
Assert.NotNull(Mocker.LocalNodeInfoRequest);
|
||||
if (useContext)
|
||||
{
|
||||
Assert.Empty(Mocker.LocalNodeInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Equal(Mocker.CancellationTokenSource.Token, Mocker.CancellationToken);
|
||||
Assert.NotNull(Mocker.DateTime);
|
||||
|
||||
Assert.True(Mocker.DateTime.Value >= validTimeoutFrom);
|
||||
Assert.True(Mocker.DateTime.Value <= validTimeoutTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Empty(Mocker.LocalNodeInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,8 +6,9 @@ using System.Text;
|
|||
using FrostFS.Refs;
|
||||
using FrostFS.SDK.Client;
|
||||
using FrostFS.SDK.Client.Mappers.GRPC;
|
||||
|
||||
using FrostFS.SDK.Cryptography;
|
||||
using Google.Protobuf;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
|
@ -60,7 +61,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
var param = new PrmObjectClientCutPut(
|
||||
Mocker.ObjectHeader,
|
||||
payload: new MemoryStream(bytes),
|
||||
bufferMaxSize: 1024);
|
||||
bufferMaxSize: blockSize);
|
||||
|
||||
Random rnd = new();
|
||||
|
||||
|
@ -87,7 +88,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
// PART1
|
||||
Assert.Equal(blockSize, objects[0].Payload.Length);
|
||||
Assert.True(bytes.AsMemory(0, blockSize).ToArray().SequenceEqual(objects[0].Payload));
|
||||
Assert.Equal(bytes.AsMemory(0, blockSize).ToArray(), objects[0].Payload);
|
||||
|
||||
Assert.NotNull(objects[0].Header.Split.SplitId);
|
||||
Assert.Null(objects[0].Header.Split.Previous);
|
||||
|
@ -96,7 +97,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
// PART2
|
||||
Assert.Equal(blockSize, objects[1].Payload.Length);
|
||||
Assert.True(bytes.AsMemory(blockSize, blockSize).ToArray().SequenceEqual(objects[1].Payload));
|
||||
Assert.Equal(bytes.AsMemory(blockSize, blockSize).ToArray(), objects[1].Payload);
|
||||
|
||||
Assert.Equal(objects[0].Header.Split.SplitId, objects[1].Header.Split.SplitId);
|
||||
Assert.True(objects[1].Header.Attributes.Count == 0);
|
||||
|
@ -104,7 +105,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
// last part
|
||||
Assert.Equal(bytes.Length % blockSize, objects[2].Payload.Length);
|
||||
Assert.True(bytes.AsMemory(2 * blockSize).ToArray().SequenceEqual(objects[2].Payload));
|
||||
Assert.Equal(bytes.AsMemory(2 * blockSize).ToArray(), objects[2].Payload);
|
||||
|
||||
Assert.NotNull(objects[3].Header.Split.Parent);
|
||||
Assert.NotNull(objects[3].Header.Split.ParentHeader);
|
||||
|
@ -128,6 +129,351 @@ public class ObjectTest : ObjectTestsBase
|
|||
Assert.Equal(result.Value, modelObjId.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ClientCutWithInterruptionOnFirstPartTest()
|
||||
{
|
||||
NetworkMocker.Parameters.Add("MaxObjectSize", [0x0, 0xa]);
|
||||
|
||||
var blockSize = 2560;
|
||||
byte[] bytes = File.ReadAllBytes(@".\..\..\..\cat.jpg");
|
||||
var fileLength = bytes.Length;
|
||||
|
||||
var splitId = Guid.NewGuid();
|
||||
var progress = new UploadProgressInfo(splitId);
|
||||
|
||||
var param = new PrmObjectClientCutPut(
|
||||
Mocker.ObjectHeader,
|
||||
payload: new MemoryStream(bytes),
|
||||
bufferMaxSize: blockSize,
|
||||
progress: progress);
|
||||
|
||||
Random rnd = new();
|
||||
|
||||
Collection<byte[]> objIds = new([new byte[32], new byte[32], new byte[32]]);
|
||||
rnd.NextBytes(objIds.ElementAt(0));
|
||||
rnd.NextBytes(objIds.ElementAt(1));
|
||||
rnd.NextBytes(objIds.ElementAt(2));
|
||||
|
||||
foreach (var objId in objIds)
|
||||
Mocker.ResultObjectIds!.Add(objId);
|
||||
|
||||
int sentBlockCount = 0;
|
||||
Mocker.Callback = () =>
|
||||
{
|
||||
if (++sentBlockCount == 1)
|
||||
throw new FrostFsException("some error");
|
||||
};
|
||||
|
||||
bool gotException = false;
|
||||
try
|
||||
{
|
||||
var result = await GetClient().PutClientCutObjectAsync(param, default);
|
||||
}
|
||||
catch (FrostFsException ex)
|
||||
{
|
||||
if (ex.Message == "some error")
|
||||
gotException = true;
|
||||
}
|
||||
|
||||
Assert.True(gotException);
|
||||
|
||||
var singleObjects = Mocker.PutSingleRequests.ToArray();
|
||||
|
||||
Assert.Empty(singleObjects);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ClientCutWithInterruptionOnMiddlePartTest()
|
||||
{
|
||||
NetworkMocker.Parameters.Add("MaxObjectSize", [0x0, 0xa]);
|
||||
|
||||
var blockSize = 2560;
|
||||
byte[] bytes = File.ReadAllBytes(@".\..\..\..\cat.jpg");
|
||||
var fileLength = bytes.Length;
|
||||
|
||||
var splitId = Guid.Parse("67e4bbe9-86ca-474d-9385-6569ce89db61");
|
||||
var progress = new UploadProgressInfo(splitId);
|
||||
|
||||
var param = new PrmObjectClientCutPut(
|
||||
Mocker.ObjectHeader,
|
||||
payload: new MemoryStream(bytes),
|
||||
bufferMaxSize: blockSize,
|
||||
progress: progress);
|
||||
|
||||
Random rnd = new();
|
||||
|
||||
Collection<byte[]> objIds = new([new byte[32], new byte[32], new byte[32]]);
|
||||
rnd.NextBytes(objIds.ElementAt(0));
|
||||
rnd.NextBytes(objIds.ElementAt(1));
|
||||
rnd.NextBytes(objIds.ElementAt(2));
|
||||
|
||||
foreach (var objId in objIds)
|
||||
Mocker.ResultObjectIds!.Add(objId);
|
||||
|
||||
int sentBlockCount = 0;
|
||||
Mocker.Callback = () =>
|
||||
{
|
||||
if (++sentBlockCount == 2)
|
||||
throw new FrostFsException("some error");
|
||||
};
|
||||
|
||||
bool gotException = false;
|
||||
try
|
||||
{
|
||||
_ = await GetClient().PutClientCutObjectAsync(param, default);
|
||||
}
|
||||
catch (FrostFsException ex)
|
||||
{
|
||||
if (ex.Message == "some error")
|
||||
gotException = true;
|
||||
}
|
||||
|
||||
Assert.True(gotException);
|
||||
|
||||
var singleObjects = Mocker.PutSingleRequests.ToArray();
|
||||
|
||||
Assert.NotNull(Mocker.ClientStreamWriter?.Messages);
|
||||
|
||||
var objects = Mocker.PutSingleRequests.Select(o => o.Body.Object).ToArray();
|
||||
|
||||
Assert.Single(objects);
|
||||
|
||||
Assert.Single(progress.GetParts());
|
||||
|
||||
var part = progress.GetPart(0);
|
||||
Assert.Equal(0, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
// PART1
|
||||
Assert.Equal(blockSize, objects[0].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(0, blockSize).ToArray(), objects[0].Payload);
|
||||
|
||||
Assert.NotNull(objects[0].Header.Split.SplitId);
|
||||
Assert.Null(objects[0].Header.Split.Previous);
|
||||
Assert.True(objects[0].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[0].Header.Split.Parent);
|
||||
|
||||
// resume uploading
|
||||
sentBlockCount = 10;
|
||||
|
||||
var result = await GetClient().PutClientCutObjectAsync(param, default);
|
||||
|
||||
singleObjects = Mocker.PutSingleRequests.ToArray();
|
||||
|
||||
Assert.NotNull(Mocker.ClientStreamWriter?.Messages);
|
||||
|
||||
objects = Mocker.PutSingleRequests.Select(o => o.Body.Object).ToArray();
|
||||
|
||||
Assert.Equal(4, objects.Length);
|
||||
|
||||
// PART1
|
||||
Assert.Equal(blockSize, objects[0].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(0, blockSize).ToArray(), objects[0].Payload);
|
||||
|
||||
Assert.NotNull(objects[0].Header.Split.SplitId);
|
||||
Assert.Null(objects[0].Header.Split.Previous);
|
||||
Assert.True(objects[0].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[0].Header.Split.Parent);
|
||||
|
||||
// PART2
|
||||
Assert.Equal(blockSize, objects[1].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(blockSize, blockSize).ToArray(), objects[1].Payload);
|
||||
|
||||
Assert.Equal(objects[0].Header.Split.SplitId, objects[1].Header.Split.SplitId);
|
||||
Assert.True(objects[1].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[1].Header.Split.Parent);
|
||||
|
||||
// last part
|
||||
Assert.Equal(bytes.Length % blockSize, objects[2].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(2 * blockSize).ToArray(), objects[2].Payload);
|
||||
|
||||
Assert.NotNull(objects[3].Header.Split.Parent);
|
||||
Assert.NotNull(objects[3].Header.Split.ParentHeader);
|
||||
Assert.NotNull(objects[3].Header.Split.ParentSignature);
|
||||
Assert.Equal(objects[2].Header.Split.SplitId, objects[3].Header.Split.SplitId);
|
||||
Assert.True(objects[2].Header.Attributes.Count == 0);
|
||||
|
||||
// link object
|
||||
Assert.Equal(objects[2].Header.Split.Parent, objects[3].Header.Split.Parent);
|
||||
Assert.Equal(objects[2].Header.Split.ParentHeader, objects[3].Header.Split.ParentHeader);
|
||||
Assert.Equal(objects[2].Header.Split.SplitId, objects[3].Header.Split.SplitId);
|
||||
Assert.Equal(0, (int)objects[3].Header.PayloadLength);
|
||||
Assert.True(objects[3].Header.Attributes.Count == 0);
|
||||
|
||||
Assert.Single(objects[3].Header.Split.ParentHeader.Attributes);
|
||||
Assert.Equal("k", objects[3].Header.Split.ParentHeader.Attributes[0].Key);
|
||||
Assert.Equal("v", objects[3].Header.Split.ParentHeader.Attributes[0].Value);
|
||||
|
||||
var modelObjId = FrostFsObjectId.FromHash(objects[3].Header.Split.Parent.Value.ToByteArray());
|
||||
|
||||
Assert.Equal(result.Value, modelObjId.ToString());
|
||||
|
||||
Assert.Equal(3, progress.GetParts().Count);
|
||||
part = progress.GetPart(0);
|
||||
Assert.Equal(0, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
part = progress.GetPart(1);
|
||||
Assert.Equal(2560, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
part = progress.GetPart(2);
|
||||
Assert.Equal(2 * 2560, part.Offset);
|
||||
Assert.Equal(1620, part.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ClientCutWithInterruptionOnLastPartTest()
|
||||
{
|
||||
NetworkMocker.Parameters.Add("MaxObjectSize", [0x0, 0xa]);
|
||||
|
||||
var blockSize = 2560;
|
||||
byte[] bytes = File.ReadAllBytes(@".\..\..\..\cat.jpg");
|
||||
var fileLength = bytes.Length;
|
||||
|
||||
var splitId = Guid.Parse("67e4bbe9-86ca-474d-9385-6569ce89db61");
|
||||
var progress = new UploadProgressInfo(splitId);
|
||||
|
||||
var param = new PrmObjectClientCutPut(
|
||||
Mocker.ObjectHeader,
|
||||
payload: new MemoryStream(bytes),
|
||||
bufferMaxSize: blockSize,
|
||||
progress: progress);
|
||||
|
||||
Random rnd = new();
|
||||
|
||||
Collection<byte[]> objIds = new([new byte[32], new byte[32], new byte[32]]);
|
||||
rnd.NextBytes(objIds.ElementAt(0));
|
||||
rnd.NextBytes(objIds.ElementAt(1));
|
||||
rnd.NextBytes(objIds.ElementAt(2));
|
||||
|
||||
foreach (var objId in objIds)
|
||||
Mocker.ResultObjectIds!.Add(objId);
|
||||
|
||||
int sentBlockCount = 0;
|
||||
Mocker.Callback = () =>
|
||||
{
|
||||
if (++sentBlockCount == 3)
|
||||
throw new FrostFsException("some error");
|
||||
};
|
||||
|
||||
bool gotException = false;
|
||||
try
|
||||
{
|
||||
_ = await GetClient().PutClientCutObjectAsync(param, default);
|
||||
}
|
||||
catch (FrostFsException ex)
|
||||
{
|
||||
if (ex.Message == "some error")
|
||||
gotException = true;
|
||||
}
|
||||
|
||||
Assert.True(gotException);
|
||||
|
||||
var singleObjects = Mocker.PutSingleRequests.ToArray();
|
||||
|
||||
Assert.NotNull(Mocker.ClientStreamWriter?.Messages);
|
||||
|
||||
var objects = Mocker.PutSingleRequests.Select(o => o.Body.Object).ToArray();
|
||||
|
||||
Assert.Equal(2, objects.Length);
|
||||
|
||||
Assert.Equal(2, progress.GetParts().Count);
|
||||
|
||||
var part = progress.GetPart(0);
|
||||
Assert.Equal(0, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
part = progress.GetPart(1);
|
||||
Assert.Equal(2560, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
// PART1
|
||||
Assert.Equal(blockSize, objects[0].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(0, blockSize).ToArray(), objects[0].Payload);
|
||||
|
||||
Assert.NotNull(objects[0].Header.Split.SplitId);
|
||||
Assert.Null(objects[0].Header.Split.Previous);
|
||||
Assert.True(objects[0].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[0].Header.Split.Parent);
|
||||
|
||||
// PART2
|
||||
Assert.Equal(blockSize, objects[1].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(blockSize, blockSize).ToArray(), objects[1].Payload);
|
||||
|
||||
Assert.Equal(objects[0].Header.Split.SplitId, objects[1].Header.Split.SplitId);
|
||||
Assert.True(objects[1].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[1].Header.Split.Parent);
|
||||
|
||||
// resume uploading
|
||||
sentBlockCount = 10;
|
||||
|
||||
var result = await GetClient().PutClientCutObjectAsync(param, default);
|
||||
|
||||
singleObjects = Mocker.PutSingleRequests.ToArray();
|
||||
|
||||
Assert.NotNull(Mocker.ClientStreamWriter?.Messages);
|
||||
|
||||
objects = Mocker.PutSingleRequests.Select(o => o.Body.Object).ToArray();
|
||||
|
||||
Assert.Equal(4, objects.Length);
|
||||
|
||||
// PART1
|
||||
Assert.Equal(blockSize, objects[0].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(0, blockSize).ToArray(), objects[0].Payload);
|
||||
|
||||
Assert.NotNull(objects[0].Header.Split.SplitId);
|
||||
Assert.Null(objects[0].Header.Split.Previous);
|
||||
Assert.True(objects[0].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[0].Header.Split.Parent);
|
||||
|
||||
// PART2
|
||||
Assert.Equal(blockSize, objects[1].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(blockSize, blockSize).ToArray(), objects[1].Payload);
|
||||
|
||||
Assert.Equal(objects[0].Header.Split.SplitId, objects[1].Header.Split.SplitId);
|
||||
Assert.True(objects[1].Header.Attributes.Count == 0);
|
||||
Assert.Null(objects[1].Header.Split.Parent);
|
||||
|
||||
// last part
|
||||
Assert.Equal(bytes.Length % blockSize, objects[2].Payload.Length);
|
||||
Assert.Equal(bytes.AsMemory(2 * blockSize).ToArray(), objects[2].Payload);
|
||||
|
||||
Assert.NotNull(objects[3].Header.Split.Parent);
|
||||
Assert.NotNull(objects[3].Header.Split.ParentHeader);
|
||||
Assert.NotNull(objects[3].Header.Split.ParentSignature);
|
||||
Assert.Equal(objects[2].Header.Split.SplitId, objects[3].Header.Split.SplitId);
|
||||
Assert.True(objects[2].Header.Attributes.Count == 0);
|
||||
|
||||
// link object
|
||||
Assert.Equal(objects[2].Header.Split.Parent, objects[3].Header.Split.Parent);
|
||||
Assert.Equal(objects[2].Header.Split.ParentHeader, objects[3].Header.Split.ParentHeader);
|
||||
Assert.Equal(objects[2].Header.Split.SplitId, objects[3].Header.Split.SplitId);
|
||||
Assert.Equal(0, (int)objects[3].Header.PayloadLength);
|
||||
Assert.True(objects[3].Header.Attributes.Count == 0);
|
||||
|
||||
Assert.Single(objects[3].Header.Split.ParentHeader.Attributes);
|
||||
Assert.Equal("k", objects[3].Header.Split.ParentHeader.Attributes[0].Key);
|
||||
Assert.Equal("v", objects[3].Header.Split.ParentHeader.Attributes[0].Value);
|
||||
|
||||
var modelObjId = FrostFsObjectId.FromHash(objects[3].Header.Split.Parent.Value.ToByteArray());
|
||||
|
||||
Assert.Equal(result.Value, modelObjId.ToString());
|
||||
|
||||
Assert.Equal(3, progress.GetParts().Count);
|
||||
part = progress.GetPart(0);
|
||||
Assert.Equal(0, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
part = progress.GetPart(1);
|
||||
Assert.Equal(2560, part.Offset);
|
||||
Assert.Equal(2560, part.Length);
|
||||
|
||||
part = progress.GetPart(2);
|
||||
Assert.Equal(2 * 2560, part.Offset);
|
||||
Assert.Equal(1620, part.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void DeleteObject()
|
||||
{
|
||||
|
|
99
src/FrostFS.SDK.Tests/Unit/ObjectToolsTests.cs
Normal file
99
src/FrostFS.SDK.Tests/Unit/ObjectToolsTests.cs
Normal file
|
@ -0,0 +1,99 @@
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using FrostFS.SDK.Client;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
public class ObjectToolsTests
|
||||
{
|
||||
internal readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
[Fact]
|
||||
public void CalculateObjectIdTest()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("testPayload");
|
||||
|
||||
var payloadHash = SHA256.HashData(payload);
|
||||
|
||||
FrostFsContainerId containerId = new("test");
|
||||
FrostFsObjectHeader header = new(containerId);
|
||||
|
||||
var ecdsaKey = key.LoadWif();
|
||||
var owner = FrostFsOwner.FromKey(ecdsaKey);
|
||||
|
||||
var clientKey = new ClientKey(ecdsaKey);
|
||||
|
||||
var objId = ObjectTools.CalculateObjectId(header, payloadHash, owner, new FrostFsVersion(2, 13), clientKey);
|
||||
|
||||
Assert.NotNull(objId.Value);
|
||||
Assert.Equal("HuAojwCYi62iUKr1FtSCCkMLLWv1uAnznF8iSb1bRV1N", objId.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CalculateObjectIdTest1()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("testPayload");
|
||||
|
||||
var payloadHash = SHA256.HashData(payload);
|
||||
var ecdsaKey = key.LoadWif();
|
||||
var owner = FrostFsOwner.FromKey(ecdsaKey);
|
||||
|
||||
var clientKey = new ClientKey(ecdsaKey);
|
||||
FrostFsContainerId containerId = new("test");
|
||||
FrostFsObjectHeader header = new(containerId, FrostFsObjectType.Regular, null, null, owner, new FrostFsVersion(2, 13));
|
||||
|
||||
var objId = ObjectTools.CalculateObjectId(header, payloadHash, owner, new FrostFsVersion(2, 13), clientKey);
|
||||
|
||||
Assert.NotNull(objId.Value);
|
||||
Assert.Equal("HuAojwCYi62iUKr1FtSCCkMLLWv1uAnznF8iSb1bRV1N", objId.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CalculateObjectIdWithAttrTest()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("testPayload");
|
||||
|
||||
var payloadHash = SHA256.HashData(payload);
|
||||
var ecdsaKey = key.LoadWif();
|
||||
var owner = FrostFsOwner.FromKey(ecdsaKey);
|
||||
|
||||
var clientKey = new ClientKey(ecdsaKey);
|
||||
FrostFsContainerId containerId = new("test");
|
||||
|
||||
FrostFsAttributePair[] attribs = [new("key", "val")];
|
||||
|
||||
FrostFsObjectHeader header = new(containerId, FrostFsObjectType.Regular, attribs, null, owner, new FrostFsVersion(2, 13));
|
||||
|
||||
var objId = ObjectTools.CalculateObjectId(header, payloadHash, owner, new FrostFsVersion(2, 13), clientKey);
|
||||
|
||||
Assert.NotNull(objId.Value);
|
||||
Assert.Equal("4zq5NYEbzkrfmdKne3GnpavE24gU2PnuV17ZExb9hcn3", objId.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CalculateObjectIdWithSplitIdTest()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("testPayload");
|
||||
|
||||
var payloadHash = SHA256.HashData(payload);
|
||||
var ecdsaKey = key.LoadWif();
|
||||
var owner = FrostFsOwner.FromKey(ecdsaKey);
|
||||
|
||||
var clientKey = new ClientKey(ecdsaKey);
|
||||
FrostFsContainerId containerId = new("test");
|
||||
|
||||
FrostFsAttributePair[] attribs = [new("key", "val")];
|
||||
|
||||
var guid = Guid.Parse("790a8d04-f5c3-4cd6-b46f-a78ee7e325f2");
|
||||
SplitId splitId = new(guid);
|
||||
FrostFsSplit split = new (splitId);
|
||||
|
||||
FrostFsObjectHeader header = new(containerId, FrostFsObjectType.Regular, attribs, split, owner, new FrostFsVersion(2, 13));
|
||||
|
||||
var objId = ObjectTools.CalculateObjectId(header, payloadHash, owner, new FrostFsVersion(2, 13), clientKey);
|
||||
|
||||
Assert.NotNull(objId.Value);
|
||||
Assert.Equal("HCYzsuXyfe5LmQzi58hPQxExGPAFv7dU5TzEACLxM1os", objId.Value);
|
||||
}
|
||||
}
|
307
src/FrostFS.SDK.Tests/Unit/PlacementPolicyTests.cs
Normal file
307
src/FrostFS.SDK.Tests/Unit/PlacementPolicyTests.cs
Normal file
|
@ -0,0 +1,307 @@
|
|||
using System.Xml.Linq;
|
||||
using FrostFS.Netmap;
|
||||
using FrostFS.SDK.Client;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
public class PlacementPolicyTests : NetworkTestsBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, 1)]
|
||||
[InlineData(true, 3)]
|
||||
[InlineData(true, 5)]
|
||||
[InlineData(false, 1)]
|
||||
[InlineData(false, 3)]
|
||||
[InlineData(false, 5)]
|
||||
public void PlacementPolicySimpleFullTest(bool unique, uint backupFactor)
|
||||
{
|
||||
PlacementPolicy policy = new()
|
||||
{
|
||||
ContainerBackupFactor = backupFactor,
|
||||
Unique = unique
|
||||
};
|
||||
|
||||
var result = policy.ToModel();
|
||||
|
||||
Assert.Equal(backupFactor, result.BackupFactor);
|
||||
Assert.Equal(unique, result.Unique);
|
||||
Assert.Empty(result.Filters);
|
||||
Assert.Empty(result.Replicas);
|
||||
Assert.Empty(result.Selectors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PlacementPolicyFullTest()
|
||||
{
|
||||
PlacementPolicy policy = new()
|
||||
{
|
||||
ContainerBackupFactor = 3,
|
||||
Unique = true
|
||||
};
|
||||
|
||||
policy.Filters.AddRange(
|
||||
[
|
||||
new () { Name = "filter1", Key = "filterKey1", Op =Operation.Eq, Value = "testValue1" },
|
||||
new () { Name = "filter2", Key = "filterKey2", Op =Operation.And, Value = "testValue2" }
|
||||
]);
|
||||
|
||||
policy.Selectors.AddRange(
|
||||
[
|
||||
new () { Name = "name1", Attribute = "attrib1", Clause = Clause.Same, Count = 5, Filter = "filter1" },
|
||||
new () { Name = "name2", Attribute = "attrib2", Clause = Clause.Distinct, Count = 4, Filter = "filter2" }
|
||||
]);
|
||||
|
||||
policy.Replicas.AddRange(
|
||||
[
|
||||
new () { EcDataCount = 2, EcParityCount = 3, Count = 4, Selector = "selector1"},
|
||||
new () { EcDataCount = 5, EcParityCount = 6, Count = 7, Selector = "selector2"},
|
||||
]);
|
||||
|
||||
var result = policy.ToModel();
|
||||
|
||||
Assert.Equal(3L, result.BackupFactor);
|
||||
Assert.True(result.Unique);
|
||||
Assert.Equal(2, result.Filters.Count);
|
||||
Assert.Equal(2, result.Replicas.Length);
|
||||
Assert.Equal(2, result.Selectors.Count);
|
||||
|
||||
var rep0 = result.Replicas[0];
|
||||
Assert.Equal(2u, rep0.EcDataCount);
|
||||
Assert.Equal(3u, rep0.EcParityCount);
|
||||
Assert.Equal(4, 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("selector2", rep1.Selector);
|
||||
|
||||
var f0 = result.Filters[0];
|
||||
Assert.Equal("filterKey1", f0.Key);
|
||||
Assert.Equal("filter1", f0.Name);
|
||||
Assert.Equal(1, f0.Operation);
|
||||
Assert.Equal("testValue1", f0.Value);
|
||||
|
||||
var f1 = result.Filters[1];
|
||||
Assert.Equal("filterKey2", f1.Key);
|
||||
Assert.Equal("filter2", f1.Name);
|
||||
Assert.Equal(8, f1.Operation);
|
||||
Assert.Equal("testValue2", f1.Value);
|
||||
|
||||
var s0 = result.Selectors[0];
|
||||
Assert.Equal("name1", s0.Name);
|
||||
Assert.Equal("attrib1", s0.Attribute);
|
||||
Assert.Equal(1, s0.Clause);
|
||||
Assert.Equal(5L, s0.Count);
|
||||
Assert.Equal("filter1", s0.Filter);
|
||||
|
||||
var s1 = result.Selectors[1];
|
||||
Assert.Equal("name2", s1.Name);
|
||||
Assert.Equal("attrib2", s1.Attribute);
|
||||
Assert.Equal(2, s1.Clause);
|
||||
Assert.Equal(4L, s1.Count);
|
||||
Assert.Equal("filter2", s1.Filter);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, "test" , 0, 0)]
|
||||
[InlineData(1, "", 1000, 9999)]
|
||||
[InlineData(1, "some long text to test reasonable length of the selector name", 100000000, 100000001)]
|
||||
[InlineData(100, "test2", 1, 1)]
|
||||
[InlineData(1, " ", 2, 3)]
|
||||
[InlineData(10, "!", 0, 0)]
|
||||
[InlineData(1, "123", 0, 0)]
|
||||
public void ReplicaToModelTest(uint count, string selector, uint ecDataCount, uint ecParityCount)
|
||||
{
|
||||
Replica replica = new ()
|
||||
{
|
||||
Count = count,
|
||||
Selector = selector,
|
||||
EcDataCount = ecDataCount,
|
||||
EcParityCount = ecParityCount
|
||||
};
|
||||
|
||||
FrostFsReplica model = replica.ToModel();
|
||||
|
||||
Assert.Equal(count, (uint)model.Count);
|
||||
Assert.Equal(selector, model.Selector);
|
||||
Assert.Equal(ecDataCount, model.EcDataCount);
|
||||
Assert.Equal(ecParityCount, model.EcParityCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, "test", 0, 0)]
|
||||
[InlineData(1, "", 1000, 9999)]
|
||||
[InlineData(1, "some long text to test reasonable length of the selector name", 100000000, 100000001)]
|
||||
[InlineData(100, "test2", 1, 1)]
|
||||
[InlineData(1, " ", 2, 3)]
|
||||
[InlineData(10, "!", 0, 0)]
|
||||
[InlineData(1, "123", 0, 0)]
|
||||
public void ReplicaToMessagelTest(int count, string selector, uint ecDataCount, uint ecParityCount)
|
||||
{
|
||||
FrostFsReplica replica = new ()
|
||||
{
|
||||
Count = count,
|
||||
Selector = selector,
|
||||
EcDataCount = ecDataCount,
|
||||
EcParityCount = ecParityCount
|
||||
};
|
||||
|
||||
Replica message = replica.ToMessage();
|
||||
|
||||
Assert.Equal((uint)count, message.Count);
|
||||
Assert.Equal(selector, message.Selector);
|
||||
Assert.Equal(ecDataCount, message.EcDataCount);
|
||||
Assert.Equal(ecParityCount, message.EcParityCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("test", 1, 2, "attribute", "filter")]
|
||||
[InlineData("test", 0, 0, "longlonglonglonglonglonglonglonglonglonglonglonglong attribute", "longlonglonglonglonglonglonglonglonglonglonglonglong filter")]
|
||||
[InlineData("test", 0, 1, "attribute", "filter")]
|
||||
public void SelectorToMessageTest(string name, uint count, int clause, string attr, string filter)
|
||||
{
|
||||
FrostFsSelector selector = new (name)
|
||||
{
|
||||
Count = count,
|
||||
Clause = clause,
|
||||
Attribute = attr,
|
||||
Filter = filter,
|
||||
};
|
||||
|
||||
var message = selector.ToMessage();
|
||||
|
||||
Assert.Equal(name, message.Name);
|
||||
Assert.Equal(count, message.Count);
|
||||
Assert.Equal(clause, (int)message.Clause);
|
||||
Assert.Equal(attr, message.Attribute);
|
||||
Assert.Equal(filter, message.Filter);
|
||||
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("test", 1, Clause.Same, "attribute", "filter")]
|
||||
[InlineData("test", 0, Clause.Distinct, "longlonglonglonglonglonglonglonglonglonglonglonglong attribute", "longlonglonglonglonglonglonglonglonglonglonglonglong filter")]
|
||||
public void SelectorToModelTest(string name, uint count, Clause clause, string attr, string filter)
|
||||
{
|
||||
Selector selector = new ()
|
||||
{
|
||||
Name = name,
|
||||
Count = count,
|
||||
Clause = clause,
|
||||
Attribute = attr,
|
||||
Filter = filter
|
||||
};
|
||||
|
||||
var model = selector.ToModel();
|
||||
|
||||
Assert.Equal(name, model.Name);
|
||||
Assert.Equal(count, model.Count);
|
||||
Assert.Equal((int)clause, model.Clause);
|
||||
Assert.Equal(attr, model.Attribute);
|
||||
Assert.Equal(filter, model.Filter);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "", 1, "")]
|
||||
[InlineData("name", "key", 1, "val")]
|
||||
[InlineData("longlonglonglonglonglonglonglonglonglonglonglonglong name", "longlonglonglonglonglonglonglonglonglonglonglonglong key", 10, "longlonglonglonglonglonglonglonglonglonglonglonglong val")]
|
||||
public void FilterToMessageTest(string name, string key, int operation, string value)
|
||||
{
|
||||
FrostFsFilter filter = new (name, key, operation, value, []);
|
||||
|
||||
var message = filter.ToMessage();
|
||||
|
||||
Assert.Equal(name, message.Name);
|
||||
Assert.Equal(key, message.Key);
|
||||
Assert.Equal(operation, (int)message.Op);
|
||||
Assert.Equal(value, message.Value);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "", 1, "")]
|
||||
[InlineData("name", "key", 2, "val")]
|
||||
[InlineData("longlonglonglonglonglonglonglonglonglonglonglonglong name", "longlonglonglonglonglonglonglonglonglonglonglonglong key", 10, "longlonglonglonglonglonglonglonglonglonglonglonglong val")]
|
||||
public void SubFilterToMessageTest(string name, string key, int operation, string value)
|
||||
{
|
||||
FrostFsFilter subFilter = new(name, key, operation, value, []);
|
||||
|
||||
FrostFsFilter filter = new("name", "key", 1, "value", [subFilter]);
|
||||
|
||||
var message = filter.ToMessage();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SubFiltersToMessageTest()
|
||||
{
|
||||
string[] names = ["", "name1", "some pretty long name for name test"];
|
||||
string[] keys = ["", "key1", "some pretty long key for name test"];
|
||||
int[] operations = [1, 2, 10];
|
||||
string[] values = ["", "val1", "some pretty long value for name test"];
|
||||
|
||||
var subFilter = new FrostFsFilter[3];
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
subFilter[i] = new FrostFsFilter(names[i], keys[i], operations[i], values[i], []);
|
||||
}
|
||||
|
||||
FrostFsFilter filter = new("name", "key", 1, "value", subFilter);
|
||||
|
||||
var message = filter.ToMessage();
|
||||
|
||||
Assert.Equal(3, message.Filters.Count);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "", Operation.Unspecified, "")]
|
||||
[InlineData("name", "key", Operation.Unspecified, "val")]
|
||||
[InlineData("name", "key", Operation.And, "val")]
|
||||
[InlineData("name", "key", Operation.Eq, "val")]
|
||||
[InlineData("name", "key", Operation.Le, "val")]
|
||||
[InlineData("name", "key", Operation.Like, "val")]
|
||||
[InlineData("name", "key", Operation.Ge, "val")]
|
||||
[InlineData("name", "key", Operation.Gt, "val")]
|
||||
[InlineData("name", "key", Operation.Lt, "val")]
|
||||
[InlineData("name", "key", Operation.Ne, "val")]
|
||||
[InlineData("name", "key", Operation.Not, "val")]
|
||||
[InlineData("name", "key", Operation.Or, "val")]
|
||||
[InlineData("longlonglonglonglonglonglonglonglonglonglonglonglong name", "longlonglonglonglonglonglonglonglonglonglonglonglong key", Operation.Like, "longlonglonglonglonglonglonglonglonglonglonglonglong val")]
|
||||
public void FrostFsFilterToModelTest(string name, string key, Operation operation, string value)
|
||||
{
|
||||
Filter filter = new()
|
||||
{
|
||||
Name = name,
|
||||
Key = key,
|
||||
Op = operation,
|
||||
Value = value
|
||||
};
|
||||
|
||||
var model = filter.ToModel();
|
||||
|
||||
Assert.Equal(name, model.Name);
|
||||
Assert.Equal(key, model.Key);
|
||||
Assert.Equal((int)operation, model.Operation);
|
||||
Assert.Equal(value, model.Value);
|
||||
}
|
||||
}
|
39
src/FrostFS.SDK.Tests/Unit/SignatureTests.cs
Normal file
39
src/FrostFS.SDK.Tests/Unit/SignatureTests.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System.Text;
|
||||
using FrostFS.SDK.Client;
|
||||
using FrostFS.SDK.Client.Mappers.GRPC;
|
||||
|
||||
namespace FrostFS.SDK.Tests.Unit;
|
||||
|
||||
public class SignatureTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(Refs.SignatureScheme.EcdsaSha512)]
|
||||
[InlineData(Refs.SignatureScheme.EcdsaRfc6979Sha256)]
|
||||
[InlineData(Refs.SignatureScheme.EcdsaRfc6979Sha256WalletConnect)]
|
||||
|
||||
public void SignatureToMessageTest(Refs.SignatureScheme scheme)
|
||||
{
|
||||
var key = Encoding.UTF8.GetBytes("datafortest");
|
||||
var sign = Encoding.UTF8.GetBytes("signdatafortest");
|
||||
|
||||
var frostFsScheme = scheme switch
|
||||
{
|
||||
Refs.SignatureScheme.EcdsaRfc6979Sha256 => SignatureScheme.EcdsaRfc6979Sha256,
|
||||
Refs.SignatureScheme.EcdsaRfc6979Sha256WalletConnect => SignatureScheme.EcdsaRfc6979Sha256WalletConnect,
|
||||
Refs.SignatureScheme.EcdsaSha512 => SignatureScheme.EcdsaSha512
|
||||
};
|
||||
|
||||
FrostFsSignature signature = new()
|
||||
{
|
||||
Key = key,
|
||||
Scheme = frostFsScheme,
|
||||
Sign = sign
|
||||
};
|
||||
|
||||
var result = signature.ToMessage();
|
||||
|
||||
Assert.Equal(scheme, result.Scheme);
|
||||
Assert.Equal(sign, result.Sign.ToByteArray());
|
||||
Assert.Equal(key, result.Key.ToByteArray());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue