Skip to content

Commit 303996a

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 303996a

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Net.Http;
3+
using System.Text;
4+
using GitCredentialManager.Diagnostics;
5+
using GitCredentialManager.Tests.Objects;
6+
using Xunit;
7+
8+
namespace Core.Tests.Commands;
9+
10+
public class DiagnoseCommandTests
11+
{
12+
[Theory]
13+
[InlineData(false, false, 0, "Sending HEAD request to http://example.com... OK\n")]
14+
[InlineData(true, false, 1, "Sending HEAD request to http://example.com... warning: HEAD request failed.\n" +
15+
"Sending HEAD request to http://httpforever.com... OK\n")]
16+
[InlineData(false, true, 1, "Sending HEAD request to http://example.com... warning: HEAD request failed.\n" +
17+
"Sending HEAD request to http://httpforever.com... warning: HEAD request failed.\n")]
18+
public void NetworkingDiagnostic_SendHttpRequest(bool simulatePrimaryUriFailure, bool simulateNoNetwork,
19+
int expectedBackupCalls, string expectedOutput)
20+
{
21+
var primaryUriString = "http://example.com";
22+
var backupUriString = "http://httpforever.com";
23+
var sb = new StringBuilder();
24+
var context = new TestCommandContext();
25+
var networkingDiagnostic = new NetworkingDiagnostic(context);
26+
var primaryUri = new Uri(primaryUriString);
27+
var backupUri = new Uri(backupUriString);
28+
var httpHandler = new TestHttpMessageHandler
29+
{
30+
SimulatePrimaryUriFailure = simulatePrimaryUriFailure,
31+
SimulateNoNetwork = simulateNoNetwork
32+
};
33+
var httpResponse = new HttpResponseMessage();
34+
35+
httpHandler.Setup(HttpMethod.Head, primaryUri, httpResponse);
36+
httpHandler.Setup(HttpMethod.Head, backupUri, httpResponse);
37+
38+
networkingDiagnostic.SendHttpRequest(sb, new HttpClient(httpHandler));
39+
40+
httpHandler.AssertRequest(HttpMethod.Head, primaryUri, expectedNumberOfCalls: 1);
41+
httpHandler.AssertRequest(HttpMethod.Head, backupUri, expectedNumberOfCalls: expectedBackupCalls);
42+
Assert.Equal(expectedOutput, sb.ToString());
43+
}
44+
}

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)