/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.basics.currency;
import static com.opengamma.strata.basics.currency.MultiCurrencyAmount.toMultiCurrencyAmount;
import static com.opengamma.strata.collect.TestHelper.assertSerialization;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static com.opengamma.strata.collect.TestHelper.coverImmutableBean;
import static org.testng.Assert.assertEquals;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.joda.beans.BeanBuilder;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
/**
* Test {@link MultiCurrencyAmount}.
*/
@Test
public class MultiCurrencyAmountTest {
private static final Currency CCY1 = Currency.AUD;
private static final Currency CCY2 = Currency.CAD;
private static final Currency CCY3 = Currency.CHF;
private static final double AMT1 = 101;
private static final double AMT2 = 103;
private static final double AMT3 = 107;
private static final CurrencyAmount CA1 = CurrencyAmount.of(CCY1, AMT1);
private static final CurrencyAmount CA2 = CurrencyAmount.of(CCY2, AMT2);
private static final CurrencyAmount CA3 = CurrencyAmount.of(CCY3, AMT3);
//-------------------------------------------------------------------------
public void test_empty() {
assertMCA(MultiCurrencyAmount.empty());
}
//-------------------------------------------------------------------------
public void test_of_CurrencyDouble() {
assertMCA(MultiCurrencyAmount.of(CCY1, AMT1), CA1);
}
public void test_of_CurrencyDouble_null() {
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(null, AMT1));
}
//-------------------------------------------------------------------------
public void test_of_VarArgs_empty() {
assertMCA(MultiCurrencyAmount.of());
}
public void test_of_VarArgs() {
assertMCA(MultiCurrencyAmount.of(CA1, CA3), CA1, CA3);
}
public void test_of_VarArgs_duplicate() {
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(CA1, CurrencyAmount.of(CCY1, AMT2)));
}
public void test_of_VarArgs_null() {
CurrencyAmount[] array = null;
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(array));
}
//-------------------------------------------------------------------------
public void test_of_Iterable() {
Iterable<CurrencyAmount> iterable = Arrays.asList(CA1, CA3);
assertMCA(MultiCurrencyAmount.of(iterable), CA1, CA3);
}
public void test_of_Iterable_duplicate() {
Iterable<CurrencyAmount> iterable = Arrays.asList(CA1, CurrencyAmount.of(CCY1, AMT2));
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(iterable));
}
public void test_of_Iterable_null() {
Iterable<CurrencyAmount> iterable = null;
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(iterable));
}
public void test_of_Iterable_containsNull() {
Iterable<CurrencyAmount> iterable = Arrays.asList(CA1, null, CA2);
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(iterable));
}
//-------------------------------------------------------------------------
public void test_of_Map() {
Map<Currency, Double> map = ImmutableMap.<Currency, Double>builder()
.put(CCY1, AMT1)
.put(CCY3, AMT3)
.build();
assertMCA(MultiCurrencyAmount.of(map), CA1, CA3);
}
public void test_of_Map_null() {
Map<Currency, Double> map = null;
assertThrowsIllegalArg(() -> MultiCurrencyAmount.of(map));
}
//-------------------------------------------------------------------------
public void test_total_Iterable() {
Iterable<CurrencyAmount> iterable = Arrays.asList(CA1, CA3);
assertMCA(MultiCurrencyAmount.total(iterable), CA1, CA3);
}
public void test_total_Iterable_duplicate() {
Iterable<CurrencyAmount> iterable = Arrays.asList(CA1, CurrencyAmount.of(CCY1, AMT2), CA2);
assertMCA(MultiCurrencyAmount.total(iterable), CurrencyAmount.of(CCY1, AMT1 + AMT2), CA2);
}
public void test_total_Iterable_null() {
Iterable<CurrencyAmount> iterable = null;
assertThrowsIllegalArg(() -> MultiCurrencyAmount.total(iterable));
}
public void test_total_Iterable_containsNull() {
Iterable<CurrencyAmount> iterable = Arrays.asList(CA1, null, CA2);
assertThrowsIllegalArg(() -> MultiCurrencyAmount.total(iterable));
}
//-------------------------------------------------------------------------
public void test_collector() {
List<CurrencyAmount> amount = ImmutableList.of(
CurrencyAmount.of(CCY1, 100), CurrencyAmount.of(CCY1, 150), CurrencyAmount.of(CCY2, 100));
MultiCurrencyAmount test = amount.stream().collect(toMultiCurrencyAmount());
MultiCurrencyAmount expected = MultiCurrencyAmount.of(CurrencyAmount.of(CCY1, 250), CurrencyAmount.of(CCY2, 100));
assertEquals(test, expected);
}
public void test_collector_parallel() {
List<CurrencyAmount> amount = ImmutableList.of(
CurrencyAmount.of(CCY1, 100), CurrencyAmount.of(CCY1, 150), CurrencyAmount.of(CCY2, 100));
MultiCurrencyAmount test = amount.parallelStream().collect(toMultiCurrencyAmount());
MultiCurrencyAmount expected = MultiCurrencyAmount.of(CurrencyAmount.of(CCY1, 250), CurrencyAmount.of(CCY2, 100));
assertEquals(test, expected);
}
public void test_collector_null() {
List<CurrencyAmount> amount = Arrays.asList(
CurrencyAmount.of(CCY1, 100), null, CurrencyAmount.of(CCY2, 100));
assertThrowsIllegalArg(() -> amount.stream().collect(toMultiCurrencyAmount()));
}
//-------------------------------------------------------------------------
public void test_beanBuilder() {
MultiCurrencyAmount test = MultiCurrencyAmount.meta().builder()
.set(MultiCurrencyAmount.meta().amounts(), ImmutableSortedSet.of(CA1, CA2, CA3))
.build();
assertMCA(test, CA1, CA2, CA3);
}
public void test_beanBuilder_invalid() {
BeanBuilder<? extends MultiCurrencyAmount> test = MultiCurrencyAmount.meta().builder()
.set(MultiCurrencyAmount.meta().amounts(),
ImmutableSortedSet.of(CA1, CA2, CurrencyAmount.of(CA1.getCurrency(), AMT3)));
assertThrowsIllegalArg(() -> test.build());
}
//-------------------------------------------------------------------------
public void test_contains_null() {
MultiCurrencyAmount base = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> base.contains(null));
}
//-------------------------------------------------------------------------
public void test_plus_CurrencyDouble_merge() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.plus(Currency.AUD, 3);
assertMCA(test, cb, CurrencyAmount.of(Currency.AUD, 120));
}
public void test_plus_CurrencyDouble_add() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.plus(Currency.NZD, 3);
assertMCA(test, ca, cb, CurrencyAmount.of(Currency.NZD, 3));
}
public void test_plus_CurrencyDouble_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.plus((Currency) null, 1));
}
//-------------------------------------------------------------------------
public void test_plus_CurrencyAmount_merge() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
CurrencyAmount cc = CurrencyAmount.of(Currency.AUD, 3);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.plus(cc);
assertMCA(test, cb, CurrencyAmount.of(Currency.AUD, 120));
}
public void test_plus_CurrencyAmount_add() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
CurrencyAmount cc = CurrencyAmount.of(Currency.NZD, 3);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.plus(cc);
assertMCA(test, ca, cb, cc);
}
public void test_plus_CurrencyAmount_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.plus((CurrencyAmount) null));
}
//-------------------------------------------------------------------------
public void test_plus_MultiCurrencyAmount_mergeAndAdd() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
CurrencyAmount cc = CurrencyAmount.of(Currency.AUD, 3);
CurrencyAmount cd = CurrencyAmount.of(Currency.NZD, 3);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount mc2 = MultiCurrencyAmount.of(cc, cd);
MultiCurrencyAmount test = mc1.plus(mc2);
assertMCA(test, cb, cd, CurrencyAmount.of(Currency.AUD, 120));
}
public void test_plus_MultiCurrencyAmount_empty() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount mc2 = MultiCurrencyAmount.of();
MultiCurrencyAmount test = mc1.plus(mc2);
assertMCA(test, ca, cb);
}
public void test_plus_MultiCurrencyAmount_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.plus((MultiCurrencyAmount) null));
}
//-------------------------------------------------------------------------
public void test_minus_CurrencyDouble_merge() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.minus(Currency.AUD, 3);
assertMCA(test, cb, CurrencyAmount.of(Currency.AUD, 114));
}
public void test_minus_CurrencyDouble_add() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.minus(Currency.NZD, 3);
assertMCA(test, ca, cb, CurrencyAmount.of(Currency.NZD, -3));
}
public void test_minus_CurrencyDouble_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.minus((Currency) null, 1));
}
//-------------------------------------------------------------------------
public void test_minus_CurrencyAmount_merge() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
CurrencyAmount cc = CurrencyAmount.of(Currency.AUD, 3);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.minus(cc);
assertMCA(test, cb, CurrencyAmount.of(Currency.AUD, 114));
}
public void test_minus_CurrencyAmount_add() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
CurrencyAmount cc = CurrencyAmount.of(Currency.NZD, 3);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount test = mc1.minus(cc);
assertMCA(test, ca, cb, cc.negated());
}
public void test_minus_CurrencyAmount_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.minus((CurrencyAmount) null));
}
//-------------------------------------------------------------------------
public void test_minus_MultiCurrencyAmount_mergeAndAdd() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
CurrencyAmount cc = CurrencyAmount.of(Currency.AUD, 3);
CurrencyAmount cd = CurrencyAmount.of(Currency.NZD, 3);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount mc2 = MultiCurrencyAmount.of(cc, cd);
MultiCurrencyAmount test = mc1.minus(mc2);
assertMCA(test, cb, cd.negated(), CurrencyAmount.of(Currency.AUD, 114));
}
public void test_minus_MultiCurrencyAmount_empty() {
CurrencyAmount ca = CurrencyAmount.of(Currency.AUD, 117);
CurrencyAmount cb = CurrencyAmount.of(Currency.USD, 12);
MultiCurrencyAmount mc1 = MultiCurrencyAmount.of(ca, cb);
MultiCurrencyAmount mc2 = MultiCurrencyAmount.of();
MultiCurrencyAmount test = mc1.minus(mc2);
assertMCA(test, ca, cb);
}
public void test_minus_MultiCurrencyAmount_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.minus((MultiCurrencyAmount) null));
}
//-------------------------------------------------------------------------
public void test_multipliedBy() {
MultiCurrencyAmount base = MultiCurrencyAmount.of(CA1, CA2);
MultiCurrencyAmount test = base.multipliedBy(2.5);
assertMCA(test, CA1.multipliedBy(2.5), CA2.multipliedBy(2.5));
}
//-------------------------------------------------------------------------
public void test_negated() {
MultiCurrencyAmount base = MultiCurrencyAmount.of(CA1, CA2);
MultiCurrencyAmount test = base.negated();
assertMCA(test, CA1.negated(), CA2.negated());
assertEquals(
MultiCurrencyAmount.of(CurrencyAmount.zero(Currency.USD), CurrencyAmount.zero(Currency.EUR)).negated(),
MultiCurrencyAmount.of(CurrencyAmount.zero(Currency.USD), CurrencyAmount.zero(Currency.EUR)));
assertEquals(
MultiCurrencyAmount.of(CurrencyAmount.of(Currency.USD, -0d), CurrencyAmount.of(Currency.EUR, -0d)).negated(),
MultiCurrencyAmount.of(CurrencyAmount.zero(Currency.USD), CurrencyAmount.zero(Currency.EUR)));
}
//-------------------------------------------------------------------------
public void test_mapAmounts() {
MultiCurrencyAmount base = MultiCurrencyAmount.of(CA1, CA2);
MultiCurrencyAmount test = base.mapAmounts(a -> a * 2.5 + 1);
assertMCA(test, CA1.mapAmount(a -> a * 2.5 + 1), CA2.mapAmount(a -> a * 2.5 + 1));
}
public void test_mapAmounts_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.mapAmounts(null));
}
//-------------------------------------------------------------------------
public void test_mapCurrencyAmounts() {
MultiCurrencyAmount base = MultiCurrencyAmount.of(CA1, CA2);
MultiCurrencyAmount test = base.mapCurrencyAmounts(a -> CurrencyAmount.of(CCY3, 1));
assertMCA(test, CurrencyAmount.of(CCY3, 2));
}
public void test_mapCurrencyAmounts_null() {
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertThrowsIllegalArg(() -> test.mapCurrencyAmounts(null));
}
//-------------------------------------------------------------------------
public void test_stream() {
MultiCurrencyAmount base = MultiCurrencyAmount.of(CA1, CA2);
MultiCurrencyAmount test = base.stream()
.map(ca -> ca.mapAmount(a -> a * 3))
.collect(toMultiCurrencyAmount());
assertMCA(test, CA1.mapAmount(a -> a * 3), CA2.mapAmount(a -> a * 3));
}
//-------------------------------------------------------------------------
public void test_toMap() {
ImmutableSortedMap<Currency, Double> test = MultiCurrencyAmount.of(CA1, CA2).toMap();
assertEquals(test.size(), 2);
assertEquals(test.containsKey(CA1.getCurrency()), true);
assertEquals(test.containsKey(CA2.getCurrency()), true);
assertEquals(test.get(CA1.getCurrency()), Double.valueOf(CA1.getAmount()));
assertEquals(test.get(CA2.getCurrency()), Double.valueOf(CA2.getAmount()));
}
//-------------------------------------------------------------------------
public void test_convertedTo_rateProvider_noConversionSize1() {
FxRateProvider provider = (ccy1, ccy2) -> {
throw new IllegalArgumentException();
};
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA2);
assertEquals(test.convertedTo(CCY2, provider), CA2);
}
public void test_convertedTo_rateProvider_conversionSize1() {
FxRateProvider provider = (ccy1, ccy2) -> {
if (ccy1.equals(CCY1) && ccy2.equals(CCY2)) {
return 2.5d;
}
throw new IllegalArgumentException();
};
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1);
assertEquals(test.convertedTo(CCY2, provider), CurrencyAmount.of(CCY2, AMT1 * 2.5d));
}
public void test_convertedTo_rateProvider_conversionSize2() {
FxRateProvider provider = (ccy1, ccy2) -> {
if (ccy1.equals(ccy2)) {
return 1d;
}
if (ccy1.equals(CCY1) && ccy2.equals(CCY2)) {
return 2.5d;
}
throw new IllegalArgumentException();
};
MultiCurrencyAmount test = MultiCurrencyAmount.of(CA1, CA2);
assertEquals(test.convertedTo(CCY2, provider), CA2.plus(CurrencyAmount.of(CCY2, AMT1 * 2.5d)));
}
//-----------------------------------------------------------------------
public void test_serialization() {
assertSerialization(MultiCurrencyAmount.of(CA1, CA2, CA3));
}
public void coverage() {
coverImmutableBean(MultiCurrencyAmount.of(CA1, CA2, CA3));
}
//-------------------------------------------------------------------------
private void assertMCA(MultiCurrencyAmount actual, CurrencyAmount... expected) {
assertEquals(actual.size(), expected.length);
assertEquals(actual.getAmounts().size(), expected.length);
assertEquals(actual.getAmounts(), ImmutableSet.copyOf(expected));
Set<Currency> currencies = new HashSet<>();
for (CurrencyAmount expectedAmount : expected) {
currencies.add(expectedAmount.getCurrency());
assertEquals(actual.contains(expectedAmount.getCurrency()), true);
assertEquals(actual.getAmount(expectedAmount.getCurrency()), expectedAmount);
assertEquals(actual.getAmountOrZero(expectedAmount.getCurrency()), expectedAmount);
}
assertEquals(actual.getCurrencies(), currencies);
Currency nonExisting = Currency.of("FRZ");
assertEquals(actual.contains(nonExisting), false);
assertThrowsIllegalArg(() -> actual.getAmount(nonExisting));
assertEquals(actual.getAmountOrZero(nonExisting), CurrencyAmount.zero(nonExisting));
}
}