[#24] Client: Implement pool part1
All checks were successful
DCO / DCO (pull_request) Successful in 46s
All checks were successful
DCO / DCO (pull_request) Successful in 46s
first iteration - base classes and methods Signed-off-by: Pavel Gross <p.gross@yadro.com>
This commit is contained in:
parent
d1271df207
commit
c9a75ea025
72 changed files with 2786 additions and 468 deletions
|
@ -1,49 +1,14 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Google.Protobuf;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class ContainerTestsBase
|
||||
{
|
||||
protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
protected ContainerMocker Mocker { get; set; }
|
||||
|
||||
protected ContainerTestsBase()
|
||||
{
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
Mocker = new ContainerMocker(this.key)
|
||||
{
|
||||
PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),
|
||||
Version = new FrostFsVersion(2, 13),
|
||||
ContainerGuid = Guid.NewGuid()
|
||||
};
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return ClientV2.FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
new NetworkMocker(this.key).GetMock().Object,
|
||||
new SessionMocker(this.key).GetMock().Object,
|
||||
Mocker.GetMock().Object,
|
||||
new ObjectMocker(this.key).GetMock().Object);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public class ContainerTest : ContainerTestsBase
|
||||
{
|
||||
[Fact]
|
||||
|
|
40
src/FrostFS.SDK.Tests/ContainerTestsBase.cs
Normal file
40
src/FrostFS.SDK.Tests/ContainerTestsBase.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class ContainerTestsBase
|
||||
{
|
||||
internal readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
protected ContainerMocker Mocker { get; set; }
|
||||
|
||||
protected ContainerTestsBase()
|
||||
{
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
Mocker = new ContainerMocker(this.key)
|
||||
{
|
||||
PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),
|
||||
Version = new FrostFsVersion(2, 13),
|
||||
ContainerGuid = Guid.NewGuid()
|
||||
};
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return ClientV2.FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
new NetworkMocker(this.key).GetMock().Object,
|
||||
new SessionMocker(this.key).GetMock().Object,
|
||||
Mocker.GetMock().Object,
|
||||
new ObjectMocker(this.key).GetMock().Object);
|
||||
}
|
||||
}
|
6
src/FrostFS.SDK.Tests/GlobalSuppressions.cs
Normal file
6
src/FrostFS.SDK.Tests/GlobalSuppressions.cs
Normal file
|
@ -0,0 +1,6 @@
|
|||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
||||
|
|
@ -12,7 +12,9 @@ public class MetricsInterceptor() : Interceptor
|
|||
ClientInterceptorContext<TRequest, TResponse> context,
|
||||
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
|
||||
{
|
||||
var call = continuation(request, context);
|
||||
ArgumentNullException.ThrowIfNull(continuation);
|
||||
|
||||
using var call = continuation(request, context);
|
||||
|
||||
return new AsyncUnaryCall<TResponse>(
|
||||
HandleUnaryResponse(call),
|
||||
|
@ -27,7 +29,7 @@ public class MetricsInterceptor() : Interceptor
|
|||
var watch = new Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
var response = await call.ResponseAsync;
|
||||
var response = await call.ResponseAsync.ConfigureAwait(false);
|
||||
|
||||
watch.Stop();
|
||||
|
||||
|
|
|
@ -26,8 +26,11 @@ public class AsyncStreamReaderMock(string key, FrostFsObjectHeader objectHeader)
|
|||
OwnerId = objectHeader.OwnerId!.ToMessage()
|
||||
};
|
||||
|
||||
foreach (var attr in objectHeader.Attributes)
|
||||
header.Attributes.Add(attr.ToMessage());
|
||||
if (objectHeader.Attributes != null)
|
||||
{
|
||||
foreach (var attr in objectHeader.Attributes)
|
||||
header.Attributes.Add(attr.ToMessage());
|
||||
}
|
||||
|
||||
var response = new GetResponse
|
||||
{
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System.Collections.ObjectModel;
|
||||
|
||||
using FrostFS.SDK.ProtosV2.Interfaces;
|
||||
|
||||
using Grpc.Core;
|
||||
|
@ -6,13 +8,15 @@ namespace FrostFS.SDK.Tests;
|
|||
|
||||
public class ClientStreamWriter : IClientStreamWriter<IRequest>
|
||||
{
|
||||
public List<IRequest> Messages { get; set; } = [];
|
||||
private WriteOptions? _options;
|
||||
|
||||
public Collection<IRequest> Messages { get; } = [];
|
||||
public bool CompletedTask { get; private set; }
|
||||
|
||||
public WriteOptions? WriteOptions
|
||||
{
|
||||
get => throw new NotImplementedException();
|
||||
set => throw new NotImplementedException();
|
||||
get => _options;
|
||||
set => _options = value;
|
||||
}
|
||||
|
||||
public Task CompleteAsync()
|
||||
|
|
|
@ -25,7 +25,10 @@ public abstract class ServiceBase(string key)
|
|||
public static FrostFsVersion DefaultVersion { get; } = new(2, 13);
|
||||
public static FrostFsPlacementPolicy DefaultPlacementPolicy { get; } = new FrostFsPlacementPolicy(true, new FrostFsReplica(1));
|
||||
|
||||
public Metadata Metadata { get; protected set; }
|
||||
#pragma warning disable CA2227 // this is specific object, should be treated as is
|
||||
public Metadata? Metadata { get; set; }
|
||||
#pragma warning restore CA2227
|
||||
|
||||
public DateTime? DateTime { get; protected set; }
|
||||
|
||||
public CancellationToken CancellationToken { get; protected set; }
|
||||
|
@ -35,6 +38,8 @@ public abstract class ServiceBase(string key)
|
|||
|
||||
protected ResponseVerificationHeader GetResponseVerificationHeader(IResponse response)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(response);
|
||||
|
||||
var verifyHeader = new ResponseVerificationHeader
|
||||
{
|
||||
MetaSignature = new Refs.Signature
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System.Collections.ObjectModel;
|
||||
|
||||
using FrostFS.Container;
|
||||
using FrostFS.Refs;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
|
@ -41,7 +43,7 @@ public class ContainerMocker(string key) : ContainerServiceBase(key)
|
|||
putResponse.VerifyHeader = GetResponseVerificationHeader(putResponse);
|
||||
|
||||
var metadata = new Metadata();
|
||||
var putContainerResponse = new AsyncUnaryCall<PutResponse>(
|
||||
using var putContainerResponse = new AsyncUnaryCall<PutResponse>(
|
||||
Task.FromResult(putResponse),
|
||||
Task.FromResult(metadata),
|
||||
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
||||
|
@ -180,7 +182,7 @@ public class ContainerMocker(string key) : ContainerServiceBase(key)
|
|||
|
||||
public bool ReturnContainerRemoved { get; set; }
|
||||
|
||||
public List<byte[]> ContainerIds { get; set; } = [];
|
||||
public Collection<byte[]> ContainerIds { get; } = [];
|
||||
|
||||
public List<RequestData<DeleteRequest>> Requests { get; set; } = [];
|
||||
public Collection<RequestData<DeleteRequest>> Requests { get; } = [];
|
||||
}
|
||||
|
|
|
@ -25,18 +25,17 @@ public class NetworkMocker(string key) : ServiceBase(key)
|
|||
"MaintenanceModeAllowed"
|
||||
];
|
||||
|
||||
public Dictionary<string, byte[]>? Parameters { get; set; }
|
||||
public Dictionary<string, byte[]> Parameters { get; } = [];
|
||||
|
||||
public LocalNodeInfoResponse NodeInfoResponse { get; set; }
|
||||
public LocalNodeInfoResponse? NodeInfoResponse { get; set; }
|
||||
|
||||
public LocalNodeInfoRequest LocalNodeInfoRequest { get; set; }
|
||||
public LocalNodeInfoRequest? LocalNodeInfoRequest { get; set; }
|
||||
|
||||
public NetworkInfoRequest NetworkInfoRequest { get; set; }
|
||||
public NetworkInfoRequest? NetworkInfoRequest { get; set; }
|
||||
|
||||
public NetmapSnapshotResponse NetmapSnapshotResponse { get; set; }
|
||||
|
||||
public NetmapSnapshotRequest NetmapSnapshotRequest { get; set; }
|
||||
public NetmapSnapshotResponse? NetmapSnapshotResponse { get; set; }
|
||||
|
||||
public NetmapSnapshotRequest? NetmapSnapshotRequest { get; set; }
|
||||
|
||||
public Mock<NetmapService.NetmapServiceClient> GetMock()
|
||||
{
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using FrostFS.Object;
|
||||
|
@ -92,7 +93,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
|
|||
|
||||
}
|
||||
|
||||
if (ResultObjectIds != null)
|
||||
if (ResultObjectIds != null && ResultObjectIds.Count > 0)
|
||||
{
|
||||
PutResponse putResponse = new()
|
||||
{
|
||||
|
@ -197,14 +198,14 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
|
|||
|
||||
public Header? HeadResponse { get; set; }
|
||||
|
||||
public List<byte[]>? ResultObjectIds { get; set; }
|
||||
public Collection<byte[]>? ResultObjectIds { get; } = [];
|
||||
|
||||
public ClientStreamWriter? ClientStreamWriter { get; private set; } = new();
|
||||
|
||||
public List<PutSingleRequest> PutSingleRequests { get; private set; } = [];
|
||||
public Collection<PutSingleRequest> PutSingleRequests { get; private set; } = [];
|
||||
|
||||
public List<DeleteRequest> DeleteRequests { get; private set; } = [];
|
||||
public Collection<DeleteRequest> DeleteRequests { get; private set; } = [];
|
||||
|
||||
public List<HeadRequest> HeadRequests { get; private set; } = [];
|
||||
public Collection<HeadRequest> HeadRequests { get; private set; } = [];
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@ using Moq;
|
|||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
|
||||
public class SessionMocker(string key) : ServiceBase(key)
|
||||
{
|
||||
public byte[]? SessionId { get; set; }
|
||||
|
||||
public byte[]? SessionKey { get; set; }
|
||||
|
||||
public CreateRequest CreateSessionRequest { get; private set; }
|
||||
public CreateRequest? CreateSessionRequest { get; private set; }
|
||||
|
||||
public Mock<SessionService.SessionServiceClient> GetMock()
|
||||
{
|
||||
|
@ -24,7 +25,7 @@ public class SessionMocker(string key) : ServiceBase(key)
|
|||
|
||||
if (SessionId == null)
|
||||
{
|
||||
SessionId = new byte[32];
|
||||
SessionId = new byte[16];
|
||||
rand.NextBytes(SessionId);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,55 +1,13 @@
|
|||
using System.Security.Cryptography;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using FrostFS.Netmap;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Google.Protobuf;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class NetworkTestsBase
|
||||
{
|
||||
protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
|
||||
protected FrostFsVersion Version { get; set; } = new FrostFsVersion(2, 13);
|
||||
|
||||
protected ECDsa ECDsaKey { get; set; }
|
||||
protected FrostFsOwner OwnerId { get; set; }
|
||||
protected NetworkMocker Mocker { get; set; }
|
||||
|
||||
protected NetworkTestsBase()
|
||||
{
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
ECDsaKey = key.LoadWif();
|
||||
OwnerId = FrostFsOwner.FromKey(ECDsaKey);
|
||||
|
||||
Mocker = new NetworkMocker(this.key);
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return ClientV2.FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
Mocker.GetMock().Object,
|
||||
new SessionMocker(this.key).GetMock().Object,
|
||||
new ContainerMocker(this.key).GetMock().Object,
|
||||
new ObjectMocker(this.key).GetMock().Object);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public class NetworkTest : NetworkTestsBase
|
||||
{
|
||||
[Theory]
|
||||
|
@ -57,27 +15,24 @@ public class NetworkTest : NetworkTestsBase
|
|||
[InlineData(true)]
|
||||
public async void NetworkSettingsTest(bool useContext)
|
||||
{
|
||||
Mocker.Parameters = new Dictionary<string, byte[]>
|
||||
{
|
||||
{ "AuditFee", [1] },
|
||||
{ "BasicIncomeRate", [2] },
|
||||
{ "ContainerFee", [3] },
|
||||
{ "ContainerAliasFee", [4] },
|
||||
{ "EpochDuration", [5] },
|
||||
{ "InnerRingCandidateFee", [6] },
|
||||
{ "MaxECDataCount", [7] },
|
||||
{ "MaxECParityCount", [8] },
|
||||
{ "MaxObjectSize", [9] },
|
||||
{ "WithdrawFee", [10] },
|
||||
{ "HomomorphicHashingDisabled", [1] },
|
||||
{ "MaintenanceModeAllowed", [1] },
|
||||
};
|
||||
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 param = new PrmNetworkSettings();
|
||||
|
||||
if (useContext)
|
||||
{
|
||||
param.Context = new Context
|
||||
param.Context = new CallContext
|
||||
{
|
||||
CancellationToken = Mocker.CancellationTokenSource.Token,
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
|
@ -119,6 +74,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(Mocker.NetworkInfoRequest);
|
||||
Assert.Empty(Mocker.NetworkInfoRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
|
@ -127,6 +83,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
|
||||
public async void NetmapSnapshotTest(bool useContext)
|
||||
{
|
||||
var body = new NetmapSnapshotResponse.Types.Body
|
||||
|
@ -164,7 +121,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
if (useContext)
|
||||
{
|
||||
param.XHeaders.Add("headerKey1", "headerValue1");
|
||||
param.Context = new Context
|
||||
param.Context = new CallContext
|
||||
{
|
||||
CancellationToken = Mocker.CancellationTokenSource.Token,
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
|
@ -210,6 +167,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
|
||||
if (useContext)
|
||||
{
|
||||
Assert.NotNull(Mocker.NetmapSnapshotRequest);
|
||||
Assert.Single(Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders);
|
||||
Assert.Equal(param.XHeaders.Keys[0], Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders.First().Key);
|
||||
Assert.Equal(param.XHeaders[param.XHeaders.Keys[0]], Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders.First().Value);
|
||||
|
@ -222,6 +180,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(Mocker.NetmapSnapshotRequest);
|
||||
Assert.Empty(Mocker.NetmapSnapshotRequest.MetaHeader.XHeaders);
|
||||
Assert.Null(Mocker.DateTime);
|
||||
}
|
||||
|
@ -254,7 +213,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
if (useContext)
|
||||
{
|
||||
param.XHeaders.Add("headerKey1", "headerValue1");
|
||||
param.Context = new Context
|
||||
param.Context = new CallContext
|
||||
{
|
||||
CancellationToken = Mocker.CancellationTokenSource.Token,
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
|
@ -282,6 +241,7 @@ public class NetworkTest : NetworkTestsBase
|
|||
Assert.Equal("value1", result.Attributes["key1"]);
|
||||
Assert.Equal("value2", result.Attributes["key2"]);
|
||||
|
||||
Assert.NotNull(Mocker.LocalNodeInfoRequest);
|
||||
if (useContext)
|
||||
{
|
||||
Assert.Single(Mocker.LocalNodeInfoRequest.MetaHeader.XHeaders);
|
||||
|
|
48
src/FrostFS.SDK.Tests/NetworkTestsBase.cs
Normal file
48
src/FrostFS.SDK.Tests/NetworkTestsBase.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public abstract class NetworkTestsBase
|
||||
{
|
||||
internal readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
|
||||
protected FrostFsVersion Version { get; set; } = new FrostFsVersion(2, 13);
|
||||
|
||||
protected ECDsa ECDsaKey { get; set; }
|
||||
protected FrostFsOwner OwnerId { get; set; }
|
||||
protected NetworkMocker Mocker { get; set; }
|
||||
|
||||
protected NetworkTestsBase()
|
||||
{
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
ECDsaKey = key.LoadWif();
|
||||
OwnerId = FrostFsOwner.FromKey(ECDsaKey);
|
||||
|
||||
Mocker = new NetworkMocker(this.key);
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return ClientV2.FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
Mocker.GetMock().Object,
|
||||
new SessionMocker(this.key).GetMock().Object,
|
||||
new ContainerMocker(this.key).GetMock().Object,
|
||||
new ObjectMocker(this.key).GetMock().Object);
|
||||
}
|
||||
}
|
|
@ -1,71 +1,19 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
using FrostFS.Refs;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Google.Protobuf;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class ObjectTestsBase
|
||||
{
|
||||
protected static readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
protected FrostFsContainerId ContainerId { get; set; }
|
||||
|
||||
protected NetworkMocker NetworkMocker { get; set; } = new NetworkMocker(key);
|
||||
protected SessionMocker SessionMocker { get; set; } = new SessionMocker(key);
|
||||
protected ContainerMocker ContainerMocker { get; set; } = new ContainerMocker(key);
|
||||
protected ObjectMocker Mocker { get; set; }
|
||||
|
||||
protected ObjectTestsBase()
|
||||
{
|
||||
var ecdsaKey = key.LoadWif();
|
||||
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
Mocker = new ObjectMocker(key)
|
||||
{
|
||||
PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),
|
||||
Version = new FrostFsVersion(2, 13),
|
||||
ContainerGuid = Guid.NewGuid()
|
||||
};
|
||||
|
||||
ContainerId = new FrostFsContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes()));
|
||||
|
||||
Mocker.ObjectHeader = new(
|
||||
ContainerId,
|
||||
FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("k", "v")],
|
||||
null,
|
||||
FrostFsOwner.FromKey(ecdsaKey),
|
||||
new FrostFsVersion(2, 13));
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
NetworkMocker.GetMock().Object,
|
||||
SessionMocker.GetMock().Object,
|
||||
ContainerMocker.GetMock().Object,
|
||||
Mocker.GetMock().Object);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
|
||||
public class ObjectTest : ObjectTestsBase
|
||||
{
|
||||
[Fact]
|
||||
|
@ -75,7 +23,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
var ecdsaKey = key.LoadWif();
|
||||
|
||||
var ctx = new Context
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Key = ecdsaKey,
|
||||
OwnerId = FrostFsOwner.FromKey(ecdsaKey),
|
||||
|
@ -88,18 +36,21 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
Assert.NotNull(result);
|
||||
|
||||
Assert.Equal(Mocker.ObjectHeader!.ContainerId.GetValue(), result.Header.ContainerId.GetValue());
|
||||
Assert.Equal(Mocker.ObjectHeader!.OwnerId!.Value, result.Header.OwnerId!.Value);
|
||||
Assert.NotNull(Mocker.ObjectHeader);
|
||||
|
||||
Assert.Equal(Mocker.ObjectHeader.ContainerId.GetValue(), result.Header.ContainerId.GetValue());
|
||||
Assert.Equal(Mocker.ObjectHeader.OwnerId!.Value, result.Header.OwnerId!.Value);
|
||||
Assert.Equal(Mocker.ObjectHeader.PayloadLength, result.Header.PayloadLength);
|
||||
Assert.NotNull(result.Header.Attributes);
|
||||
Assert.Single(result.Header.Attributes);
|
||||
Assert.Equal(Mocker.ObjectHeader.Attributes[0].Key, result.Header.Attributes[0].Key);
|
||||
Assert.Equal(Mocker.ObjectHeader.Attributes[0].Value, result.Header.Attributes[0].Value);
|
||||
Assert.Equal(Mocker.ObjectHeader.Attributes![0].Key, result.Header.Attributes[0].Key);
|
||||
Assert.Equal(Mocker.ObjectHeader.Attributes![0].Value, result.Header.Attributes[0].Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void PutObjectTest()
|
||||
{
|
||||
Mocker.ResultObjectIds = new([SHA256.HashData([])]);
|
||||
Mocker.ResultObjectIds.Add(SHA256.HashData([]));
|
||||
|
||||
Random rnd = new();
|
||||
var bytes = new byte[1024];
|
||||
|
@ -134,7 +85,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
[Fact]
|
||||
public async void ClientCutTest()
|
||||
{
|
||||
NetworkMocker.Parameters = new Dictionary<string, byte[]>() { { "MaxObjectSize", [0x0, 0xa] } };
|
||||
NetworkMocker.Parameters.Add("MaxObjectSize", [0x0, 0xa]);
|
||||
|
||||
var blockSize = 2560;
|
||||
byte[] bytes = File.ReadAllBytes(@".\..\..\..\TestData\cat.jpg");
|
||||
|
@ -150,17 +101,19 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
Random rnd = new();
|
||||
|
||||
List<byte[]> objIds = new([new byte[32], new byte[32], new byte[32]]);
|
||||
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));
|
||||
|
||||
Mocker.ResultObjectIds = objIds;
|
||||
foreach (var objId in objIds)
|
||||
Mocker.ResultObjectIds.Add(objId);
|
||||
|
||||
var result = await GetClient().PutObjectAsync(param);
|
||||
|
||||
var singleObjects = Mocker.PutSingleRequests.ToArray();
|
||||
|
||||
Assert.NotNull(Mocker.ClientStreamWriter?.Messages);
|
||||
var streamObjects = Mocker.ClientStreamWriter.Messages.ToArray();
|
||||
|
||||
Assert.Single(singleObjects);
|
||||
|
@ -262,6 +215,7 @@ public class ObjectTest : ObjectTestsBase
|
|||
|
||||
Assert.Equal(FrostFsObjectType.Regular, response.ObjectType);
|
||||
|
||||
Assert.NotNull(response.Attributes);
|
||||
Assert.Single(response.Attributes);
|
||||
|
||||
Assert.Equal(Mocker.HeadResponse.Attributes[0].Key, response.Attributes.First().Key);
|
||||
|
|
59
src/FrostFS.SDK.Tests/ObjectTestsBase.cs
Normal file
59
src/FrostFS.SDK.Tests/ObjectTestsBase.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class ObjectTestsBase
|
||||
{
|
||||
protected static readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
protected FrostFsContainerId ContainerId { get; set; }
|
||||
|
||||
protected NetworkMocker NetworkMocker { get; set; } = new NetworkMocker(key);
|
||||
protected SessionMocker SessionMocker { get; set; } = new SessionMocker(key);
|
||||
protected ContainerMocker ContainerMocker { get; set; } = new ContainerMocker(key);
|
||||
protected ObjectMocker Mocker { get; set; }
|
||||
|
||||
protected ObjectTestsBase()
|
||||
{
|
||||
var ecdsaKey = key.LoadWif();
|
||||
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
Mocker = new ObjectMocker(key)
|
||||
{
|
||||
PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),
|
||||
Version = new FrostFsVersion(2, 13),
|
||||
ContainerGuid = Guid.NewGuid()
|
||||
};
|
||||
|
||||
ContainerId = new FrostFsContainerId(Base58.Encode(Mocker.ContainerGuid.ToBytes()));
|
||||
|
||||
Mocker.ObjectHeader = new(
|
||||
ContainerId,
|
||||
FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("k", "v")],
|
||||
null,
|
||||
FrostFsOwner.FromKey(ecdsaKey),
|
||||
new FrostFsVersion(2, 13));
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
NetworkMocker.GetMock().Object,
|
||||
SessionMocker.GetMock().Object,
|
||||
ContainerMocker.GetMock().Object,
|
||||
Mocker.GetMock().Object);
|
||||
}
|
||||
}
|
603
src/FrostFS.SDK.Tests/PoolSmokeTests.cs
Normal file
603
src/FrostFS.SDK.Tests/PoolSmokeTests.cs
Normal file
|
@ -0,0 +1,603 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using static FrostFS.Session.SessionToken.Types.Body;
|
||||
|
||||
namespace FrostFS.SDK.SmokeTests;
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
|
||||
public class PoolSmokeTests : SmokeTestsBase
|
||||
{
|
||||
private static readonly PrmWait lightWait = new(100, 1);
|
||||
|
||||
private InitParameters GetDefaultParams()
|
||||
{
|
||||
return new InitParameters
|
||||
{
|
||||
Key = keyString.LoadWif(),
|
||||
|
||||
NodeParams = [new(1, this.url, 100.0f)],
|
||||
DialOptions = [new()
|
||||
{
|
||||
Authority = "",
|
||||
Block = false,
|
||||
DisableHealthCheck = false,
|
||||
DisableRetry = false,
|
||||
ReturnLastError = true,
|
||||
Timeout = 30_000_000
|
||||
}
|
||||
],
|
||||
ClientBuilder = null,
|
||||
GracefulCloseOnSwitchTimeout = 30_000_000,
|
||||
Logger = null
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void NetworkMapTest()
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext());
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
var result = await pool.GetNetmapSnapshotAsync(default);
|
||||
|
||||
Assert.True(result.Epoch > 0);
|
||||
Assert.Single(result.NodeInfoCollection);
|
||||
|
||||
var item = result.NodeInfoCollection[0];
|
||||
Assert.Equal(2, item.Version.Major);
|
||||
Assert.Equal(13, item.Version.Minor);
|
||||
Assert.Equal(NodeState.Online, item.State);
|
||||
Assert.True(item.PublicKey.Length > 0);
|
||||
Assert.Single(item.Addresses);
|
||||
Assert.Equal(9, item.Attributes.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void NodeInfoTest()
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext());
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
var result = await pool.GetNodeInfoAsync();
|
||||
|
||||
Assert.Equal(2, result.Version.Major);
|
||||
Assert.Equal(13, result.Version.Minor);
|
||||
Assert.Equal(NodeState.Online, result.State);
|
||||
Assert.Equal(33, result.PublicKey.Length);
|
||||
Assert.Single(result.Addresses);
|
||||
Assert.Equal(9, result.Attributes.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void NodeInfoStatisticsTest()
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var callbackText = string.Empty;
|
||||
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Callback = (cs) => callbackText = $"{cs.MethodName} took {cs.ElapsedMicroSeconds} microseconds"
|
||||
};
|
||||
|
||||
var error = await pool.Dial(ctx).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
var result = await client.GetNodeInfoAsync();
|
||||
|
||||
Assert.False(string.IsNullOrEmpty(callbackText));
|
||||
Assert.Contains(" took ", callbackText, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void GetSessionTest()
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext()).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
var prm = new PrmSessionCreate(100);
|
||||
|
||||
var token = await pool.CreateSessionAsync(prm).ConfigureAwait(true);
|
||||
|
||||
var session = new Session.SessionToken().Deserialize(token.Token);
|
||||
|
||||
var ownerHash = Base58.Decode(OwnerId!.Value);
|
||||
|
||||
Assert.NotNull(session);
|
||||
Assert.Null(session.Body.Container);
|
||||
Assert.Null(session.Body.Object);
|
||||
Assert.Equal(16, session.Body.Id.Length);
|
||||
Assert.Equal(100ul, session.Body.Lifetime.Exp);
|
||||
Assert.Equal(ownerHash, session.Body.OwnerId.Value);
|
||||
Assert.Equal(33, session.Body.SessionKey.Length);
|
||||
Assert.Equal(ContextOneofCase.None, session.Body.ContextCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void CreateObjectWithSessionToken()
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext()).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
var token = await pool.CreateSessionAsync(new PrmSessionCreate(int.MaxValue));
|
||||
|
||||
var createContainerParam = new PrmContainerCreate(
|
||||
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1))));
|
||||
|
||||
createContainerParam.XHeaders.Add("key1", "value1");
|
||||
|
||||
var containerId = await pool.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var bytes = GetRandomBytes(1024);
|
||||
|
||||
var param = new PrmObjectPut
|
||||
{
|
||||
Header = new FrostFsObjectHeader(
|
||||
containerId: containerId,
|
||||
type: FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("fileName", "test")]),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = false,
|
||||
SessionToken = token
|
||||
};
|
||||
|
||||
var objectId = await pool.PutObjectAsync(param).ConfigureAwait(true);
|
||||
|
||||
var @object = await pool.GetObjectAsync(new PrmObjectGet(containerId, objectId));
|
||||
|
||||
var downloadedBytes = new byte[@object.Header.PayloadLength];
|
||||
MemoryStream ms = new(downloadedBytes);
|
||||
|
||||
ReadOnlyMemory<byte>? chunk = null;
|
||||
while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
|
||||
{
|
||||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await Cleanup(pool);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void FilterTest()
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext()).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
var createContainerParam = new PrmContainerCreate(
|
||||
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1))))
|
||||
{
|
||||
WaitParams = lightWait
|
||||
};
|
||||
|
||||
var containerId = await pool.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var bytes = new byte[] { 1, 2, 3 };
|
||||
|
||||
var ParentHeader = new FrostFsObjectHeader(
|
||||
containerId: containerId,
|
||||
type: FrostFsObjectType.Regular)
|
||||
{
|
||||
PayloadLength = 3
|
||||
};
|
||||
|
||||
var param = new PrmObjectPut
|
||||
{
|
||||
Header = new FrostFsObjectHeader(
|
||||
containerId: containerId,
|
||||
type: FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("fileName", "test")],
|
||||
new FrostFsSplit()),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = false
|
||||
};
|
||||
|
||||
var objectId = await pool.PutObjectAsync(param);
|
||||
|
||||
var head = await pool.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId));
|
||||
|
||||
var ecdsaKey = this.keyString.LoadWif();
|
||||
|
||||
var networkInfo = await pool.GetNetmapSnapshotAsync();
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByContainerId(FrostFsMatchType.Equals, containerId));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByOwnerId(FrostFsMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey)));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterBySplitId(FrostFsMatchType.Equals, param.Header.Split!.SplitId));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test"));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByObjectId(FrostFsMatchType.Equals, objectId));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByVersion(FrostFsMatchType.Equals, networkInfo.NodeInfoCollection[0].Version));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByEpoch(FrostFsMatchType.Equals, networkInfo.Epoch));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByPayloadLength(FrostFsMatchType.Equals, 3));
|
||||
|
||||
var checkSum = CheckSum.CreateCheckSum(bytes);
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByPayloadHash(FrostFsMatchType.Equals, checkSum));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByPhysicallyStored());
|
||||
}
|
||||
|
||||
private static async Task CheckFilter(Pool pool, FrostFsContainerId containerId, IObjectFilter filter)
|
||||
{
|
||||
var resultObjectsCount = 0;
|
||||
|
||||
PrmObjectSearch searchParam = new(containerId) { Filters = [filter] };
|
||||
|
||||
await foreach (var objId in pool.SearchObjectsAsync(searchParam))
|
||||
{
|
||||
resultObjectsCount++;
|
||||
var objHeader = await pool.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objId));
|
||||
}
|
||||
|
||||
Assert.True(0 < resultObjectsCount, $"Filter for {filter.Key} doesn't work");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1)]
|
||||
[InlineData(3 * 1024 * 1024)] // exactly one chunk size - 3MB
|
||||
[InlineData(6 * 1024 * 1024 + 100)]
|
||||
public async void SimpleScenarioTest(int objectSize)
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext()).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
bool callbackInvoked = false;
|
||||
var ctx = new CallContext
|
||||
{
|
||||
// Timeout = TimeSpan.FromSeconds(20),
|
||||
Callback = new((CallStatistics cs) =>
|
||||
{
|
||||
callbackInvoked = true;
|
||||
Assert.True(cs.ElapsedMicroSeconds > 0);
|
||||
})
|
||||
};
|
||||
|
||||
var createContainerParam = new PrmContainerCreate(
|
||||
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1)), [new("testKey", "testValue")]))
|
||||
{
|
||||
Context = ctx
|
||||
};
|
||||
|
||||
var createdContainer = await pool.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var container = await pool.GetContainerAsync(new PrmContainerGet(createdContainer) { Context = ctx });
|
||||
Assert.NotNull(container);
|
||||
Assert.True(callbackInvoked);
|
||||
|
||||
var bytes = GetRandomBytes(objectSize);
|
||||
|
||||
var param = new PrmObjectPut
|
||||
{
|
||||
Header = new FrostFsObjectHeader(
|
||||
containerId: createdContainer,
|
||||
type: FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("fileName", "test")]),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = false,
|
||||
Context = new CallContext
|
||||
{
|
||||
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
|
||||
}
|
||||
};
|
||||
|
||||
var objectId = await pool.PutObjectAsync(param);
|
||||
|
||||
var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
|
||||
|
||||
bool hasObject = false;
|
||||
await foreach (var objId in pool.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] }))
|
||||
{
|
||||
hasObject = true;
|
||||
|
||||
var objHeader = await pool.GetObjectHeadAsync(new PrmObjectHeadGet(createdContainer, objectId));
|
||||
Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
|
||||
Assert.NotNull(objHeader.Attributes);
|
||||
Assert.Single(objHeader.Attributes!);
|
||||
Assert.Equal("fileName", objHeader.Attributes!.First().Key);
|
||||
Assert.Equal("test", objHeader.Attributes!.First().Value);
|
||||
}
|
||||
|
||||
Assert.True(hasObject);
|
||||
|
||||
var @object = await pool.GetObjectAsync(new PrmObjectGet(createdContainer, objectId));
|
||||
|
||||
var downloadedBytes = new byte[@object.Header.PayloadLength];
|
||||
MemoryStream ms = new(downloadedBytes);
|
||||
|
||||
ReadOnlyMemory<byte>? chunk = null;
|
||||
while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
|
||||
{
|
||||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
await foreach (var _ in pool.ListContainersAsync())
|
||||
{
|
||||
Assert.Fail("Containers exist");
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1)]
|
||||
[InlineData(3 * 1024 * 1024)] // exactly one chunk size - 3MB
|
||||
[InlineData(6 * 1024 * 1024 + 100)]
|
||||
public async void SimpleScenarioWithSessionTest(int objectSize)
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext()).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
var token = await pool.CreateSessionAsync(new PrmSessionCreate(int.MaxValue));
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
|
||||
};
|
||||
|
||||
var createContainerParam = new PrmContainerCreate(
|
||||
new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1))))
|
||||
{
|
||||
Context = ctx
|
||||
};
|
||||
|
||||
var container = await pool.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var containerInfo = await pool.GetContainerAsync(new PrmContainerGet(container) { Context = ctx });
|
||||
Assert.NotNull(containerInfo);
|
||||
|
||||
var bytes = GetRandomBytes(objectSize);
|
||||
|
||||
var param = new PrmObjectPut
|
||||
{
|
||||
Header = new FrostFsObjectHeader(
|
||||
containerId: container,
|
||||
type: FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("fileName", "test")]),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = false,
|
||||
Context = new CallContext
|
||||
{
|
||||
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
|
||||
},
|
||||
SessionToken = token
|
||||
};
|
||||
|
||||
var objectId = await pool.PutObjectAsync(param);
|
||||
|
||||
var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
|
||||
|
||||
bool hasObject = false;
|
||||
await foreach (var objId in pool.SearchObjectsAsync(new PrmObjectSearch(container) { Filters = [filter], SessionToken = token }))
|
||||
{
|
||||
hasObject = true;
|
||||
|
||||
var objHeader = await pool.GetObjectHeadAsync(new PrmObjectHeadGet(container, objectId) { SessionToken = token });
|
||||
Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
|
||||
Assert.NotNull(objHeader.Attributes);
|
||||
Assert.Single(objHeader.Attributes);
|
||||
Assert.Equal("fileName", objHeader.Attributes.First().Key);
|
||||
Assert.Equal("test", objHeader.Attributes.First().Value);
|
||||
}
|
||||
|
||||
Assert.True(hasObject);
|
||||
|
||||
var @object = await pool.GetObjectAsync(new PrmObjectGet(container, objectId) { SessionToken = token });
|
||||
|
||||
var downloadedBytes = new byte[@object.Header.PayloadLength];
|
||||
MemoryStream ms = new(downloadedBytes);
|
||||
|
||||
ReadOnlyMemory<byte>? chunk = null;
|
||||
while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
|
||||
{
|
||||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
await foreach (var _ in pool.ListContainersAsync())
|
||||
{
|
||||
Assert.Fail("Containers exist");
|
||||
}
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
var options = GetDefaultParams();
|
||||
|
||||
using var pool = new Pool(options);
|
||||
|
||||
var error = await pool.Dial(new CallContext()).ConfigureAwait(true);
|
||||
|
||||
Assert.Null(error);
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
var createContainerParam = new PrmContainerCreate(new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1))))
|
||||
{
|
||||
WaitParams = lightWait
|
||||
};
|
||||
|
||||
var containerId = await pool.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(10),
|
||||
Interceptors = new([new MetricsInterceptor()])
|
||||
};
|
||||
|
||||
var container = await pool.GetContainerAsync(new PrmContainerGet(containerId) { Context = ctx });
|
||||
|
||||
Assert.NotNull(container);
|
||||
|
||||
byte[] bytes = GetRandomBytes(objectSize);
|
||||
|
||||
var param = new PrmObjectPut
|
||||
{
|
||||
Header = new FrostFsObjectHeader(
|
||||
containerId: containerId,
|
||||
type: FrostFsObjectType.Regular,
|
||||
[new FrostFsAttributePair("fileName", "test")]),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = true
|
||||
};
|
||||
|
||||
var objectId = await pool.PutObjectAsync(param);
|
||||
|
||||
var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
|
||||
|
||||
bool hasObject = false;
|
||||
await foreach (var objId in pool.SearchObjectsAsync(new PrmObjectSearch(containerId, filter)))
|
||||
{
|
||||
hasObject = true;
|
||||
|
||||
var objHeader = await pool.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId));
|
||||
Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
|
||||
Assert.NotNull(objHeader.Attributes);
|
||||
Assert.Single(objHeader.Attributes);
|
||||
Assert.Equal("fileName", objHeader.Attributes[0].Key);
|
||||
Assert.Equal("test", objHeader.Attributes[0].Value);
|
||||
}
|
||||
|
||||
Assert.True(hasObject);
|
||||
|
||||
var @object = await pool.GetObjectAsync(new PrmObjectGet(containerId, objectId));
|
||||
|
||||
var downloadedBytes = new byte[@object.Header.PayloadLength];
|
||||
MemoryStream ms = new(downloadedBytes);
|
||||
|
||||
ReadOnlyMemory<byte>? chunk = null;
|
||||
while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
|
||||
{
|
||||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await CheckFilter(pool, containerId, new FilterByRootObject());
|
||||
|
||||
await Cleanup(pool);
|
||||
|
||||
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
|
||||
|
||||
IAsyncEnumerator<FrostFsContainerId>? enumerator = null;
|
||||
do
|
||||
{
|
||||
if (deadline <= DateTime.UtcNow)
|
||||
{
|
||||
Assert.Fail("Containers exist");
|
||||
break;
|
||||
}
|
||||
|
||||
enumerator = pool.ListContainersAsync().GetAsyncEnumerator();
|
||||
await Task.Delay(500);
|
||||
}
|
||||
while (await enumerator!.MoveNextAsync());
|
||||
}
|
||||
|
||||
private static byte[] GetRandomBytes(int size)
|
||||
{
|
||||
Random rnd = new();
|
||||
var bytes = new byte[size];
|
||||
rnd.NextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static IOptions<SingleOwnerClientSettings> GetSingleOwnerOptions(string key, string url)
|
||||
{
|
||||
return Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = url
|
||||
});
|
||||
}
|
||||
|
||||
private static IOptions<ClientSettings> GetOptions(string url)
|
||||
{
|
||||
return Options.Create(new ClientSettings
|
||||
{
|
||||
Host = url
|
||||
});
|
||||
}
|
||||
|
||||
static async Task Cleanup(Pool pool)
|
||||
{
|
||||
await foreach (var cid in pool.ListContainersAsync())
|
||||
{
|
||||
await pool.DeleteContainerAsync(new PrmContainerDelete(cid) { WaitParams = lightWait }).ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +1,11 @@
|
|||
using System.Security.Cryptography;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class SessionTestsBase
|
||||
{
|
||||
protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
|
||||
|
||||
protected ECDsa ECDsaKey { get; set; }
|
||||
protected FrostFsOwner OwnerId { get; set; }
|
||||
protected SessionMocker Mocker { get; set; }
|
||||
|
||||
protected SessionTestsBase()
|
||||
{
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
ECDsaKey = key.LoadWif();
|
||||
OwnerId = FrostFsOwner.FromKey(ECDsaKey);
|
||||
|
||||
Mocker = new SessionMocker(this.key)
|
||||
{
|
||||
PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),
|
||||
Version = new FrostFsVersion(2, 13)
|
||||
};
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return ClientV2.FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
new NetworkMocker(this.key).GetMock().Object,
|
||||
Mocker.GetMock().Object,
|
||||
new ContainerMocker(this.key).GetMock().Object,
|
||||
new ObjectMocker(this.key).GetMock().Object);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
public class SessionTest : SessionTestsBase
|
||||
{
|
||||
[Theory]
|
||||
|
@ -64,7 +19,7 @@ public class SessionTest : SessionTestsBase
|
|||
if (useContext)
|
||||
{
|
||||
param.XHeaders.Add("headerKey1", "headerValue1");
|
||||
param.Context = new Context
|
||||
param.Context = new CallContext
|
||||
{
|
||||
CancellationToken = Mocker.CancellationTokenSource.Token,
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
|
@ -101,7 +56,6 @@ public class SessionTest : SessionTestsBase
|
|||
Assert.NotNull(Mocker.CreateSessionRequest.MetaHeader);
|
||||
Assert.Equal(Mocker.Version.ToMessage(), Mocker.CreateSessionRequest.MetaHeader.Version);
|
||||
|
||||
|
||||
Assert.Null(Mocker.Metadata);
|
||||
|
||||
if (useContext)
|
||||
|
|
48
src/FrostFS.SDK.Tests/SessionTestsBase.cs
Normal file
48
src/FrostFS.SDK.Tests/SessionTestsBase.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System.Security.Cryptography;
|
||||
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FrostFS.SDK.Tests;
|
||||
|
||||
public abstract class SessionTestsBase
|
||||
{
|
||||
internal readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||
|
||||
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||
|
||||
protected ECDsa ECDsaKey { get; set; }
|
||||
protected FrostFsOwner OwnerId { get; set; }
|
||||
protected SessionMocker Mocker { get; set; }
|
||||
|
||||
protected SessionTestsBase()
|
||||
{
|
||||
Settings = Options.Create(new SingleOwnerClientSettings
|
||||
{
|
||||
Key = key,
|
||||
Host = "http://localhost:8080"
|
||||
});
|
||||
|
||||
ECDsaKey = key.LoadWif();
|
||||
OwnerId = FrostFsOwner.FromKey(ECDsaKey);
|
||||
|
||||
Mocker = new SessionMocker(this.key)
|
||||
{
|
||||
PlacementPolicy = new FrostFsPlacementPolicy(true, new FrostFsReplica(1)),
|
||||
Version = new FrostFsVersion(2, 13)
|
||||
};
|
||||
}
|
||||
|
||||
protected IFrostFSClient GetClient()
|
||||
{
|
||||
return ClientV2.FrostFSClient.GetTestInstance(
|
||||
Settings,
|
||||
null,
|
||||
new NetworkMocker(this.key).GetMock().Object,
|
||||
Mocker.GetMock().Object,
|
||||
new ContainerMocker(this.key).GetMock().Object,
|
||||
new ObjectMocker(this.key).GetMock().Object);
|
||||
}
|
||||
}
|
|
@ -1,24 +1,42 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using FrostFS.SDK.ClientV2;
|
||||
using FrostFS.SDK.ClientV2.Interfaces;
|
||||
using FrostFS.SDK.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using static FrostFS.Session.SessionToken.Types.Body;
|
||||
using FrostFS.SDK.ClientV2;
|
||||
|
||||
namespace FrostFS.SDK.SmokeTests;
|
||||
|
||||
public class SmokeTests : SmokeTestsBase
|
||||
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
|
||||
[SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "No secure purpose")]
|
||||
public class SmokeClientTests : SmokeTestsBase
|
||||
{
|
||||
private static readonly PrmWait lightWait = new(100, 1);
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async void AccountTest(bool isSingleOnwerClient)
|
||||
{
|
||||
using var client = isSingleOnwerClient
|
||||
? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url))
|
||||
: FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
|
||||
PrmBalance? prm = isSingleOnwerClient ? default : new() { Context = Ctx };
|
||||
|
||||
var result = await client.GetBalanceAsync(prm);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public async void NetworkMapTest(bool isSingleOnwerClient)
|
||||
{
|
||||
using var client = isSingleOnwerClient ? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url)) : FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
using var client = isSingleOnwerClient ? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url)) : FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
|
||||
PrmNetmapSnapshot? prm = isSingleOnwerClient ? default : new() { Context = Ctx };
|
||||
var result = await client.GetNetmapSnapshotAsync(prm);
|
||||
|
@ -41,7 +59,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[InlineData(true)]
|
||||
public async void NodeInfoTest(bool isSingleOnwerClient)
|
||||
{
|
||||
using var client = isSingleOnwerClient ? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url)) : FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
using var client = isSingleOnwerClient ? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url)) : FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
|
||||
PrmNodeInfo? prm = isSingleOnwerClient ? default : new() { Context = Ctx };
|
||||
|
||||
|
@ -56,14 +74,14 @@ public class SmokeTests : SmokeTestsBase
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async void NodeInfo_Statistics_Test()
|
||||
public async void NodeInfoStatisticsTest()
|
||||
{
|
||||
var ctx = new Context
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Callback = (cs) => Console.WriteLine($"{cs.MethodName} took {cs.ElapsedMicroSeconds} microseconds")
|
||||
};
|
||||
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
var result = await client.GetNodeInfoAsync();
|
||||
}
|
||||
|
@ -73,7 +91,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[InlineData(true)]
|
||||
public async void GetSessionTest(bool isSingleOnwerClient)
|
||||
{
|
||||
using var client = isSingleOnwerClient ? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url)) : FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
using var client = isSingleOnwerClient ? FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url)) : FrostFSClient.GetInstance(GetOptions(this.url));
|
||||
|
||||
PrmSessionCreate? prm = isSingleOnwerClient ? new PrmSessionCreate(100) : new PrmSessionCreate(100) { Context = Ctx };
|
||||
|
||||
|
@ -81,7 +99,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
var session = new Session.SessionToken().Deserialize(token.Token);
|
||||
|
||||
var ownerHash = Base58.Decode(OwnerId.Value);
|
||||
var ownerHash = Base58.Decode(OwnerId!.Value);
|
||||
|
||||
Assert.NotNull(session);
|
||||
Assert.Null(session.Body.Container);
|
||||
|
@ -96,7 +114,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[Fact]
|
||||
public async void CreateObjectWithSessionToken()
|
||||
{
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
|
@ -144,11 +162,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[Fact]
|
||||
public async void FilterTest()
|
||||
{
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||
|
||||
//var prm = new PrmApeChainList(new FrostFsChainTarget(FrostFsTargetType.Namespace, "root"));
|
||||
|
||||
//var chains = await client.ListChainAsync(prm);
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
|
@ -184,7 +198,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
var head = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId));
|
||||
|
||||
var ecdsaKey = this.key.LoadWif();
|
||||
var ecdsaKey = this.keyString.LoadWif();
|
||||
|
||||
var networkInfo = await client.GetNetmapSnapshotAsync();
|
||||
|
||||
|
@ -192,7 +206,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
await CheckFilter(client, containerId, new FilterByOwnerId(FrostFsMatchType.Equals, FrostFsOwner.FromKey(ecdsaKey)));
|
||||
|
||||
await CheckFilter(client, containerId, new FilterBySplitId(FrostFsMatchType.Equals, param.Header.Split.SplitId));
|
||||
await CheckFilter(client, containerId, new FilterBySplitId(FrostFsMatchType.Equals, param.Header.Split!.SplitId));
|
||||
|
||||
await CheckFilter(client, containerId, new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test"));
|
||||
|
||||
|
@ -232,12 +246,12 @@ public class SmokeTests : SmokeTestsBase
|
|||
[InlineData(6 * 1024 * 1024 + 100)]
|
||||
public async void SimpleScenarioTest(int objectSize)
|
||||
{
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
bool callbackInvoked = false;
|
||||
var ctx = new Context
|
||||
var ctx = new CallContext
|
||||
{
|
||||
// Timeout = TimeSpan.FromSeconds(20),
|
||||
Callback = new((CallStatistics cs) =>
|
||||
|
@ -269,7 +283,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[new FrostFsAttributePair("fileName", "test")]),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = false,
|
||||
Context = new Context
|
||||
Context = new CallContext
|
||||
{
|
||||
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
|
||||
}
|
||||
|
@ -286,6 +300,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(createdContainer, objectId));
|
||||
Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
|
||||
Assert.NotNull(objHeader.Attributes);
|
||||
Assert.Single(objHeader.Attributes);
|
||||
Assert.Equal("fileName", objHeader.Attributes.First().Key);
|
||||
Assert.Equal("test", objHeader.Attributes.First().Value);
|
||||
|
@ -304,7 +319,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes));
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
|
@ -320,13 +335,13 @@ public class SmokeTests : SmokeTestsBase
|
|||
[InlineData(6 * 1024 * 1024 + 100)]
|
||||
public async void SimpleScenarioWithSessionTest(int objectSize)
|
||||
{
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
var ctx = new Context
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(20),
|
||||
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
|
||||
|
@ -353,7 +368,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[new FrostFsAttributePair("fileName", "test")]),
|
||||
Payload = new MemoryStream(bytes),
|
||||
ClientCut = false,
|
||||
Context = new Context
|
||||
Context = new CallContext
|
||||
{
|
||||
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
|
||||
},
|
||||
|
@ -371,6 +386,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(container, objectId) { SessionToken = token });
|
||||
Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
|
||||
Assert.NotNull(objHeader.Attributes);
|
||||
Assert.Single(objHeader.Attributes);
|
||||
Assert.Equal("fileName", objHeader.Attributes.First().Key);
|
||||
Assert.Equal("test", objHeader.Attributes.First().Value);
|
||||
|
@ -389,7 +405,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes));
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
|
@ -408,7 +424,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
[InlineData(200)]
|
||||
public async void ClientCutScenarioTest(int objectSize)
|
||||
{
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||
using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
|
||||
|
||||
await Cleanup(client);
|
||||
|
||||
|
@ -419,7 +435,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var ctx = new Context
|
||||
var ctx = new CallContext
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(10),
|
||||
Interceptors = new([new MetricsInterceptor()])
|
||||
|
@ -452,6 +468,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
|
||||
var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(containerId, objectId));
|
||||
Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
|
||||
Assert.NotNull(objHeader.Attributes);
|
||||
Assert.Single(objHeader.Attributes);
|
||||
Assert.Equal("fileName", objHeader.Attributes[0].Key);
|
||||
Assert.Equal("test", objHeader.Attributes[0].Value);
|
||||
|
@ -470,7 +487,7 @@ public class SmokeTests : SmokeTestsBase
|
|||
ms.Write(chunk.Value.Span);
|
||||
}
|
||||
|
||||
Assert.Equal(MD5.HashData(bytes), MD5.HashData(downloadedBytes));
|
||||
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
|
||||
|
||||
await CheckFilter(client, containerId, new FilterByRootObject());
|
||||
|
|
@ -7,24 +7,24 @@ namespace FrostFS.SDK.SmokeTests;
|
|||
|
||||
public abstract class SmokeTestsBase
|
||||
{
|
||||
protected readonly string key = "KzPXA6669m2pf18XmUdoR8MnP1pi1PMmefiFujStVFnv7WR5SRmK";
|
||||
|
||||
protected readonly string url = "http://172.23.32.4:8080";
|
||||
internal readonly string keyString = "KzPXA6669m2pf18XmUdoR8MnP1pi1PMmefiFujStVFnv7WR5SRmK";
|
||||
|
||||
protected ECDsa Key { get; }
|
||||
internal readonly string url = "http://172.23.32.4:8080";
|
||||
|
||||
protected FrostFsOwner OwnerId { get; }
|
||||
protected ECDsa? Key { get; }
|
||||
|
||||
protected FrostFsVersion Version { get; }
|
||||
protected FrostFsOwner? OwnerId { get; }
|
||||
|
||||
protected Context Ctx { get; }
|
||||
protected FrostFsVersion? Version { get; }
|
||||
|
||||
protected CallContext? Ctx { get; }
|
||||
|
||||
protected SmokeTestsBase()
|
||||
{
|
||||
Key = key.LoadWif();
|
||||
Key = keyString.LoadWif();
|
||||
OwnerId = FrostFsOwner.FromKey(Key);
|
||||
Version = new FrostFsVersion(2, 13);
|
||||
|
||||
Ctx = new Context { Key = Key, OwnerId = OwnerId, Version = Version };
|
||||
Ctx = new CallContext { Key = Key, OwnerId = OwnerId, Version = Version };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue