-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8aacd1d
commit c3ecf32
Showing
21 changed files
with
334 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using Reqnroll.Infrastructure; | ||
using Reqnroll.Tracing; | ||
|
||
namespace Reqnroll.Bindings; | ||
|
||
#pragma warning disable CS0618 // Type or member is obsolete | ||
public class DryRunBindingInvoker : IAsyncBindingInvoker, IBindingInvoker | ||
#pragma warning restore CS0618 // Type or member is obsolete | ||
{ | ||
public object InvokeBinding(IBinding binding, IContextManager contextManager, object[] arguments, ITestTracer testTracer, out TimeSpan duration) | ||
{ | ||
duration = TimeSpan.Zero; | ||
return null; | ||
} | ||
|
||
public Task<object> InvokeBindingAsync(IBinding binding, IContextManager contextManager, object[] arguments, ITestTracer testTracer, DurationHolder durationHolder) | ||
{ | ||
durationHolder.Duration = TimeSpan.Zero; | ||
return Task.FromResult((object)null); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Reflection; | ||
using BoDi; | ||
using Reqnroll.Bindings.Discovery; | ||
using Reqnroll.Bindings.Provider.Data; | ||
using Reqnroll.Bindings.Reflection; | ||
using Reqnroll.Configuration; | ||
using Reqnroll.Infrastructure; | ||
using SpecFlow.Internal.Json; | ||
|
||
namespace Reqnroll.Bindings.Provider; | ||
public class BindingProviderService | ||
{ | ||
public static string DiscoverBindings(Assembly testAssembly, string jsonConfiguration) | ||
{ | ||
if (string.IsNullOrWhiteSpace(jsonConfiguration)) jsonConfiguration = "{}"; | ||
var globalContainer = CreateGlobalContainer(testAssembly, jsonConfiguration); | ||
var bindingRegistryBuilder = globalContainer.Resolve<IRuntimeBindingRegistryBuilder>(); | ||
BuildBindingRegistry(testAssembly, bindingRegistryBuilder); | ||
var bindingRegistry = globalContainer.Resolve<IBindingRegistry>(); | ||
var resultData = ParseDiscoveryResult(bindingRegistry, testAssembly); | ||
var jsonString = resultData.ToJson(); | ||
return jsonString; | ||
} | ||
|
||
private static BindingData ParseDiscoveryResult(IBindingRegistry bindingRegistry, Assembly testAssembly) | ||
{ | ||
var resultData = new BindingData(); | ||
|
||
StepDefinitionData CreateStepDefinition(IStepDefinitionBinding stepDefinitionBinding) | ||
{ | ||
var stepDefinition = new StepDefinitionData | ||
{ | ||
Source = GetSource(stepDefinitionBinding.Method), | ||
Type = stepDefinitionBinding.StepDefinitionType.ToString(), | ||
Regex = stepDefinitionBinding.Regex?.ToString(), | ||
ParamTypes = GetParamTypes(stepDefinitionBinding.Method), | ||
Scope = GetScope(stepDefinitionBinding), | ||
Expression = stepDefinitionBinding.SourceExpression, | ||
Error = stepDefinitionBinding.ErrorMessage | ||
}; | ||
|
||
return stepDefinition; | ||
} | ||
|
||
HookData CreateHook(IHookBinding hookBinding) | ||
{ | ||
var hook = new HookData | ||
{ | ||
Source = GetSource(hookBinding.Method), | ||
Type = hookBinding.HookType.ToString(), | ||
HookOrder = hookBinding.HookOrder, | ||
Scope = GetScope(hookBinding), | ||
}; | ||
|
||
return hook; | ||
} | ||
|
||
StepArgumentTransformationData CreateStepArgumentTransformation(IStepArgumentTransformationBinding stepArgumentTransformationBinding) | ||
{ | ||
var stepArgumentTransformation = new StepArgumentTransformationData | ||
{ | ||
Source = GetSource(stepArgumentTransformationBinding.Method), | ||
Name = stepArgumentTransformationBinding.Name, | ||
Regex = stepArgumentTransformationBinding.Regex?.ToString(), | ||
ParamTypes = GetParamTypes(stepArgumentTransformationBinding.Method), | ||
}; | ||
|
||
return stepArgumentTransformation; | ||
} | ||
|
||
string[] GetParamTypes(IBindingMethod bindingMethod) | ||
{ | ||
return bindingMethod.Parameters.Select(p => p.Type.FullName).ToArray(); | ||
} | ||
|
||
BindingScopeData GetScope(IScopedBinding scopedBinding) | ||
{ | ||
if (!scopedBinding.IsScoped) | ||
return null; | ||
|
||
return new BindingScopeData | ||
{ | ||
Tag = scopedBinding.BindingScope.Tag == null | ||
? null | ||
: "@" + scopedBinding.BindingScope.Tag, | ||
FeatureTitle = scopedBinding.BindingScope.FeatureTitle, | ||
ScenarioTitle = scopedBinding.BindingScope.ScenarioTitle | ||
}; | ||
} | ||
|
||
BindingSourceData GetSource(IBindingMethod bindingMethod) | ||
{ | ||
if (bindingMethod is not RuntimeBindingMethod runtimeBindingMethod || | ||
runtimeBindingMethod.MethodInfo.DeclaringType == null) return null; | ||
|
||
var methodInfo = runtimeBindingMethod.MethodInfo; | ||
return new BindingSourceData | ||
{ | ||
Method = new BindingSourceMethodData | ||
{ | ||
Type = methodInfo.DeclaringType!.FullName, | ||
Assembly = methodInfo.DeclaringType.Assembly == testAssembly ? null : methodInfo.DeclaringType.Assembly.FullName, | ||
MetadataToken = methodInfo.MetadataToken, | ||
FullName = methodInfo.ToString() | ||
} | ||
}; | ||
} | ||
|
||
resultData.StepDefinitions = bindingRegistry.GetStepDefinitions().Select(CreateStepDefinition).ToArray(); | ||
resultData.Hooks = bindingRegistry.GetHooks().Select(CreateHook).ToArray(); | ||
resultData.StepArgumentTransformations = bindingRegistry.GetStepTransformations().Select(CreateStepArgumentTransformation).ToArray(); | ||
resultData.Errors = bindingRegistry.GetErrorMessages().Select(e => $"{e.Type}: {e.Message}").ToArray(); | ||
return resultData; | ||
} | ||
|
||
private static void BuildBindingRegistry(Assembly testAssembly, IRuntimeBindingRegistryBuilder bindingRegistryBuilder) | ||
{ | ||
var bindingAssemblies = bindingRegistryBuilder.GetBindingAssemblies(testAssembly); | ||
foreach (Assembly assembly in bindingAssemblies) | ||
{ | ||
bindingRegistryBuilder.BuildBindingsFromAssembly(assembly); | ||
} | ||
bindingRegistryBuilder.BuildingCompleted(); | ||
} | ||
|
||
class BindingDiscoveryDependencyProvider : DefaultDependencyProvider | ||
{ | ||
public override void RegisterGlobalContainerDefaults(ObjectContainer container) | ||
{ | ||
base.RegisterGlobalContainerDefaults(container); | ||
container.RegisterTypeAs<DryRunBindingInvoker, IAsyncBindingInvoker>(); | ||
#pragma warning disable CS0618 | ||
container.RegisterTypeAs<DryRunBindingInvoker, IBindingInvoker>(); | ||
#pragma warning restore CS0618 | ||
} | ||
} | ||
|
||
private static IObjectContainer CreateGlobalContainer(Assembly testAssembly, string jsonConfiguration) | ||
{ | ||
var containerBuilder = new ContainerBuilder(new BindingDiscoveryDependencyProvider()) | ||
{ | ||
SkipLoadingProvider = true | ||
}; | ||
var configurationProvider = new JsonStringRuntimeConfigurationProvider(jsonConfiguration); | ||
return containerBuilder.CreateGlobalContainer(testAssembly, configurationProvider); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
|
||
public class BindingData | ||
{ | ||
public string[] Errors { get; set; } | ||
public string[] Warnings { get; set; } | ||
public StepDefinitionData[] StepDefinitions { get; set; } | ||
public HookData[] Hooks { get; set; } | ||
public StepArgumentTransformationData[] StepArgumentTransformations { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
|
||
public class BindingScopeData | ||
{ | ||
public string Tag { get; set; } | ||
public string FeatureTitle { get; set; } | ||
public string ScenarioTitle { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
|
||
public class BindingSourceData | ||
{ | ||
public BindingSourceMethodData Method { get; set; } | ||
public string SourceLocation { get; set; } | ||
} |
10 changes: 10 additions & 0 deletions
10
Reqnroll/Bindings/Provider/Data/BindingSourceMethodData.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
|
||
public class BindingSourceMethodData | ||
{ | ||
public string Type { get; set; } // full type name (with namespace) | ||
public string Assembly { get; set; } // assembly name, null if the assembly is the main test assembly | ||
public string FullName { get; set; } // method name with signature: <return-type> <name>(<param-type1>,<param-type2>) | ||
public int? MetadataToken { get; set; } // MethodInfo.MetadataToken | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
public class HookData | ||
{ | ||
public BindingSourceData Source { get; set; } | ||
public BindingScopeData Scope { get; set; } | ||
public string Type { get; set; } | ||
public int HookOrder { get; set; } | ||
} |
12 changes: 12 additions & 0 deletions
12
Reqnroll/Bindings/Provider/Data/StepArgumentTransformationData.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
public class StepArgumentTransformationData | ||
{ | ||
public BindingSourceData Source { get; set; } | ||
|
||
public string Name { get; set; } | ||
|
||
public string Regex { get; set; } | ||
|
||
public string[] ParamTypes { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#nullable disable | ||
namespace Reqnroll.Bindings.Provider.Data; | ||
|
||
public class StepDefinitionData | ||
{ | ||
public BindingSourceData Source { get; set; } | ||
public string Type { get; set; } | ||
public string Expression { get; set; } | ||
public string Regex { get; set; } | ||
public string[] ParamTypes { get; set; } | ||
public BindingScopeData Scope { get; set; } | ||
|
||
public string Error { get; set; } | ||
} |
20 changes: 20 additions & 0 deletions
20
Reqnroll/Configuration/JsonStringRuntimeConfigurationProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System; | ||
using Reqnroll.Configuration.JsonConfig; | ||
|
||
namespace Reqnroll.Configuration; | ||
public class JsonStringRuntimeConfigurationProvider(string jsonConfigFileContent) : IRuntimeConfigurationProvider | ||
{ | ||
public ReqnrollConfiguration LoadConfiguration(ReqnrollConfiguration reqnrollConfiguration) | ||
{ | ||
if (reqnrollConfiguration == null) | ||
throw new ArgumentNullException(nameof(reqnrollConfiguration)); | ||
|
||
if (jsonConfigFileContent == null) return reqnrollConfiguration; | ||
|
||
if (!jsonConfigFileContent.Trim().StartsWith("{")) | ||
throw new NotSupportedException($"Only JSON config value can be provided! Provided value: {jsonConfigFileContent}"); | ||
|
||
var jsonConfigurationLoader = new JsonConfigurationLoader(); | ||
return jsonConfigurationLoader.LoadJson(reqnrollConfiguration, jsonConfigFileContent); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.