308 lines
11 KiB
C#
308 lines
11 KiB
C#
using System.Collections.ObjectModel;
|
|
using System.Security.Cryptography;
|
|
|
|
using FrostFS.Object;
|
|
using FrostFS.SDK.Client;
|
|
using FrostFS.SDK.Client.Mappers.GRPC;
|
|
|
|
using Google.Protobuf;
|
|
|
|
using Grpc.Core;
|
|
|
|
using Moq;
|
|
|
|
namespace FrostFS.SDK.Tests;
|
|
|
|
public class ObjectMocker(string key) : ObjectServiceBase(key)
|
|
{
|
|
public FrostFsObjectId? ObjectId { get; set; }
|
|
|
|
public FrostFsObjectHeader? ObjectHeader { get; set; }
|
|
|
|
public Header? HeadResponse { get; set; }
|
|
|
|
public Collection<byte[]>? ResultObjectIds { get; } = [];
|
|
|
|
public ClientStreamWriter? ClientStreamWriter { get; } = new();
|
|
|
|
public PatchStreamWriter? PatchStreamWriter { get; } = new();
|
|
|
|
public Collection<PutSingleRequest> PutSingleRequests { get; } = [];
|
|
|
|
public Collection<DeleteRequest> DeleteRequests { get; } = [];
|
|
|
|
public Collection<HeadRequest> HeadRequests { get; } = [];
|
|
|
|
public byte[] RangeResponse { get; set; } = [];
|
|
|
|
public GetRangeRequest? GetRangeRequest { get; set; }
|
|
|
|
public GetRangeHashRequest? GetRangeHashRequest { get; set; }
|
|
|
|
public Collection<ByteString> RangeHashResponses { get; } = [];
|
|
|
|
public Action? Callback;
|
|
|
|
public override Mock<ObjectService.ObjectServiceClient> GetMock()
|
|
{
|
|
var mock = new Mock<ObjectService.ObjectServiceClient>();
|
|
|
|
if (ObjectHeader != null)
|
|
{
|
|
mock.Setup(x => x.Get(
|
|
It.IsAny<GetRequest>(),
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((GetRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
Verifier.CheckRequest(r);
|
|
|
|
return new AsyncServerStreamingCall<GetResponse>(
|
|
new AsyncStreamReaderMock(StringKey, ObjectHeader),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
|
|
HeadResponse ??= new Header
|
|
{
|
|
CreationEpoch = 99,
|
|
ContainerId = ObjectHeader.ContainerId.ToMessage(),
|
|
ObjectType = ObjectType.Regular,
|
|
OwnerId = ObjectHeader.OwnerId!.ToMessage(),
|
|
PayloadLength = 1,
|
|
PayloadHash = new Refs.Checksum { Type = Refs.ChecksumType.Sha256, Sum = ByteString.CopyFrom(SHA256.HashData([0xff])) },
|
|
Version = ObjectHeader.Version!.ToMessage()
|
|
};
|
|
|
|
HeadResponse headResponse = new()
|
|
{
|
|
Body = new HeadResponse.Types.Body
|
|
{
|
|
Header = new HeaderWithSignature
|
|
{
|
|
Header = HeadResponse
|
|
}
|
|
},
|
|
MetaHeader = ResponseMetaHeader
|
|
};
|
|
|
|
headResponse.Body.Header.Header.Attributes.Add(new Header.Types.Attribute { Key = "k", Value = "v" });
|
|
|
|
headResponse.Body.Header.Signature = new Refs.Signature
|
|
{
|
|
Key = Key.PublicKeyProto,
|
|
Sign = Key.ECDsaKey.SignData(headResponse.Body.Header.ToByteArray()),
|
|
};
|
|
|
|
headResponse.VerifyHeader = GetResponseVerificationHeader(headResponse);
|
|
|
|
mock.Setup(x => x.HeadAsync(
|
|
It.IsAny<HeadRequest>(),
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((HeadRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
Verifier.CheckRequest(r);
|
|
|
|
HeadRequests.Add(r);
|
|
|
|
return new AsyncUnaryCall<HeadResponse>(
|
|
Task.FromResult(headResponse),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
|
|
}
|
|
|
|
if (ResultObjectIds != null && ResultObjectIds.Count > 0)
|
|
{
|
|
PutResponse putResponse = new()
|
|
{
|
|
Body = new PutResponse.Types.Body
|
|
{
|
|
ObjectId = new Refs.ObjectID
|
|
{
|
|
Value = ByteString.CopyFrom(ResultObjectIds.ElementAt(0))
|
|
}
|
|
},
|
|
MetaHeader = ResponseMetaHeader,
|
|
};
|
|
|
|
putResponse.VerifyHeader = GetResponseVerificationHeader(putResponse);
|
|
|
|
mock.Setup(x => x.Put(
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
return new AsyncClientStreamingCall<PutRequest, PutResponse>(
|
|
ClientStreamWriter!,
|
|
Task.FromResult(putResponse),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
}
|
|
|
|
PutSingleResponse putSingleResponse = new()
|
|
{
|
|
Body = new PutSingleResponse.Types.Body(),
|
|
MetaHeader = ResponseMetaHeader,
|
|
};
|
|
|
|
putSingleResponse.VerifyHeader = GetResponseVerificationHeader(putSingleResponse);
|
|
|
|
mock.Setup(x => x.PutSingleAsync(
|
|
It.IsAny<PutSingleRequest>(),
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((PutSingleRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
Callback?.Invoke();
|
|
Verifier.CheckRequest(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),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
|
|
if (ObjectId != null)
|
|
{
|
|
DeleteResponse deleteResponse = new()
|
|
{
|
|
Body = new DeleteResponse.Types.Body
|
|
{
|
|
Tombstone = new Refs.Address
|
|
{
|
|
ContainerId = ObjectHeader!.ContainerId.ToMessage(),
|
|
ObjectId = ObjectId.ToMessage()
|
|
}
|
|
},
|
|
MetaHeader = ResponseMetaHeader
|
|
};
|
|
|
|
deleteResponse.VerifyHeader = GetResponseVerificationHeader(deleteResponse);
|
|
|
|
mock.Setup(x => x.DeleteAsync(
|
|
It.IsAny<DeleteRequest>(),
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((DeleteRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
Verifier.CheckRequest(r);
|
|
|
|
DeleteRequests.Add(r);
|
|
|
|
return new AsyncUnaryCall<DeleteResponse>(
|
|
Task.FromResult(deleteResponse),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
}
|
|
|
|
mock.Setup(x => x.GetRange(
|
|
It.IsAny<GetRangeRequest>(),
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((GetRangeRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
Verifier.CheckRequest(r);
|
|
|
|
GetRangeRequest = r;
|
|
|
|
return new AsyncServerStreamingCall<GetRangeResponse>(
|
|
new AsyncStreamRangeReaderMock(StringKey, RangeResponse),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
|
|
mock.Setup(x => x.GetRangeHashAsync(
|
|
It.IsAny<GetRangeHashRequest>(),
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((GetRangeHashRequest r, Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
Verifier.CheckRequest(r);
|
|
|
|
GetRangeHashRequest = r;
|
|
|
|
var response = new GetRangeHashResponse
|
|
{
|
|
Body = new GetRangeHashResponse.Types.Body(),
|
|
MetaHeader = ResponseMetaHeader
|
|
};
|
|
|
|
if (RangeHashResponses != null)
|
|
{
|
|
foreach (var hash in RangeHashResponses)
|
|
{
|
|
response.Body.HashList.Add(hash);
|
|
}
|
|
}
|
|
|
|
response.VerifyHeader = GetResponseVerificationHeader(response);
|
|
|
|
return new AsyncUnaryCall<GetRangeHashResponse>(
|
|
Task.FromResult(response),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
|
|
|
|
mock.Setup(x => x.Patch(
|
|
It.IsAny<Metadata>(),
|
|
It.IsAny<DateTime?>(),
|
|
It.IsAny<CancellationToken>()))
|
|
.Returns((Metadata m, DateTime? dt, CancellationToken ct) =>
|
|
{
|
|
var patchResponse = new PatchResponse
|
|
{
|
|
Body = new PatchResponse.Types.Body
|
|
{
|
|
ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom(SHA256.HashData([1, 2, 3])) },
|
|
},
|
|
MetaHeader = ResponseMetaHeader
|
|
};
|
|
|
|
patchResponse.VerifyHeader = GetResponseVerificationHeader(patchResponse);
|
|
|
|
return new AsyncClientStreamingCall<PatchRequest, PatchResponse>(
|
|
PatchStreamWriter!,
|
|
Task.FromResult(patchResponse),
|
|
Task.FromResult(ResponseMetaData),
|
|
() => new Grpc.Core.Status(StatusCode.OK, string.Empty),
|
|
() => ResponseMetaData,
|
|
() => { });
|
|
});
|
|
|
|
return mock;
|
|
}
|
|
}
|
|
|