Skip to content

Commit af74464

Browse files
committed
Add test to validate the urls
1 parent 6601eb7 commit af74464

File tree

2 files changed

+95
-15
lines changed

2 files changed

+95
-15
lines changed

com.unity.netcode.gameobjects/Runtime/HelpUrls.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ internal static class HelpUrls
66
private const string k_BaseManualUrl = k_BaseUrl + "manual/";
77
private const string k_BaseApiUrl = k_BaseUrl + "api/Unity.Netcode";
88

9+
// The HelpUrls have to be defined as public for the test to work
910
public const string NetworkManager = k_BaseManualUrl + "components/core/networkmanager.html";
1011
public const string NetworkObject = k_BaseManualUrl + "components/core/networkobject.html";
1112
public const string NetworkAnimator = k_BaseManualUrl + "components/helper/networkanimator.html";
@@ -15,8 +16,7 @@ internal static class HelpUrls
1516
public const string NetworkTransform = k_BaseManualUrl + "components/helper/networktransform.html";
1617
public const string AnticipatedNetworkTransform = k_BaseManualUrl + "advanced-topics/client-anticipation.html";
1718
public const string UnityTransport = k_BaseApiUrl + ".Transports.UTP.UnityTransport.html";
18-
public const string SecretsLoaderHelper = k_BaseManualUrl + ".Transports.UTP.SecretsLoaderHelper.html";
19+
public const string SecretsLoaderHelper = k_BaseApiUrl + ".Transports.UTP.SecretsLoaderHelper.html";
1920
public const string SinglePlayerTransport = k_BaseApiUrl + ".Transports.SinglePlayer.SinglePlayerTransport.html";
20-
public const string NotValid = k_BaseApiUrl + ".SomeObject.NotValid.html";
2121
}
2222
}

