Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions integration-test/ExecutionOrchestratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public async Task RecoverableIsTrueOnExceptionThrownWhenContinueOnFailure()
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);
var gaugeMethod = assemblyLoader.GetStepRegistry()
.MethodFor("I throw a serializable exception and continue");
.LookupStep("I throw a serializable exception and continue").Methods[0];
var executionResult = await orchestrator.ExecuteStep(gaugeMethod, 1);
ClassicAssert.IsTrue(executionResult.Failed);
ClassicAssert.IsTrue(executionResult.RecoverableError);
Expand All @@ -63,7 +63,7 @@ public async Task ShouldCreateTableFromTargetType()
new HookExecutor(assemblyLoader, executionInfoMapper, hookRegistry, _loggerFactory.CreateLogger<HookExecutor>()),
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);
var gaugeMethod = assemblyLoader.GetStepRegistry().MethodFor("Step that takes a table {}");
var gaugeMethod = assemblyLoader.GetStepRegistry().LookupStep("Step that takes a table {}").Methods[0];
var table = new Table(new List<string> { "foo", "bar" });
table.AddRow(new List<string> { "foorow1", "barrow1" });
table.AddRow(new List<string> { "foorow2", "barrow2" });
Expand Down Expand Up @@ -91,7 +91,7 @@ public async Task ShouldExecuteMethodAndReturnResult()
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);
var gaugeMethod = assemblyLoader.GetStepRegistry()
.MethodFor("A context step which gets executed before every scenario");
.LookupStep("A context step which gets executed before every scenario").Methods[0];

var executionResult = await orchestrator.ExecuteStep(gaugeMethod, 1);
ClassicAssert.False(executionResult.Failed);
Expand All @@ -117,7 +117,7 @@ public async Task ShouldGetPendingMessages()
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);

var gaugeMethod = assemblyLoader.GetStepRegistry().MethodFor("Say {} to {}");
var gaugeMethod = assemblyLoader.GetStepRegistry().LookupStep("Say {} to {}").Methods[0];

var executionResult = await executionOrchestrator.ExecuteStep(gaugeMethod, 1, "hello", "world");

Expand All @@ -144,7 +144,7 @@ public async Task ShouldGetStacktraceForAggregateException()
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);

var gaugeMethod = assemblyLoader.GetStepRegistry().MethodFor("I throw an AggregateException");
var gaugeMethod = assemblyLoader.GetStepRegistry().LookupStep("I throw an AggregateException").Methods[0];
var executionResult = await executionOrchestrator.ExecuteStep(gaugeMethod, 1);

ClassicAssert.True(executionResult.Failed);
Expand All @@ -163,7 +163,7 @@ public void ShouldGetStepTextsForMethod()
var assemblyLoader = new AssemblyLoader(assemblyLocater, gaugeLoadContext, reflectionWrapper,
activatorWrapper, new StepRegistry(), _loggerFactory.CreateLogger<AssemblyLoader>(), _configuration);
var registry = assemblyLoader.GetStepRegistry();
var gaugeMethod = registry.MethodFor("and an alias");
var gaugeMethod = registry.LookupStep("and an alias").Methods[0];
var stepTexts = gaugeMethod.Aliases.ToList();

ClassicAssert.Contains("Step with text", stepTexts);
Expand All @@ -189,7 +189,7 @@ public async Task SuccessIsFalseOnSerializableExceptionThrown()
new HookExecutor(assemblyLoader, executionInfoMapper, hookRegistry, _loggerFactory.CreateLogger<HookExecutor>()),
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);
var gaugeMethod = assemblyLoader.GetStepRegistry().MethodFor("I throw a serializable exception");
var gaugeMethod = assemblyLoader.GetStepRegistry().LookupStep("I throw a serializable exception").Methods[0];

var executionResult = await executionOrchestrator.ExecuteStep(gaugeMethod, 1);

Expand Down Expand Up @@ -219,7 +219,7 @@ public async Task SuccessIsFalseOnUnserializableExceptionThrown()
new StepExecutor(assemblyLoader, _loggerFactory.CreateLogger<StepExecutor>(), executionInfoMapper), _configuration,
_loggerFactory.CreateLogger<ExecutionOrchestrator>(), dataStoreFactory);

