Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions Dummies.UnitTests/AnyContinuousTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#region Usings declarations

using NFluent;

#endregion

namespace Dummies.UnitTests;

public sealed class AnyContinuousTests {

private const int SampleCount = 200;

[Fact(DisplayName = "Double: unconstrained draws are always finite.")]
public void DoubleIsFinite() {
for (int i = 0; i < SampleCount; i++) {
double value = Any.Double().Generate();
Check.That(double.IsNaN(value) || double.IsInfinity(value)).IsFalse();
}
}

[Fact(DisplayName = "Double: sign constraints are strict, Zero pins, NonZero excludes.")]
public void DoubleSignFamily() {
for (int i = 0; i < SampleCount; i++) {
Check.That(Any.Double().Positive().Generate()).IsStrictlyGreaterThan(0d);
Check.That(Any.Double().Negative().Generate()).IsStrictlyLessThan(0d);
Check.That(Any.Double().NonZero().Generate()).IsNotEqualTo(0d);
}
Check.That(Any.Double().Zero().Generate()).IsEqualTo(0d);
Check.ThatCode(() => Any.Double().Zero().NonZero()).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Double().Positive().Negative()).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Double: Between contains, GreaterThan is strict, and conflicts name both sides.")]
public void DoubleBounds() {
for (int i = 0; i < SampleCount; i++) {
double bounded = Any.Double().Between(1d, 2d).Generate();
Check.That(bounded).IsGreaterOrEqualThan(1d);
Check.That(bounded).IsLessOrEqualThan(2d);
Check.That(Any.Double().GreaterThan(1d).LessThanOrEqualTo(2d).Generate()).IsStrictlyGreaterThan(1d);
}

ConflictingAnyConstraintException conflict = Assert.Throws<ConflictingAnyConstraintException>(
() => Any.Double().GreaterThan(100d).LessThan(10d));
Check.That(conflict.Message).Contains("LessThan(10)");
Check.That(conflict.Message).Contains("GreaterThan(100)");
Check.ThatCode(() => Any.Double().GreaterThan(double.MaxValue)).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Double: non-finite arguments are rejected as argument errors.")]
public void DoubleRejectsNonFinite() {
Check.ThatCode(() => Any.Double().GreaterThan(double.NaN)).Throws<ArgumentException>();
Check.ThatCode(() => Any.Double().LessThan(double.PositiveInfinity)).Throws<ArgumentException>();
Check.ThatCode(() => Any.Double().Between(double.NegativeInfinity, 0d)).Throws<ArgumentException>();
Check.ThatCode(() => Any.Double().OneOf(1d, double.NaN)).Throws<ArgumentException>();
Check.ThatCode(() => Any.Double().Between(10d, 1d)).Throws<ArgumentException>();
}

[Fact(DisplayName = "Double: OneOf stays within and Except/DifferentFrom never yield the excluded value.")]
public void DoubleSets() {
double[] allowed = [1.5d, 2.5d];
for (int i = 0; i < SampleCount; i++) {
Check.That(allowed.Contains(Any.Double().OneOf(allowed).Generate())).IsTrue();
Check.That(Any.Double().OneOf(allowed).Except(1.5d).Generate()).IsEqualTo(2.5d);
Check.That(Any.Double().OneOf(allowed).DifferentFrom(2.5d).Generate()).IsEqualTo(1.5d);
}
}

[Fact(DisplayName = "Single: finite draws, strict signs, bounds contained, NaN rejected.")]
public void SingleBehaves() {
for (int i = 0; i < SampleCount; i++) {
float value = Any.Single().Generate();
Check.That(float.IsNaN(value) || float.IsInfinity(value)).IsFalse();
Check.That(Any.Single().Positive().Generate()).IsStrictlyGreaterThan(0f);

float bounded = Any.Single().Between(1f, 2f).Generate();
Check.That(bounded).IsGreaterOrEqualThan(1f);
Check.That(bounded).IsLessOrEqualThan(2f);
}

Check.That(Any.Single().Zero().Generate()).IsEqualTo(0f);
Check.ThatCode(() => Any.Single().GreaterThan(float.NaN)).Throws<ArgumentException>();
Check.ThatCode(() => Any.Single().GreaterThan(float.MaxValue)).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Single().Positive().Negative()).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Decimal: strict signs, pinned zero, contained bounds, and strict GreaterThan via exclusion.")]
public void DecimalBehaves() {
for (int i = 0; i < SampleCount; i++) {
Check.That(Any.Decimal().Positive().Generate()).IsStrictlyGreaterThan(0m);
Check.That(Any.Decimal().Negative().Generate()).IsStrictlyLessThan(0m);

decimal bounded = Any.Decimal().Between(1m, 2m).Generate();
Check.That(bounded).IsGreaterOrEqualThan(1m);
Check.That(bounded).IsLessOrEqualThan(2m);
Check.That(Any.Decimal().Between(1m, 2m).GreaterThan(1m).Generate()).IsStrictlyGreaterThan(1m);
}

Check.That(Any.Decimal().Zero().Generate()).IsEqualTo(0m);
Check.ThatCode(() => Any.Decimal().Zero().NonZero()).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Decimal().Between(10m, 1m)).Throws<ArgumentException>();

ConflictingAnyConstraintException conflict = Assert.Throws<ConflictingAnyConstraintException>(
() => Any.Decimal().GreaterThan(100m).LessThan(10m));
Check.That(conflict.Message).Contains("LessThan(10)");
Check.That(conflict.Message).Contains("GreaterThan(100)");
}

[Fact(DisplayName = "Continuous generators convert implicitly to their value type.")]
public void ImplicitConversions() {
double d = Any.Double().Between(1d, 2d);
float f = Any.Single().Between(1f, 2f);
decimal m = Any.Decimal().Between(1m, 2m);

Check.That(d).IsGreaterOrEqualThan(1d);
Check.That(f).IsGreaterOrEqualThan(1f);
Check.That(m).IsGreaterOrEqualThan(1m);
}

}
106 changes: 106 additions & 0 deletions Dummies.UnitTests/AnyModernTypeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#region Usings declarations

