Files
sbox-public/engine/Sandbox.Hotload.Test/HotloadTests.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

147 lines
4.5 KiB
C#

extern alias After;
extern alias Before;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mono.Cecil;
using Sandbox;
using Sandbox.ActionGraphs;
using Sandbox.Internal;
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using NodeLibrary = Facepunch.ActionGraphs.NodeLibrary;
namespace Hotload
{
[AttributeUsage( AttributeTargets.Field )]
public sealed class ResetAttribute : Attribute { }
public abstract class HotloadTests
{
private static void ResetStaticFields<TAttrib>()
where TAttrib : Attribute
{
foreach ( var type in typeof( TAttrib ).Assembly.GetTypes() )
{
foreach ( var fieldInfo in type.GetFields( BindingFlags.Static | BindingFlags.Public ) )
{
if ( fieldInfo.GetCustomAttribute<TAttrib>() != null )
{
fieldInfo.SetValue( null, fieldInfo.FieldType.IsValueType ? Activator.CreateInstance( fieldInfo.FieldType ) : null );
}
}
}
}
protected static Sandbox.Hotload CreateHotload()
{
Sandbox.Hotload.AssemblyNameFormatter = name => name.Name;
var hotload = new Sandbox.Hotload { TraceRoots = true, TracePaths = true, IncludeTypeTimings = true, IncludeProcessorTimings = true };
hotload.WatchAssembly( "Sandbox.Hotload.Test" );
hotload.WatchAssembly( "Sandbox.Engine", t => t.Name == nameof( ReflectionQueryCache ) );
hotload.ReplacingAssembly( typeof( Before.TestClass1 ).Assembly, typeof( After.TestClass1 ).Assembly );
hotload.AssemblyResolver = new DefaultAssemblyResolver();
hotload.AddUpgrader<Sandbox.Upgraders.AutoSkipUpgrader>();
hotload.AddUpgraders( typeof( TypeDescription ).Assembly );
return hotload;
}
protected static HotloadResult Hotload( bool allowErrors = false )
{
var hotload = CreateHotload();
var result = hotload.UpdateReferences();
Assert.IsFalse( result.NoAction );
Console.WriteLine( $"NoAction = {result.NoAction}" );
Console.WriteLine( $"InstancesProcessed = {result.InstancesProcessed}" );
Console.WriteLine( $"ProcessingTime = {result.ProcessingTime:F2}ms" );
Console.WriteLine( $"result.Entries = {result.Entries.Count}" );
foreach ( var entry in result.Entries )
{
Console.WriteLine( $" [{entry.Type}] {entry.ToString().Replace( "\n", "\n " )}" );
}
Console.WriteLine( "Type Timings:" );
foreach ( var pair in result.TypeTimings.OrderByDescending( x => x.Value.Milliseconds ) )
{
Console.WriteLine( $" {pair.Key}:" );
Console.WriteLine( $" Instances = {pair.Value.Instances}" );
Console.WriteLine( $" TimeSpan = {pair.Value.Milliseconds:F2}ms" );
Console.WriteLine( " Roots:" );
foreach ( var rootPair in pair.Value.Roots.OrderByDescending( x => x.Value.Milliseconds ) )
{
Console.WriteLine( $" {rootPair.Key}:" );
Console.WriteLine( $" Instances = {rootPair.Value.Instances}" );
Console.WriteLine( $" TimeSpan = {rootPair.Value.Milliseconds:F2}ms" );
}
}
Console.WriteLine( "Processor Timings:" );
foreach ( var pair in result.ProcessorTimings.OrderByDescending( x => x.Value.Milliseconds ) )
{
Console.WriteLine( $" {pair.Key}:" );
Console.WriteLine( $" Instances = {pair.Value.Instances}" );
Console.WriteLine( $" TimeSpan = {pair.Value.Milliseconds:F2}ms" );
Console.WriteLine( " Roots:" );
foreach ( var rootPair in pair.Value.Roots.OrderByDescending( x => x.Value.Milliseconds ) )
{
Console.WriteLine( $" {rootPair.Key}:" );
Console.WriteLine( $" Instances = {rootPair.Value.Instances}" );
Console.WriteLine( $" TimeSpan = {rootPair.Value.Milliseconds:F2}ms" );
}
}
if ( !allowErrors )
{
Assert.IsFalse( result.HasErrors );
}
return result;
}
private NodeLibrary _oldNodeLibrary;
public TypeLibrary TypeLibrary;
public NodeLibrary Nodes => Game.NodeLibrary;
[TestInitialize]
public void Initialize()
{
_oldNodeLibrary = Nodes;
ResetStaticFields<Before.ResetAttribute>();
ResetStaticFields<After.ResetAttribute>();
ResetStaticFields<ResetAttribute>();
TypeLibrary = new TypeLibrary();
TypeLibrary.AddAssembly( typeof( LogNodes ).Assembly, false );
Game.NodeLibrary = new NodeLibrary( new TypeLoader( () => TypeLibrary ), new GraphLoader() );
var result = Nodes.AddAssembly( typeof( LogNodes ).Assembly );
foreach ( var (method, e) in result.Errors )
{
Debug.WriteLine( $"{method}: {e}" );
}
Assert.IsFalse( result.AlreadyAdded );
Assert.AreEqual( 0, result.Errors.Count );
}
[TestCleanup]
public void Cleanup()
{
Game.NodeLibrary = _oldNodeLibrary;
}
}
}