mirror of https://github.com/dapr/dotnet-sdk.git
337 lines
13 KiB
C#
337 lines
13 KiB
C#
// ------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
// ------------------------------------------------------------
|
|
|
|
namespace Dapr.Client.Test
|
|
{
|
|
using System;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using Dapr.Client.Autogen.Grpc;
|
|
using FluentAssertions;
|
|
using Grpc.Core;
|
|
using Grpc.Net.Client;
|
|
using Xunit;
|
|
|
|
public class StateHttpClientTest
|
|
{
|
|
private const string DaprDefaultEndpoint = "127.0.0.1";
|
|
|
|
[Fact]
|
|
public async Task GetStateAsync_CanReadState()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.GetStateAsync<Widget>("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
var data = new Widget() { Size = "small", Color = "yellow", };
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
SendResponseWithState(data, entry);
|
|
|
|
// Get response and validate
|
|
var state = await task;
|
|
state.Size.Should().Be("small");
|
|
state.Color.Should().Be("yellow");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetStateAsync_CanReadEmptyState_ReturnsDefault()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.GetStateAsync<Widget>("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
SendResponseWithState<Widget>(null, entry);
|
|
|
|
// Get response and validate
|
|
var state = await task;
|
|
state.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetStateAsync_ThrowsForNonSuccess()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
// Create Response & Respond
|
|
var task = daprClient.GetStateAsync<Widget>("testStore", "test");
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
var response = GrpcUtils.CreateResponse(HttpStatusCode.NotAcceptable);
|
|
entry.Completion.SetResult(response);
|
|
|
|
await FluentActions.Awaiting(async () => await task).Should().ThrowAsync<RpcException>();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SaveStateAsync_CanSaveState()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var widget = new Widget() { Size = "small", Color = "yellow", };
|
|
var task = daprClient.SaveStateAsync("testStore", "test", widget);
|
|
|
|
|
|
// Get Request and validate
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<SaveStateEnvelope>(entry.Request);
|
|
|
|
envelope.StoreName.Should().Be("testStore");
|
|
envelope.Requests.Count.Should().Be(1);
|
|
var request = envelope.Requests[0];
|
|
request.Key.Should().Be("test");
|
|
|
|
var stateJson = request.Value.Value.ToStringUtf8();
|
|
var stateFromRequest = JsonSerializer.Deserialize<Widget>(stateJson);
|
|
stateFromRequest.Size.Should().Be(widget.Size);
|
|
stateFromRequest.Color.Should().Be(widget.Color);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SaveStateAsync_CanClearState()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.SaveStateAsync<object>("testStore", "test", null);
|
|
|
|
// Get Request and validate
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<SaveStateEnvelope>(entry.Request);
|
|
|
|
envelope.StoreName.Should().Be("testStore");
|
|
envelope.Requests.Count.Should().Be(1);
|
|
var request = envelope.Requests[0];
|
|
request.Key.Should().Be("test");
|
|
|
|
request.Value.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SetStateAsync_ThrowsForNonSuccess()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var widget = new Widget() { Size = "small", Color = "yellow", };
|
|
var task = daprClient.SaveStateAsync("testStore", "test", widget);
|
|
|
|
// Create Response & Respond
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
var response = GrpcUtils.CreateResponse(HttpStatusCode.NotAcceptable);
|
|
entry.Completion.SetResult(response);
|
|
|
|
await FluentActions.Awaiting(async () => await task).Should().ThrowAsync<RpcException>();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DeleteStateAsync_CanDeleteState()
|
|
{
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.DeleteStateAsync("testStore", "test");
|
|
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<DeleteStateEnvelope>(entry.Request);
|
|
envelope.StoreName.Should().Be("testStore");
|
|
envelope.Key.Should().Be("test");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DeleteStateAsync_ThrowsForNonSuccess()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.DeleteStateAsync("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
var response = GrpcUtils.CreateResponse(HttpStatusCode.NotAcceptable);
|
|
entry.Completion.SetResult(response);
|
|
|
|
await FluentActions.Awaiting(async () => await task).Should().ThrowAsync<RpcException>();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetStateEntryAsync_CanReadState()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.GetStateEntryAsync<Widget>("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
var data = new Widget() { Size = "small", Color = "yellow", };
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
SendResponseWithState(data, entry);
|
|
|
|
// Get response and validate
|
|
var state = await task;
|
|
state.Value.Size.Should().Be("small");
|
|
state.Value.Color.Should().Be("yellow");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetStateEntryAsync_CanReadEmptyState_ReturnsDefault()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.GetStateEntryAsync<Widget>("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
SendResponseWithState<Widget>(null, entry);
|
|
|
|
var state = await task;
|
|
state.Key.Should().Be("test");
|
|
state.Value.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetStateEntryAsync_CanSaveState()
|
|
{
|
|
// Configure Client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.GetStateEntryAsync<Widget>("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
var data = new Widget() { Size = "small", Color = "yellow", };
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
SendResponseWithState(data, entry);
|
|
|
|
var state = await task;
|
|
state.Key.Should().Be("test");
|
|
state.Value.Size.Should().Be("small");
|
|
state.Value.Color.Should().Be("yellow");
|
|
|
|
// Modify the state and save it
|
|
state.Value.Color = "green";
|
|
var task2 = state.SaveAsync();
|
|
|
|
// Get Request and validate
|
|
httpClient.Requests.TryDequeue(out entry).Should().BeTrue();
|
|
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<SaveStateEnvelope>(entry.Request);
|
|
|
|
envelope.StoreName.Should().Be("testStore");
|
|
envelope.Requests.Count.Should().Be(1);
|
|
var request = envelope.Requests[0];
|
|
request.Key.Should().Be("test");
|
|
|
|
var stateJson = request.Value.Value.ToStringUtf8();
|
|
var stateFromRequest = JsonSerializer.Deserialize<Widget>(stateJson);
|
|
stateFromRequest.Size.Should().Be("small");
|
|
stateFromRequest.Color.Should().Be("green");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetStateEntryAsync_CanDeleteState()
|
|
{
|
|
// Configure client
|
|
var httpClient = new TestHttpClient();
|
|
var daprClient = new DaprClientBuilder()
|
|
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
|
.Build();
|
|
|
|
var task = daprClient.GetStateEntryAsync<Widget>("testStore", "test");
|
|
|
|
// Create Response & Respond
|
|
var data = new Widget() { Size = "small", Color = "yellow", };
|
|
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
|
SendResponseWithState(data, entry);
|
|
|
|
var state = await task;
|
|
state.Key.Should().Be("test");
|
|
state.Value.Size.Should().Be("small");
|
|
state.Value.Color.Should().Be("yellow");
|
|
|
|
state.Value.Color = "green";
|
|
var task2 = state.DeleteAsync();
|
|
|
|
// Get Request and validate
|
|
httpClient.Requests.TryDequeue(out entry).Should().BeTrue();
|
|
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<DeleteStateEnvelope>(entry.Request);
|
|
envelope.StoreName.Should().Be("testStore");
|
|
envelope.Key.Should().Be("test");
|
|
}
|
|
|
|
private static string GetStateUrl(int port, string storeName, string key)
|
|
{
|
|
return $"http://{DaprDefaultEndpoint}:{port}/v1.0/state/{storeName}/{key}";
|
|
}
|
|
|
|
private static string SaveStateUrl(int port, string storeName)
|
|
{
|
|
return $"http://{DaprDefaultEndpoint}:{port}/v1.0/state/{storeName}";
|
|
}
|
|
|
|
private static string DeleteStateUrl(int port, string storeName, string key)
|
|
{
|
|
return $"http://{DaprDefaultEndpoint}:{port}/v1.0/state/{storeName}/{key}";
|
|
}
|
|
|
|
private async void SendResponseWithState<T>(T state, TestHttpClient.Entry entry)
|
|
{
|
|
var stateAny = await ProtobufUtils.ConvertToAnyAsync(state);
|
|
var stateResponse = new GetStateResponseEnvelope();
|
|
stateResponse.Data = stateAny;
|
|
stateResponse.Etag = "test";
|
|
|
|
var streamContent = await GrpcUtils.CreateResponseContent(stateResponse);
|
|
var response = GrpcUtils.CreateResponse(HttpStatusCode.OK, streamContent);
|
|
entry.Completion.SetResult(response);
|
|
}
|
|
|
|
private class Widget
|
|
{
|
|
public string Size { get; set; }
|
|
|
|
public string Color { get; set; }
|
|
}
|
|
}
|
|
}
|