Skip to content

Commit 396e586

Browse files
committed
Adding invocation log E2E test
1 parent 62c624e commit 396e586

File tree

6 files changed

+109
-0
lines changed

6 files changed

+109
-0
lines changed

test/WebJobs.Script.Tests.E2E/FunctionAppFixture.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public FunctionAppFixture()
3636

3737
public TelemetryClient Telemetry => TelemetryContext.Client;
3838

39+
public KuduClient KuduClient => _kuduClient;
40+
3941
public string FunctionDefaultKey { get; }
4042

4143
public string FunctionAppMasterKey { get; private set; }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"bindings": [
3+
{
4+
"authLevel": "function",
5+
"name": "req",
6+
"type": "httpTrigger",
7+
"direction": "in"
8+
},
9+
{
10+
"name": "$return",
11+
"type": "http",
12+
"direction": "out"
13+
}
14+
],
15+
"disabled": false
16+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public static string Run(HttpRequestMessage req, ExecutionContext context) => context.InvocationId.ToString();

test/WebJobs.Script.Tests.E2E/GeneralEndToEndTests.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Globalization;
67
using System.Net.Http;
78
using System.Net.Http.Headers;
9+
using System.Text;
810
using System.Threading.Tasks;
911
using Microsoft.ApplicationInsights;
1012
using Microsoft.ApplicationInsights.DataContracts;
13+
using Newtonsoft.Json.Linq;
1114
using Xunit;
1215

1316
namespace WebJobs.Script.EndToEndTests
@@ -107,6 +110,85 @@ public async Task ParallelRequests_ReturnExpectedResults()
107110
}
108111
}
109112

113+
[Fact]
114+
[TestTrace]
115+
public async Task Invocation_Logs_AreReturned()
116+
{
117+
using (var client = CreateClient())
118+
{
119+
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
120+
121+
string invocationId = await client.GetStringAsync($"api/GetInvocationId?code={_fixture.FunctionDefaultKey}");
122+
123+
string siteName = NormalizeFunctionName(Settings.SiteName);
124+
JToken resultToken = null;
125+
// We retry for a bit as data may take a while to become available
126+
for (int i = 0; i < 20; i++)
127+
{
128+
var invocationsRequest = new HttpRequestMessage(HttpMethod.Get, $"azurejobs/api/functions/definitions/{siteName}-GetInvocationId/invocations?limit=10");
129+
var response = await _fixture.KuduClient.SendAsync(invocationsRequest);
130+
131+
var results = await response.Content.ReadAsAsync<JObject>();
132+
133+
resultToken = results.SelectToken($"$..entries[?(@.id == '{invocationId}')]");
134+
135+
if (resultToken != null)
136+
{
137+
break;
138+
}
139+
140+
await Task.Delay(3000);
141+
}
142+
143+
_fixture.Assert.True(resultToken != null);
144+
}
145+
}
146+
147+
// Assumes we have a valid function name.
148+
// Function names are case-insensitive, case-preserving.
149+
// Table storage is case-sensitive. So need to normalize case to use as table keys.
150+
// Normalize must be one-to-one to avoid collisions.
151+
// Escape any non-alphanumeric characters so that we
152+
// a) have a valid rowkey name
153+
// b) don't have characeters that conflict with separators in the row key (like '-')
154+
public static string NormalizeFunctionName(string functionName)
155+
{
156+
var sb = new StringBuilder();
157+
foreach (var ch in functionName)
158+
{
159+
if (ch >= 'a' && ch <= 'z')
160+
{
161+
sb.Append(ch);
162+
}
163+
else if (ch >= 'A' && ch <= 'Z')
164+
{
165+
sb.Append((char)(ch - 'A' + 'a'));
166+
}
167+
else if (ch >= '0' && ch <= '9')
168+
{
169+
sb.Append(ch);
170+
}
171+
else
172+
{
173+
sb.Append(EscapeStorageCharacter(ch));
174+
}
175+
}
176+
return sb.ToString();
177+
}
178+
179+
private static string EscapeStorageCharacter(char character)
180+
{
181+
var ordinalValue = (ushort)character;
182+
if (ordinalValue < 0x100)
183+
{
184+
return string.Format(CultureInfo.InvariantCulture, ":{0:X2}", ordinalValue);
185+
}
186+
else
187+
{
188+
return string.Format(CultureInfo.InvariantCulture, "::{0:X4}", ordinalValue);
189+
}
190+
}
191+
110192

111193
public HttpClient CreateClient()
112194
{

test/WebJobs.Script.Tests.E2E/KuduClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public async Task<string> GetFunctionsMasterKey()
5959
return result.GetValue("masterKey").ToString();
6060
}
6161

62+
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request) => _client.SendAsync(request);
63+
6264
protected virtual void Dispose(bool disposing)
6365
{
6466
if (!_disposed)

test/WebJobs.Script.Tests.E2E/WebJobs.Script.Tests.E2E.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@
100100
</ItemGroup>
101101
<ItemGroup>
102102
<None Include="app.config" />
103+
<None Include="Functions\wwwroot\GetInvocationId\function.json">
104+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
105+
</None>
106+
<None Include="Functions\wwwroot\GetInvocationId\run.csx">
107+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
108+
</None>
103109
<None Include="Functions\wwwroot\host.json">
104110
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
105111
</None>

0 commit comments

Comments
 (0)