com.unity.netcode.gameobjects/Tests/Runtime/HelpUrlTests.cs

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using System.Net.Http;
8+
using System.Text.RegularExpressions;
89
using System.Threading.Tasks;
910
using NUnit.Framework;
1011
using Unity.Netcode.Runtime;
@@ -15,14 +16,18 @@ namespace Unity.Netcode.RuntimeTests
1516
{
1617
internal class HelpUrlTests
1718
{
18-
private static readonly HttpClient k_HttpClient = new HttpClient();
19+
private const string k_PackageName = "com.unity.netcode.gameobjects";
20+
private static readonly HttpClient k_HttpClient = new();
21+
22+
private bool m_VerboseLogging = false;
1923

2024
[UnityTest]
2125
public IEnumerator ValidateUrlsAreValid()
2226
{
2327
var names = new List<string>();
2428
var allUrls = new List<string>();
2529

30+
// GetFields() can only see public strings. Ensure each HelpUrl is public.
2631
foreach (var constant in typeof(HelpUrls).GetFields())
2732
{
2833
if (constant.IsLiteral && !constant.IsInitOnly)
@@ -31,12 +36,13 @@ public IEnumerator ValidateUrlsAreValid()
3136
allUrls.Add((string)constant.GetValue(null));
3237
}
3338
}
34-
Debug.Log($"Found {allUrls.Count} URLs");
39+
40+
VerboseLog($"Found {allUrls.Count} URLs");
3541

3642
var tasks = new List<Task<bool>>();
3743
foreach (var url in allUrls)
3844
{
39-
tasks.Add(IsRemoteFileAvailable(url));
45+
tasks.Add(AreUnityDocsAvailableAt(url));
4046
}
4147

4248
while (tasks.Any(task => !task.IsCompleted))
@@ -46,7 +52,42 @@ public IEnumerator ValidateUrlsAreValid()
4652

4753
for (int i = 0; i < allUrls.Count; i++)
4854
{
49-
Assert.IsTrue(tasks[i].Result, $"HelpUrls.{names[i]} is an invalid path!");
55+
Assert.IsTrue(tasks[i].Result, $"HelpUrls.{names[i]} has an invalid path! Path: {allUrls[i]}");
56+
}
57+
}
58+
59+
private async Task<bool> AreUnityDocsAvailableAt(string url)
60+
{
61+
try
62+
{
63+
var split = url.Split('#');
64+
url = split[0];
65+
66+
var stream = await GetContentFromRemoteFile(url);
67+
68+
var redirectUrl = CalculateRedirectURl(url, stream);
69+
VerboseLog($"Calculated Redirect URL: {redirectUrl}");
70+
71+
var content = await GetContentFromRemoteFile(redirectUrl);
72+
73+
// If original url had an anchor part (e.g. some/url.html#anchor)
74+
if (split.Length > 1)
75+
{
76+
var anchorString = split[1];
77+
78+
// All headings will have an id with the anchorstring (e.g. <h2 id="anchor">)
79+
if (!content.Contains($"id=\"{anchorString}\">"))
80+
{
81+
return false;
82+
}
83+
}
84+
85+
return true;
86+
}
87+
catch (Exception e)
88+
{
89+
VerboseLog(e.Message);
90+
return false;
5091
}
5192
}
5293

@@ -55,29 +96,68 @@ public IEnumerator ValidateUrlsAreValid()
5596
/// </summary>
5697
/// <param name="url">URL to a remote file.</param>
5798
/// <returns>True if the file at the <paramref name="url"/> is able to be downloaded, false if the file does not exist, or if the file is restricted.</returns>
58-
private static async Task<bool> IsRemoteFileAvailable(string url)
99+
private async Task<string> GetContentFromRemoteFile(string url)
59100
{
60101
//Checking if URI is well formed is optional
61102
var uri = new Uri(url);
62103
if (!uri.IsWellFormedOriginalString())
63104
{
64-
Debug.LogError($"URL {url} is not well formed");
65-
return false;
105+
throw new Exception($"URL {url} is not well formed");
66106
}
67107

68108
try
69109
{
70-
using var request = new HttpRequestMessage(HttpMethod.Head, uri);
110+
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
71111
using var response = await k_HttpClient.SendAsync(request);
112+
if (!response.IsSuccessStatusCode || response.Content.Headers.ContentLength <= 0)
113+
{
114+
throw new Exception($"Failed to get remote file from URL {url}");
115+
}
72116

73-
var exists = response.IsSuccessStatusCode && response.Content.Headers.ContentLength > 0;
74-
Debug.Log($"url {url} returned status code {response.StatusCode}");
75-
return exists;
117+
return await response.Content.ReadAsStringAsync();
76118
}
77119
catch
78120
{
79-
Debug.LogError($"URL {url} request failed");
80-
return false;
121+
throw new Exception($"URL {url} request failed");
122+
}
123+
}
124+
125+
private string CalculateRedirectURl(string originalRequest, string content)
126+
{
127+
var uri = new Uri(originalRequest);
128+
var baseRequest = $"{uri.Scheme}://{uri.Host}";
129+
foreach (var segment in uri.Segments)
130+
{
131+
if (segment.Contains(k_PackageName))
132+
{
133+
break;
134+
}
135+
baseRequest += segment;
136+
}
137+
138+
var subfolderRegex = new Regex(@"[?&](\w[\w.]*)=([^?&]+)").Match(uri.Query);
139+
var subfolder = "";
140+
foreach (Group match in subfolderRegex.Groups)
141+
{
142+
subfolder = match.Value;
143+
}
144+
145+
string pattern = @"com.unity.netcode.gameobjects\@(\d+.\d+)";
146+
var targetDestination = "";
147+
foreach (Match match in Regex.Matches(content, pattern))
148+
{
149+
targetDestination = match.Value;
150+
break;
151+
}
152+
153+
return baseRequest + targetDestination + subfolder;
154+
}
155+
156+
private void VerboseLog(string message)
157+
{
158+
if (m_VerboseLogging)
159+
{
160+
Debug.unityLogger.Log(message);
81161
}
82162
}
83163

0 commit comments

Comments
 (0)