1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using Microsoft.DevTunnels.Contracts;
using Microsoft.DevTunnels.Management;
using Xunit;
namespace Microsoft.DevTunnels.Test;
public class TunnelManagementClientTests
{
private const string TunnelId = "tnnl0001";
private const string ClusterId = "usw2";
private readonly CancellationToken timeout = System.Diagnostics.Debugger.IsAttached ? default : new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token;
private readonly ProductInfoHeaderValue userAgent = TunnelUserAgent.GetUserAgent(typeof(TunnelManagementClientTests).Assembly);
private readonly Uri tunnelServiceUri = new Uri("https://localhost:3000/");
[Fact]
public async Task HttpRequestOptions()
{
var options = new TunnelRequestOptions()
{
HttpRequestOptions = new Dictionary<string, object>
{
{ "foo", "bar" },
{ "bazz", 100 },
}
};
var tunnel = new Tunnel
{
TunnelId = TunnelId,
ClusterId = ClusterId,
};
var handler = new MockHttpMessageHandler(
(message, ct) =>
{
Assert.True(message.Options.TryGetValue(new HttpRequestOptionsKey<string>("foo"), out string strValue) && strValue == "bar");
Assert.True(message.Options.TryGetValue(new HttpRequestOptionsKey<int>("bazz"), out int intValue) && intValue == 100);
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = JsonContent.Create(tunnel);
return Task.FromResult(result);
});
var client = new TunnelManagementClient(this.userAgent, null, this.tunnelServiceUri, handler);
tunnel = await client.GetTunnelAsync(tunnel, options, this.timeout);
Assert.NotNull(tunnel);
Assert.Equal(TunnelId, tunnel.TunnelId);
Assert.Equal(ClusterId, tunnel.ClusterId);
}
[Fact]
public async Task PreserveAccessTokens()
{
var requestTunnel = new Tunnel
{
TunnelId = TunnelId,
ClusterId = ClusterId,
AccessTokens = new Dictionary<string, string>
{
[TunnelAccessScopes.Manage] = "manage-token-1",
[TunnelAccessScopes.Connect] = "connect-token-1",
},
};
var handler = new MockHttpMessageHandler(
(message, ct) =>
{
var responseTunnel = new Tunnel
{
TunnelId = TunnelId,
ClusterId = ClusterId,
AccessTokens = new Dictionary<string, string>
{
[TunnelAccessScopes.Manage] = "manage-token-2",
[TunnelAccessScopes.Host] = "host-token-2",
},
};
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = JsonContent.Create(responseTunnel);
return Task.FromResult(result);
});
var client = new TunnelManagementClient(this.userAgent, null, this.tunnelServiceUri, handler);
var resultTunnel = await client.GetTunnelAsync(requestTunnel, options: null, this.timeout);
Assert.NotNull(resultTunnel);
Assert.NotNull(resultTunnel.AccessTokens);
// Tokens in the request tunnel should be preserved, unless updated by the response.
Assert.Collection(
resultTunnel.AccessTokens.OrderBy((item) => item.Key),
(item) => Assert.Equal(new KeyValuePair<string, string>(
TunnelAccessScopes.Connect, "connect-token-1"), item), // preserved
(item) => Assert.Equal(new KeyValuePair<string, string>(
TunnelAccessScopes.Host, "host-token-2"), item), // added
(item) => Assert.Equal(new KeyValuePair<string, string>(
TunnelAccessScopes.Manage, "manage-token-2"), item)); // updated
}
private sealed class MockHttpMessageHandler : DelegatingHandler
{
private readonly Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> handler;
public MockHttpMessageHandler(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> handler)
: base(new HttpClientHandler
{
AllowAutoRedirect = false,
UseDefaultCredentials = false,
})
{
this.handler = Requires.NotNull(handler, nameof(handler));
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) =>
this.handler(request, cancellationToken);
}
}
|