Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<PackageVersion Include="Json.More.Net" Version="2.2.0" />
<PackageVersion Include="JsonSchema.Net" Version="8.0.3" />
<PackageVersion Include="JsonPointer.Net" Version="6.0.0" />
<PackageVersion Include="WolverineFx" Version="5.8.0" />
<PackageVersion Include="WolverineFx" Version="5.9.0" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="FSharp.Formatting" Version="4.0.0-rc1" />
<PackageVersion Include="FSharp.Literate" Version="4.0.0-rc1" />
Expand Down
9 changes: 8 additions & 1 deletion src/Morphir.Core/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
"resolved": "5.0.0-beta-61",
"contentHash": "h/Bc8Ch+rINFObd8X8WiKHRuj4qcolyAZd17A6Pik8qK42RCGlH1FhZopOXVvCDTCxtTf6z6HvZvW36SKWN4JA=="
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.1, )",
"resolved": "10.0.1",
"contentHash": "ISahzLHsHY7vrwqr2p1YWZ+gsxoBRtH7gWRDK8fDUst9pp2He0GiesaqEfeX0V8QMCJM3eNEHGGpnIcPjFo2NQ=="
},
"StaticCS": {
"type": "Direct",
"requested": "[0.3.1, )",
Expand All @@ -66,6 +72,7 @@
"resolved": "1.1.1",
"contentHash": "MalY0Y/uM/LjXtHfX/26l2VtN4LDNZ2OE3aumNOHDLsT4fNYy2hiHXI4CXCqKpNUNm7iJ2brrc4J89UdaL56FA=="
}
}
},
"net10.0/linux-x64": {}
}
}
10 changes: 5 additions & 5 deletions src/Morphir.Tool/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@
},
"WolverineFx": {
"type": "Direct",
"requested": "[5.8.0, )",
"resolved": "5.8.0",
"contentHash": "BzHf+tPyU48gtJkyKuDKsWk8v8K55P6bcCehCTqsTdLzCrb0frQKvB7LHtHURwagvXvqBHiLZQuTT50KS2shew==",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "kHmwFs3QpM9WaXZ3k+ruV/MKBdZYqFLGciTfMpbHWFwfp9BqLgXqY9T5rUvWamSU69qh93yBog7PmZOv5umidg==",
"dependencies": {
"JasperFx": "1.11.3",
"JasperFx.Events": "1.12.2",
Expand Down Expand Up @@ -675,7 +675,7 @@
"Serilog.Extensions.Hosting": "[5.0.1, )",
"Serilog.Sinks.Console": "[6.1.1, )",
"System.CommandLine": "[2.0.1, )",
"WolverineFx": "[5.8.0, )"
"WolverineFx": "[5.9.0, )"
}
},
"morphir.core": {
Expand All @@ -699,7 +699,7 @@
"Serilog": "[4.3.0, )",
"Serilog.Extensions.Hosting": "[5.0.1, )",
"Serilog.Sinks.Console": "[6.1.1, )",
"WolverineFx": "[5.8.0, )"
"WolverineFx": "[5.9.0, )"
}
},
"Dunet": {
Expand Down
19 changes: 16 additions & 3 deletions src/Morphir.Tooling/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@
"Microsoft.Extensions.Options": "10.0.0"
}
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.1, )",
"resolved": "10.0.1",
"contentHash": "ISahzLHsHY7vrwqr2p1YWZ+gsxoBRtH7gWRDK8fDUst9pp2He0GiesaqEfeX0V8QMCJM3eNEHGGpnIcPjFo2NQ=="
},
"Serilog": {
"type": "Direct",
"requested": "[4.3.0, )",
Expand Down Expand Up @@ -100,9 +106,9 @@
},
"WolverineFx": {
"type": "Direct",
"requested": "[5.8.0, )",
"resolved": "5.8.0",
"contentHash": "BzHf+tPyU48gtJkyKuDKsWk8v8K55P6bcCehCTqsTdLzCrb0frQKvB7LHtHURwagvXvqBHiLZQuTT50KS2shew==",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "kHmwFs3QpM9WaXZ3k+ruV/MKBdZYqFLGciTfMpbHWFwfp9BqLgXqY9T5rUvWamSU69qh93yBog7PmZOv5umidg==",
"dependencies": {
"JasperFx": "1.11.3",
"JasperFx.Events": "1.12.2",
Expand Down Expand Up @@ -736,6 +742,13 @@
"resolved": "8.0.4",
"contentHash": "pBrE2re4pjuvOJTsnApY2calA2VXEfk+GSXigCVvLpD3PL19a5NzhB4a//IlVtaL31jcY30WI8WDDHqhCaKxvw=="
}
},
"net10.0/linux-x64": {
"System.Diagnostics.EventLog": {
"type": "Transitive",
"resolved": "10.0.0",
"contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
}
}
}
}
53 changes: 48 additions & 5 deletions src/Morphir/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
"Oakton": "6.3.0"
}
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.1, )",
"resolved": "10.0.1",
"contentHash": "ISahzLHsHY7vrwqr2p1YWZ+gsxoBRtH7gWRDK8fDUst9pp2He0GiesaqEfeX0V8QMCJM3eNEHGGpnIcPjFo2NQ=="
},
"Serilog": {
"type": "Direct",
"requested": "[4.3.0, )",
Expand Down Expand Up @@ -81,9 +87,9 @@
},
"WolverineFx": {
"type": "Direct",
"requested": "[5.8.0, )",
"resolved": "5.8.0",
"contentHash": "BzHf+tPyU48gtJkyKuDKsWk8v8K55P6bcCehCTqsTdLzCrb0frQKvB7LHtHURwagvXvqBHiLZQuTT50KS2shew==",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "kHmwFs3QpM9WaXZ3k+ruV/MKBdZYqFLGciTfMpbHWFwfp9BqLgXqY9T5rUvWamSU69qh93yBog7PmZOv5umidg==",
"dependencies": {
"JasperFx": "1.11.3",
"JasperFx.Events": "1.12.2",
Expand Down Expand Up @@ -680,11 +686,11 @@
"Json.More.Net": "[2.2.0, )",
"JsonSchema.Net": "[8.0.3, )",
"Microsoft.Extensions.Hosting": "[10.0.0, )",
"Morphir.Core": "[1.0.0, )",
"Morphir.Core": "[0.3.0-rc.2, )",
"Serilog": "[4.3.0, )",
"Serilog.Extensions.Hosting": "[5.0.1, )",
"Serilog.Sinks.Console": "[6.1.1, )",
"WolverineFx": "[5.8.0, )"
"WolverineFx": "[5.9.0, )"
}
},
"Dunet": {
Expand Down Expand Up @@ -807,6 +813,43 @@
"resolved": "8.0.4",
"contentHash": "pBrE2re4pjuvOJTsnApY2calA2VXEfk+GSXigCVvLpD3PL19a5NzhB4a//IlVtaL31jcY30WI8WDDHqhCaKxvw=="
}
},
"net10.0/linux-x64": {
"Extism.runtime.linux-arm64": {
"type": "Transitive",
"resolved": "1.13.0",
"contentHash": "JKTbKrJ9zqxfKaYBEJQX1bBky6kug/i+uU462Etu9MrnC00t6+FsNzW+lg8O6kqZIZIw+k/QSzQJTbE9+ACoXQ=="
},
"Extism.runtime.linux-musl-arm64": {
"type": "Transitive",
"resolved": "1.13.0",
"contentHash": "a2PUlV8dc9kgUZa8PBb6VuEo8tioX0wQnU0Rn8J5ZGBECoC68VayBmIfdx+OmR9pzpN6IsorjTPlBoRvGHhy3w=="
},
"Extism.runtime.linux-x64": {
"type": "Transitive",
"resolved": "1.13.0",
"contentHash": "/WEePguMvmRn/IY34iFuFNOS28RCKBPBKKG3xpUfpZ7bcnj80e/NPyyMRQQLaZSBJkiDvn7hJwJvt+n3cPF7rA=="
},
"Extism.runtime.osx-arm64": {
"type": "Transitive",
"resolved": "1.13.0",
"contentHash": "L19ANqXBgEZHDrWiQGRz+BGi8N7Rqirw7QTbEKFyJEutEfO25IafOQgr+UAk7/fXCRgUEz55KlBDhMETlEZeVg=="
},
"Extism.runtime.osx-x64": {
"type": "Transitive",
"resolved": "1.13.0",
"contentHash": "BJawGsM0VP2uUf0X4J4wVer9k7G7dmDmMGDWjC21nmVFsfkswWsYmM8SkB9S98rAofni6yvNwT23MOSfu8RGPw=="
},
"Extism.runtime.win-x64": {
"type": "Transitive",
"resolved": "1.13.0",
"contentHash": "tezN2DRh8PWrKHZiP8fDqnFRASGyxL2lVeDVDPV8YqHVGzqAl1POzYUvxkNkGeozHSrCWJ4ZCTJg4TmG6GQdwg=="
},
"System.Diagnostics.EventLog": {
"type": "Transitive",
"resolved": "10.0.0",
"contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
}
}
}
}
2 changes: 1 addition & 1 deletion tests/Morphir.E2E.Tests/Infrastructure/ExecutableRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public async Task<ExecutableExecutionResult> ExecuteCommandAsync(
/// <summary>
/// Check if a line is an infrastructure log message that should be filtered
/// </summary>
private static bool IsInfrastructureLogMessage(string line)
internal static bool IsInfrastructureLogMessage(string line)
{
if (string.IsNullOrWhiteSpace(line))
return true;
Expand Down
186 changes: 186 additions & 0 deletions tests/Morphir.E2E.Tests/Infrastructure/ExecutableRunnerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
using FluentAssertions;
using TUnit.Core;

namespace Morphir.E2E.Tests.Infrastructure;

/// <summary>
/// Unit tests for ExecutableRunner log filtering to ensure infrastructure logs don't contaminate test output
/// </summary>
public class ExecutableRunnerTests
{
[Test]
public void IsInfrastructureLogMessage_ShouldFilter_WolverineFx58Patterns()
{
// WolverineFx 5.8.0 log patterns
var wolverine58Logs = new[]
{
"[07:05:03 INF] Searching assembly Morphir.Tooling, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null for Wolverine message handlers",
"[07:05:03 INF] Wolverine assigned node id for envelope persistence is -2035786101",
"[07:05:03 INF] Started message listening at stub://replies/",
"[07:05:03 INF] Application started. Press Ctrl+C to shut down.",
"[07:05:03 INF] Hosting environment: Production",
"[07:05:03 INF] Content root path: /home/runner/work/morphir-dotnet/morphir-dotnet",
"[07:05:03 INF] Application is shutting down...",
"[07:05:30 INF] Starting Wolverine messaging for application assembly Morphir.Tooling, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null",
"[07:05:30 INF] The Wolverine code generation mode is Static with pre-generated types being loaded from Morphir.Tooling, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null.",
"[07:05:30 INF] See https://wolverine.netlify.app/guide/codegen.html for more information about debugging static type loading issues with Wolverine"
};

foreach (var log in wolverine58Logs)
{
ExecutableRunner.IsInfrastructureLogMessage(log).Should().BeTrue($"'{log}' should be filtered");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldFilter_WolverineFx59Patterns()
{
// WolverineFx 5.9.0 new log patterns
var wolverine59Logs = new[]
{
"[07:06:06 INF] Exporting Open Telemetry metrics from Wolverine with name Wolverine:Morphir.Tooling, version 5.9.0.0",
// All 5.8.0 patterns should still work
"[07:06:06 INF] Starting Wolverine messaging for application assembly Morphir.Tooling, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null",
"[07:06:06 INF] The Wolverine code generation mode is Static with pre-generated types being loaded from Morphir.Tooling, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null.",
"[07:06:06 INF] See https://wolverine.netlify.app/guide/codegen.html for more information about debugging static type loading issues with Wolverine",
"[07:06:06 INF] Searching assembly Morphir.Tooling, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null for Wolverine message handlers",
"[07:06:06 INF] Wolverine assigned node id for envelope persistence is -1376780885",
"[07:06:06 INF] Started message listening at stub://replies/",
"[07:06:06 INF] Application started. Press Ctrl+C to shut down.",
"[07:06:06 INF] Hosting environment: Production",
"[07:06:06 INF] Content root path: /home/runner/work/morphir-dotnet/morphir-dotnet",
"[07:06:06 INF] Application is shutting down..."
};

foreach (var log in wolverine59Logs)
{
ExecutableRunner.IsInfrastructureLogMessage(log).Should().BeTrue($"'{log}' should be filtered");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldNotFilter_ActualCommandOutput()
{
// Actual command output that should NOT be filtered
var commandOutputs = new[]
{
"✓ VALID",
"✗ INVALID",
"Schema Version: v3",
"Morphir command line",
"Commands:",
"Description:",
"Usage:",
"{\"IsValid\":true,\"SchemaVersion\":\"3\",\"DetectionMethod\":\"auto\"}",
"[{\"Path\":\"$.formatVersion\",\"Message\":\"Missing required property\"}]",
"⚠ Warning: Code generation directory not found",
"✓ Wolverine code written to src/Morphir.Tooling/Internal/Generated"
};

foreach (var output in commandOutputs)
{
ExecutableRunner.IsInfrastructureLogMessage(output).Should().BeFalse($"'{output}' should NOT be filtered");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldNotFilter_ErrorMessages()
{
// Error messages that should NOT be filtered (except when they're JSON output)
var errorMessages = new[]
{
"fail: Validation failed",
"error: File not found",
"Error: Invalid schema version"
};

foreach (var error in errorMessages)
{
ExecutableRunner.IsInfrastructureLogMessage(error).Should().BeFalse($"'{error}' should NOT be filtered");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldNotFilter_JsonOutputErrorsField()
{
// JSON output with "Errors" field should NOT be filtered
var jsonOutputs = new[]
{
" \"Errors\": [",
"{\"IsValid\":false,\"Errors\":[{\"Path\":\"$.formatVersion\"}]}"
};

// These should NOT be filtered because they are valid JSON output
foreach (var json in jsonOutputs)
{
ExecutableRunner.IsInfrastructureLogMessage(json).Should().BeFalse($"'{json}' should NOT be filtered (valid JSON output)");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldFilter_InfoPrefixedLogs()
{
// Logs with "info:" prefix from Microsoft.Hosting or Wolverine
var infoPrefixedLogs = new[]
{
"info: Wolverine.WolverineExtensions[0]",
"info: Microsoft.Hosting.Lifetime[0]"
};

foreach (var log in infoPrefixedLogs)
{
ExecutableRunner.IsInfrastructureLogMessage(log).Should().BeTrue($"'{log}' should be filtered");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldFilter_SerilogFormattedLogs()
{
// Serilog formatted log messages with [HH:mm:ss LEVEL] pattern
// Added in PR #244 to handle WolverineFx 5.8.0+ log output
var serilogLogs = new[]
{
"[07:05:03 INF] Any info level message",
"[23:59:59 INF] Info message at end of day",
"[00:00:00 INF] Info message at midnight",
"[12:34:56 WRN] Any warning level message",
"[01:23:45 WRN] Warning with details",
"[11:22:33 DBG] Any debug level message",
"[09:08:07 DBG] Debug trace information"
};

foreach (var log in serilogLogs)
{
ExecutableRunner.IsInfrastructureLogMessage(log).Should().BeTrue($"'{log}' should be filtered");
}
}

[Test]
public void IsInfrastructureLogMessage_ShouldNotFilter_NonSerilogBracketedContent()
{
// Content with brackets that should NOT match Serilog pattern
var nonSerilogContent = new[]
{
"[INFO] Not Serilog format - no timestamp",
"[07:05] Missing log level",
"[Not a timestamp INF] Wrong format",
"[ERROR] Different log format",
"Some text [07:05:03 INF] with log in middle",
" [07:05:03 INF] Indented log message should still filter" // This SHOULD filter (leading spaces ok)
};

// First 5 should NOT be filtered, last one SHOULD be filtered
for (int i = 0; i < nonSerilogContent.Length - 1; i++)
{
ExecutableRunner.IsInfrastructureLogMessage(nonSerilogContent[i]).Should().BeFalse(
$"'{nonSerilogContent[i]}' should NOT be filtered (doesn't start with Serilog pattern)");
}

// The indented one should be filtered because regex anchors to start after whitespace is trimmed
// Actually, looking at the regex: ^\[\d{2}:\d{2}:\d{2}\s+(INF|WRN|DBG)\]
// The ^ means start of string, so indented lines won't match. Let me verify:
var indentedLog = " [07:05:03 INF] Indented log message";
ExecutableRunner.IsInfrastructureLogMessage(indentedLog).Should().BeFalse(
$"'{indentedLog}' should NOT be filtered (regex uses ^ anchor which doesn't match indented lines)");
}
}
Loading
Loading