From 6ea7f16fb97313aab207439f0da90f2bc070baa9 Mon Sep 17 00:00:00 2001 From: Ben Fradet Date: Mon, 22 Apr 2019 11:15:20 +0200 Subject: [PATCH] Remove infinite recursion when converting currencies (closes #166) --- .../com.snowplowanalytics/forex/Forex.scala | 23 ++++++++----------- .../forex/OerClient.scala | 2 +- .../ForexNowSpec.scala | 8 +++++++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/scala/com.snowplowanalytics/forex/Forex.scala b/src/main/scala/com.snowplowanalytics/forex/Forex.scala index e294964..b0b9e22 100644 --- a/src/main/scala/com.snowplowanalytics/forex/Forex.scala +++ b/src/main/scala/com.snowplowanalytics/forex/Forex.scala @@ -92,7 +92,7 @@ object Forex { */ final case class Forex[F[_]: Monad: ZonedClock](config: ForexConfig, client: OerClient[F]) { - def rate: ForexLookupTo[F] = ForexLookupTo(1, config.baseCurrency, config, client) + def rate: ForexLookupTo[F] = convert(1d, config.baseCurrency) /** * Starts building a fluent interface, performs currency look up from *source* currency. @@ -100,26 +100,23 @@ final case class Forex[F[_]: Monad: ZonedClock](config: ForexConfig, client: Oer * @param currency Source currency * @return ForexLookupTo object which is the part of the fluent interface */ - def rate(currency: CurrencyUnit): ForexLookupTo[F] = - ForexLookupTo(1, currency, config, client) + def rate(currency: CurrencyUnit): ForexLookupTo[F] = convert(1d, currency) /** - * Starts building a currency conversion from the supplied currency, for the supplied amount. + * Starts building a currency conversion for the supplied amount, using the currency specified in config * @param amount The amount of currency to be converted - * @param currency CurrencyUnit to convert from - * @return a ForexLookupTo, part of the currency conversion fluent interface. + * @return a ForexLookupTo, part of the currency conversion fluent interface */ - def convert(amount: Double, currency: CurrencyUnit): ForexLookupTo[F] = - convert(amount, currency) + def convert(amount: Double): ForexLookupTo[F] = convert(amount, config.baseCurrency) /** - * Starts building a currency conversion for the supplied amount, using the currency specified in config + * Starts building a currency conversion from the supplied currency, for the supplied amount. * @param amount The amount of currency to be converted - * @return a ForexLookupTo, part of the currency conversion fluent interface + * @param currency CurrencyUnit to convert from + * @return a ForexLookupTo, part of the currency conversion fluent interface. */ - def convert(amount: Double): ForexLookupTo[F] = - ForexLookupTo(amount, config.baseCurrency, config, client) - + def convert(amount: Double, currency: CurrencyUnit): ForexLookupTo[F] = + ForexLookupTo(amount, currency, config, client) } /** diff --git a/src/main/scala/com.snowplowanalytics/forex/OerClient.scala b/src/main/scala/com.snowplowanalytics/forex/OerClient.scala index cd5bd70..90c9dd0 100644 --- a/src/main/scala/com.snowplowanalytics/forex/OerClient.scala +++ b/src/main/scala/com.snowplowanalytics/forex/OerClient.scala @@ -31,7 +31,7 @@ import responses._ * @param nowishCache - user defined nowishCache * @param eodCache - user defined eodCache */ -case class OerClient[F[_]: Monad]( +final case class OerClient[F[_]: Monad]( config: ForexConfig, nowishCache: Option[NowishCache[F]] = None, eodCache: Option[EodCache[F]] = None diff --git a/src/test/scala/com.snowplowanalytics.forex/ForexNowSpec.scala b/src/test/scala/com.snowplowanalytics.forex/ForexNowSpec.scala index 53b1f1b..d4c4123 100644 --- a/src/test/scala/com.snowplowanalytics.forex/ForexNowSpec.scala +++ b/src/test/scala/com.snowplowanalytics.forex/ForexNowSpec.scala @@ -39,9 +39,17 @@ class ForexNowSpec extends Specification { val ioTradeInYenNow = ioFx.flatMap(_.convert(10000).to(CurrencyUnit.JPY).now) ioTradeInYenNow.unsafeRunSync() must beRight( (m: Money) => m.isGreaterThan(Money.of(CurrencyUnit.JPY, 10000, RoundingMode.HALF_EVEN))) + val ioTradeInYenNow2 = ioFx + .flatMap(_.convert(10000, CurrencyUnit.USD).to(CurrencyUnit.JPY).now) + ioTradeInYenNow2.unsafeRunSync() must beRight( + (m: Money) => m.isGreaterThan(Money.of(CurrencyUnit.JPY, 10000, RoundingMode.HALF_EVEN))) val evalTradeInYenNow = evalFx.flatMap(_.convert(10000).to(CurrencyUnit.JPY).now) evalTradeInYenNow.value must beRight( (m: Money) => m.isGreaterThan(Money.of(CurrencyUnit.JPY, 10000, RoundingMode.HALF_EVEN))) + val evalTradeInYenNow2 = evalFx + .flatMap(_.convert(10000, CurrencyUnit.USD).to(CurrencyUnit.JPY).now) + evalTradeInYenNow2.value must beRight( + (m: Money) => m.isGreaterThan(Money.of(CurrencyUnit.JPY, 10000, RoundingMode.HALF_EVEN))) } }