Skip to content

Commit 5afa56b

Browse files
committed
diagnose: add http fallback uri
Currently, failure to access http://example.com causes failure of the Networking Diagnostic portion of the diagnose command. To improve the experience for users who are unable to access http://example.com, this change: 1. Adds a fallback URI - if accessing http://example.com throws an exception, we now try http://httpforever.com. 2. Prints a warning when either the primary or both the primary and fallback uris throw an exception (instead of failing the Networking Diagnostic).
1 parent 0d70623 commit 5afa56b

File tree

3 files changed

+110
-3
lines changed

3 files changed

+110
-3
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using System.Net.Http;
3+
using System.Security.AccessControl;
4+
using System.Text;
5+
using GitCredentialManager.Diagnostics;
6+
using GitCredentialManager.Tests.Objects;
7+
using Xunit;
8+
9+
namespace Core.Tests.Commands;
10+
11+
public class DiagnoseCommandTests
12+
{
13+
[Fact]
14+
public void NetworkingDiagnostic_SendHttpRequest_Primary_OK()
15+
{
16+
var primaryUriString = "http://example.com";
17+
var sb = new StringBuilder();
18+
var context = new TestCommandContext();
19+
var networkingDiagnostic = new NetworkingDiagnostic(context);
20+
var primaryUri = new Uri(primaryUriString);
21+
var httpHandler = new TestHttpMessageHandler();
22+
var httpResponse = new HttpResponseMessage();
23+
var expected = $"Sending HEAD request to {primaryUriString}... OK{Environment.NewLine}";
24+
25+
httpHandler.Setup(HttpMethod.Head, primaryUri, httpResponse);
26+
27+
networkingDiagnostic.SendHttpRequest(sb, new HttpClient(httpHandler));
28+
29+
httpHandler.AssertRequest(HttpMethod.Head, primaryUri, expectedNumberOfCalls: 1);
30+
Assert.Contains(expected, sb.ToString());
31+
}
32+
33+
[Fact]
34+
public void NetworkingDiagnostic_SendHttpRequest_Backup_OK()
35+
{
36+
var primaryUriString = "http://example.com";
37+
var backupUriString = "http://httpforever.com";
38+
var sb = new StringBuilder();
39+
var context = new TestCommandContext();
40+
var networkingDiagnostic = new NetworkingDiagnostic(context);
41+
var primaryUri = new Uri(primaryUriString);
42+
var backupUri = new Uri(backupUriString);
43+
var httpHandler = new TestHttpMessageHandler { SimulatePrimaryUriFailure = true };
44+
var httpResponse = new HttpResponseMessage();
45+
var expected = $"Sending HEAD request to {primaryUriString}... warning: HEAD request failed{Environment.NewLine}" +
46+
$"Sending HEAD request to {backupUriString}... OK{Environment.NewLine}";
47+
48+
httpHandler.Setup(HttpMethod.Head, primaryUri, httpResponse);
49+
httpHandler.Setup(HttpMethod.Head, backupUri, httpResponse);
50+
51+
networkingDiagnostic.SendHttpRequest(sb, new HttpClient(httpHandler));
52+
53+
httpHandler.AssertRequest(HttpMethod.Head, primaryUri, expectedNumberOfCalls: 1);
54+
httpHandler.AssertRequest(HttpMethod.Head, backupUri, expectedNumberOfCalls: 1);
55+
Assert.Contains(expected, sb.ToString());
56+
}
57+
58+
[Fact]
59+
public void NetworkingDiagnostic_SendHttpRequest_No_Network()
60+
{
61+
var primaryUriString = "http://example.com";
62+
var backupUriString = "http://httpforever.com";
63+
var sb = new StringBuilder();
64+
var context = new TestCommandContext();
65+
var networkingDiagnostic = new NetworkingDiagnostic(context);
66+
var primaryUri = new Uri(primaryUriString);
67+
var backupUri = new Uri(backupUriString);
68+
var httpHandler = new TestHttpMessageHandler { SimulateNoNetwork = true };
69+
var httpResponse = new HttpResponseMessage();
70+
var expected = $"Sending HEAD request to {primaryUriString}... warning: HEAD request failed{Environment.NewLine}" +
71+
$"Sending HEAD request to {backupUriString}... warning: HEAD request failed{Environment.NewLine}";
72+
73+
httpHandler.Setup(HttpMethod.Head, primaryUri, httpResponse);
74+
httpHandler.Setup(HttpMethod.Head, backupUri, httpResponse);
75+
76+
networkingDiagnostic.SendHttpRequest(sb, new HttpClient(httpHandler));
77+
78+
httpHandler.AssertRequest(HttpMethod.Head, primaryUri, expectedNumberOfCalls: 1);
79+
httpHandler.AssertRequest(HttpMethod.Head, backupUri, expectedNumberOfCalls: 1);
80+
Assert.Contains(expected, sb.ToString());
81+
}
82+
}

