2021-04-29 15:35:57 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
2022-03-23 10:41:59 -04:00
using System ;
using System.Collections.Generic ;
2022-05-19 14:34:21 -04:00
using System.Linq ;
2022-09-14 11:53:21 -04:00
using System.Runtime.InteropServices ;
2022-03-23 10:41:59 -04:00
using System.Text ;
2021-04-29 15:10:34 -04:00
using EpicGames.Core ;
2024-04-17 10:39:36 -04:00
using EpicGames.Perforce ;
2021-04-29 15:10:34 -04:00
using Microsoft.Extensions.Logging ;
using Microsoft.VisualStudio.TestTools.UnitTesting ;
2024-04-25 09:23:28 -04:00
namespace AutomationTool.Tests
2021-04-29 15:10:34 -04:00
{
[TestClass]
public class LogParserTests
{
2021-11-08 12:18:49 -05:00
const string LogLine = "LogLine" ;
2021-04-29 15:10:34 -04:00
2022-09-14 11:53:21 -04:00
static readonly DirectoryReference s_rootDir = new DirectoryReference ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ? "C:\\Horde" : "/horde" ) ;
static string MakeAbsolutePath ( string path ) = > FileReference . Combine ( s_rootDir , path ) . FullName ;
2021-04-29 15:10:34 -04:00
class LoggerCapture : ILogger
{
2022-03-21 09:19:47 -04:00
int _logLineIndex ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
public List < LogEvent > _events = new List < LogEvent > ( ) ;
2021-04-29 15:10:34 -04:00
2024-04-17 10:39:36 -04:00
public IDisposable BeginScope < TState > ( TState state ) = > null ! ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
public bool IsEnabled ( LogLevel logLevel ) = > true ;
2021-04-29 15:10:34 -04:00
2022-08-11 21:59:55 -04:00
public void Log < TState > ( LogLevel logLevel , EventId eventId , TState state , Exception ? exception , Func < TState , Exception ? , string > formatter )
2021-04-29 15:10:34 -04:00
{
2022-05-16 16:15:28 -04:00
LogEvent logEvent = LogEvent . Read ( JsonLogEvent . FromLoggerState ( logLevel , eventId , state , exception , formatter ) . Data . Span ) ;
if ( logEvent . Level ! = LogLevel . Information | | logEvent . Id ! = default | | logEvent . Properties ! = null )
2021-04-29 15:10:34 -04:00
{
2022-05-19 14:34:21 -04:00
KeyValuePair < string , object > [ ] items = new [ ] { new KeyValuePair < string , object > ( LogLine , _logLineIndex ) } ;
logEvent . Properties = ( logEvent . Properties = = null ) ? items : Enumerable . Concat ( logEvent . Properties , items ) ;
2022-03-21 09:19:47 -04:00
_events . Add ( logEvent ) ;
2021-04-29 15:10:34 -04:00
}
2022-05-16 16:15:28 -04:00
2022-03-21 09:19:47 -04:00
_logLineIndex + + ;
2021-04-29 15:10:34 -04:00
}
}
2021-10-28 10:55:48 -04:00
[TestMethod]
public void StructuredOutputMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-10-28 10:55:48 -04:00
{
2022-05-16 16:15:28 -04:00
new LogEvent ( DateTime . UtcNow , LogLevel . Information , new EventId ( 123 ) , "Hello 123" , null , null , null ) . ToJson ( ) ,
new LogEvent ( DateTime . UtcNow , LogLevel . Information , default , "Building 43 projects (see Log \u0027Engine/Programs/AutomationTool/Saved/Logs/Log.txt\u0027 for more details)" , null , null , null ) . ToJson ( ) ,
new LogEvent ( DateTime . UtcNow , LogLevel . Warning , default , " Restore..." , null , null , null ) . ToJson ( ) ,
new LogEvent ( DateTime . UtcNow , LogLevel . Error , default , " Build..." , null , null , null ) . ToJson ( ) ,
2021-10-28 10:55:48 -04:00
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 3 , logEvents . Count ) ;
2021-10-28 10:55:48 -04:00
2022-03-21 09:19:47 -04:00
int idx = 0 ;
2021-10-28 10:55:48 -04:00
2022-03-21 09:19:47 -04:00
LogEvent logEvent = logEvents [ idx + + ] ;
Assert . AreEqual ( LogLevel . Information , logEvent . Level ) ;
Assert . AreEqual ( new EventId ( 123 ) , logEvent . Id ) ;
Assert . AreEqual ( "Hello 123" , logEvent . Message ) ;
2021-10-28 10:55:48 -04:00
2022-03-21 09:19:47 -04:00
logEvent = logEvents [ idx + + ] ;
Assert . AreEqual ( LogLevel . Warning , logEvent . Level ) ;
Assert . AreEqual ( new EventId ( 0 ) , logEvent . Id ) ;
Assert . AreEqual ( " Restore..." , logEvent . Message ) ;
2021-10-28 10:55:48 -04:00
2022-03-21 09:19:47 -04:00
logEvent = logEvents [ idx + + ] ;
Assert . AreEqual ( LogLevel . Error , logEvent . Level ) ;
Assert . AreEqual ( new EventId ( 0 ) , logEvent . Id ) ;
Assert . AreEqual ( " Build..." , logEvent . Message ) ;
2021-10-28 10:55:48 -04:00
}
2021-04-29 15:10:34 -04:00
[TestMethod]
public void ExitCodeEventMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@"Took 620.820352s to run UE4Editor-Cmd.exe, ExitCode=777003" ,
2022-09-16 15:05:51 -04:00
@"Editor terminated with exit code 777003 while running GenerateSkinSwapDetections for D:\Build\++UE5\Sync\ShooterGame\ShooterGame.uproject; see log D:\Build\++UE5\Sync\Engine\Programs\AutomationTool\Saved\Logs\GenerateSkinSwapDetections-2020.08.18-21.47.07.txt" ,
@"Error executing D:\build\++ShooterGame\Sync\Engine\Build\Windows\link - filter\link - filter.exe(tool returned code: STATUS_ACCESS_VIOLATION)" ,
2022-02-23 13:00:27 -05:00
@"Error executing C:\Windows\system32\cmd.exe (tool returned code: 1)" ,
2022-06-14 20:46:54 -04:00
@"AutomationTool exiting with ExitCode=1 (Error_Unknown)" ,
2021-04-29 15:10:34 -04:00
@"BUILD FAILED"
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
2022-06-14 20:46:54 -04:00
CheckEventGroup ( logEvents , 1 , 3 , LogLevel . Error , KnownLogEvents . ExitCode ) ;
2021-04-29 15:10:34 -04:00
}
2022-06-02 14:08:20 -04:00
[TestMethod]
public void ExitCodeEventMatcher2 ( )
{
string [ ] lines =
{
@"1 error generated." ,
@"" ,
@"Error executing d:\build\AutoSDK\Sync\HostWin64\Android\-24\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe (tool returned code: 1)" ,
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
2022-06-03 09:43:36 -04:00
CheckEventGroup ( logEvents , 2 , 1 , LogLevel . Error , KnownLogEvents . ExitCode ) ;
2022-06-02 14:08:20 -04:00
}
2022-11-11 12:08:08 -05:00
[TestMethod]
public void ExitCodeEventMatcher3 ( )
{
string [ ] lines =
{
@"Took 5406.5523184s to run UnrealEditor-Cmd.exe, ExitCode=-1073741819" ,
@"Editor terminated with exit code -1073741819 while running Cook for D:\build\++UE5\Sync\Samples\Games\AncientGame\AncientGame.uproject; see log d:\build\++UE5\Sync\Engine\Programs\AutomationTool\Saved\Logs\Cook-2022.11.11-08.02.19.txt" ,
@"AutomationTool executed for 1h 33m 5s" ,
@"AutomationTool exiting with ExitCode=1 (Error_Unknown)" ,
@"BUILD FAILED"
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 1 , 1 , LogLevel . Error , KnownLogEvents . ExitCode ) ;
}
2021-04-29 15:10:34 -04:00
[TestMethod]
public void CrashEventMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@" LogOutputDevice: Error: begin: stack for UAT" ,
@" LogOutputDevice: Error: === Handled ensure: ===" ,
@" LogOutputDevice: Error:" ,
@" LogOutputDevice: Error: Ensure condition failed: Foo [File:D:/build/++UE5/Sync/Foo.cpp] [Line: 233]" ,
@" LogOutputDevice: Error:" ,
@" LogOutputDevice: Error: Stack:" ,
@" LogOutputDevice: Error: [Callstack] 0x00007ff6b68a035d UnrealEditor-Cmd.exe!GuardedMain() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Launch.cpp:129]" ,
@" LogOutputDevice: Error: [Callstack] 0x00007ff6b68a05fa UnrealEditor-Cmd.exe!GuardedMainWrapper() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:142]" ,
@" LogOutputDevice: Error: [Callstack] 0x00007ff6b68b522d UnrealEditor-Cmd.exe!WinMain() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:273]" ,
@" LogOutputDevice: Error: [Callstack] 0x00007ff6b68b7522 UnrealEditor-Cmd.exe!__scrt_common_main_seh() [D:\a01\_work\9\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288]" ,
@" LogOutputDevice: Error: [Callstack] 0x00007ff96a517974 KERNEL32.DLL!UnknownFunction []" ,
@" LogOutputDevice: Error: [Callstack] 0x00007ff96d14a271 ntdll.dll!UnknownFunction []" ,
@" LogOutputDevice: Error:" ,
@" LogOutputDevice: Error: end: stack for UAT"
} ;
{
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
CheckEventGroup ( logEvents , 0 , 14 , LogLevel . Error , KnownLogEvents . Engine_Crash ) ;
2021-04-29 15:10:34 -04:00
}
{
2022-05-17 15:51:07 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) . Replace ( "Error:" , "Warning:" , StringComparison . Ordinal ) ) ;
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents , 0 , 14 , LogLevel . Warning , KnownLogEvents . Engine_Crash ) ;
2021-04-29 15:10:34 -04:00
}
}
2021-10-06 14:12:18 -04:00
[TestMethod]
public void CrashEventMatcher2 ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-10-06 14:12:18 -04:00
{
@"Took 620.820352s to run UE4Editor-Cmd.exe, ExitCode=3" ,
@"Took 620.820352s to run UE4Editor-Cmd.exe, ExitCode=30" ,
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Error , KnownLogEvents . AutomationTool_CrashExitCode ) ;
2021-10-06 14:12:18 -04:00
}
2022-12-14 15:50:39 -05:00
[TestMethod]
public void AssertionFailedEventMatcher ( )
{
string [ ] lines =
{
@"Assertion failed: !NumUsed.GetValue() [File:Runtime/Core/Public/Containers/LockFreeFixedSizeAllocator.h] [Line: 201]"
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Error , KnownLogEvents . Engine_AssertionFailed ) ;
}
2021-04-29 15:10:34 -04:00
[TestMethod]
public void SymbolStripSpuriousEventMatcher ( )
{
// Symbol stripping error
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@"Stripping symbols: d:\build\++UE5\Sync\Engine\Plugins\Runtime\GoogleVR\GoogleVRController\Binaries\Win64\UnrealEditor-GoogleVRController.pdb -> d:\build\++UE5\Sync\ArchiveForUGS\Staging\Engine\Plugins\Runtime\GoogleVR\GoogleVRController\Binaries\Win64\UnrealEditor-GoogleVRController.pdb" ,
@"ERROR: Error: EC_OK -- ??" ,
@"ERROR:" ,
@"Stripping symbols: d:\build\++UE5\Sync\Engine\Plugins\Runtime\GoogleVR\GoogleVRHMD\Binaries\Win64\UnrealEditor-GoogleVRHMD.pdb -> d:\build\++UE5\Sync\ArchiveForUGS\Staging\Engine\Plugins\Runtime\GoogleVR\GoogleVRHMD\Binaries\Win64\UnrealEditor-GoogleVRHMD.pdb" ,
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
2023-02-28 09:13:04 -05:00
CheckEventGroup ( logEvents , 1 , 2 , LogLevel . Information , KnownLogEvents . Systemic_PdbUtil ) ;
2021-04-29 15:10:34 -04:00
}
}
[TestMethod]
public void CsCompileEventMatcher ( )
{
// C# compile error
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
2022-09-14 12:20:36 -04:00
@" GenerateSigningRequestDialog.cs(22,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [" + MakeAbsolutePath ( @"Engine\Source\Programs\IOS\iPhonePackager\iPhonePackager.csproj" ) + @"]" ,
@" Utilities.cs(16,7): error CS0246: The type or namespace name 'Org' could not be found (are you missing a using directive or an assembly reference?) [" + MakeAbsolutePath ( @"Engine\Source\Programs\IOS\iPhonePackager\iPhonePackager.csproj" ) + @"]"
2021-04-29 15:10:34 -04:00
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
Assert . AreEqual ( 2 , logEvents . Count ) ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 0 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "CS0246" , logEvents [ 0 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "22" , logEvents [ 0 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty1 = ( LogValue ) logEvents [ 0 ] . GetProperty ( "file" ) ;
2022-03-21 09:19:47 -04:00
Assert . AreEqual ( @"GenerateSigningRequestDialog.cs" , fileProperty1 . Text ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty1 . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Engine/Source/Programs/IOS/iPhonePackager/GenerateSigningRequestDialog.cs" , fileProperty1 . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
Assert . AreEqual ( @"//UE4/Main/Engine/Source/Programs/IOS/iPhonePackager/GenerateSigningRequestDialog.cs@12345" , fileProperty1 . Properties [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 1 , 1 ) , 1 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "CS0246" , logEvents [ 1 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "16" , logEvents [ 1 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty2 = ( LogValue ) logEvents [ 1 ] . GetProperty ( "file" ) ;
2022-03-21 09:19:47 -04:00
Assert . AreEqual ( @"Utilities.cs" , fileProperty2 . Text ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty2 . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Engine/Source/Programs/IOS/iPhonePackager/Utilities.cs" , fileProperty2 . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
Assert . AreEqual ( @"//UE4/Main/Engine/Source/Programs/IOS/iPhonePackager/Utilities.cs@12345" , fileProperty2 . Properties [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
}
[TestMethod]
public void CsCompileEventMatcher2 ( )
{
// C# compile error
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
2022-09-14 12:20:36 -04:00
@" Configuration\TargetRules.cs(1497,58): warning CS8625: Cannot convert null literal to non-nullable reference type. [" + MakeAbsolutePath ( @"Engine\Source\Programs\UnrealBuildTool\UnrealBuildTool.csproj" ) + @"]" ,
2021-04-29 15:10:34 -04:00
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > events = Parse ( String . Join ( "\n" , lines ) ) ;
CheckEventGroup ( events , 0 , 1 , LogLevel . Warning , KnownLogEvents . Compiler ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "CS8625" , events [ 0 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "1497" , events [ 0 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty = ( LogValue ) events [ 0 ] . GetProperty ( "file" ) ;
2022-03-21 09:19:47 -04:00
Assert . AreEqual ( @"Configuration\TargetRules.cs" , fileProperty . Text ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs" , fileProperty . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
Assert . AreEqual ( @"//UE4/Main/Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs@12345" , fileProperty . Properties ! [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
}
[TestMethod]
public void CsCompileEventMatcher3 ( )
{
// C# compile error from UBT
{
2022-09-14 11:53:21 -04:00
string absPath = MakeAbsolutePath ( @"Engine\Source\Runtime\CoreOnline\CoreOnline.Build.cs" ) ;
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
2022-09-14 11:53:21 -04:00
@" ERROR: " + absPath + @"(4,7): error CS0246: The type or namespace name 'Tools' could not be found (are you missing a using directive or an assembly reference?)" ,
@" WARNING: " + absPath + @"(4,7): warning CS0246: The type or namespace name 'Tools' could not be found (are you missing a using directive or an assembly reference?)"
2021-04-29 15:10:34 -04:00
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
Assert . AreEqual ( 2 , logEvents . Count ) ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 0 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "CS0246" , logEvents [ 0 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "4" , logEvents [ 0 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty = ( LogValue ) logEvents [ 0 ] . GetProperty ( "file" ) ;
2022-09-14 11:53:21 -04:00
Assert . AreEqual ( absPath , fileProperty . Text ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Engine/Source/Runtime/CoreOnline/CoreOnline.Build.cs" , fileProperty . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
Assert . AreEqual ( @"//UE4/Main/Engine/Source/Runtime/CoreOnline/CoreOnline.Build.cs@12345" , fileProperty . Properties ! [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 1 , 1 ) , 1 , 1 , LogLevel . Warning , KnownLogEvents . Compiler ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "CS0246" , logEvents [ 1 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "4" , logEvents [ 1 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty1 = logEvents [ 1 ] . GetProperty < LogValue > ( "file" ) ;
2022-09-14 11:53:21 -04:00
Assert . AreEqual ( absPath , fileProperty1 . Text ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty1 . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Engine/Source/Runtime/CoreOnline/CoreOnline.Build.cs" , fileProperty1 . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
Assert . AreEqual ( @"//UE4/Main/Engine/Source/Runtime/CoreOnline/CoreOnline.Build.cs@12345" , fileProperty1 . Properties ! [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
}
2023-09-06 13:42:06 -04:00
[TestMethod]
public void CsCompileEventMatcher4 ( )
{
// C# compile error from UBT startup
{
string [ ] lines =
{
@"Building AutomationTool..." ,
@"Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET" ,
@"Copyright (C) Microsoft Corporation. All rights reserved." ,
@"Engine/Source/Programs/Shared/EpicGames.Horde/Storage/Workspace.cs(405,11): error CS1501: No overload for method 'ReadList' takes 2 arguments [Engine/Source/Programs/Shared/EpicGames.Horde/EpicGames.Horde.csproj]" ,
@"Engine/Source/Programs/Shared/EpicGames.Horde/Storage/Workspace.cs(423,12): error CS1501: No overload for method 'ReadList' takes 2 arguments [Engine/Source/Programs/Shared/EpicGames.Horde/EpicGames.Horde.csproj]" ,
@"Build FAILED." ,
@"Engine/Source/Programs/Shared/EpicGames.Horde/Storage/Workspace.cs(405,11): error CS1501: No overload for method 'ReadList' takes 2 arguments [Engine/Source/Programs/Shared/EpicGames.Horde/EpicGames.Horde.csproj]" ,
@"Engine/Source/Programs/Shared/EpicGames.Horde/Storage/Workspace.cs(423,12): error CS1501: No overload for method 'ReadList' takes 2 arguments [Engine/Source/Programs/Shared/EpicGames.Horde/EpicGames.Horde.csproj]" ,
@" 0 Warning(s)" ,
@" 2 Error(s)" ,
@"Time Elapsed 00:00:06.84" ,
@"RunUBT ERROR: UnrealBuildTool failed to compile." ,
@"RunUAT.bat ERROR: AutomationTool failed to compile." ,
@"BUILD FAILED" ,
} ;
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
Assert . AreEqual ( 6 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 3 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 1 , 1 ) , 4 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 2 , 1 ) , 6 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 3 , 1 ) , 7 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 4 , 1 ) , 11 , 1 , LogLevel . Error , KnownLogEvents . Compiler_Summary ) ;
CheckEventGroup ( logEvents . Slice ( 5 , 1 ) , 12 , 1 , LogLevel . Error , KnownLogEvents . Compiler_Summary ) ;
}
}
2023-10-12 14:34:42 -04:00
[TestMethod]
public void CsCompileEventMatcher5 ( )
{
string [ ] lines =
{
@" EpicGames.BuildGraph.Tests -> /mnt/horde/DMH/Sync/Engine/Source/Programs/Shared/EpicGames.BuildGraph.Tests/bin/Analyze/net6.0/EpicGames.BuildGraph.Tests.dll" ,
@"Engine/Source/Programs/Shared/EpicGames.Horde/Storage/BlobData.cs(4,1): warning IDE0005: Using directive is unnecessary. [/mnt/horde/DMH/Sync/Engine/Source/Programs/Shared/EpicGames.Horde/EpicGames.Horde.csproj]" ,
@"Engine/Source/Programs/Shared/EpicGames.Horde/Storage/BlobData.cs(7,1): warning IDE0005: Using directive is unnecessary. [/mnt/horde/DMH/Sync/Engine/Source/Programs/Shared/EpicGames.Horde/EpicGames.Horde.csproj]" ,
@" EpicGames.Horde -> /mnt/horde/DMH/Sync/Engine/Source/Programs/Shared/EpicGames.Horde/bin/Analyze/net6.0/EpicGames.Horde.dll" ,
@" RemoteWorker -> /mnt/horde/DMH/Sync/Engine/Source/Programs/Horde/Samples/RemoteWorker/bin/Debug/net6.0/RemoteWorker.dll" ,
@" EpicGames.Serialization.Tests -> /mnt/horde/DMH/Sync/Engine/Source/Programs/Shared/EpicGames.Serialization.Tests/bin/Analyze/net6.0/EpicGames.Serialization.Tests.dll" ,
} ;
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
Assert . AreEqual ( 2 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 1 , 1 , LogLevel . Warning , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 1 , 1 ) , 2 , 1 , LogLevel . Warning , KnownLogEvents . Compiler ) ;
}
2021-05-20 09:24:18 -04:00
[TestMethod]
public void HttpEventMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-05-20 09:24:18 -04:00
{
@"WARNING: Failed to resolve binaries for artifact fe1b277b-7751-4a52-8059-ec3f943811de:xsx with error: fe1b277b-7751-4a52-8059-ec3f943811de:xsx Failed.Unexpected error retrieving response.BaseUrl = https://content-service-latest-gamedev.cdae.dev.use1a.on.epicgames.com/api. Status = Timeout. McpConfig = ValkyrieDevLatest."
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Warning , KnownLogEvents . Generic ) ;
2021-05-20 09:24:18 -04:00
}
2021-04-29 15:10:34 -04:00
[TestMethod]
public void MicrosoftEventMatcher ( )
{
// Generic Microsoft errors which can be parsed by visual studio
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
2022-09-14 12:20:36 -04:00
@" " + MakeAbsolutePath ( @"Foo\Bar.txt" ) + @"(20): warning TL2012: Some error message" ,
@" " + MakeAbsolutePath ( @"Foo\Bar.txt" ) + @"(20, 30) : warning TL2034: Some error message" ,
2021-04-29 15:10:34 -04:00
@" CSC : error CS2012: Cannot open 'D:\Build\++UE4\Sync\Engine\Source\Programs\Enterprise\Datasmith\DatasmithRevitExporter\Resources\obj\Release\DatasmithRevitResources.dll' for writing -- 'The process cannot access the file 'D:\Build\++UE4\Sync\Engine\Source\Programs\Enterprise\Datasmith\DatasmithRevitExporter\Resources\obj\Release\DatasmithRevitResources.dll' because it is being used by another process.' [D:\Build\++UE4\Sync\Engine\Source\Programs\Enterprise\Datasmith\DatasmithRevitExporter\Resources\DatasmithRevitResources.csproj]"
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
Assert . AreEqual ( 3 , logEvents . Count ) ;
2021-04-29 15:10:34 -04:00
// 0
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 0 , 1 , LogLevel . Warning , KnownLogEvents . Microsoft ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "TL2012" , logEvents [ 0 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "20" , logEvents [ 0 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty0 = ( LogValue ) logEvents [ 0 ] . GetProperty ( "file" ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty0 . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Foo/Bar.txt" , fileProperty0 . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
// 1
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 1 , 1 ) , 1 , 1 , LogLevel . Warning , KnownLogEvents . Microsoft ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "TL2034" , logEvents [ 1 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "20" , logEvents [ 1 ] . GetProperty ( "line" ) . ToString ( ) ) ;
Assert . AreEqual ( "30" , logEvents [ 1 ] . GetProperty ( "column" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue fileProperty1 = logEvents [ 1 ] . GetProperty < LogValue > ( "file" ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , fileProperty1 . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"Foo/Bar.txt" , fileProperty1 . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
// 2
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents . Slice ( 2 , 1 ) , 2 , 1 , LogLevel . Error , KnownLogEvents . Microsoft ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "CS2012" , logEvents [ 2 ] . GetProperty ( "code" ) . ToString ( ) ) ;
Assert . AreEqual ( "CSC" , logEvents [ 2 ] . GetProperty ( "tool" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
}
[TestMethod]
public void WarningsAsErrorsEventMatcher ( )
{
// Visual C++ error
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
2022-09-14 12:20:36 -04:00
MakeAbsolutePath ( @"Engine\Plugins\Experimental\VirtualCamera\Source\VirtualCamera\Private\VCamBlueprintFunctionLibrary.cpp" ) + @"(249): error C2220: the following warning is treated as an error" ,
MakeAbsolutePath ( @"Engine\Plugins\Experimental\VirtualCamera\Source\VirtualCamera\Private\VCamBlueprintFunctionLibrary.cpp" ) + @"(249): warning C4996: 'UEditorLevelLibrary::PilotLevelActor': The Editor Scripting Utilities Plugin is deprecated - Use the function in Level Editor Subsystem Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile." ,
2021-04-29 15:10:34 -04:00
@"..\Plugins\Editor\EditorScriptingUtilities\Source\EditorScriptingUtilities\Public\EditorLevelLibrary.h(122): note: see declaration of 'UEditorLevelLibrary::PilotLevelActor'" ,
2022-09-14 12:20:36 -04:00
MakeAbsolutePath ( @"Engine\Plugins\Experimental\VirtualCamera\Source\VirtualCamera\Private\VCamBlueprintFunctionLibrary.cpp" ) + @"(314): warning C4996: 'UEditorLevelLibrary::EditorSetGameView': The Editor Scripting Utilities Plugin is deprecated - Use the function in Level Editor Subsystem Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile." ,
2021-04-29 15:10:34 -04:00
@"..\Plugins\Editor\EditorScriptingUtilities\Source\EditorScriptingUtilities\Public\EditorLevelLibrary.h(190): note: see declaration of 'UEditorLevelLibrary::EditorSetGameView'"
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
Assert . AreEqual ( 5 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 0 , 1 , LogLevel . Error , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 1 , 2 ) , 1 , 2 , LogLevel . Error , KnownLogEvents . Compiler ) ;
CheckEventGroup ( logEvents . Slice ( 3 , 2 ) , 3 , 2 , LogLevel . Error , KnownLogEvents . Compiler ) ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
LogEvent logEvent = logEvents [ 1 ] ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "C4996" , logEvent . GetProperty ( "code" ) . ToString ( ) ) ;
2022-03-21 09:19:47 -04:00
Assert . AreEqual ( LogLevel . Error , logEvent . Level ) ;
2021-04-29 15:10:34 -04:00
2022-03-21 09:19:47 -04:00
//LogValue FileProperty = (LogValue)Event.Properties["file"];
2021-04-29 15:10:34 -04:00
2021-11-08 12:18:49 -05:00
// FIXME: Fails on Linux. Properties dict is empty
//Assert.AreEqual(@"//UE4/Main/Engine/Plugins/Experimental/VirtualCamera/Source/VirtualCamera/Private/VCamBlueprintFunctionLibrary.cpp@12345", FileProperty.Properties["depotPath"].ToString());
2021-04-29 15:10:34 -04:00
2022-05-19 14:34:21 -04:00
LogValue noteProperty1 = logEvents [ 2 ] . GetProperty < LogValue > ( "file" ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( @"SourceFile" , noteProperty1 . Type . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"//UE4/Main/Engine/Plugins/Editor/EditorScriptingUtilities/Source/EditorScriptingUtilities/Public/EditorLevelLibrary.h@12345" , noteProperty1 . Properties ! [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
}
2022-04-15 14:30:03 -04:00
[TestMethod]
public void AssetLogEventMatcher ( )
{
string [ ] lines =
{
2022-09-14 12:20:36 -04:00
@"LogBlueprint: Warning: [AssetLog] " + MakeAbsolutePath ( @"QAGame\Plugins\NiagaraFluids\Content\Blueprints\Phsyarum_BP.uasset" ) + @": [Compiler] Fill Texture 2D : Usage of 'Fill Texture 2D' has been deprecated. This function has been replaced by object user variables on the emitter to specify render targets to fill with data." ,
2022-04-15 14:30:03 -04:00
} ;
2022-09-14 12:20:36 -04:00
List < LogEvent > events = Parse ( String . Join ( "\n" , lines ) ) ;
2022-04-15 14:30:03 -04:00
Assert . AreEqual ( 1 , events . Count ) ;
Assert . AreEqual ( events [ 0 ] . Id , KnownLogEvents . Engine_AssetLog ) ;
2022-05-19 14:34:21 -04:00
LogValue assetProperty = events [ 0 ] . GetProperty < LogValue > ( "asset" ) ;
2023-10-04 11:41:26 -04:00
Assert . AreEqual ( new Utf8String ( "Asset" ) , assetProperty . Type ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( @"//UE4/Main/QAGame/Plugins/NiagaraFluids/Content/Blueprints/Phsyarum_BP.uasset@12345" , assetProperty . Properties ! [ LogEventPropertyName . DepotPath ] . ToString ( ) ) ;
Assert . AreEqual ( @"QAGame/Plugins/NiagaraFluids/Content/Blueprints/Phsyarum_BP.uasset" , assetProperty . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
2022-04-15 14:30:03 -04:00
}
2021-04-29 15:10:34 -04:00
[TestMethod]
public void SourceFileLineEventMatcher ( )
{
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( "ERROR: C:\\Horde\\InstalledEngineBuild.xml(50): Some error" ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Error , KnownLogEvents . AutomationTool_SourceFileLine ) ;
2021-11-08 12:18:49 -05:00
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "ERROR" , logEvents [ 0 ] . GetProperty ( "severity" ) . ToString ( ) ) ;
Assert . AreEqual ( "C:\\Horde\\InstalledEngineBuild.xml" , logEvents [ 0 ] . GetProperty ( "file" ) . ToString ( ) ) ;
Assert . AreEqual ( "50" , logEvents [ 0 ] . GetProperty ( "line" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
[TestMethod]
public void SourceFileEventMatcher ( )
{
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( " WARNING: Engine\\Plugins\\Test\\Foo.cpp: Missing copyright boilerplate" ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Warning , KnownLogEvents . AutomationTool_MissingCopyright ) ;
2021-11-08 12:18:49 -05:00
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "WARNING" , logEvents [ 0 ] . GetProperty ( "severity" ) . ToString ( ) ) ;
Assert . AreEqual ( "Engine\\Plugins\\Test\\Foo.cpp" , logEvents [ 0 ] . GetProperty ( "file" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
[TestMethod]
public void MSBuildEventMatcher ( )
{
2022-09-14 12:20:36 -04:00
List < LogEvent > logEvents = Parse ( @" C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(4207,5): warning MSB3026: Could not copy ""obj\Development\DotNETUtilities.dll"" to ""..\..\..\..\Binaries\DotNET\DotNETUtilities.dll"". Beginning retry 2 in 1000ms. The process cannot access the file '..\..\..\..\Binaries\DotNET\DotNETUtilities.dll' because it is being used by another process. The file is locked by: ""UnrealAutomationTool(13236)"" [" + MakeAbsolutePath ( @"Engine\Source\Programs\DotNETCommon\DotNETUtilities\DotNETUtilities.csproj" ) + @"]" ) ;
2022-03-21 09:19:47 -04:00
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Information , KnownLogEvents . Systemic_MSBuild ) ;
2021-11-08 12:18:49 -05:00
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( "warning" , logEvents [ 0 ] . GetProperty ( "severity" ) . ToString ( ) ) ;
2021-04-29 15:10:34 -04:00
}
[TestMethod]
public void MonoEventMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@"Running: sh -c 'xbuild ""/Users/build/Build/++UE4/Sync/Engine/Source/Programs/AutomationTool/Gauntlet/Gauntlet.Automation.csproj"" /verbosity:quiet /nologo /target:Build /p:Platform=AnyCPU /p:Configuration=Development /p:EngineDir=/Users/build/Build/++UE4/Sync/Engine /p:TreatWarningsAsErrors=false /p:NoWarn=""612,618,672,1591"" /p:BuildProjectReferences=true /p:DefineConstants=MONO /p:DefineConstants=__MonoCS__ /verbosity:quiet /nologo |grep -i error; if [ $? -ne 1 ]; then exit 1; else exit 0; fi'" ,
@" /Users/build/Build/++UE4/Sync/Engine/Source/Programs/AutomationTool/Gauntlet/Gauntlet.Automation.csproj: error : /Users/build/Build/++UE4/Sync/Engine/Source/Programs/AutomationTool/Gauntlet/Gauntlet.Automation.csproj: /Users/build/Build/++UE4/Sync/Engine/Source/Programs/AutomationTool/Gauntlet/Gauntlet.Automation.csproj could not import ""../../../../Platforms/*/Source/Programs/AutomationTool/Gauntlet/*.Gauntlet.targets""" ,
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) ) ;
CheckEventGroup ( logEvents , 1 , 1 , LogLevel . Error , KnownLogEvents . Generic ) ;
2021-04-29 15:10:34 -04:00
}
[TestMethod]
public void AndroidGradleErrorMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #0: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #1: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #2: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #3: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #4: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #5: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #6: shutdown" ,
@" AAPT2 aapt2-4.0.0-6051327-windows Daemon #7: shutdown" ,
@"" ,
@" FAILURE: Build failed with an exception." ,
@"" ,
@" * What went wrong:" ,
@" Execution failed for task ':app:buildUeDevelopmentDebugPreBundle'." ,
@" > Required array size too large" ,
@"" ,
@" * Try:" ,
@" Run with --debug option to get more log output. Run with --scan to get full insights." ,
@"" ,
@" * Exception is:" ,
@" org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:buildUeDevelopmentDebugPreBundle'." ,
@" at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:205)" ,
@" at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263)" ,
@" at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:203)" ,
@" at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:184)" ,
@" at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)" ,
@" at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)" ,
@" at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)" ,
@" at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)" ,
@" at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)" ,
@" at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)" ,
@" at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)" ,
@" at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)" ,
@" at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)" ,
@" at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)" ,
@" at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)" ,
@" at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)" ,
@" at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)" ,
@" at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)" ,
@" at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)" ,
@" at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)" ,
@" at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)" ,
@" at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)" ,
@"" ,
@" Something else"
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 33 , logEvents . Count ) ;
2024-03-15 10:23:20 -04:00
for ( int idx = 0 ; idx < 33 ; idx + + )
2021-11-08 12:18:49 -05:00
{
2022-03-21 09:19:47 -04:00
Assert . AreEqual ( LogLevel . Error , logEvents [ idx ] . Level ) ;
2021-11-08 12:18:49 -05:00
}
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( 9 , logEvents [ 0 ] . GetProperty ( LogLine ) ) ;
Assert . AreEqual ( lines . Length , logEvents [ 0 ] . GetProperty < int > ( LogLine ) + logEvents [ 0 ] . LineCount + 2 ) ;
2021-04-29 15:10:34 -04:00
}
[TestMethod]
public void SuspendLogParsing ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@" <-- Suspend Log Parsing -->" ,
2022-09-16 15:05:51 -04:00
@" Error: File Copy failed with Could not find a part of the path 'P:\Builds\Automation\ShooterGame\Logs\++ShooterGame+Release-14.60\CL-14584315\ShooterGame.QuickSmokeAthena_(Win64_Development_Client)\Client\Saved\Settings\ShooterGame\Saved\Config\CrashReportClient\UE4CC-Win64-C4477473430A2DD50ABDD297FF7811CD\CrashReportClient.ini'.." ,
2021-04-29 15:10:34 -04:00
@" <-- Resume Log Parsing -->"
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 0 , logEvents . Count ) ;
2021-04-29 15:10:34 -04:00
}
2021-05-11 13:12:19 -04:00
[TestMethod]
public void DockerWarningMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-05-11 13:12:19 -04:00
{
@"#14 8.477 cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' -c -o lauxlib.o lauxlib.c" ,
@"#14 8.499 lauxlib.c: In function 'luaL_loadfile':" ,
@"#14 8.499 lauxlib.c:577:4: warning: this 'while' clause does not guard... [-Wmisleading-indentation]" ,
@"#14 8.499 while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;" ,
@"#14 8.499 ^~~~~" ,
@"#14 8.499 lauxlib.c:578:5: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'while'" ,
@"#14 8.499 lf.extraline = 0;" ,
@"#14 8.499 ^~" ,
@"#14 8.643 cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' -c -o lbaselib.o lbaselib.c" ,
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 2 , 1 , LogLevel . Warning , KnownLogEvents . Compiler ) ;
2021-05-11 13:12:19 -04:00
}
2021-06-10 09:26:12 -04:00
[TestMethod]
public void DockerErrorMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-06-10 09:26:12 -04:00
{
@" #14 9.301 cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' -c -o lua.o lua.c" ,
@" #14 9.419 cc -o lua lua.o liblua.a -lm" ,
@" #14 9.447 /usr/bin/ld: liblua.a(loslib.o): in function `os_tmpname':" ,
@" #14 9.447 loslib.c:(.text+0x280): warning: the use of `tmpnam' is dangerous, better use `mkstemp'" ,
@" #14 9.448 cc -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' -c -o luac.o luac.c"
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 2 , 2 , LogLevel . Warning , KnownLogEvents . Linker ) ;
2021-06-10 09:26:12 -04:00
}
2023-09-26 08:53:53 -04:00
[TestMethod]
public void DockerDiskSpaceMatcher ( )
{
string [ ] lines =
{
@" Horde.Server -> /app/out/" ,
@"Error processing tar file(exit status 1): write /app/Source/Programs/Horde/Horde.Server/obj/Release/net6.0/Horde.Server.dll: no space left on device" ,
@"Took 32.59s to run docker, ExitCode=1" ,
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 1 , 1 , LogLevel . Error , KnownLogEvents . Systemic_OutOfDiskSpace ) ;
}
2021-04-29 15:10:34 -04:00
[TestMethod]
public void SystemicErrorMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
2021-04-29 15:10:34 -04:00
{
@" LogDerivedDataCache: Warning: Access to //epicgames.net/root/DDC-Global-UE4 appears to be slow. 'Touch' will be disabled and queries/writes will be limited."
} ;
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Information , KnownLogEvents . Systemic_SlowDDC ) ;
2021-04-29 15:10:34 -04:00
}
2023-10-17 17:31:08 -04:00
[TestMethod]
public void SystemicErrorMatcher2 ( )
{
string [ ] lines =
{
@"LogDerivedDataCache: Warning: //amznfsxahfo0vod.epicgames.net/share/DDC: Loading //amznfsxahfo0vod.epicgames.net/share/DDC/Buckets/Test/d2/31/fca1bb2ff10d802e76beb932c2d43a2d539e.udd from 'CacheRecord' is very slow (0.00 MiB/s); consider disabling this cache store."
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
CheckEventGroup ( logEvents , 0 , 1 , LogLevel . Information , KnownLogEvents . Systemic_SlowDDC ) ;
}
2022-02-17 18:58:59 -05:00
[TestMethod]
public void LogChannelMatcher ( )
{
2022-03-21 09:19:47 -04:00
string [ ] lines =
{
@"Execution of commandlet took: 749.68 seconds" ,
2022-09-16 15:05:51 -04:00
@"LogShooterGAme: Error: Serialized Class /Script/Engine.AnimSequence for a property of Class /Script/Engine.BlendSpace. Reference will be nullptred." ,
2022-02-17 18:58:59 -05:00
@" Property = ObjectProperty /Game/Animation/Game/Enemies/HuskHusky/HuskyHusk_AnimBlueprint.HuskyHusk_AnimBlueprint_C:AnimBlueprintGeneratedConstantData:ObjectProperty_358" ,
@" Item = AnimSequence /Game/Animation/Game/Enemies/HuskyHusk_Riot/Locomotion/Idle/Idle_Shield.Idle_Shield" ,
2022-02-18 08:21:14 -05:00
@"LogDataAssetDirectoryExporter: Display: 'Platform' property is of type: string" ,
2022-02-17 18:58:59 -05:00
@"Took 0.17187880000000003s to run p4.exe, ExitCode=0"
} ;
{
2022-03-21 09:19:47 -04:00
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 4 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 0 , 3 ) , 1 , 3 , LogLevel . Error , KnownLogEvents . Engine_LogChannel ) ;
CheckEventGroup ( logEvents . Slice ( 3 , 1 ) , 4 , 1 , LogLevel . Information , KnownLogEvents . Engine_LogChannel ) ;
2022-02-17 18:58:59 -05:00
}
{
2022-05-17 15:51:07 -04:00
List < LogEvent > logEvents = Parse ( String . Join ( "\n" , lines ) . Replace ( "Error:" , "Warning:" , StringComparison . Ordinal ) ) ;
2022-03-21 09:19:47 -04:00
Assert . AreEqual ( 4 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 0 , 3 ) , 1 , 3 , LogLevel . Warning , KnownLogEvents . Engine_LogChannel ) ;
CheckEventGroup ( logEvents . Slice ( 3 , 1 ) , 4 , 1 , LogLevel . Information , KnownLogEvents . Engine_LogChannel ) ;
2022-02-17 18:58:59 -05:00
}
}
2023-10-12 13:54:33 -04:00
[TestMethod]
public void ShaderEventMatcher ( )
{
string [ ] lines =
{
@"LogCook: Display: Cook Diagnostics: OpenFileHandles=10353, VirtualMemory=20078MiB" ,
@"LogShaderCompilers: Warning: Failed to compile Material /Game/Crowd/Character/Shared/Materials/MetaHuman/M_Crowd_Head_v2.M_Crowd_Head_v2 for platform SF_XSX_SM6, Default Material will be used in game." ,
@" error:validation errors" ,
@" error:Root Signature in DXIL container is not compatible with shader." ,
@" error:Shader SRV descriptor range (RegisterSpace=0, NumDescriptors=1, BaseShaderRegister=64) is not fully bound in root signature." ,
@"Validation failed." ,
@" Shader compile failed" ,
@"LogCook: Display: Excluding /Interchange/gltf/MaterialInstances/MI_ClearCoat_Mask_DS"
} ;
{
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 8 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 1 , 6 ) , 1 , 6 , LogLevel . Warning , KnownLogEvents . Engine_ShaderCompiler ) ;
}
}
2024-04-29 16:47:38 -04:00
[TestMethod]
public void ThreadSanitizerErrorMatcher_NoMatch ( )
{
string [ ] lines =
{
@"==================" ,
@"WARNING: ThreadSanitizer: data race (pid=21089)" ,
@" Write of size 1 at 0x00004060ea38 by thread T25:" ,
@" #0 FPaths::IsStaged() /mnt/horde/++UE5/Sync/Engine/Source/./Runtime/Core/Private/Misc/Paths.cpp:172:33 (CitySampleEditor+0x2c0f2f44) (BuildId: 6622c84dbb6a946e)" ,
@"" ,
@" Previous write of size 1 at 0x00004060ea38 by thread T20:" ,
@" #0 FPaths::IsStaged() /mnt/horde/++UE5/Sync/Engine/Source/./Runtime/Core/Private/Misc/Paths.cpp:172:33 (CitySampleEditor+0x2c0f2f44) (BuildId: 6622c84dbb6a946e)" ,
} ;
// We won't find a terminating string for the TSAN report so we only log a source file warning
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 1 , logEvents . Count ) ;
Assert . AreEqual ( LogLevel . Warning , logEvents [ 0 ] . Level ) ;
Assert . AreEqual ( KnownLogEvents . AutomationTool_SourceFileLine , logEvents [ 0 ] . Id ) ;
}
2024-04-26 08:42:40 -04:00
[TestMethod]
public void ThreadSanitizerErrorMatcher ( )
{
string [ ] lines =
{
@"==================" ,
@"WARNING: ThreadSanitizer: data race (pid=21089)" ,
@" Write of size 1 at 0x00004060ea38 by thread T25:" ,
@" #0 FPaths::IsStaged() /mnt/horde/++UE5/Sync/Engine/Source/./Runtime/Core/Private/Misc/Paths.cpp:172:33 (CitySampleEditor+0x2c0f2f44) (BuildId: 6622c84dbb6a946e)" ,
@"" ,
@" Previous write of size 1 at 0x00004060ea38 by thread T20:" ,
@" #0 FPaths::IsStaged() /mnt/horde/++UE5/Sync/Engine/Source/./Runtime/Core/Private/Misc/Paths.cpp:172:33 (CitySampleEditor+0x2c0f2f44) (BuildId: 6622c84dbb6a946e)" ,
@"" ,
@" Location is global '??' at 0x000000000000 (CitySampleEditor+0x4060ea38)" ,
@"" ,
@" Thread T25 'Backgro-ker #19' (tid=21138, running) created by thread T7 at:" ,
@" #0 pthread_create /src/build/llvm-src/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:1048 (CitySampleEditor+0x10351c92) (BuildId: 6622c84dbb6a946e)" ,
@" #1 FRunnableThreadPThread::CreateThreadWithName(unsigned long*, pthread_attr_t*, void* (*)(void*), void*, char const*) /mnt/horde/++UE5/Sync/Engine/Source/Runtime/Core/Private/HAL/PThreadRunnableThread.h:90:10 (CitySampleEditor+0x2bd32c50) (BuildId: 6622c84dbb6a946e)" ,
@"" ,
@" Thread T20 'Backgro-ker #14' (tid=21133, running) created by thread T5 at:" ,
@" #0 pthread_create /src/build/llvm-src/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:1048 (CitySampleEditor+0x10351c92) (BuildId: 6622c84dbb6a946e)" ,
@" #1 FRunnableThreadPThread::CreateThreadWithName(unsigned long*, pthread_attr_t*, void* (*)(void*), void*, char const*) /mnt/horde/++UE5/Sync/Engine/Source/Runtime/Core/Private/HAL/PThreadRunnableThread.h:90:10 (CitySampleEditor+0x2bd32c50) (BuildId: 6622c84dbb6a946e)" ,
@"" ,
@"SUMMARY: ThreadSanitizer: data race /mnt/horde/++UE5/Sync/Engine/Source/./Runtime/Core/Private/Misc/Paths.cpp:172:33 in FPaths::IsStaged()" ,
@"=================="
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 20 , logEvents [ 0 ] . LineCount ) ;
2024-05-01 07:12:59 -04:00
CheckEventGroup ( logEvents , 0 , 20 , LogLevel . Warning , KnownLogEvents . Sanitizer_Thread ) ;
2024-04-26 08:42:40 -04:00
Assert . AreEqual ( "/mnt/horde/++UE5/Sync/Engine/Source/Runtime/Core/Private/HAL/PThreadRunnableThread.h" , logEvents [ 12 ] . GetProperty ( "SourceFile" ) . ToString ( ) ) ;
Assert . AreEqual ( "90" , logEvents [ 12 ] . GetProperty ( "Line" ) . ToString ( ) ) ;
Assert . AreEqual ( "10" , logEvents [ 12 ] . GetProperty ( "Column" ) . ToString ( ) ) ;
Assert . AreEqual ( "FRunnableThreadPThread::CreateThreadWithName(unsigned long*, pthread_attr_t*, void* (*)(void*), void*, char const*)" , logEvents [ 12 ] . GetProperty ( "Symbol" ) . ToString ( ) ) ;
// Summary
Assert . AreEqual ( "/mnt/horde/++UE5/Sync/Engine/Source/./Runtime/Core/Private/Misc/Paths.cpp" , logEvents [ 18 ] . GetProperty ( "SummarySourceFile" ) . ToString ( ) ) ;
Assert . AreEqual ( "172" , logEvents [ 18 ] . GetProperty ( "Line" ) . ToString ( ) ) ;
Assert . AreEqual ( "33" , logEvents [ 18 ] . GetProperty ( "Column" ) . ToString ( ) ) ;
Assert . AreEqual ( "FPaths::IsStaged()" , logEvents [ 18 ] . GetProperty ( "Symbol" ) . ToString ( ) ) ;
Assert . AreEqual ( "data race" , logEvents [ 18 ] . GetProperty ( "SummaryReason" ) . ToString ( ) ) ;
}
2024-05-01 07:12:59 -04:00
[TestMethod]
public void AddressSanitizerErrorMatcher ( )
{
string [ ] lines =
{
@"=================================================================" ,
@"==30562==ERROR: AddressSanitizer: heap-use-after-free on address 0x617002aa8418 at pc 0x7f98a08bd090 bp 0x7ffc30203af0 sp 0x7ffc30203ae8" ,
@"READ of size 8 at 0x617002aa8418 thread T0" ,
@" #0 0x7f98a08bd08f in UObjectBase::GetFName() const /mnt/horde/FNR+Main+Inc/Sync/Engine/Source/Runtime/CoreUObject/Public/UObject/UObjectBase.h:166:10" ,
@"" ,
@"0x617002aa8418 is located 24 bytes inside of 712-byte region [0x617002aa8400,0x617002aa86c8)" ,
@"freed by thread T0 here:" ,
@" #0 0x7f9a283e6b08 in __interceptor_free.part.5 /src/build/llvm-src/compiler-rt/lib/asan/asan_malloc_linux.cpp:52" ,
@"" ,
@"previously allocated by thread T0 here:" ,
@" #0 0x7f9a283e730d in posix_memalign /src/build/llvm-src/compiler-rt/lib/asan/asan_malloc_linux.cpp:145" ,
@"" ,
@"SUMMARY: AddressSanitizer: heap-use-after-free /mnt/horde/FNR+Main+Inc/Sync/Engine/Source/Runtime/CoreUObject/Public/UObject/UObjectBase.h:166:10 in UObjectBase::GetFName() const" ,
@"Shadow bytes around the buggy address:" ,
@" 0x617002aa8180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" ,
@" 0x617002aa8200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" ,
@" 0x617002aa8280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" ,
@" 0x617002aa8300: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa" ,
@" 0x617002aa8380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa" ,
@"=>0x617002aa8400: fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd" ,
@" 0x617002aa8480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd" ,
@" 0x617002aa8500: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd" ,
@" 0x617002aa8580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd" ,
@" 0x617002aa8600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd" ,
@" 0x617002aa8680: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa" ,
@"Shadow byte legend (one shadow byte represents 8 application bytes):" ,
@" Addressable: 00" ,
@" Partially addressable: 01 02 03 04 05 06 07 " ,
@" Heap left redzone: fa" ,
@" Freed heap region: fd" ,
@" Stack left redzone: f1" ,
@" Stack mid redzone: f2" ,
@" Stack right redzone: f3" ,
@" Stack after return: f5" ,
@" Stack use after scope: f8" ,
@" Global redzone: f9" ,
@" Global init order: f6" ,
@" Poisoned by user: f7" ,
@" Container overflow: fc" ,
@" Array cookie: ac" ,
@" Intra object redzone: bb" ,
@" ASan internal: fe" ,
@" Left alloca redzone: ca" ,
@" Right alloca redzone: cb" ,
@"==30562==ABORTING" ,
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 45 , logEvents [ 0 ] . LineCount ) ;
CheckEventGroup ( logEvents , 0 , 45 , LogLevel . Error , KnownLogEvents . Sanitizer_Address ) ;
LogValue ? column ;
Assert . AreEqual ( "/src/build/llvm-src/compiler-rt/lib/asan/asan_malloc_linux.cpp" , logEvents [ 7 ] . GetProperty ( "SourceFile" ) . ToString ( ) ) ;
Assert . AreEqual ( "52" , logEvents [ 7 ] . GetProperty ( "Line" ) . ToString ( ) ) ;
Assert . IsFalse ( logEvents [ 7 ] . TryGetProperty ( "Column" , out column ) ) ;
Assert . AreEqual ( "__interceptor_free.part.5" , logEvents [ 7 ] . GetProperty ( "Symbol" ) . ToString ( ) ) ;
// Summary
Assert . AreEqual ( "/mnt/horde/FNR+Main+Inc/Sync/Engine/Source/Runtime/CoreUObject/Public/UObject/UObjectBase.h" , logEvents [ 12 ] . GetProperty ( "SummarySourceFile" ) . ToString ( ) ) ;
Assert . AreEqual ( "166" , logEvents [ 12 ] . GetProperty ( "Line" ) . ToString ( ) ) ;
Assert . IsTrue ( logEvents [ 12 ] . TryGetProperty ( "Column" , out column ) ) ;
Assert . AreEqual ( "10" , column . ToString ( ) ) ;
Assert . AreEqual ( "UObjectBase::GetFName() const" , logEvents [ 12 ] . GetProperty ( "Symbol" ) . ToString ( ) ) ;
Assert . AreEqual ( "heap-use-after-free" , logEvents [ 12 ] . GetProperty ( "SummaryReason" ) . ToString ( ) ) ;
}
2022-05-27 18:27:52 -04:00
[TestMethod]
public void LocalizationChannelMatcher ( )
{
string [ ] lines =
{
2022-06-09 09:34:06 -04:00
@"[2022.05.31-04.25.40:235][ 0]LogGatherTextFromSourceCommandlet: Warning: Plugins/Enterprise/VariantManager/Source/VariantManager/Private/SVariantManager.cpp(3717): LOCTEXT macro has an empty identifier and cannot be gathered." ,
@"[2022.06.01-04.29.09:630][ 0]LogLocTextHelper: Warning: Plugins/Experimental/UVEditor/Source/UVEditor/Private/UVEditorCommands.cpp(39): Text conflict from UI_COMMAND macro for namespace ""UICommands.FUVEditorCommands"" and key ""SplitAction_ToolTip"". The conflicting sources are ""Given an edge selection, split those edges. Given a vertex selection, split any selected bowtie vertices. Given a triangle selection, split along selection boundaries."" and ""Given an edge selection, split those edges. Given a vertex selection, split any selected bowtie vertices.""." ,
@"[2022.06.01-04.29.09:630][ 0]LogLocTextHelper: Warning: Content/Localization/Engine/Engine.manifest: See conflicting location." ,
2022-05-27 18:27:52 -04:00
} ;
{
List < LogEvent > logEvents = Parse ( lines ) ;
2022-06-08 16:40:03 -04:00
Assert . AreEqual ( 3 , logEvents . Count ) ;
CheckEventGroup ( logEvents . Slice ( 0 , 1 ) , 0 , 1 , LogLevel . Warning , KnownLogEvents . Engine_Localization ) ;
CheckEventGroup ( logEvents . Slice ( 1 , 2 ) , 1 , 2 , LogLevel . Warning , KnownLogEvents . Engine_Localization ) ;
2022-05-27 18:27:52 -04:00
LogEvent logEvent = logEvents [ 0 ] ;
2022-05-31 08:06:56 -04:00
Assert . AreEqual ( "LogGatherTextFromSourceCommandlet" , logEvent . GetProperty ( "channel" ) . ToString ( ) ) ;
2022-05-27 18:27:52 -04:00
Assert . AreEqual ( "Warning" , logEvent . GetProperty ( "severity" ) . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( "Engine/Plugins/Enterprise/VariantManager/Source/VariantManager/Private/SVariantManager.cpp" , logEvent . GetProperty < LogValue > ( "file" ) ! . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
2022-05-31 08:06:56 -04:00
Assert . AreEqual ( "3717" , logEvent . GetProperty ( "line" ) . ToString ( ) ) ;
2022-06-08 16:40:03 -04:00
Assert . AreEqual ( 0 , logEvent . LineIndex ) ;
Assert . AreEqual ( 1 , logEvent . LineCount ) ;
logEvent = logEvents [ 1 ] ;
Assert . AreEqual ( "LogLocTextHelper" , logEvent . GetProperty ( "channel" ) . ToString ( ) ) ;
Assert . AreEqual ( "Warning" , logEvent . GetProperty ( "severity" ) . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( "Engine/Plugins/Experimental/UVEditor/Source/UVEditor/Private/UVEditorCommands.cpp" , logEvent . GetProperty < LogValue > ( "file" ) ! . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
2022-06-08 16:40:03 -04:00
Assert . AreEqual ( "39" , logEvent . GetProperty ( "line" ) . ToString ( ) ) ;
Assert . AreEqual ( 0 , logEvent . LineIndex ) ;
Assert . AreEqual ( 2 , logEvent . LineCount ) ;
logEvent = logEvents [ 2 ] ;
Assert . AreEqual ( "LogLocTextHelper" , logEvent . GetProperty ( "channel" ) . ToString ( ) ) ;
Assert . AreEqual ( "Warning" , logEvent . GetProperty ( "severity" ) . ToString ( ) ) ;
2023-10-04 10:49:04 -04:00
Assert . AreEqual ( "Engine/Content/Localization/Engine/Engine.manifest" , logEvent . GetProperty < LogValue > ( "file" ) ! . Properties ! [ LogEventPropertyName . RelativePath ] . ToString ( ) ) ;
2022-06-08 16:40:03 -04:00
Assert . AreEqual ( 1 , logEvent . LineIndex ) ;
Assert . AreEqual ( 2 , logEvent . LineCount ) ;
2022-05-27 18:27:52 -04:00
}
}
2022-05-31 12:02:25 -04:00
[TestMethod]
public void HangingIndentMatcher ( )
{
string [ ] lines =
{
@"first line" ,
@"first line in multi-line message" ,
@" this is a hanging indent" ,
@" this is also hanging" ,
@"this is a separate item" ,
} ;
LogBuffer buffer = new LogBuffer ( 10 ) ;
buffer . AddLines ( lines ) ;
2022-06-08 16:40:03 -04:00
Assert . IsTrue ( buffer . IsAligned ( 0 , buffer . CurrentLine ) ) ;
Assert . IsTrue ( buffer . IsAligned ( 1 , buffer . CurrentLine ) ) ;
Assert . IsTrue ( buffer . IsAligned ( 2 , buffer . CurrentLine ) ) ;
Assert . IsTrue ( buffer . IsAligned ( 3 , buffer . CurrentLine ) ) ;
Assert . IsTrue ( buffer . IsAligned ( 4 , buffer . CurrentLine ) ) ;
Assert . IsFalse ( buffer . IsAligned ( 5 , buffer . CurrentLine ) ) ;
2022-05-31 12:02:25 -04:00
2022-06-08 16:40:03 -04:00
string? firstIndentedLine = buffer [ 2 ] ;
Assert . IsTrue ( buffer . IsAligned ( 2 , firstIndentedLine ) ) ;
Assert . IsTrue ( buffer . IsAligned ( 3 , firstIndentedLine ) ) ;
Assert . IsFalse ( buffer . IsAligned ( 4 , firstIndentedLine ) ) ;
2022-05-31 12:02:25 -04:00
2022-06-08 16:40:03 -04:00
Assert . IsFalse ( buffer . IsHanging ( 1 , buffer . CurrentLine ) ) ;
Assert . IsTrue ( buffer . IsHanging ( 2 , buffer . CurrentLine ) ) ;
Assert . IsTrue ( buffer . IsHanging ( 3 , buffer . CurrentLine ) ) ;
Assert . IsFalse ( buffer . IsHanging ( 4 , buffer . CurrentLine ) ) ;
Assert . IsFalse ( buffer . IsHanging ( 2 , firstIndentedLine ) ) ;
Assert . IsTrue ( buffer . IsHanging ( 3 , firstIndentedLine ) ) ;
Assert . IsFalse ( buffer . IsHanging ( 4 , firstIndentedLine ) ) ;
2022-05-31 12:02:25 -04:00
}
2022-06-09 13:18:32 -04:00
[TestMethod]
public void MsTestEventMatcher ( )
{
string [ ] lines =
{
@"Microsoft (R) Test Execution Command Line Tool Version 17.2.0 (x64)" ,
@"Copyright (c) Microsoft Corporation. All rights reserved." ,
@"Starting test execution, please wait..." ,
@"A total of 1 test files matched the specified pattern." ,
@"" ,
@" Failed ExplicitGroupingTest [219 ms]" ,
@" Error Message:" ,
@" Assert.AreEqual failed. Expected:<2>. Actual:<1>." ,
@" Stack Trace:" ,
@" at Horde.Build.Tests.IssueServiceTests.ExplicitGroupingTest() in /app/Source/Programs/Horde/Horde.Build.Tests/IssueServiceTests.cs:line 1382" ,
@" at Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.ThreadOperations.ExecuteWithAbortSafety(Action action)" ,
@"" ,
@" Standard Output Messages:" ,
@" info: Horde.Build.Issues.IssueService[0]" ,
@" Updating issues for 62a21de84f3b4344e94f3f10:0000:0004" ,
@" info: Horde.Build.Logs.LogEventCollection[0]" ,
@" Querying for log events for log 62a21de84f3b4344e94f3f15 creation time 06/09/2022 16:20:56" ,
@" info: Horde.Build.Auditing.AuditLog[0]" ,
@" Created issue 1" ,
@" info: Horde.Build.Auditing.AuditLog[0]" ,
@" Changed severity to Error" ,
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 6 , logEvents . Count ) ;
CheckEventGroup ( logEvents , 5 , 6 , LogLevel . Error , KnownLogEvents . MSTest ) ;
}
2023-08-23 10:13:47 -04:00
[TestMethod]
public void MsTestEventMatcher2 ( )
{
string [ ] lines =
{
@" Passed ConditionSimple [154 ms]" ,
@" Passed GetPoolQueueSizes [1 s]" ,
@" Failed DowntimeActive [6 s]" ,
@" Error Message:" ,
@" Assert.AreEqual failed. Expected:<1>. Actual:<0>." ,
@" Stack Trace:" ,
@" at Horde.Server.Tests.Fleet.JobQueueStrategyTest.DowntimeActive() in /app/Source/Programs/Horde/Horde.Server.Tests/Fleet/JobQueueStrategyTest.cs:line 40" ,
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 5 , logEvents . Count ) ;
CheckEventGroup ( logEvents , 2 , 5 , LogLevel . Error , KnownLogEvents . MSTest ) ;
}
2024-04-25 09:23:28 -04:00
[TestMethod]
public void MsTestEventMatcher3 ( )
{
string [ ] lines =
{
@" info: Horde.Server.Auditing.AuditLog[0]" ,
@" Session 662a561ef41fb04ceda48319 started" ,
@"" ,
@" Failed AutoConformAgentsAsync (True,200,) [208 ms]" ,
@" Error Message:" ,
@" Assert.AreEqual failed. Expected:<True>. Actual:<False>." ,
@" Stack Trace:" ,
@" at Horde.Server.Tests.Agents.Pools.PoolUpdateServiceTest.AutoConformAgentsAsync(Boolean conformRequested, Nullable`1[] autoConformThresholdsM) in /app/Source/Programs/Horde/Horde.Server.Tests/Agents/Pools/PoolUpdateServiceTest.cs:line 120" ,
} ;
List < LogEvent > logEvents = Parse ( lines ) ;
Assert . AreEqual ( 5 , logEvents . Count ) ;
CheckEventGroup ( logEvents , 3 , 5 , LogLevel . Error , KnownLogEvents . MSTest ) ;
}
2022-05-17 15:51:07 -04:00
static List < LogEvent > Parse ( IEnumerable < string > lines )
2021-04-29 15:10:34 -04:00
{
2022-03-21 09:19:47 -04:00
return Parse ( String . Join ( "\n" , lines ) ) ;
}
2022-05-17 15:51:07 -04:00
static List < LogEvent > Parse ( string text )
2022-03-21 09:19:47 -04:00
{
2022-09-14 11:53:21 -04:00
return Parse ( text , s_rootDir ) ;
2022-03-21 09:19:47 -04:00
}
2022-05-17 15:51:07 -04:00
static List < LogEvent > Parse ( string text , DirectoryReference workspaceDir )
2022-03-21 09:19:47 -04:00
{
byte [ ] textBytes = Encoding . UTF8 . GetBytes ( text ) ;
Random generator = new Random ( 0 ) ;
LoggerCapture logger = new LoggerCapture ( ) ;
2022-05-17 15:51:07 -04:00
2024-04-17 10:39:36 -04:00
PerforceMetadataLogger perforceLogger = new PerforceMetadataLogger ( logger ) ;
2022-05-17 15:51:07 -04:00
perforceLogger . AddClientView ( workspaceDir , "//UE4/Main/..." , 12345 ) ;
2024-04-17 10:39:36 -04:00
using ( LogEventParser parser = new LogEventParser ( perforceLogger ) )
2021-04-29 15:10:34 -04:00
{
2024-04-17 10:39:36 -04:00
parser . AddMatchersFromAssembly ( typeof ( AutomationTool . Automation ) . Assembly ) ;
parser . AddMatchersFromAssembly ( typeof ( UnrealBuildTool . TargetRules ) . Assembly ) ;
2022-03-21 09:19:47 -04:00
int pos = 0 ;
2024-03-15 10:23:20 -04:00
while ( pos < textBytes . Length )
2021-04-29 15:10:34 -04:00
{
2022-03-21 09:19:47 -04:00
int len = Math . Min ( ( int ) ( generator . NextDouble ( ) * 256 ) , textBytes . Length - pos ) ;
parser . WriteData ( textBytes . AsMemory ( pos , len ) ) ;
pos + = len ;
2021-04-29 15:10:34 -04:00
}
}
2022-03-21 09:19:47 -04:00
return logger . _events ;
2021-04-29 15:10:34 -04:00
}
2021-11-08 12:18:49 -05:00
2022-05-17 15:51:07 -04:00
static void CheckEventGroup ( IEnumerable < LogEvent > logEvents , int index , int count , LogLevel level , EventId eventId = default )
2021-11-08 12:18:49 -05:00
{
2022-03-21 09:19:47 -04:00
IEnumerator < LogEvent > enumerator = logEvents . GetEnumerator ( ) ;
for ( int idx = 0 ; idx < count ; idx + + )
2021-11-08 12:18:49 -05:00
{
2022-03-21 09:19:47 -04:00
Assert . IsTrue ( enumerator . MoveNext ( ) ) ;
2021-11-08 12:18:49 -05:00
2022-03-21 09:19:47 -04:00
LogEvent logEvent = enumerator . Current ;
2023-01-23 13:00:45 -05:00
Assert . AreEqual ( level , logEvent . Level , "Log level mismatch" ) ;
Assert . AreEqual ( eventId , logEvent . Id , "Event ID mismatch" ) ;
Assert . AreEqual ( idx , logEvent . LineIndex , "Line index mismatch" ) ;
Assert . AreEqual ( count , logEvent . LineCount , "Line count mismatch" ) ;
2022-05-19 14:34:21 -04:00
Assert . AreEqual ( index + idx , logEvent . GetProperty ( LogLine ) ) ;
2021-11-08 12:18:49 -05:00
}
2022-03-21 09:19:47 -04:00
Assert . IsFalse ( enumerator . MoveNext ( ) ) ;
2021-11-08 12:18:49 -05:00
}
2021-04-29 15:10:34 -04:00
}
}