Skip to content

Commit

Permalink
Update operators and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mikernet committed Mar 8, 2024
1 parent 75117b2 commit 088c12d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 72 deletions.
24 changes: 24 additions & 0 deletions Source/Singulink.Globalization.Currency/Money.GenericMath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Numerics;

namespace Singulink.Globalization;

#if NET7_0_OR_GREATER

/// <content>
/// Contains generic math implementation of <see cref="Money"/>.
/// </content>
partial struct Money :
IAdditionOperators<Money, Money, Money>,
IAdditionOperators<Money, decimal, Money>,
IComparisonOperators<Money, Money, bool>,
IDecrementOperators<Money>,
IDivisionOperators<Money, decimal, Money>,
IDivisionOperators<Money, Money, decimal>,
IIncrementOperators<Money>,
IMultiplyOperators<Money, decimal, Money>,
ISubtractionOperators<Money, Money, Money>,
ISubtractionOperators<Money, decimal, Money>,
IUnaryNegationOperators<Money, Money>,
IUnaryPlusOperators<Money, Money>;

#endif
25 changes: 14 additions & 11 deletions Source/Singulink.Globalization.Currency/Money.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,25 +133,28 @@ public Currency Currency
return x._amount >= y._amount;
}

public static Money operator +(Money x, Money y) => CreateDefaultable(x._amount + y._amount, CombineCurrencies(x._currency, y._currency));
public static Money operator +(Money x, Money y) => CreateDefaultable(x._amount + y._amount, CombineCurrenciesForAddOrSubtract(x._currency, y._currency));

public static Money operator +(Money x, decimal y) => CreateDefaultable(x._amount + y, x._currency);

public static Money operator +(decimal x, Money y) => y + x;

public static Money operator -(Money x, Money y) => CreateDefaultable(x._amount - y._amount, CombineCurrencies(x._currency, y._currency));
public static Money operator -(Money x, Money y) => CreateDefaultable(x._amount - y._amount, CombineCurrenciesForAddOrSubtract(x._currency, y._currency));

public static Money operator -(Money x, decimal y) => CreateDefaultable(x._amount - y, x._currency);

public static Money operator -(decimal x, Money y) => CreateDefaultable(x - y._amount, y._currency);

public static Money operator *(Money x, decimal y) => CreateDefaultable(x._amount * y, x._currency);

public static Money operator *(decimal x, Money y) => y * x;

public static Money operator /(Money x, decimal y) => CreateDefaultable(x._amount / y, x._currency);

public static Money operator /(decimal x, Money y) => CreateDefaultable(x / y._amount, y._currency);
public static decimal operator /(Money x, Money y)
{
if (x._currency != y._currency)
{
void Throw() => throw new ArgumentException("Currencies must match to divide money values.");
Throw();
}

return x._amount / y._amount;
}

