using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using NUnit.Framework; using Robust.Client.ComponentTrees; using Robust.Client.GameObjects; using Robust.Server.Debugging; using Robust.Server.GameObjects; using Robust.Server.GameStates; using Robust.Server.Physics; using Robust.Shared.Configuration; using Robust.Shared.Containers; using Robust.Shared.ContentPack; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Controllers; using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; using Robust.Shared.Reflection; using Robust.Shared.Threading; using Robust.Shared.Utility; using InputSystem = Robust.Server.GameObjects.InputSystem; using MapSystem = Robust.Server.GameObjects.MapSystem; namespace Robust.UnitTesting { public enum UnitTestProject : byte { Server, Client } [Parallelizable] public abstract partial class RobustUnitTest { public virtual UnitTestProject Project => UnitTestProject.Server; [OneTimeSetUp] public void BaseSetup() { // Clear state across tests. var deps = IoCManager.InitThread(); deps.Clear(); RegisterIoC(); var assemblies = new List(4); switch (Project) { case UnitTestProject.Client: assemblies.Add(AppDomain.CurrentDomain.GetAssemblyByName("Robust.Client")); break; case UnitTestProject.Server: assemblies.Add(AppDomain.CurrentDomain.GetAssemblyByName("Robust.Server")); break; default: throw new NotSupportedException($"Unknown testing project: {Project}"); } assemblies.Add(AppDomain.CurrentDomain.GetAssemblyByName("Robust.Shared")); assemblies.Add(Assembly.GetExecutingAssembly()); var configurationManager = deps.Resolve(); configurationManager.Initialize(Project == UnitTestProject.Server); deps.Resolve().Initialize(); foreach (var assembly in assemblies) { configurationManager.LoadCVarsFromAssembly(assembly); } var contentAssemblies = GetContentAssemblies(); foreach (var assembly in contentAssemblies) { configurationManager.LoadCVarsFromAssembly(assembly); } configurationManager.LoadCVarsFromAssembly(typeof(RobustUnitTest).Assembly); var systems = deps.Resolve(); // Required systems systems.LoadExtraSystemType(); // uhhh so maybe these are the wrong system for the client, but I CBF adding sprite system and all the rest, // and it was like this when I found it. systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); if (Project == UnitTestProject.Client) { systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); } else { systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); systems.LoadExtraSystemType(); } var entMan = deps.Resolve(); var mapMan = deps.Resolve(); // Required components for the engine to work // Why are we still here? Just to suffer? Why can't we just use [RegisterComponent] magic? // TODO End Suffering. var compFactory = deps.Resolve(); if (!compFactory.AllRegisteredTypes.Contains(typeof(EyeComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(MapComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(MapGridComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(ContainerManagerComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(MetaDataComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(TransformComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(PhysicsComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(PhysicsMapComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(BroadphaseComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(FixturesComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(JointComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(GridTreeComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(MovedGridsComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(JointRelayTargetComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(OccluderComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(OccluderTreeComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(SpriteTreeComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(LightTreeComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(Gravity2DComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(CollisionWakeComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(CollideOnAnchorComponent))) { compFactory.RegisterClass(); } if (!compFactory.AllRegisteredTypes.Contains(typeof(ActorComponent))) { compFactory.RegisterClass(); } deps.Resolve().Initialize(); // So by default EntityManager does its own EntitySystemManager initialize during Startup. // We want to bypass this and load our own systems hence we will manually initialize it here. entMan.Initialize(); // RobustUnitTest is complete hot garbage. // This makes EventTables ignore *all* the screwed up component abuse it causes. entMan.EventBus.OnlyCallOnRobustUnitTestISwearToGodPleaseSomebodyKillThisNightmare(); mapMan.Initialize(); systems.Initialize(); deps.Resolve().LoadAssemblies(assemblies); var modLoader = deps.Resolve(); modLoader.Assemblies = contentAssemblies; modLoader.TryLoadModulesFrom(ResPath.Root, ""); entMan.Startup(); mapMan.Startup(); } [OneTimeTearDown] public void BaseTearDown() { IoCManager.Clear(); } /// /// Called after all IoC registration has been done, but before the graph has been built. /// This allows one to add new IoC types or overwrite existing ones if needed. /// protected virtual void OverrideIoC() { } protected virtual Assembly[] GetContentAssemblies() { return Array.Empty(); } } }