src/shared/Core/Diagnostics/NetworkingDiagnostic.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace GitCredentialManager.Diagnostics
1212
public class NetworkingDiagnostic : Diagnostic
1313
{
1414
private const string TestHttpUri = "http://example.com";
15+
private const string TestHttpUriFallback = "http://httpforever.com";
1516
private const string TestHttpsUri = "https://example.com";
1617

1718
public NetworkingDiagnostic(ICommandContext commandContext)
@@ -28,9 +29,7 @@ protected override async Task<bool> RunInternalAsync(StringBuilder log, IList<st
2829
bool hasNetwork = NetworkInterface.GetIsNetworkAvailable();
2930
log.AppendLine($"IsNetworkAvailable: {hasNetwork}");
3031

31-
log.Append($"Sending HEAD request to {TestHttpUri}...");
32-
using var httpResponse = await httpClient.HeadAsync(TestHttpUri);
33-
log.AppendLine(" OK");
32+
SendHttpRequest(log, httpClient);
3433

3534
log.Append($"Sending HEAD request to {TestHttpsUri}...");
3635
using var httpsResponse = await httpClient.HeadAsync(TestHttpsUri);
@@ -98,5 +97,23 @@ protected override async Task<bool> RunInternalAsync(StringBuilder log, IList<st
9897

9998
return true;
10099
}
100+
101+
internal /* For testing purposes */ async void SendHttpRequest(StringBuilder log, HttpClient httpClient)
102+
{
103+
foreach (var uri in new List<string> { TestHttpUri, TestHttpUriFallback })
104+
{
105+
try
106+
{
107+
log.Append($"Sending HEAD request to {uri}...");
108+
using var httpResponse = await httpClient.HeadAsync(uri);
109+
log.AppendLine(" OK");
110+
break;
111+
}
112+
catch (HttpRequestException)
113+
{
114+
log.AppendLine(" warning: HEAD request failed");
115+
}
116+
}
117+
}
101118
}
102119
}

src/shared/TestInfrastructure/Objects/TestHttpMessageHandler.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class TestHttpMessageHandler : HttpMessageHandler
2323
public bool ThrowOnUnexpectedRequest { get; set; }
2424
public bool SimulateNoNetwork { get; set; }
2525

26+
public bool SimulatePrimaryUriFailure { get; set; }
27+
2628
public IDictionary<(HttpMethod method, Uri uri), int> RequestCounts => _requestCounts;
2729

2830
public void Setup(HttpMethod method, Uri uri, AsyncRequestHandler handler)
@@ -80,6 +82,12 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
8082
throw new HttpRequestException("Simulated no network");
8183
}
8284

85+
if (SimulatePrimaryUriFailure && request.RequestUri != null &&
86+
request.RequestUri.ToString().Equals("http://example.com/"))
87+
{
88+
throw new HttpRequestException("Simulated http failure.");
89+
}
90+
8391
foreach (var kvp in _handlers)
8492
{
8593
if (kvp.Key == requestKey)

0 commit comments

Comments
 (0)