var gaugeMethod = assemblyLoader.GetStepRegistry().MethodFor("I throw an unserializable exception");
var gaugeMethod = assemblyLoader.GetStepRegistry().LookupStep("I throw an unserializable exception").Methods[0];
var executionResult = await executionOrchestrator.ExecuteStep(gaugeMethod, 1);
ClassicAssert.True(executionResult.Failed);
ClassicAssert.AreEqual(expectedMessage, executionResult.ErrorMessage);
Expand Down
2 changes: 1 addition & 1 deletion integration-test/ExternalReferenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public async Task ShouldGetStepsFromReference(string referenceType, string stepT
var assemblyLoader = new AssemblyLoader(assemblyLocater, gaugeLoadContext, new ReflectionWrapper(),
new ActivatorWrapper(serviceProvider), new StepRegistry(), _loggerFactory.CreateLogger<AssemblyLoader>(), config);

var stepValidationProcessor = new StepValidationProcessor(assemblyLoader.GetStepRegistry());
var stepValidationProcessor = new StepValidationProcessor(assemblyLoader.GetStepRegistry(), _loggerFactory.CreateLogger<StepValidationProcessor>());
var message = new StepValidateRequest
{
StepText = stepText,
Expand Down
2 changes: 1 addition & 1 deletion src/Gauge.Dotnet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>Gauge.Runner</PackageId>
<Authors>The Gauge Team</Authors>
<Version>0.7.6</Version>
<Version>0.7.7</Version>
<Company>ThoughtWorks Inc.</Company>
<Product>Gauge</Product>
<Description>C# runner for Gauge. https://gauge.org</Description>
Expand Down
8 changes: 5 additions & 3 deletions src/Loaders/AssemblyLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ public IStepRegistry GetStepRegistry()
foreach (var stepText in stepTexts)
{
var stepValue = GetStepValue(stepText);
if (_registry.ContainsStep(stepValue))
var lookup = _registry.LookupStep(stepValue);
if (lookup.Exists)
{
_logger.LogDebug("'{StepValue}': implementation found in StepRegistry, setting reflected methodInfo", stepValue);
_registry.MethodFor(stepValue).MethodInfo = info;
_registry.MethodFor(stepValue).ContinueOnFailure = info.IsRecoverableStep(this);
var existing = lookup.Methods[0];
existing.MethodInfo = info;
existing.ContinueOnFailure = info.IsRecoverableStep(this);
}
else
{
Expand Down
11 changes: 7 additions & 4 deletions src/Loaders/StaticLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ public IStepRegistry GetStepRegistry()
public void LoadStepsFromText(string content, string filepath)
{
var steps = GetStepsFrom(content);
AddStepsToRegistry(filepath, steps);
var entries = BuildStepEntries(filepath, steps);
_stepRegistry.ReplaceSteps(filepath, entries);
}

public void ReloadSteps(string content, string filepath)
{
if (IsFileRemoved(filepath)) return;
_stepRegistry.RemoveSteps(filepath);
LoadStepsFromText(content, filepath);
}

Expand Down Expand Up @@ -94,8 +94,10 @@ public void LoadImplementations()
}
}

private void AddStepsToRegistry(string fileName, IEnumerable<MethodDeclarationSyntax> stepMethods)
private static IReadOnlyList<(string stepValue, GaugeMethod method)> BuildStepEntries(
string fileName, IEnumerable<MethodDeclarationSyntax> stepMethods)
{
var entries = new List<(string, GaugeMethod)>();
foreach (var stepMethod in stepMethods)
{
var attributeListSyntax = stepMethod.AttributeLists.WithStepAttribute();
Expand All @@ -120,9 +122,10 @@ private void AddStepsToRegistry(string fileName, IEnumerable<MethodDeclarationSy
FileName = fileName,
IsExternal = false
};
_stepRegistry.AddStep(stepValue, entry);
entries.Add((stepValue, entry));
}
}
return entries;
}

private static IEnumerable<MethodDeclarationSyntax> GetStepsFrom(string content)
Expand Down
5 changes: 3 additions & 2 deletions src/Processors/ExecuteStepProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ public ExecuteStepProcessor(IStepRegistry registry, IExecutionOrchestrator execu
[DebuggerHidden]
public async Task<ExecutionStatusResponse> Process(int streamId, ExecuteStepRequest request)
{
if (!_stepRegistry.ContainsStep(request.ParsedStepText))
var lookup = _stepRegistry.LookupStep(request.ParsedStepText);
if (!lookup.Exists)
return ExecutionError("Step Implementation not found");

var method = _stepRegistry.MethodFor(request.ParsedStepText);
var method = lookup.Methods[0];

var parameters = method.ParameterCount;
var args = new string[parameters];
Expand Down
8 changes: 6 additions & 2 deletions src/Processors/RefactorProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,13 @@ private static FileChanges ConvertToProtoFileChanges(RefactoringChange fileChang

private GaugeMethod GetGaugeMethod(ProtoStepValue stepValue)
{
if (_stepRegistry.HasMultipleImplementations(stepValue.StepValue))
var lookup = _stepRegistry.LookupStep(stepValue.StepValue);
if (!lookup.Exists)
throw new Exception(string.Format("Step implementation not found for : {0}",
stepValue.ParameterizedStepValue));
if (lookup.HasMultipleImplementations)
throw new Exception(string.Format("Multiple step implementations found for : {0}",
stepValue.ParameterizedStepValue));
return _stepRegistry.MethodFor(stepValue.StepValue);
return lookup.Methods[0];
}
}
16 changes: 7 additions & 9 deletions src/Processors/StepNameProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,17 @@ public Task<StepNameResponse> Process(int stream, StepNameRequest request)
{

var parsedStepText = request.StepValue;
var isStepPresent = _stepRegistry.ContainsStep(parsedStepText);
var lookup = _stepRegistry.LookupStep(parsedStepText);
var response = new StepNameResponse
{
IsStepPresent = isStepPresent
IsStepPresent = lookup.Exists
};

if (!isStepPresent) return Task.FromResult(response);
if (!lookup.Exists) return Task.FromResult(response);

var stepText = _stepRegistry.GetStepText(parsedStepText);
var hasAlias = _stepRegistry.HasAlias(stepText);
var info = _stepRegistry.MethodFor(parsedStepText);
var info = lookup.Methods[0];
response.IsExternal = info.IsExternal;
response.HasAlias = hasAlias;
response.HasAlias = info.HasAlias;
if (!response.IsExternal)
{
response.FileName = info.FileName;
Expand All @@ -49,10 +47,10 @@ public Task<StepNameResponse> Process(int stream, StepNameRequest request)
};
}

if (hasAlias)
if (info.HasAlias)
response.StepName.AddRange(info.Aliases);
else
response.StepName.Add(stepText);
response.StepName.Add(info.StepText);

return Task.FromResult(response);
}
Expand Down
21 changes: 17 additions & 4 deletions src/Processors/StepValidationProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@
using Gauge.Dotnet.Extensions;
using Gauge.Dotnet.Registries;
using Gauge.Messages;
using Microsoft.Extensions.Logging;

namespace Gauge.Dotnet.Processors;

public class StepValidationProcessor : IGaugeProcessor<StepValidateRequest, StepValidateResponse>
{
private readonly IStepRegistry _stepRegistry;
private readonly ILogger<StepValidationProcessor> _logger;

public StepValidationProcessor(IStepRegistry stepRegistry)
public StepValidationProcessor(IStepRegistry stepRegistry, ILogger<StepValidationProcessor> logger)
{
_stepRegistry = stepRegistry;
_logger = logger;
}

public Task<StepValidateResponse> Process(int stream, StepValidateRequest request)
Expand All @@ -27,17 +30,27 @@ public Task<StepValidateResponse> Process(int stream, StepValidateRequest reques
var errorMessage = "";
var suggestion = "";
var errorType = StepValidateResponse.Types.ErrorType.StepImplementationNotFound;
if (!_stepRegistry.ContainsStep(stepToValidate))

var lookup = _stepRegistry.LookupStep(stepToValidate);
if (!lookup.Exists)
{
isValid = false;
errorMessage = string.Format("No implementation found for : {0}. Full Step Text :", stepToValidate);
suggestion = GetSuggestion(request.StepValue);
}
else if (_stepRegistry.HasMultipleImplementations(stepToValidate))
else if (lookup.HasMultipleImplementations)
{
isValid = false;
errorType = StepValidateResponse.Types.ErrorType.DuplicateStepImplementation;
errorMessage = string.Format("Multiple step implementations found for : {0}", stepToValidate);
var locations = string.Join("\n", lookup.Methods.Select(m =>
$" {m.ClassName}.{m.Name} in {m.FileName}:{m.Span.StartLinePosition.Line + 1}"));
errorMessage = $"Step: {stepToValidate}\n{locations}";
_logger.LogDebug("Duplicate step implementation found for: {StepText}", stepToValidate);
foreach (var m in lookup.Methods)
{
_logger.LogDebug("Duplicate: {ClassName}.{MethodName} in {FileName}:{Line}",
m.ClassName, m.Name, m.FileName, m.Span.StartLinePosition.Line + 1);
}
}
return Task.FromResult(GetStepValidateResponseMessage(isValid, errorType, errorMessage, suggestion));
}
Expand Down
5 changes: 2 additions & 3 deletions src/Registries/IStepRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ namespace Gauge.Dotnet.Registries;

public interface IStepRegistry
{
bool ContainsStep(string parsedStepText);
GaugeMethod MethodFor(string parsedStepText);
bool HasAlias(string stepText);
string GetStepText(string parameterizedStepText);
IEnumerable<string> GetStepTexts();
bool HasMultipleImplementations(string parsedStepText);
StepLookupResult LookupStep(string parsedStepText);
void AddStep(string stepValue, GaugeMethod stepMethod);
void ReplaceSteps(string filepath, IReadOnlyList<(string stepValue, GaugeMethod method)> newSteps);
void RemoveSteps(string filepath);
IEnumerable<StepPosition> GetStepPositions(string filePath);
bool IsFileCached(string file);
Expand Down
14 changes: 14 additions & 0 deletions src/Registries/StepLookupResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*----------------------------------------------------------------
* Copyright (c) ThoughtWorks, Inc.
* Licensed under the Apache License, Version 2.0
* See LICENSE.txt in the project root for license information.
*----------------------------------------------------------------*/

using Gauge.Dotnet.Models;

namespace Gauge.Dotnet.Registries;

public readonly record struct StepLookupResult(
bool Exists,
bool HasMultipleImplementations,
IReadOnlyList<GaugeMethod> Methods);
Loading