using NFluent;

#endregion

namespace Dummies.UnitTests;

public sealed class AnyModernTypeTests {

private const int SampleCount = 200;

private static readonly DateOnly AnchorDate = new(2026, 1, 1);
private static readonly TimeOnly AnchorTime = new(12, 0, 0);

[Fact(DisplayName = "DateOnly: Between is inclusive and reached; After/Before are exclusive; conflicts surface.")]
public void DateOnlyBehaves() {
HashSet<DateOnly> seen = new();
for (int i = 0; i < SampleCount; i++) {
DateOnly value = Any.DateOnly().Between(AnchorDate, AnchorDate.AddDays(2)).Generate();
seen.Add(value);
Check.That(value >= AnchorDate && value <= AnchorDate.AddDays(2)).IsTrue();
Check.That(Any.DateOnly().After(AnchorDate).Before(AnchorDate.AddDays(2)).Generate()).IsEqualTo(AnchorDate.AddDays(1));
}
Check.That(seen.Contains(AnchorDate)).IsTrue();
Check.That(seen.Contains(AnchorDate.AddDays(2))).IsTrue();

Check.ThatCode(() => Any.DateOnly().After(DateOnly.MaxValue)).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.DateOnly().Between(AnchorDate.AddDays(1), AnchorDate)).Throws<ArgumentException>();
}

[Fact(DisplayName = "DateOnly: OneOf/Except/DifferentFrom behave.")]
public void DateOnlySets() {
DateOnly[] allowed = [AnchorDate, AnchorDate.AddDays(7)];
for (int i = 0; i < SampleCount; i++) {
Check.That(allowed.Contains(Any.DateOnly().OneOf(allowed).Generate())).IsTrue();
Check.That(Any.DateOnly().OneOf(allowed).Except(AnchorDate).Generate()).IsEqualTo(AnchorDate.AddDays(7));
Check.That(Any.DateOnly().OneOf(allowed).DifferentFrom(AnchorDate.AddDays(7)).Generate()).IsEqualTo(AnchorDate);
}
}