public static Money operator ++(Money value)
{
Expand Down Expand Up @@ -245,7 +248,7 @@ private static void EnsureSameCurrencyForCompare(Currency? x, Currency? y)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Currency? CombineCurrencies(Currency? x, Currency? y)
private static Currency? CombineCurrenciesForAddOrSubtract(Currency? x, Currency? y)
{
if (x == y)
return x;
Expand All @@ -255,7 +258,7 @@ private static void EnsureSameCurrencyForCompare(Currency? x, Currency? y)

if (y is not null)
{
static void Throw() => throw new ArgumentException("Currencies must match (or one of the values can be a default value that has no currency associated with it).");
static void Throw() => throw new ArgumentException("Currencies must match to add or subtract money values (or one of the values can be a default value that has no currency associated with it).");
Throw();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,40 +146,34 @@ public void Addition_DifferentCurrency_ThrowsArgumentException()
}

[TestMethod]
public void Addition_OneDefault_ReturnsNonDefaultValue()
public void Addition_BothMoneyOneDefault_ReturnsNonDefaultValue()
{
(Usd100 + Money.Default).ShouldBe(Usd100);
(Money.Default + Usd100).ShouldBe(Usd100);
}

[TestMethod]
public void Addition_BothDefault_ReturnsDefault()
public void Addition_BothDefaultMoney_ReturnsDefault()
{
(Money.Default + Money.Default).ShouldBe(Money.Default);
}

[TestMethod]
public void Addition_MoneyAndDecimal_ReturnsCorrectResult()
{
(Usd100 + 200m).ShouldBe(Usd300);
}

[TestMethod]
public void Addition_MoneyAndNegativeDecimal_ReturnsCorrectResult()
public void Addition_DefaultMoneyAndZero_ReturnsDefault ()
{
(Usd200 + -100m).ShouldBe(Usd100);
(Money.Default + 0m).ShouldBe(Money.Default);
}

[TestMethod]
public void Addition_DecimalAndMoney_ReturnsCorrectResult()
public void Addition_DefaultMoneyAndDecimal_Throws()
{
(100m + Usd200).ShouldBe(Usd300);
Should.Throw<ArgumentException>(() => Money.Default + 5);
}

[TestMethod]
public void Addition_NegativeDecimalAndMoney_ReturnsCorrectResult()
public void Addition_MoneyAndDecimal_ReturnsCorrectResult()
{
(-100m + Usd200).ShouldBe(Usd100);
(Usd100 + 200m).ShouldBe(Usd300);
}

[TestMethod]
Expand All @@ -195,52 +189,40 @@ public void Subtraction_DifferentCurrency_ThrowsArgumentException()
}

[TestMethod]
public void Subtraction_OneDefault_ReturnsNonDefaultValue()
public void Subtraction_BothMoneyOneDefault_ReturnsNonDefaultValue()
{
(Usd100 - Money.Default).ShouldBe(Usd100);
(Money.Default - Usd100).ShouldBe(-Usd100);
}

[TestMethod]
public void Subtraction_BothDefault_ReturnsDefault()
public void Subtraction_BothDefaultMoney_ReturnsDefault()
{
(Money.Default - Money.Default).ShouldBe(Money.Default);
}

[TestMethod]
public void Subtraction_MoneyAndDecimal_ReturnsCorrectResult()
{
(Usd200 - 100m).ShouldBe(Usd100);
}

[TestMethod]
public void Subtraction_MoneyAndNegativeDecimal_ReturnsCorrectResult()
{
(Usd200 - -100m).ShouldBe(Usd300);
}

[TestMethod]
public void Subtraction_DecimalAndMoney_ReturnsCorrectResult()
public void Subtraction_DefaultMoneyAndZero_ReturnsDefault()
{
(200m - Usd100).ShouldBe(Usd100);
(Money.Default - 0m).ShouldBe(Money.Default);
}

[TestMethod]
public void Subtraction_NegativeDecimalAndMoney_ReturnsCorrectResult()
public void Subtraction_DefaultMoneyAndDecimal_Throws()
{
(-100m - Usd200).ShouldBe(-Usd300);
Should.Throw<ArgumentException>(() => Money.Default - 5);
}

[TestMethod]
public void Subtraction_DecimalMinusMoney_ReturnsCorrectResult()
public void Subtraction_MoneyAndDecimal_ReturnsCorrectResult()
{
(200m - Usd100).ShouldBe(Usd100);
(Usd200 - 100m).ShouldBe(Usd100);
}

[TestMethod]
public void Subtraction_NegativeDecimalMinusMoney_ReturnsCorrectResult()
public void Subtraction_MoneyAndNegativeDecimal_ReturnsCorrectResult()
{
(-100m - Usd200).ShouldBe(-Usd300);
(Usd200 - -100m).ShouldBe(Usd300);
}

[TestMethod]
Expand All @@ -261,24 +243,6 @@ public void Multiplication_MoneyAndZero_ReturnsZero()
(Usd100 * 0m).ShouldBe(Usd0);
}

[TestMethod]
public void Multiplication_DecimalAndMoney_ReturnsCorrectResult()
{
(2m * Usd100).ShouldBe(Usd200);
}

[TestMethod]
public void Multiplication_NegativeDecimalAndMoney_ReturnsCorrectResult()
{
(-2m * Usd100).ShouldBe(-Usd200);
}

[TestMethod]
public void Multiplication_ZeroAndMoney_ReturnsZero()
{
(0m * Usd100).ShouldBe(Usd0);
}

[TestMethod]
public void Division_MoneyAndDecimal_ReturnsCorrectResult()
{
Expand All @@ -304,21 +268,28 @@ public void Division_MoneyAndZero_ThrowsDivideByZeroException()
}

[TestMethod]
public void Division_DecimalAndMoney_ReturnsCorrectResult()
public void Division_SameCurrency_ReturnsCorrectResult()
{
(Usd200 / Usd100).ShouldBe(2m);
}

[TestMethod]
public void Division_OneDefaultMoney_Throws()
{
(20000m / Usd100).ShouldBe(Usd200);
Should.Throw<ArgumentException>(() => Money.Default / Usd100);
Should.Throw<ArgumentException>(() => Usd100 / Money.Default);
}

[TestMethod]
public void Division_NegativeDecimalAndMoney_ReturnsCorrectResult()
public void Division_DifferentCurrencies_Throws()
{
(-20000m / Usd100).ShouldBe(UsdMinus200);
Should.Throw<ArgumentException>(() => Usd100 / Cad100);
}

[TestMethod]
public void Division_DecimalAndZeroMoney_ThrowsDivideByZeroException()
public void Division_BothDefaultMoney_ThrowsDivideByZeroException()
{
Should.Throw<DivideByZeroException>(() => 200m / Usd0);
Should.Throw<DivideByZeroException>(() => Money.Default / Money.Default);
}

[TestMethod]
Expand All @@ -343,7 +314,7 @@ public void Decrement_ReturnsCorrectResult()
}

[TestMethod]
public void Decrement_DefaultVakue_Throws()
public void Decrement_DefaultValue_Throws()
{
var value = Money.Default;
Should.Throw<ArgumentException>(() => value--);
Expand Down

0 comments on commit 088c12d

Please sign in to comment.