Skip to content

Commit 5830f70

Browse files
committed
Fix invocation parameter ordering issue (#709)
1 parent a3d2dff commit 5830f70

File tree

5 files changed

+85
-6
lines changed

5 files changed

+85
-6
lines changed

src/WebJobs.Script.WebHost/Controllers/AdminController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public HttpResponseMessage Invoke(string name, [FromBody] FunctionInvocation inv
4545
return new HttpResponseMessage(HttpStatusCode.NotFound);
4646
}
4747

48-
ParameterDescriptor inputParameter = function.Parameters.First();
48+
ParameterDescriptor inputParameter = function.Parameters.First(p => p.IsTrigger);
4949
Dictionary<string, object> arguments = new Dictionary<string, object>()
5050
{
5151
{ inputParameter.Name, invocation.Input }

src/WebJobs.Script/Description/FunctionInvokerBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ internal FunctionInvokerBase(ScriptHost host, FunctionMetadata functionMetadata,
4747

4848
PrimaryHostTraceProperties = new Dictionary<string, object>
4949
{
50-
{ ScriptConstants.TracePropertyPrimaryHostKey, Metadata.Name }
50+
{ ScriptConstants.TracePropertyPrimaryHostKey, true }
5151
};
5252
}
5353

src/WebJobs.Script/Host/ScriptHost.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public string InstanceId
7777

7878
public ScriptHostConfiguration ScriptConfig { get; private set; }
7979

80-
public Collection<FunctionDescriptor> Functions { get; private set; }
80+
public virtual Collection<FunctionDescriptor> Functions { get; private set; }
8181

8282
public Dictionary<string, Collection<string>> FunctionErrors { get; private set; }
8383

@@ -156,7 +156,7 @@ internal void AddFunctionError(string functionName, string error)
156156
functionErrors.Add(error);
157157
}
158158

159-
public async Task CallAsync(string method, Dictionary<string, object> arguments, CancellationToken cancellationToken = default(CancellationToken))
159+
public virtual async Task CallAsync(string method, Dictionary<string, object> arguments, CancellationToken cancellationToken = default(CancellationToken))
160160
{
161161
// TODO: Don't hardcode Functions Type name
162162
// TODO: Validate inputs

src/WebJobs.Script/Host/ScriptHostManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public ScriptHostManager(ScriptHostConfiguration config, IScriptHostFactory scri
5252
/// </summary>
5353
public virtual bool IsRunning { get; private set; }
5454

55-
public ScriptHost Instance
55+
public virtual ScriptHost Instance
5656
{
5757
get
5858
{
Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,99 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

4+
using System;
5+
using System.Collections.Generic;
6+
using System.Collections.ObjectModel;
7+
using System.Net;
8+
using System.Net.Http;
49
using System.Reflection;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
using Microsoft.Azure.WebJobs.Host;
13+
using Microsoft.Azure.WebJobs.Script.Description;
14+
using Microsoft.Azure.WebJobs.Script.WebHost;
515
using Microsoft.Azure.WebJobs.Script.WebHost.Controllers;
616
using Microsoft.Azure.WebJobs.Script.WebHost.Filters;
17+
using Microsoft.Azure.WebJobs.Script.WebHost.Models;
18+
using Moq;
719
using Xunit;
820

921
namespace Microsoft.Azure.WebJobs.Script.Tests
1022
{
1123
public class AdminControllerTests
1224
{
25+
private Mock<ScriptHost> hostMock;
26+
private Mock<WebScriptHostManager> managerMock;
27+
private Collection<FunctionDescriptor> testFunctions;
28+
private AdminController testController;
29+
30+
public AdminControllerTests()
31+
{
32+
testFunctions = new Collection<FunctionDescriptor>();
33+
34+
var config = new ScriptHostConfiguration();
35+
hostMock = new Mock<ScriptHost>(MockBehavior.Strict, new object[] { config });
36+
hostMock.Setup(p => p.Functions).Returns(testFunctions);
37+
38+
SecretManager secretManager = new SecretManager();
39+
WebHostSettings settings = new WebHostSettings();
40+
managerMock = new Mock<WebScriptHostManager>(MockBehavior.Strict, new object[] { config, secretManager, settings });
41+
managerMock.SetupGet(p => p.Instance).Returns(hostMock.Object);
42+
43+
testController = new AdminController(managerMock.Object);
44+
}
45+
1346
[Fact]
14-
public void AdminController_HasAuthorizationLevelAttribute()
47+
public void HasAuthorizationLevelAttribute()
1548
{
1649
AuthorizationLevelAttribute attribute = typeof(AdminController).GetCustomAttribute<AuthorizationLevelAttribute>();
1750
Assert.Equal(AuthorizationLevel.Admin, attribute.Level);
1851
}
52+
53+
[Fact]
54+
public async Task Invoke_CallsFunction()
55+
{
56+
string testFunctionName = "TestFunction";
57+
string triggerParameterName = "testTrigger";
58+
string testInput = Guid.NewGuid().ToString();
59+
bool functionInvoked = false;
60+
61+
hostMock.Setup(p => p.CallAsync(It.IsAny<string>(), It.IsAny<Dictionary<string, object>>(), CancellationToken.None))
62+
.Callback<string, Dictionary<string, object>, CancellationToken>((name, args, token) =>
63+
{
64+
functionInvoked = true;
65+
66+
// verify the correct arguments were passed to the invoke
67+
Assert.Equal(testFunctionName, name);
68+
Assert.Equal(1, args.Count);
69+
Assert.Equal(testInput, (string)args[triggerParameterName]);
70+
})
71+
.Returns(Task.CompletedTask);
72+
73+
// Add a few parameters, with the trigger parameter last
74+
// to verify parameter order handling
75+
Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>
76+
{
77+
new ParameterDescriptor("context", typeof(ExecutionContext)),
78+
new ParameterDescriptor("log", typeof(TraceWriter)),
79+
new ParameterDescriptor(triggerParameterName, typeof(string))
80+
{
81+
IsTrigger = true
82+
}
83+
};
84+
testFunctions.Add(new FunctionDescriptor(testFunctionName, null, null, parameters));
85+
86+
FunctionInvocation invocation = new FunctionInvocation
87+
{
88+
Input = testInput
89+
};
90+
HttpResponseMessage response = testController.Invoke(testFunctionName, invocation);
91+
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
92+
93+
// allow the invoke task to run
94+
await Task.Delay(200);
95+
96+
Assert.True(functionInvoked);
97+
}
1998
}
2099
}

0 commit comments

Comments
 (0)