[Fact(DisplayName = "TimeOnly: bounds behave and the exclusive window pins the middle tick.")]
public void TimeOnlyBehaves() {
for (int i = 0; i < SampleCount; i++) {
TimeOnly value = Any.TimeOnly().Between(AnchorTime, AnchorTime.Add(TimeSpan.FromMinutes(5))).Generate();
Check.That(value >= AnchorTime && value <= AnchorTime.Add(TimeSpan.FromMinutes(5))).IsTrue();

TimeOnly middle = Any.TimeOnly().After(AnchorTime).Before(new TimeOnly(AnchorTime.Ticks + 2)).Generate();
Check.That(middle.Ticks).IsEqualTo(AnchorTime.Ticks + 1);
}

Check.ThatCode(() => Any.TimeOnly().After(TimeOnly.MaxValue)).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Int128: signs, pins, full-width variety, extremes and conflicts.")]
public void Int128Behaves() {
HashSet<Int128> seen = new();
for (int i = 0; i < SampleCount; i++) {
seen.Add(Any.Int128().Generate());
Check.That(Any.Int128().Positive().Generate() > 0).IsTrue();
Check.That(Any.Int128().Negative().Generate() < 0).IsTrue();

Int128 bounded = Any.Int128().Between(1, 3).Generate();
Check.That(bounded >= 1 && bounded <= 3).IsTrue();
}
Check.That(seen.Count).IsStrictlyGreaterThan(1);

Check.That(Any.Int128().Zero().Generate() == 0).IsTrue();
Check.ThatCode(() => Any.Int128().GreaterThan(Int128.MaxValue)).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Int128().Positive().Negative()).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "UInt128: bounds, exclusivity and full-width variety.")]
public void UInt128Behaves() {
HashSet<UInt128> seen = new();
for (int i = 0; i < SampleCount; i++) {
seen.Add(Any.UInt128().Generate());

UInt128 bounded = Any.UInt128().Between(1, 3).Generate();
Check.That(bounded >= 1 && bounded <= 3).IsTrue();
Check.That(Any.UInt128().GreaterThan(5).LessThanOrEqualTo(6).Generate() == 6).IsTrue();
}
Check.That(seen.Count).IsStrictlyGreaterThan(1);

Check.That(Any.UInt128().Zero().Generate() == 0).IsTrue();
Check.ThatCode(() => Any.UInt128().GreaterThan(UInt128.MaxValue)).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Half: finite draws, strict Positive, pinned Zero, contained bounds, argument checks.")]
public void HalfBehaves() {
for (int i = 0; i < SampleCount; i++) {
Half value = Any.Half().Generate();
Check.That(Half.IsNaN(value) || Half.IsInfinity(value)).IsFalse();
Check.That(Any.Half().Positive().Generate() > Half.Zero).IsTrue();

Half bounded = Any.Half().Between((Half)1f, (Half)2f).Generate();
Check.That(bounded >= (Half)1f && bounded <= (Half)2f).IsTrue();
}

Check.That(Any.Half().Zero().Generate() == Half.Zero).IsTrue();
Check.ThatCode(() => Any.Half().GreaterThan(Half.NaN)).Throws<ArgumentException>();
Check.ThatCode(() => Any.Half().GreaterThan(Half.MaxValue)).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Half().Positive().Negative()).Throws<ConflictingAnyConstraintException>();
}

}
140 changes: 140 additions & 0 deletions Dummies.UnitTests/AnySetTypeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#region Usings declarations

using NFluent;

#endregion

namespace Dummies.UnitTests;

