mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-02 06:14:52 +00:00
test: change methodology to have a mock assembly
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Abstractions;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
using PepperDash.Essentials.Core.Factory;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Devices
|
||||
@@ -16,11 +17,12 @@ namespace PepperDash.Essentials.Core.Devices
|
||||
|
||||
public ICrestronControlSystem Processor { get; private set; }
|
||||
|
||||
public CrestronProcessorTestable(string key, ICrestronControlSystem processor)
|
||||
public CrestronProcessorTestable(string key, ICrestronControlSystem processor = null)
|
||||
: base(key)
|
||||
{
|
||||
SwitchedOutputs = new Dictionary<uint, ISwitchedOutput>();
|
||||
Processor = processor ?? throw new ArgumentNullException(nameof(processor));
|
||||
// Use factory if processor not provided
|
||||
Processor = processor ?? CrestronEnvironmentFactory.GetControlSystem();
|
||||
GetRelays();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using PepperDash.Essentials.Core.Abstractions;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Factory
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for creating Crestron environment dependencies
|
||||
/// Allows switching between real Crestron libraries and mock implementations
|
||||
/// </summary>
|
||||
public static class CrestronEnvironmentFactory
|
||||
{
|
||||
private static ICrestronEnvironmentProvider _provider;
|
||||
private static bool _isTestMode = false;
|
||||
|
||||
static CrestronEnvironmentFactory()
|
||||
{
|
||||
// Default to runtime provider
|
||||
_provider = new CrestronRuntimeProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables test mode with mock implementations
|
||||
/// </summary>
|
||||
public static void EnableTestMode()
|
||||
{
|
||||
_isTestMode = true;
|
||||
_provider = new CrestronMockProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables test mode and returns to runtime implementations
|
||||
/// </summary>
|
||||
public static void DisableTestMode()
|
||||
{
|
||||
_isTestMode = false;
|
||||
_provider = new CrestronRuntimeProvider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a custom provider for Crestron environment
|
||||
/// </summary>
|
||||
public static void SetProvider(ICrestronEnvironmentProvider provider)
|
||||
{
|
||||
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the factory is in test mode
|
||||
/// </summary>
|
||||
public static bool IsTestMode => _isTestMode;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current control system instance
|
||||
/// </summary>
|
||||
public static ICrestronControlSystem GetControlSystem()
|
||||
{
|
||||
return _provider.GetControlSystem();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a relay port
|
||||
/// </summary>
|
||||
public static IRelayPort CreateRelayPort(uint portNumber)
|
||||
{
|
||||
return _provider.CreateRelayPort(portNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a digital input
|
||||
/// </summary>
|
||||
public static IDigitalInput CreateDigitalInput(uint portNumber)
|
||||
{
|
||||
return _provider.CreateDigitalInput(portNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a versiport
|
||||
/// </summary>
|
||||
public static IVersiPort CreateVersiPort(uint portNumber)
|
||||
{
|
||||
return _provider.CreateVersiPort(portNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets console manager for debugging
|
||||
/// </summary>
|
||||
public static IConsoleManager GetConsoleManager()
|
||||
{
|
||||
return _provider.GetConsoleManager();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets system information
|
||||
/// </summary>
|
||||
public static ISystemInfo GetSystemInfo()
|
||||
{
|
||||
return _provider.GetSystemInfo();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provider interface for Crestron environment dependencies
|
||||
/// </summary>
|
||||
public interface ICrestronEnvironmentProvider
|
||||
{
|
||||
ICrestronControlSystem GetControlSystem();
|
||||
IRelayPort CreateRelayPort(uint portNumber);
|
||||
IDigitalInput CreateDigitalInput(uint portNumber);
|
||||
IVersiPort CreateVersiPort(uint portNumber);
|
||||
IConsoleManager GetConsoleManager();
|
||||
ISystemInfo GetSystemInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Console manager abstraction
|
||||
/// </summary>
|
||||
public interface IConsoleManager
|
||||
{
|
||||
void Print(string message);
|
||||
void PrintLine(string message);
|
||||
void RegisterCommand(string command, Action<string> handler, string help);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// System information abstraction
|
||||
/// </summary>
|
||||
public interface ISystemInfo
|
||||
{
|
||||
string ProgramName { get; }
|
||||
string SerialNumber { get; }
|
||||
string MacAddress { get; }
|
||||
string IpAddress { get; }
|
||||
string FirmwareVersion { get; }
|
||||
DateTime SystemUpTime { get; }
|
||||
}
|
||||
}
|
||||
265
src/PepperDash.Essentials.Core/Factory/CrestronMockProvider.cs
Normal file
265
src/PepperDash.Essentials.Core/Factory/CrestronMockProvider.cs
Normal file
@@ -0,0 +1,265 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PepperDash.Essentials.Core.Abstractions;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Factory
|
||||
{
|
||||
/// <summary>
|
||||
/// Mock provider for unit testing without Crestron hardware
|
||||
/// </summary>
|
||||
public class CrestronMockProvider : ICrestronEnvironmentProvider
|
||||
{
|
||||
private MockControlSystem _controlSystem;
|
||||
|
||||
public CrestronMockProvider()
|
||||
{
|
||||
_controlSystem = new MockControlSystem();
|
||||
}
|
||||
|
||||
public ICrestronControlSystem GetControlSystem()
|
||||
{
|
||||
return _controlSystem;
|
||||
}
|
||||
|
||||
public IRelayPort CreateRelayPort(uint portNumber)
|
||||
{
|
||||
if (!_controlSystem.RelayPorts.ContainsKey(portNumber))
|
||||
{
|
||||
_controlSystem.RelayPorts[portNumber] = new MockRelayPort();
|
||||
}
|
||||
return _controlSystem.RelayPorts[portNumber];
|
||||
}
|
||||
|
||||
public IDigitalInput CreateDigitalInput(uint portNumber)
|
||||
{
|
||||
if (!_controlSystem.DigitalInputs.ContainsKey(portNumber))
|
||||
{
|
||||
_controlSystem.DigitalInputs[portNumber] = new MockDigitalInput();
|
||||
}
|
||||
return _controlSystem.DigitalInputs[portNumber];
|
||||
}
|
||||
|
||||
public IVersiPort CreateVersiPort(uint portNumber)
|
||||
{
|
||||
if (!_controlSystem.VersiPorts.ContainsKey(portNumber))
|
||||
{
|
||||
_controlSystem.VersiPorts[portNumber] = new MockVersiPort();
|
||||
}
|
||||
return _controlSystem.VersiPorts[portNumber];
|
||||
}
|
||||
|
||||
public IConsoleManager GetConsoleManager()
|
||||
{
|
||||
return new MockConsoleManager();
|
||||
}
|
||||
|
||||
public ISystemInfo GetSystemInfo()
|
||||
{
|
||||
return new MockSystemInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the mock control system for testing
|
||||
/// </summary>
|
||||
public void ConfigureMockSystem(Action<MockControlSystem> configure)
|
||||
{
|
||||
configure(_controlSystem);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of control system for testing
|
||||
/// </summary>
|
||||
public class MockControlSystem : ICrestronControlSystem
|
||||
{
|
||||
public bool SupportsRelay { get; set; } = true;
|
||||
public uint NumberOfRelayPorts { get; set; } = 8;
|
||||
public Dictionary<uint, IRelayPort> RelayPorts { get; set; } = new Dictionary<uint, IRelayPort>();
|
||||
public Dictionary<uint, IDigitalInput> DigitalInputs { get; set; } = new Dictionary<uint, IDigitalInput>();
|
||||
public Dictionary<uint, IVersiPort> VersiPorts { get; set; } = new Dictionary<uint, IVersiPort>();
|
||||
public string ProgramIdTag { get; set; } = "TEST_PROGRAM";
|
||||
public string ControllerPrompt { get; set; } = "TEST>";
|
||||
public bool SupportsEthernet { get; set; } = true;
|
||||
public bool SupportsDigitalInput { get; set; } = true;
|
||||
public uint NumberOfDigitalInputPorts { get; set; } = 8;
|
||||
public bool SupportsVersiPort { get; set; } = true;
|
||||
public uint NumberOfVersiPorts { get; set; } = 8;
|
||||
|
||||
public MockControlSystem()
|
||||
{
|
||||
// Initialize with default relay ports
|
||||
for (uint i = 1; i <= NumberOfRelayPorts; i++)
|
||||
{
|
||||
RelayPorts[i] = new MockRelayPort();
|
||||
}
|
||||
|
||||
// Initialize with default digital inputs
|
||||
for (uint i = 1; i <= NumberOfDigitalInputPorts; i++)
|
||||
{
|
||||
DigitalInputs[i] = new MockDigitalInput();
|
||||
}
|
||||
|
||||
// Initialize with default versiports
|
||||
for (uint i = 1; i <= NumberOfVersiPorts; i++)
|
||||
{
|
||||
VersiPorts[i] = new MockVersiPort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of relay port for testing
|
||||
/// </summary>
|
||||
public class MockRelayPort : IRelayPort
|
||||
{
|
||||
private bool _state;
|
||||
|
||||
public bool State => _state;
|
||||
|
||||
public event EventHandler<bool> StateChanged;
|
||||
|
||||
public void Open()
|
||||
{
|
||||
_state = false;
|
||||
StateChanged?.Invoke(this, _state);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_state = true;
|
||||
StateChanged?.Invoke(this, _state);
|
||||
}
|
||||
|
||||
public void Pulse(int delayMs)
|
||||
{
|
||||
Close();
|
||||
System.Threading.Tasks.Task.Delay(delayMs).ContinueWith(_ => Open());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test helper to set state directly
|
||||
/// </summary>
|
||||
public void SetState(bool state)
|
||||
{
|
||||
_state = state;
|
||||
StateChanged?.Invoke(this, _state);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of digital input for testing
|
||||
/// </summary>
|
||||
public class MockDigitalInput : IDigitalInput
|
||||
{
|
||||
private bool _state;
|
||||
|
||||
public bool State => _state;
|
||||
|
||||
public event EventHandler<Abstractions.DigitalInputEventArgs> StateChange;
|
||||
|
||||
/// <summary>
|
||||
/// Test helper to simulate input change
|
||||
/// </summary>
|
||||
public void SimulateStateChange(bool newState)
|
||||
{
|
||||
_state = newState;
|
||||
StateChange?.Invoke(this, new Abstractions.DigitalInputEventArgs(newState));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of versiport for testing
|
||||
/// </summary>
|
||||
public class MockVersiPort : IVersiPort
|
||||
{
|
||||
private bool _digitalIn;
|
||||
private bool _digitalOut;
|
||||
private ushort _analogIn;
|
||||
|
||||
public bool DigitalIn => _digitalIn;
|
||||
public ushort AnalogIn => _analogIn;
|
||||
|
||||
public event EventHandler<Abstractions.VersiPortEventArgs> VersiportChange;
|
||||
|
||||
public void SetDigitalOut(bool value)
|
||||
{
|
||||
_digitalOut = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test helper to simulate digital input change
|
||||
/// </summary>
|
||||
public void SimulateDigitalInChange(bool value)
|
||||
{
|
||||
_digitalIn = value;
|
||||
VersiportChange?.Invoke(this, new Abstractions.VersiPortEventArgs
|
||||
{
|
||||
EventType = Abstractions.VersiPortEventType.DigitalInChange,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test helper to simulate analog input change
|
||||
/// </summary>
|
||||
public void SimulateAnalogInChange(ushort value)
|
||||
{
|
||||
_analogIn = value;
|
||||
VersiportChange?.Invoke(this, new Abstractions.VersiPortEventArgs
|
||||
{
|
||||
EventType = Abstractions.VersiPortEventType.AnalogInChange,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of console manager for testing
|
||||
/// </summary>
|
||||
public class MockConsoleManager : IConsoleManager
|
||||
{
|
||||
public List<string> OutputLines { get; } = new List<string>();
|
||||
public Dictionary<string, Action<string>> Commands { get; } = new Dictionary<string, Action<string>>();
|
||||
|
||||
public void Print(string message)
|
||||
{
|
||||
OutputLines.Add(message);
|
||||
Console.Write(message);
|
||||
}
|
||||
|
||||
public void PrintLine(string message)
|
||||
{
|
||||
OutputLines.Add(message);
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
public void RegisterCommand(string command, Action<string> handler, string help)
|
||||
{
|
||||
Commands[command] = handler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test helper to execute a registered command
|
||||
/// </summary>
|
||||
public void ExecuteCommand(string command, string args)
|
||||
{
|
||||
if (Commands.TryGetValue(command, out var handler))
|
||||
{
|
||||
handler(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of system info for testing
|
||||
/// </summary>
|
||||
public class MockSystemInfo : ISystemInfo
|
||||
{
|
||||
public string ProgramName { get; set; } = "TestProgram";
|
||||
public string SerialNumber { get; set; } = "TEST123456";
|
||||
public string MacAddress { get; set; } = "00:11:22:33:44:55";
|
||||
public string IpAddress { get; set; } = "192.168.1.100";
|
||||
public string FirmwareVersion { get; set; } = "1.0.0.0";
|
||||
public DateTime SystemUpTime { get; set; } = DateTime.Now.AddHours(-1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PepperDash.Essentials.Core.Abstractions;
|
||||
|
||||
#if !TEST_BUILD
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
#endif
|
||||
|
||||
namespace PepperDash.Essentials.Core.Factory
|
||||
{
|
||||
/// <summary>
|
||||
/// Runtime provider that uses actual Crestron libraries
|
||||
/// </summary>
|
||||
public class CrestronRuntimeProvider : ICrestronEnvironmentProvider
|
||||
{
|
||||
private ICrestronControlSystem _controlSystem;
|
||||
|
||||
public ICrestronControlSystem GetControlSystem()
|
||||
{
|
||||
if (_controlSystem == null)
|
||||
{
|
||||
#if !TEST_BUILD
|
||||
// In runtime, wrap the actual Crestron control system
|
||||
// Note: This would need to be adapted based on the actual Crestron API
|
||||
// For now, return a null implementation
|
||||
#endif
|
||||
{
|
||||
// Return a null object pattern implementation for non-Crestron environments
|
||||
_controlSystem = new NullControlSystem();
|
||||
}
|
||||
}
|
||||
return _controlSystem;
|
||||
}
|
||||
|
||||
public IRelayPort CreateRelayPort(uint portNumber)
|
||||
{
|
||||
#if !TEST_BUILD
|
||||
var controlSystem = GetControlSystem();
|
||||
if (controlSystem.RelayPorts.TryGetValue(portNumber, out var port))
|
||||
{
|
||||
return port;
|
||||
}
|
||||
#endif
|
||||
return new NullRelayPort();
|
||||
}
|
||||
|
||||
public IDigitalInput CreateDigitalInput(uint portNumber)
|
||||
{
|
||||
#if !TEST_BUILD
|
||||
// Implementation would wrap actual Crestron digital input
|
||||
// This is a simplified version
|
||||
#endif
|
||||
return new NullDigitalInput();
|
||||
}
|
||||
|
||||
public IVersiPort CreateVersiPort(uint portNumber)
|
||||
{
|
||||
#if !TEST_BUILD
|
||||
// Implementation would wrap actual Crestron versiport
|
||||
// This is a simplified version
|
||||
#endif
|
||||
return new NullVersiPort();
|
||||
}
|
||||
|
||||
public IConsoleManager GetConsoleManager()
|
||||
{
|
||||
#if !TEST_BUILD
|
||||
return new CrestronConsoleManager();
|
||||
#else
|
||||
return new NullConsoleManager();
|
||||
#endif
|
||||
}
|
||||
|
||||
public ISystemInfo GetSystemInfo()
|
||||
{
|
||||
#if !TEST_BUILD
|
||||
return new CrestronSystemInfo();
|
||||
#else
|
||||
return new NullSystemInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Null Object Pattern Implementations
|
||||
|
||||
private class NullControlSystem : ICrestronControlSystem
|
||||
{
|
||||
public bool SupportsRelay => false;
|
||||
public uint NumberOfRelayPorts => 0;
|
||||
public Dictionary<uint, IRelayPort> RelayPorts => new Dictionary<uint, IRelayPort>();
|
||||
public string ProgramIdTag => "NULL";
|
||||
public string ControllerPrompt => "NULL>";
|
||||
public bool SupportsEthernet => false;
|
||||
public bool SupportsDigitalInput => false;
|
||||
public uint NumberOfDigitalInputPorts => 0;
|
||||
public bool SupportsVersiPort => false;
|
||||
public uint NumberOfVersiPorts => 0;
|
||||
}
|
||||
|
||||
private class NullRelayPort : IRelayPort
|
||||
{
|
||||
public bool State => false;
|
||||
public void Open() { }
|
||||
public void Close() { }
|
||||
public void Pulse(int delayMs) { }
|
||||
}
|
||||
|
||||
private class NullDigitalInput : IDigitalInput
|
||||
{
|
||||
public bool State => false;
|
||||
public event EventHandler<Abstractions.DigitalInputEventArgs> StateChange;
|
||||
}
|
||||
|
||||
private class NullVersiPort : IVersiPort
|
||||
{
|
||||
public bool DigitalIn => false;
|
||||
public ushort AnalogIn => 0;
|
||||
public void SetDigitalOut(bool value) { }
|
||||
public event EventHandler<Abstractions.VersiPortEventArgs> VersiportChange;
|
||||
}
|
||||
|
||||
private class NullConsoleManager : IConsoleManager
|
||||
{
|
||||
public void Print(string message) { }
|
||||
public void PrintLine(string message) { }
|
||||
public void RegisterCommand(string command, Action<string> handler, string help) { }
|
||||
}
|
||||
|
||||
private class NullSystemInfo : ISystemInfo
|
||||
{
|
||||
public string ProgramName => "NULL";
|
||||
public string SerialNumber => "000000";
|
||||
public string MacAddress => "00:00:00:00:00:00";
|
||||
public string IpAddress => "0.0.0.0";
|
||||
public string FirmwareVersion => "0.0.0";
|
||||
public DateTime SystemUpTime => DateTime.Now;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if !TEST_BUILD
|
||||
private class CrestronConsoleManager : IConsoleManager
|
||||
{
|
||||
public void Print(string message)
|
||||
{
|
||||
CrestronConsole.Print(message);
|
||||
}
|
||||
|
||||
public void PrintLine(string message)
|
||||
{
|
||||
CrestronConsole.PrintLine(message);
|
||||
}
|
||||
|
||||
public void RegisterCommand(string command, Action<string> handler, string help)
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand((s) => handler(s), command, help, ConsoleAccessLevelEnum.AccessOperator);
|
||||
}
|
||||
}
|
||||
|
||||
private class CrestronSystemInfo : ISystemInfo
|
||||
{
|
||||
public string ProgramName => "CrestronProgram";
|
||||
public string SerialNumber => "000000";
|
||||
public string MacAddress => "00:00:00:00:00:00";
|
||||
public string IpAddress => "0.0.0.0";
|
||||
public string FirmwareVersion => "1.0.0";
|
||||
public DateTime SystemUpTime => DateTime.Now;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user