Skip to content

Commit

Permalink
[currency converter] allow to deduce reverse rate (prebid#1126)
Browse files Browse the repository at this point in the history
This CL allows the currency rate currency to deduce a currency rate even
if not directly defined in the table but the reverse rate is present.

E.q.

USD => EUR is 1.0897
EUR => USD is not set

Old behavior when asking rate from EUR to USD will not be found,
New behavior is using the known reverse rate to deduce the rate.

Rate for 2 USD will be 2 * (1 / 1.0897)
  • Loading branch information
benjaminch authored and mansinahar committed Apr 15, 2020
1 parent ed0784c commit 31b6ac5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
5 changes: 4 additions & 1 deletion currencies/rates.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ func (r *Rates) GetRate(from string, to string) (float64, error) {
}
if r.Conversions != nil {
if conversion, present := r.Conversions[fromUnit.String()][toUnit.String()]; present {
// In case we have an entry FROM -> TO
return conversion, err
} else if conversion, present := r.Conversions[toUnit.String()][fromUnit.String()]; present {
// In case we have an entry TO -> FROM
return 1 / conversion, err
}

return 0, fmt.Errorf("Currency conversion rate not found: '%s' => '%s'", fromUnit.String(), toUnit.String())
}
return 0, errors.New("rates are nil")
Expand Down
54 changes: 54 additions & 0 deletions currencies/rates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,60 @@ func TestGetRate(t *testing.T) {
}
}

func TestGetRate_ReverseConversion(t *testing.T) {

// Setup:
rates := currencies.NewRates(time.Now(), map[string]map[string]float64{
"USD": {
"GBP": 0.77208,
},
"EUR": {
"USD": 0.88723,
},
})

testCases := []struct {
from string
to string
expectedRate float64
description string
}{
{
from: "USD",
to: "GBP",
expectedRate: 0.77208,
description: "case 1 - Rate is present directly and will be returned as is",
},
{
from: "EUR",
to: "USD",
expectedRate: 0.88723,
description: "case 2 - Rate is present directly and will be returned as is (2)",
},
{
from: "GBP",
to: "USD",
expectedRate: 1 / 0.77208,
description: "case 3 - Rate is not present but the reverse one is, will return the computed rate from the reverse entry",
},
{
from: "USD",
to: "EUR",
expectedRate: 1 / 0.88723,
description: "case 4 - Rate is not present but the reverse one is, will return the computed rate from the reverse entry (2)",
},
}

for _, tc := range testCases {
// Execute:
rate, err := rates.GetRate(tc.from, tc.to)

// Verify:
assert.Nil(t, err, "err should be nil: "+tc.description)
assert.Equal(t, tc.expectedRate, rate, "rate doesn't match the expected one: "+tc.description)
}
}

func TestGetRate_EmptyRates(t *testing.T) {

// Setup:
Expand Down

0 comments on commit 31b6ac5

Please sign in to comment.