public sealed class AnySetTypeTests {

private const int SampleCount = 200;

private enum OrderStatus {

Draft,
Validated,
Cancelled

}

[Fact(DisplayName = "Bool: unconstrained draws hit both values; pins pin; contradictory pins conflict.")]
public void BoolBehaves() {
HashSet<bool> seen = new();
for (int i = 0; i < SampleCount; i++) { seen.Add(Any.Bool().Generate()); }
Check.That(seen.Count).IsEqualTo(2);

for (int i = 0; i < SampleCount; i++) {
Check.That(Any.Bool().True().Generate()).IsTrue();
Check.That(Any.Bool().False().Generate()).IsFalse();
Check.That(Any.Bool().DifferentFrom(true).Generate()).IsFalse();
}

ConflictingAnyConstraintException conflict = Assert.Throws<ConflictingAnyConstraintException>(
() => Any.Bool().True().False());
Check.That(conflict.Message).Contains("False()");
Check.That(conflict.Message).Contains("True()");

bool value = Any.Bool().True();
Check.That(value).IsTrue();
}

[Fact(DisplayName = "Guid: unconstrained draws are non-empty, varied, and reproducible under a context seed.")]
public void GuidBehaves() {
HashSet<Guid> seen = new();
for (int i = 0; i < SampleCount; i++) {
Guid value = Any.Guid().Generate();
seen.Add(value);
Check.That(value).IsNotEqualTo(Guid.Empty);
}
Check.That(seen.Count).IsStrictlyGreaterThan(1);

Check.That(Any.WithSeed(42).Guid().Generate()).IsEqualTo(Any.WithSeed(42).Guid().Generate());
}

[Fact(DisplayName = "Guid: Empty pins, NonEmpty excludes, and the pair conflicts in both orders.")]
public void GuidEmptyFamily() {
Check.That(Any.Guid().Empty().Generate()).IsEqualTo(Guid.Empty);
for (int i = 0; i < SampleCount; i++) {
Check.That(Any.Guid().NonEmpty().Generate()).IsNotEqualTo(Guid.Empty);
}

Check.ThatCode(() => Any.Guid().Empty().NonEmpty()).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Guid().NonEmpty().Empty()).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Guid: OneOf stays within, exhausting it conflicts, DifferentFrom never yields the value.")]
public void GuidSets() {
Guid first = Guid.NewGuid();
Guid second = Guid.NewGuid();

for (int i = 0; i < SampleCount; i++) {
Guid value = Any.Guid().OneOf(first, second).Generate();
Check.That(value == first || value == second).IsTrue();
Check.That(Any.Guid().OneOf(first, second).DifferentFrom(first).Generate()).IsEqualTo(second);
}

Check.ThatCode(() => Any.Guid().OneOf(first).Except(first)).Throws<ConflictingAnyConstraintException>();
}

[Fact(DisplayName = "Enum: unconstrained draws yield only declared members and reach all of them.")]
public void EnumDrawsDeclaredMembers() {
HashSet<OrderStatus> seen = new();
for (int i = 0; i < SampleCount; i++) {
OrderStatus value = Any.Enum<OrderStatus>().Generate();
seen.Add(value);
Check.That(System.Enum.IsDefined(typeof(OrderStatus), value)).IsTrue();
}
Check.That(seen.Count).IsEqualTo(3);
}

[Fact(DisplayName = "Enum: OneOf restricts, Except removes, exhausting the pool conflicts.")]
public void EnumSets() {
for (int i = 0; i < SampleCount; i++) {
OrderStatus restricted = Any.Enum<OrderStatus>().OneOf(OrderStatus.Draft, OrderStatus.Validated).Generate();
Check.That(restricted == OrderStatus.Draft || restricted == OrderStatus.Validated).IsTrue();
Check.That(Any.Enum<OrderStatus>().Except(OrderStatus.Cancelled).Generate()).IsNotEqualTo(OrderStatus.Cancelled);
Check.That(Any.Enum<OrderStatus>().OneOf(OrderStatus.Draft, OrderStatus.Validated).DifferentFrom(OrderStatus.Draft).Generate()).IsEqualTo(OrderStatus.Validated);
}

ConflictingAnyConstraintException conflict = Assert.Throws<ConflictingAnyConstraintException>(
() => Any.Enum<OrderStatus>().Except(OrderStatus.Draft, OrderStatus.Validated, OrderStatus.Cancelled));
Check.That(conflict.Message).Contains("Except(");
}

[Fact(DisplayName = "Enum: OneOf rejects undeclared numeric values — the declared-members-only contract holds.")]
public void EnumOneOfRejectsUndeclaredValues() {
ArgumentException rejected = Assert.Throws<ArgumentException>(
() => Any.Enum<OrderStatus>().OneOf((OrderStatus)42));
Check.That(rejected.Message).Contains("42");
Check.That(rejected.Message).Contains("OrderStatus");

Check.ThatCode(() => Any.Enum<OrderStatus>().OneOf(OrderStatus.Draft, (OrderStatus)42)).Throws<ArgumentException>();
}

[Fact(DisplayName = "Char: the default pool is ASCII letters and digits; families narrow it.")]
public void CharPools() {
for (int i = 0; i < SampleCount; i++) {
char value = Any.Char().Generate();
Check.That(value is >= 'A' and <= 'Z' or >= 'a' and <= 'z' or >= '0' and <= '9').IsTrue();
Check.That(Any.Char().Numeric().Generate() is >= '0' and <= '9').IsTrue();
Check.That(Any.Char().Alpha().Generate() is >= 'A' and <= 'Z' or >= 'a' and <= 'z').IsTrue();
Check.That(Any.Char().LowerCase().Generate() is >= 'A' and <= 'Z').IsFalse();
Check.That(Any.Char().Alpha().UpperCase().Generate() is >= 'A' and <= 'Z').IsTrue();
}
}

[Fact(DisplayName = "Char: OneOf restricts, exclusions apply, and contradictions conflict.")]
public void CharSets() {
for (int i = 0; i < SampleCount; i++) {
char value = Any.Char().OneOf('a', 'b').Generate();
Check.That(value == 'a' || value == 'b').IsTrue();
Check.That(Any.Char().OneOf('a', 'b').DifferentFrom('a').Generate()).IsEqualTo('b');
}

Check.ThatCode(() => Any.Char().Numeric().Alpha()).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Char().OneOf('a').Except('a')).Throws<ConflictingAnyConstraintException>();
Check.ThatCode(() => Any.Char().OneOf('a').Numeric()).Throws<ConflictingAnyConstraintException>();
}

}
Loading