/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.ais.model;
import com.foundationdb.ais.model.validation.SequenceValuesValid;
import com.foundationdb.server.error.SequenceIntervalZeroException;
import com.foundationdb.server.error.SequenceLimitExceededException;
import com.foundationdb.server.error.SequenceMinGEMaxException;
import com.foundationdb.server.error.SequenceStartInRangeException;
import com.foundationdb.util.JUnitUtils;
import com.foundationdb.util.MultipleCauseException;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class SequenceTest
{
private static final boolean CYCLE = true;
private static final boolean NO_CYCLE = false;
private Sequence s(long start, long inc, long min, long max, boolean isCycle) {
AkibanInformationSchema ais = new AkibanInformationSchema();
Sequence s = Sequence.create(ais, "test", "s", start, inc, min, max, isCycle);
SequenceValuesValid valuesValid = new SequenceValuesValid();
ais.validate(Arrays.asList(valuesValid)).throwIfNecessary();
return s;
}
private void expectExceeded(Sequence s, long rawValue) {
try {
s.realValueForRawNumber(rawValue);
fail("Expected limit exceeded");
} catch(SequenceLimitExceededException e) {
// Expected
}
}
private void c(Sequence s, long rawNumber, long expectedRealValue) {
assertEquals("realValueForRawNumber at raw="+rawNumber, expectedRealValue, s.realValueForRawNumber(rawNumber));
}
@Test(expected=SequenceIntervalZeroException.class)
public void zeroInc() {
s(1, 0, 1, 10, CYCLE);
}
@Test(expected=SequenceMinGEMaxException.class)
public void minEqualMax() {
s(10, 1, 10, 10, CYCLE);
}
@Test
public void minGreaterMax() {
JUnitUtils.expectMultipleCause(
new Runnable() {
@Override
public void run() {
s(1, 1, 15, 10, CYCLE);
}
},
SequenceMinGEMaxException.class,
SequenceStartInRangeException.class
);
}
@Test(expected=SequenceStartInRangeException.class)
public void startLessMin() {
s(1, 1, 5, 10, CYCLE);
}
@Test(expected=SequenceStartInRangeException.class)
public void startGreaterMax() {
s(15, 1, 5, 10, CYCLE);
}
@Test
public void firstValueIsStart() {
Sequence s = s(5, 1, 1, 10, CYCLE);
c(s, 1, 5);
}
@Test
public void startOne_IncOne_MinOne_MaxTen_Cycle() {
long min = 1;
long max = 10;
Sequence s = s(1, 1, 1, 10, CYCLE);
for(long i = min; i <= max; ++i) {
c(s, i, i);
}
c(s, max + 1, min);
}
@Test
public void startOne_IncOne_MinOne_MaxTen_NoCycle() {
long min = 1;
long max = 10;
Sequence s = s(1, 1, min, max, NO_CYCLE);
for(long i = min; i <= max; ++i) {
c(s, i, i);
}
expectExceeded(s, max+1);
}
@Test
public void startOne_IncThree_MinOne_MaxTen_Cycle() {
long inc = 3;
long min = 1;
long max = 10;
Sequence s = s(1, inc, min, max, CYCLE);
c(s, 1, 1);
c(s, 2, 4);
c(s, 3, 7);
c(s, 4, 10);
c(s, 5, 1);
c(s, 6, 4);
c(s, 7, 7);
c(s, 8, 10);
c(s, 9, 1);
c(s, 10, 4);
}
@Test
public void startOne_IncThree_MinOne_MaxTen_NoCycle() {
long inc = 3;
long min = 1;
long max = 10;
Sequence s = s(1, inc, min, max, NO_CYCLE);
c(s, 1, 1);
c(s, 2, 4);
c(s, 3, 7);
c(s, 4, 10);
expectExceeded(s, 5);
}
@Test
public void startOne_IncThree_MinNegFive_MaxFive_Cycle() {
long inc = 3;
long min = -5;
long max = 5;
Sequence s = s(1, inc, min, max, CYCLE);
c(s, 1, 1);
c(s, 2, 4);
c(s, 3, -5);
c(s, 4, -2);
c(s, 5, 1);
c(s, 6, 4);
c(s, 7, -5);
c(s, 8, -2);
c(s, 9, 1);
c(s, 10, 4);
}
@Test
public void startTwo_IncNegThree_MinNegTwo_MaxSeven_Cycle() {
long inc = -3;
long min = -2;
long max = 7;
Sequence s = s(2, inc, min, max, CYCLE);
c(s, 1, 2);
c(s, 2, -1);
c(s, 3, 7);
c(s, 4, 4);
c(s, 5, 1);
c(s, 6, -2);
c(s, 7, 7);
c(s, 8, 4);
c(s, 9, 1);
c(s, 10, -2);
}
@Test
public void cycleWithLongMinAndMaxStartOne() {
long min = Long.MIN_VALUE;
long max = Long.MAX_VALUE;
Sequence s = s(1, 1, min, max, CYCLE);
c(s, 1, 1);
c(s, max - 1, max - 1);
c(s, max, max);
c(s, max + 1, max + 1);
}
@Test
public void cycleWithLongMinAndMaxStartMin() {
long inc = 1;
long min = Long.MIN_VALUE;
long max = Long.MAX_VALUE;
Sequence s = s(min, inc, min, max, CYCLE);
c(s, 1, min);
c(s, 2, min + 1);
c(s, max - 1, -3);
c(s, max + 0, -2);
c(s, max + 1, -1);
c(s, max + 2, 0);
c(s, max + max, max - 2);
c(s, max + max + 1, max - 1);
}
}