Vanara/UnitTests/CSharpRunner/SuccessfulConstraint.cs

272 lines
6.7 KiB
C#

using NUnit.Framework.Constraints;
using System;
using Vanara.PInvoke;
namespace Vanara.PInvoke.Tests
{
public abstract class ResultIs // : NUnit.Framework.Is
{
public static FailureConstraint Failure => new FailureConstraint();
public static MyConstraintExpression Not => MyConstraintExpression.Not;
public static SuccessfulConstraint Successful => new SuccessfulConstraint();
public static ValidHandleConstraint ValidHandle => new ValidHandleConstraint();
public static FailureConstraint FailureCode(object expectedError) => new FailureConstraint(expectedError);
public static ValueConstraint Value(object value) => new ValueConstraint(value);
}
public class MyConstraintExpression
{
private OpConstraint.Op op;
private MyConstraintExpression(OpConstraint.Op _op) => op = _op;
public static MyConstraintExpression Not => new MyConstraintExpression(OpConstraint.Op.Not);
public ValidHandleConstraint ValidHandle => new ValidHandleConstraint(op);
public ValueConstraint Value(object value) => new ValueConstraint(value, op);
}
public class FailureConstraint : Constraint
{
public FailureConstraint(object expected = null)
{
switch (expected)
{
case null:
break;
case uint i:
Expected = new Win32Error(i);
break;
case int i:
Expected = new HRESULT(i);
break;
case IErrorProvider iep:
Expected = iep;
break;
default:
throw new ArgumentException();
}
}
public object Expected { get; }
public override ConstraintResult ApplyTo<TActual>(TActual actual)
{
var success = false;
object updActual = actual;
switch (actual)
{
case bool b:
success = b;
Description = nameof(Win32Error.ERROR_SUCCESS);
if (!b)
{
var le = Win32Error.GetLastError();
if (Expected != null) Description = Expected.ToString();
success = Expected is null ? le.Failed : le.Failed && ((IErrorProvider)Expected).ToHRESULT().Equals(le.ToHRESULT());
updActual = le;
}
break;
case HRESULT hr:
success = Expected is null ? hr.Failed : hr.Failed && ((IErrorProvider)Expected).ToHRESULT().Equals(hr);
Description = Expected?.ToString() ?? nameof(HRESULT.S_OK);
break;
case Win32Error err:
success = Expected is null ? err.Failed : err.Failed && ((IErrorProvider)Expected).ToHRESULT().Equals(err.ToHRESULT());
Description = Expected?.ToString() ?? nameof(Win32Error.ERROR_SUCCESS);
break;
case NTStatus st:
success = Expected is null ? st.Failed : st.Failed && ((IErrorProvider)Expected).ToHRESULT().Equals(((IErrorProvider)st).ToHRESULT());
Description = Expected?.ToString() ?? nameof(NTStatus.STATUS_SUCCESS);
break;
case uint i:
var e = new Win32Error(i);
success = Expected is null ? e.Failed : e.Failed && ((IErrorProvider)Expected).ToHRESULT().Equals(e.ToHRESULT());
updActual = e;
Description = Expected?.ToString() ?? nameof(Win32Error.ERROR_SUCCESS);
break;
case int ui:
var h = new HRESULT(ui);
success = Expected is null ? h.Failed : h.Failed && ((IErrorProvider)Expected).ToHRESULT().Equals(h);
updActual = h;
Description = Expected?.ToString() ?? nameof(HRESULT.S_OK);
break;
default:
break;
}
return new ConstraintResult(this, updActual, success);
}
}
public class SuccessfulConstraint : Constraint
{
public SuccessfulConstraint()
{
}
public override ConstraintResult ApplyTo<TActual>(TActual actual)
{
var success = false;
var updActual = actual as IErrorProvider;
switch (actual)
{
case bool b:
success = b;
Description = nameof(Win32Error.ERROR_SUCCESS);
if (!b)
{
var le = Win32Error.GetLastError();
success = le.Succeeded;
updActual = le;
}
break;
case HRESULT hr:
success = hr.Succeeded;
Description = nameof(HRESULT.S_OK);
break;
case Win32Error err:
success = err.Succeeded;
Description = nameof(Win32Error.ERROR_SUCCESS);
break;
case NTStatus st:
success = st.Succeeded;
Description = nameof(NTStatus.STATUS_SUCCESS);
break;
case uint i:
var e = new Win32Error(i);
success = e.Succeeded;
updActual = e;
Description = nameof(Win32Error.ERROR_SUCCESS);
break;
case int ui:
var h = new HRESULT(ui);
success = h.Succeeded;
updActual = h;
Description = nameof(HRESULT.S_OK);
break;
default:
break;
}
return new ConstraintResult(this, updActual, success);
}
}
public abstract class OpConstraint : Constraint
{
public enum Op
{
None = 0,
Not = 1
}
protected Op AppliedOp { get; }
protected OpConstraint(Op op) => AppliedOp = op;
protected string Prefix
{
get
{
switch (AppliedOp)
{
case Op.Not:
return "Not ";
default:
return "";
}
}
}
}
public class ValidHandleConstraint : OpConstraint
{
public ValidHandleConstraint(OpConstraint.Op op = OpConstraint.Op.None) : base(op)
{
}
public override ConstraintResult ApplyTo<TActual>(TActual actual)
{
IntPtr val;
bool success;
switch (actual)
{
case System.Runtime.InteropServices.SafeHandle h:
success = !h.IsInvalid;
val = h.DangerousGetHandle();
break;
case IHandle ih:
val = ih.DangerousGetHandle();
var l = val.ToInt64();
success = l != 0 && l != -1;
break;
case System.IntPtr p:
val = p;
l = val.ToInt64();
success = l != 0 && l != -1;
break;
default:
throw new InvalidCastException("Cannot get a handle from value.");
}
Description = $"Valid handle";
if (AppliedOp == Op.Not)
{
success = !success;
Description = $"Invalid handle";
}
return new ErrConstraintResult(this, string.Format("0x{0:X" + IntPtr.Size + "}", val.ToInt64()), success);
}
}
public class ValueConstraint : OpConstraint
{
public object Expected { get; }
public ValueConstraint(object expected, OpConstraint.Op op = OpConstraint.Op.None) : base(op)
{
Expected = expected;
}
public override ConstraintResult ApplyTo<TActual>(TActual actual)
{
var eq = new EqualConstraint(Expected);
Description = Prefix + eq.Description;
var success = eq.ApplyTo(actual).IsSuccess;
if (AppliedOp == Op.Not)
success = !success;
return new ErrConstraintResult(this, actual, success);
}
}
public class ErrConstraintResult : ConstraintResult
{
private readonly Win32Error lastErr;
public ErrConstraintResult(IConstraint constraint, object actualValue, bool isSuccessful) : base(constraint, actualValue, isSuccessful)
{
lastErr = Win32Error.GetLastError();
}
public override void WriteAdditionalLinesTo(MessageWriter writer) => writer.Write($" (Err: {lastErr})");
}
}