Skip to content

Commit

Permalink
Fixed issue that wrongly inferrs arguments as services. (#6980)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Mar 9, 2024
1 parent 2a1f1bc commit 2c90ea1
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#nullable enable

using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Internal;
Expand All @@ -19,7 +21,16 @@ internal sealed class InferredServiceParameterExpressionBuilder(IServiceProvider
public bool IsDefaultHandler => false;

public bool CanHandle(ParameterInfo parameter)
=> serviceInspector.IsService(parameter.ParameterType);
{
if (parameter.ParameterType.IsGenericType &&
typeof(IEnumerable).IsAssignableFrom(parameter.ParameterType) &&
parameter.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
return serviceInspector.IsService(parameter.ParameterType.GetGenericArguments()[0]);
}

return serviceInspector.IsService(parameter.ParameterType);
}

public Expression Build(ParameterExpressionBuilderContext context)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Diagnostics;
using HotChocolate.Execution;
using HotChocolate.Tests;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;

Expand Down Expand Up @@ -40,35 +42,32 @@ await executor.ExecuteAsync(

[Fact]
public async Task Parallel_Ensure_Execution_Waits_For_Tasks()
{
// arrange
var query = new Query2();
=> await TryTest(async ct =>
{
// arrange
var query = new Query2();

var executor =
await new ServiceCollection()
.AddSingleton(query)
.AddGraphQL()
.AddQueryType<Query2>()
.BuildRequestExecutorAsync();
var executor =
await new ServiceCollection()
.AddSingleton(query)
.AddGraphQL()
.AddQueryType<Query2>()
.BuildRequestExecutorAsync(cancellationToken: ct);

using var cts = new CancellationTokenSource(150);
using var cts = new CancellationTokenSource(150);

// act
await executor.ExecuteAsync(
QueryRequestBuilder.New()
.SetQuery("{ task1 task2 }")
.Create(),
cts.Token);
// act
await executor.ExecuteAsync("{ task1 task2 }", cts.Token);

// assert
// the first task is completed
Assert.True(query.Task1);
Assert.True(query.Task1Done);
// assert
// the first task is completed
Assert.True(query.Task1);
Assert.True(query.Task1Done);

// the second task is completed
Assert.True(query.Task2);
Assert.True(query.Task2Done);
}
// the second task is completed
Assert.True(query.Task2);
Assert.True(query.Task2Done);
});

public class Query1
{
Expand Down Expand Up @@ -133,4 +132,40 @@ public async Task<string> GetTask2()
return "bar";
}
}

protected static async Task TryTest(Func<CancellationToken, Task> action)
{
// we will try four times ....
using var cts = new CancellationTokenSource(Debugger.IsAttached ? 600_000_000 : 60_000);
var ct = cts.Token;
var count = 0;
var wait = 50;

while (true)
{
ct.ThrowIfCancellationRequested();

if (count < 3)
{
try
{
await action(ct).ConfigureAwait(false);
break;
}
catch
{
// try again
}
}
else
{
await action(ct).ConfigureAwait(false);
break;
}

await Task.Delay(wait, ct).ConfigureAwait(false);
wait *= 2;
count++;
}
}
}
28 changes: 28 additions & 0 deletions src/HotChocolate/Core/test/Types.Tests/CodeFirstTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CookieCrumble;
Expand Down Expand Up @@ -209,6 +210,27 @@ public async Task Infer_Nullability_From_Nested_Classes()
schema.MatchSnapshot();
}

[Fact]
public async Task EnumerableArgs_Are_Inferred_As_List()
{
var schema =
await new ServiceCollection()
.AddGraphQLServer()
.AddQueryType<QueryWithEnumerableArg>()
.BuildSchemaAsync();

schema.MatchInlineSnapshot(
"""
schema {
query: QueryWithEnumerableArg
}
type QueryWithEnumerableArg {
foo(foo: [String!]!): String!
}
""");
}

public class Query
{
public string SayHello(string name) =>
Expand Down Expand Up @@ -246,6 +268,12 @@ public Task<GenericWrapper<IPet>> GetPets(
throw new NotImplementedException();
}

public class QueryWithEnumerableArg
{
public string GetFoo(IEnumerable<string> foo)
=> "foo";
}

public class GenericWrapper<T>
{
public T Value { get; set; } = default!;
Expand Down
8 changes: 6 additions & 2 deletions src/HotChocolate/Core/test/Utilities/TestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public static Task<IExecutionResult> ExpectValid(
query,
new TestConfiguration
{
ConfigureRequest = request, Configure = configure, Services = requestServices,
ConfigureRequest = request,
Configure = configure,
Services = requestServices,
});
}

Expand Down Expand Up @@ -73,7 +75,9 @@ public static Task ExpectError(
query,
new TestConfiguration
{
Configure = configure, ConfigureRequest = request, Services = requestServices,
Configure = configure,
ConfigureRequest = request,
Services = requestServices,
},
elementInspectors);
}
Expand Down

0 comments on commit 2c90ea1

Please sign in to comment.