/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.basics.schedule;
import static com.opengamma.strata.basics.schedule.Frequency.P12M;
import static com.opengamma.strata.basics.schedule.Frequency.P1D;
import static com.opengamma.strata.basics.schedule.Frequency.P1W;
import static com.opengamma.strata.basics.schedule.Frequency.P3M;
import static com.opengamma.strata.basics.schedule.Frequency.P6M;
import static com.opengamma.strata.basics.schedule.Frequency.TERM;
import static com.opengamma.strata.collect.TestHelper.assertJodaConvert;
import static com.opengamma.strata.collect.TestHelper.assertSerialization;
import static com.opengamma.strata.collect.TestHelper.assertThrows;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static java.time.temporal.ChronoUnit.CENTURIES;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.YEARS;
import static org.testng.Assert.assertEquals;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneOffset;
import java.time.temporal.UnsupportedTemporalTypeException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests for the frequency class.
*/
@Test
public class FrequencyTest {
@DataProvider(name = "create")
static Object[][] data_create() {
return new Object[][] {
{Frequency.ofDays(1), Period.ofDays(1), "P1D"},
{Frequency.ofDays(2), Period.ofDays(2), "P2D"},
{Frequency.ofDays(6), Period.ofDays(6), "P6D"},
{Frequency.ofDays(7), Period.ofDays(7), "P1W"},
{Frequency.ofDays(91), Period.ofDays(91), "P13W"},
{Frequency.ofWeeks(1), Period.ofDays(7), "P1W"},
{Frequency.ofWeeks(3), Period.ofDays(21), "P3W"},
{Frequency.ofMonths(8), Period.ofMonths(8), "P8M"},
{Frequency.ofMonths(12), Period.ofMonths(12), "P12M"},
{Frequency.ofMonths(18), Period.ofMonths(18), "P18M"},
{Frequency.ofMonths(24), Period.ofMonths(24), "P24M"},
{Frequency.ofMonths(30), Period.ofMonths(30), "P30M"},
{Frequency.ofYears(1), Period.ofYears(1), "P1Y"},
{Frequency.ofYears(2), Period.ofYears(2), "P2Y"},
{Frequency.of(Period.of(1, 2, 3)), Period.of(1, 2, 3), "P1Y2M3D"},
{Frequency.P1D, Period.ofDays(1), "P1D"},
{Frequency.P1W, Period.ofWeeks(1), "P1W"},
{Frequency.P2W, Period.ofWeeks(2), "P2W"},
{Frequency.P4W, Period.ofWeeks(4), "P4W"},
{Frequency.P13W, Period.ofWeeks(13), "P13W"},
{Frequency.P26W, Period.ofWeeks(26), "P26W"},
{Frequency.P52W, Period.ofWeeks(52), "P52W"},
{Frequency.P1M, Period.ofMonths(1), "P1M"},
{Frequency.P2M, Period.ofMonths(2), "P2M"},
{Frequency.P3M, Period.ofMonths(3), "P3M"},
{Frequency.P4M, Period.ofMonths(4), "P4M"},
{Frequency.P6M, Period.ofMonths(6), "P6M"},
{Frequency.P12M, Period.ofMonths(12), "P12M"},
};
}
@Test(dataProvider = "create")
public void test_of_int(Frequency test, Period period, String toString) {
assertEquals(test.getPeriod(), period);
assertEquals(test.toString(), toString);
assertEquals(test.isTerm(), false);
}
@Test(dataProvider = "create")
public void test_of_Period(Frequency test, Period period, String toString) {
assertEquals(Frequency.of(period), test);
assertEquals(Frequency.of(period).getPeriod(), period);
}
@Test(dataProvider = "create")
public void test_parse(Frequency test, Period period, String toString) {
assertEquals(Frequency.parse(toString), test);
assertEquals(Frequency.parse(toString).getPeriod(), period);
}
public void test_term() {
assertEquals(TERM.getPeriod(), Period.ofYears(10_000));
assertEquals(TERM.isTerm(), true);
assertEquals(TERM.toString(), "Term");
assertEquals(Frequency.parse("Term"), TERM);
}
public void test_of_notZero() {
assertThrowsIllegalArg(() -> Frequency.of(Period.ofDays(0)));
assertThrowsIllegalArg(() -> Frequency.ofDays(0));
assertThrowsIllegalArg(() -> Frequency.ofWeeks(0));
assertThrowsIllegalArg(() -> Frequency.ofMonths(0));
assertThrowsIllegalArg(() -> Frequency.ofYears(0));
}
public void test_of_notNegative() {
assertThrowsIllegalArg(() -> Frequency.of(Period.ofDays(-1)));
assertThrowsIllegalArg(() -> Frequency.of(Period.ofMonths(-1)));
assertThrowsIllegalArg(() -> Frequency.of(Period.of(0, -1, -1)));
assertThrowsIllegalArg(() -> Frequency.of(Period.of(0, -1, 1)));
assertThrowsIllegalArg(() -> Frequency.of(Period.of(0, 1, -1)));
assertThrowsIllegalArg(() -> Frequency.ofDays(-1));
assertThrowsIllegalArg(() -> Frequency.ofWeeks(-1));
assertThrowsIllegalArg(() -> Frequency.ofMonths(-1));
assertThrowsIllegalArg(() -> Frequency.ofYears(-1));
}
public void test_of_tooBig() {
assertThrowsIllegalArg(() -> Frequency.of(Period.ofMonths(12001)));
assertThrowsIllegalArg(() -> Frequency.of(Period.ofMonths(Integer.MAX_VALUE)));
assertThrowsIllegalArg(() -> Frequency.of(Period.ofYears(1001)));
assertThrowsIllegalArg(() -> Frequency.of(Period.ofYears(Integer.MAX_VALUE)));
assertThrowsIllegalArg(() -> Frequency.ofMonths(12001), "Months must not exceed 12,000");
assertThrowsIllegalArg(() -> Frequency.ofMonths(Integer.MAX_VALUE));
assertThrowsIllegalArg(() -> Frequency.ofYears(1001), "Years must not exceed 1,000");
assertThrowsIllegalArg(() -> Frequency.ofYears(Integer.MAX_VALUE));
assertThrowsIllegalArg(() -> Frequency.of(Period.of(10000, 0, 1)));
}
//-------------------------------------------------------------------------
@DataProvider(name = "ofMonths")
static Object[][] data_ofMonths() {
return new Object[][] {
{1, Period.ofMonths(1), "P1M"},
{2, Period.ofMonths(2), "P2M"},
{3, Period.ofMonths(3), "P3M"},
{4, Period.ofMonths(4), "P4M"},
{6, Period.ofMonths(6), "P6M"},
{12, Period.ofMonths(12), "P12M"},
{20, Period.ofMonths(20), "P20M"},
{24, Period.ofMonths(24), "P24M"},
{30, Period.ofMonths(30), "P30M"},
};
}
@Test(dataProvider = "ofMonths")
public void test_ofMonths(int months, Period normalized, String str) {
assertEquals(Frequency.ofMonths(months).getPeriod(), normalized);
assertEquals(Frequency.ofMonths(months).toString(), str);
}
@DataProvider(name = "ofYears")
static Object[][] data_ofYears() {
return new Object[][] {
{1, Period.ofYears(1), "P1Y"},
{2, Period.ofYears(2), "P2Y"},
{3, Period.ofYears(3), "P3Y"},
};
}
@Test(dataProvider = "ofYears")
public void test_ofYears(int years, Period normalized, String str) {
assertEquals(Frequency.ofYears(years).getPeriod(), normalized);
assertEquals(Frequency.ofYears(years).toString(), str);
}
//-------------------------------------------------------------------------
@DataProvider(name = "normalized")
static Object[][] data_normalized() {
return new Object[][] {
{Period.ofDays(1), Period.ofDays(1)},
{Period.ofDays(7), Period.ofDays(7)},
{Period.ofDays(10), Period.ofDays(10)},
{Period.ofWeeks(2), Period.ofDays(14)},
{Period.ofMonths(1), Period.ofMonths(1)},
{Period.ofMonths(2), Period.ofMonths(2)},
{Period.ofMonths(12), Period.ofYears(1)},
{Period.ofYears(1), Period.ofYears(1)},
{Period.ofMonths(20), Period.of(1, 8, 0)},
{Period.ofMonths(24), Period.ofYears(2)},
{Period.ofYears(2), Period.ofYears(2)},
{Period.ofMonths(30), Period.of(2, 6, 0)},
};
}
@Test(dataProvider = "normalized")
public void test_normalized(Period period, Period normalized) {
assertEquals(Frequency.of(period).normalized().getPeriod(), normalized);
}
//-------------------------------------------------------------------------
@DataProvider(name = "based")
static Object[][] data_based() {
return new Object[][] {
{Frequency.ofDays(1), false, false, false},
{Frequency.ofDays(2), false, false, false},
{Frequency.ofDays(6), false, false, false},
{Frequency.ofDays(7), true, false, false},
{Frequency.ofWeeks(1), true, false, false},
{Frequency.ofWeeks(3), true, false, false},
{Frequency.ofMonths(1), false, true, false},
{Frequency.ofMonths(3), false, true, false},
{Frequency.ofMonths(12), false, true, true},
{Frequency.ofYears(1), false, true, true},
{Frequency.ofYears(3), false, true, false},
{Frequency.of(Period.of(1, 2, 3)), false, false, false},
{Frequency.TERM, false, false, false},
};
}
@Test(dataProvider = "based")
public void test_isWeekBased(Frequency test, boolean weekBased, boolean monthBased, boolean annual) {
assertEquals(test.isWeekBased(), weekBased);
}
@Test(dataProvider = "based")
public void test_isMonthBased(Frequency test, boolean weekBased, boolean monthBased, boolean annual) {
assertEquals(test.isMonthBased(), monthBased);
}
@Test(dataProvider = "based")
public void test_isAnnual(Frequency test, boolean weekBased, boolean monthBased, boolean annual) {
assertEquals(test.isAnnual(), annual);
}
//-------------------------------------------------------------------------
@DataProvider(name = "events")
static Object[][] data_events() {
return new Object[][] {
{Frequency.P1D, 364},
{Frequency.P1W, 52},
{Frequency.P2W, 26},
{Frequency.P4W, 13},
{Frequency.P13W, 4},
{Frequency.P26W, 2},
{Frequency.P52W, 1},
{Frequency.P1M, 12},
{Frequency.P2M, 6},
{Frequency.P3M, 4},
{Frequency.P4M, 3},
{Frequency.P6M, 2},
{Frequency.P12M, 1},
{Frequency.TERM, 0},
};
}
@Test(dataProvider = "events")
public void test_eventsPerYear(Frequency test, int expected) {
assertEquals(test.eventsPerYear(), expected);
}
public void test_eventsPerYear_bad() {
assertThrowsIllegalArg(() -> Frequency.ofDays(3).eventsPerYear());
assertThrowsIllegalArg(() -> Frequency.ofWeeks(3).eventsPerYear());
assertThrowsIllegalArg(() -> Frequency.ofWeeks(104).eventsPerYear());
assertThrowsIllegalArg(() -> Frequency.ofMonths(5).eventsPerYear());
assertThrowsIllegalArg(() -> Frequency.ofMonths(24).eventsPerYear());
assertThrowsIllegalArg(() -> Frequency.of(Period.of(2, 2, 2)).eventsPerYear());
}
@Test(dataProvider = "events")
public void test_eventsPerYearEstimate(Frequency test, int expected) {
assertEquals(test.eventsPerYearEstimate(), expected, 1e-8);
}
public void test_eventsPerYearEstimate_bad() {
assertEquals(Frequency.ofDays(3).eventsPerYearEstimate(), 364d / 3, 1e-8);
assertEquals(Frequency.ofWeeks(3).eventsPerYearEstimate(), 364d / 21, 1e-8);
assertEquals(Frequency.ofWeeks(104).eventsPerYearEstimate(), 364d / 728, 1e-8);
assertEquals(Frequency.ofMonths(5).eventsPerYearEstimate(), 12d / 5, 1e-8);
assertEquals(Frequency.ofMonths(22).eventsPerYearEstimate(), 12d / 22, 1e-8);
assertEquals(Frequency.ofMonths(24).eventsPerYearEstimate(), 12d / 24, 1e-8);
assertEquals(Frequency.ofYears(2).eventsPerYearEstimate(), 0.5d, 1e-8);
assertEquals(Frequency.of(Period.of(10, 0, 1)).eventsPerYearEstimate(), 0.1d, 1e-3);
assertEquals(Frequency.of(Period.of(5, 0, 95)).eventsPerYearEstimate(), 0.19d, 1e-3);
assertEquals(Frequency.of(Period.of(5, 0, 97)).eventsPerYearEstimate(), 0.19d, 1e-3);
}
//-------------------------------------------------------------------------
@DataProvider(name = "exactDivide")
static Object[][] data_exactDivide() {
return new Object[][] {
{Frequency.P1D, Frequency.P1D, 1},
{Frequency.P1W, Frequency.P1D, 7},
{Frequency.P2W, Frequency.P1D, 14},
{Frequency.P1W, Frequency.P1W, 1},
{Frequency.P2W, Frequency.P1W, 2},
{Frequency.ofWeeks(3), Frequency.P1W, 3},
{Frequency.P4W, Frequency.P1W, 4},
{Frequency.P13W, Frequency.P1W, 13},
{Frequency.P26W, Frequency.P1W, 26},
{Frequency.P26W, Frequency.P2W, 13},
{Frequency.P52W, Frequency.P1W, 52},
{Frequency.P52W, Frequency.P2W, 26},
{Frequency.P1M, Frequency.P1M, 1},
{Frequency.P2M, Frequency.P1M, 2},
{Frequency.P3M, Frequency.P1M, 3},
{Frequency.P4M, Frequency.P1M, 4},
{Frequency.P6M, Frequency.P1M, 6},
{Frequency.P6M, Frequency.P2M, 3},
{Frequency.P12M, Frequency.P1M, 12},
{Frequency.P12M, Frequency.P2M, 6},
{Frequency.ofYears(1), Frequency.P6M, 2},
{Frequency.ofYears(1), Frequency.P3M, 4},
{Frequency.ofYears(2), Frequency.P6M, 4},
};
}
@Test(dataProvider = "exactDivide")
public void test_exactDivide(Frequency test, Frequency other, int expected) {
assertEquals(test.exactDivide(other), expected);
}
@Test(dataProvider = "exactDivide")
public void test_exactDivide_reverse(Frequency test, Frequency other, int expected) {
if (!test.equals(other)) {
assertThrowsIllegalArg(() -> other.exactDivide(test));
}
}
public void test_exactDivide_bad() {
assertThrowsIllegalArg(() -> Frequency.ofDays(5).exactDivide(Frequency.ofDays(2)));
assertThrowsIllegalArg(() -> Frequency.ofMonths(5).exactDivide(Frequency.ofMonths(2)));
assertThrowsIllegalArg(() -> Frequency.P1M.exactDivide(Frequency.P1W));
assertThrowsIllegalArg(() -> Frequency.P1W.exactDivide(Frequency.P1M));
assertThrowsIllegalArg(() -> Frequency.TERM.exactDivide(Frequency.P1W));
assertThrowsIllegalArg(() -> Frequency.P12M.exactDivide(Frequency.TERM));
assertThrowsIllegalArg(() -> Frequency.ofYears(1).exactDivide(Frequency.P1W));
}
//-------------------------------------------------------------------------
public void test_parse_String_roundTrip() {
assertEquals(Frequency.parse(P6M.toString()), P6M);
}
@DataProvider(name = "parseGood")
static Object[][] data_parseGood() {
return new Object[][] {
{"1D", Frequency.ofDays(1)},
{"2D", Frequency.ofDays(2)},
{"91D", Frequency.ofDays(91)},
{"2W", Frequency.ofWeeks(2)},
{"6W", Frequency.ofWeeks(6)},
{"2M", Frequency.ofMonths(2)},
{"12M", Frequency.ofMonths(12)},
{"1Y", Frequency.ofYears(1)},
};
}
@Test(dataProvider = "parseGood")
public void test_parse_String_good_noP(String input, Frequency expected) {
assertEquals(Frequency.parse(input), expected);
}
@Test(dataProvider = "parseGood")
public void test_parse_String_good_withP(String input, Frequency expected) {
assertEquals(Frequency.parse("P" + input), expected);
}
public void test_parse_String_term() {
assertEquals(Frequency.parse("Term"), Frequency.TERM);
assertEquals(Frequency.parse("TERM"), Frequency.TERM);
}
@DataProvider(name = "parseBad")
static Object[][] data_parseBad() {
return new Object[][] {
{""},
{"2"},
{"2K"},
{"-2D"},
{"PTerm"},
{null},
};
}
@Test(dataProvider = "parseBad", expectedExceptions = IllegalArgumentException.class)
public void test_parse_String_bad(String input) {
Frequency.parse(input);
}
//-------------------------------------------------------------------------
public void test_addTo() {
assertEquals(P1D.addTo(LocalDate.of(2014, 6, 30)), LocalDate.of(2014, 7, 1));
assertEquals(P1W.addTo(
OffsetDateTime.of(2014, 6, 30, 0, 0, 0, 0, ZoneOffset.UTC)),
OffsetDateTime.of(2014, 7, 7, 0, 0, 0, 0, ZoneOffset.UTC));
}
public void test_subtractFrom() {
assertEquals(P1D.subtractFrom(LocalDate.of(2014, 6, 30)), LocalDate.of(2014, 6, 29));
assertEquals(P1W.subtractFrom(
OffsetDateTime.of(2014, 6, 30, 0, 0, 0, 0, ZoneOffset.UTC)),
OffsetDateTime.of(2014, 6, 23, 0, 0, 0, 0, ZoneOffset.UTC));
}
//-------------------------------------------------------------------------
public void test_temporalAmount() {
assertEquals(P3M.getUnits(), ImmutableList.of(YEARS, MONTHS, DAYS));
assertEquals(P3M.get(MONTHS), 3);
assertEquals(LocalDate.of(2014, 6, 30).plus(P1W), LocalDate.of(2014, 7, 7));
assertEquals(LocalDate.of(2014, 6, 30).minus(P1W), LocalDate.of(2014, 6, 23));
assertThrows(() -> P3M.get(CENTURIES), UnsupportedTemporalTypeException.class);
}
//-------------------------------------------------------------------------
public void test_equals_hashCode() {
Frequency a1 = P1D;
Frequency a2 = Frequency.ofDays(1);
Frequency b = P3M;
assertEquals(a1.equals(a1), true);
assertEquals(a1.equals(b), false);
assertEquals(a1.equals(a2), true);
assertEquals(a2.equals(a1), true);
assertEquals(a2.equals(a2), true);
assertEquals(a2.equals(b), false);
assertEquals(b.equals(a1), false);
assertEquals(b.equals(a2), false);
assertEquals(b.equals(b), true);
assertEquals(a1.hashCode(), a2.hashCode());
}
public void test_equals_bad() {
assertEquals(P3M.equals(null), false);
assertEquals(P3M.equals("String"), false);
assertEquals(P3M.equals(new Object()), false);
}
//-----------------------------------------------------------------------
public void test_serialization() {
assertSerialization(P1D);
assertSerialization(P3M);
assertSerialization(P12M);
assertSerialization(TERM);
}
public void test_jodaConvert() {
assertJodaConvert(Frequency.class, P1D);
assertJodaConvert(Frequency.class, P3M);
assertJodaConvert(Frequency.class, P12M);
assertJodaConvert(Frequency.class, TERM);
}
}