Skip to content

Commit

Permalink
🔧 allow multiple usages of [RequireNonZero] and [RequireUnique]
Browse files Browse the repository at this point in the history
  • Loading branch information
fluffynuts committed Dec 12, 2024
1 parent 08422e3 commit 8113e91
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 80 deletions.
84 changes: 4 additions & 80 deletions source/TestUtils/PeanutButter.RandomGenerators/RequireNonZero.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
namespace Imported.PeanutButter.RandomGenerators;
#else
using System;
using PeanutButter.DuckTyping.AutoConversion;
using PeanutButter.Utils;

namespace PeanutButter.RandomGenerators;
Expand All @@ -13,6 +12,10 @@ namespace PeanutButter.RandomGenerators;
/// <summary>
/// Requires that the named property is randomized to a non-zero value
/// </summary>
[AttributeUsage(
AttributeTargets.Class,
AllowMultiple = true
)]
#if BUILD_PEANUTBUTTER_INTERNAL
internal
#else
Expand All @@ -34,83 +37,4 @@ ref object target
{
propInfo.SetValue(target, RandomValueGen.GetRandomInt(1));
}
}

/// <summary>
/// Restricts the possible values for a property
/// to the provided list
/// </summary>
[AttributeUsage(
validOn: AttributeTargets.Class,
AllowMultiple = true
)]
#if BUILD_PEANUTBUTTER_INTERNAL
internal
#else
public
#endif
class Restrict : RandomizerAttribute
{
/// <summary>
/// The restricted values for this property
/// </summary>
public object[] Values { get; }

/// <inheritdoc />
public Restrict(
string propertyName,
object value,
params object[] moreValues
) : base(propertyName)
{
Values = new[]
{
value
}.And(moreValues);
}

/// <inheritdoc />
public override void SetRandomValue(
PropertyOrField propInfo,
ref object target
)
{
var toSet = RandomValueGen.GetRandomFrom(Values);
if (toSet is null)
{
propInfo.SetValue(
target,
propInfo.Type.IsNullableType()
? null
: propInfo.Type.DefaultValue()
);

return;
}

var valueType = toSet.GetType();
if (valueType == propInfo.Type)
{
propInfo.SetValue(target, toSet);
return;
}

var converter = ConverterLocator.TryFindConverter(
valueType,
propInfo.Type
);
if (converter is null)
{
throw new NotImplementedException(
$"""
There is no known converter to convert between {valueType} and {propInfo.Type}.
You may implement IConverter<{valueType}, {propInfo.Type}> to resolve this:
ConverterLocator should pick it up.
"""
);
}

var converted = converter.Convert(toSet);
propInfo.SetValue(target, converted);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ namespace PeanutButter.RandomGenerators;
/// <summary>
/// Abstract class to require uniqueness on a property or field by name
/// </summary>
[AttributeUsage(
AttributeTargets.Class,
AllowMultiple = true
)]
#if BUILD_PEANUTBUTTER_INTERNAL
internal
#else
Expand Down
90 changes: 90 additions & 0 deletions source/TestUtils/PeanutButter.RandomGenerators/Restrict.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#if BUILD_PEANUTBUTTER_INTERNAL
using Imported.PeanutButter.Utils;

namespace Imported.PeanutButter.RandomGenerators;
#else
using System;
using PeanutButter.DuckTyping.AutoConversion;
using PeanutButter.Utils;

namespace PeanutButter.RandomGenerators;
#endif

/// <summary>
/// Restricts the possible values for a property
/// to the provided list
/// </summary>
[AttributeUsage(
validOn: AttributeTargets.Class,
AllowMultiple = true
)]
#if BUILD_PEANUTBUTTER_INTERNAL
internal
#else
public
#endif
class Restrict : RandomizerAttribute
{
/// <summary>
/// The restricted values for this property
/// </summary>
public object[] Values { get; }

/// <inheritdoc />
public Restrict(
string propertyName,
object value,
params object[] moreValues
) : base(propertyName)
{
Values = new[]
{
value
}.And(moreValues);
}

/// <inheritdoc />
public override void SetRandomValue(
PropertyOrField propInfo,
ref object target
)
{
var toSet = RandomValueGen.GetRandomFrom(Values);
if (toSet is null)
{
propInfo.SetValue(
target,
propInfo.Type.IsNullableType()
? null
: propInfo.Type.DefaultValue()
);

return;
}

var valueType = toSet.GetType();
if (valueType == propInfo.Type)
{
propInfo.SetValue(target, toSet);
return;
}

var converter = ConverterLocator.TryFindConverter(
valueType,
propInfo.Type
);
if (converter is null)
{
throw new NotImplementedException(
$"""
There is no known converter to convert between {valueType} and {propInfo.Type}.
You may implement IConverter<{valueType}, {propInfo.Type}> to resolve this:
ConverterLocator should pick it up.
"""
);
}

var converted = converter.Convert(toSet);
propInfo.SetValue(target, converted);
}
}

0 comments on commit 8113e91

Please sign in to comment.