From bdb79fe169b556de85d690c088b7f0fbf075778a Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Wed, 20 Sep 2006 04:01:56 +0000 Subject: Integrated more tests. --- .../carbonado/spi/TestSequenceValueGenerator.java | 258 +++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 src/test/java/com/amazon/carbonado/spi/TestSequenceValueGenerator.java (limited to 'src/test/java/com/amazon/carbonado/spi') diff --git a/src/test/java/com/amazon/carbonado/spi/TestSequenceValueGenerator.java b/src/test/java/com/amazon/carbonado/spi/TestSequenceValueGenerator.java new file mode 100644 index 0000000..ae17e5d --- /dev/null +++ b/src/test/java/com/amazon/carbonado/spi/TestSequenceValueGenerator.java @@ -0,0 +1,258 @@ +/* + * Copyright 2006 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.carbonado.spi; + +import java.util.Random; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.amazon.carbonado.PersistException; +import com.amazon.carbonado.Repository; +import com.amazon.carbonado.Storage; + +import com.amazon.carbonado.repo.toy.ToyRepository; + +import com.amazon.carbonado.stored.StorableTestBasic; + +/** + * + * + * @author Brian S O'Neill + */ +public class TestSequenceValueGenerator extends TestCase { + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } + + public static TestSuite suite() { + return new TestSuite(TestSequenceValueGenerator.class); + } + + private Repository mRepository; + + public TestSequenceValueGenerator(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + mRepository = new ToyRepository(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test_basics() throws Exception { + SequenceValueGenerator generator = new SequenceValueGenerator(mRepository, "foo"); + + for (int i=1; i<=950; i++) { + assertEquals(i, generator.nextLongValue()); + } + + generator.reset(1); + + for (int i=1; i<=950; i++) { + assertEquals(i, generator.nextIntValue()); + } + + generator.reset(1); + + for (int i=1; i<=950; i++) { + assertEquals(String.valueOf(i), generator.nextDecimalValue()); + } + + // Make sure data is persisted + + generator = new SequenceValueGenerator(mRepository, "foo"); + + assertTrue(generator.nextLongValue() > 950); + + // Make sure data is isolated + + generator = new SequenceValueGenerator(mRepository, "another"); + + for (int i=1; i<=1050; i++) { + assertEquals(i, generator.nextLongValue()); + } + + // Make sure reserved values can be returned + + generator.returnReservedValues(); + generator = new SequenceValueGenerator(mRepository, "another"); + + assertEquals(1051, generator.nextLongValue()); + } + + public void test_highIncrement() throws Exception { + SequenceValueGenerator generator = + new SequenceValueGenerator(mRepository, "foo", 1, 125); + + for (int i=0; i<950; i++) { + assertEquals(i * 125 + 1, generator.nextLongValue()); + } + } + + public void test_highInitialAndHighIncrement() throws Exception { + SequenceValueGenerator generator = + new SequenceValueGenerator(mRepository, "foo", 0x500000000L, 125); + + for (int i=0; i<950; i++) { + assertEquals(i * 125 + 0x500000000L, generator.nextLongValue()); + } + + try { + // Doesn't fit in an int. + generator.nextIntValue(); + fail(); + } catch (PersistException e) { + } + } + + public void test_lowReserve() throws Exception { + SequenceValueGenerator generator = + new SequenceValueGenerator(mRepository, "goo", 1, 1, 1); + + for (int i=1; i<=950; i++) { + assertEquals(i, generator.nextLongValue()); + } + } + + public void test_overflow() throws Exception { + Storage storage = mRepository.storageFor(StoredSequence.class); + StoredSequence seq = storage.prepare(); + seq.setName("overflow"); + seq.setInitialValue(1); + seq.setNextValue(Long.MAX_VALUE - 50); + seq.insert(); + + SequenceValueGenerator generator = new SequenceValueGenerator(mRepository, "overflow"); + + for (int i=-50; i<=-1; i++) { + assertEquals(i, generator.nextLongValue()); + } + + // Although next value could be zero, overflow logic doesn't work this + // way. Its not really worth the trouble to allow zero to be returned + // before overflowing. + + try { + // Overflow. + generator.nextLongValue(); + fail(); + } catch (PersistException e) { + } + } + + public void test_largeNumericalValue() throws Exception { + // Tests string conversion to ensure large unsigned values are properly + // generated. + + SequenceValueGenerator generator = + new SequenceValueGenerator(mRepository, "goo", Long.MAX_VALUE, 1); + + assertEquals("9223372036854775807", generator.nextDecimalValue()); + // Next values are too large to fit in an unsigned long + assertEquals("9223372036854775808", generator.nextDecimalValue()); + assertEquals("9223372036854775809", generator.nextDecimalValue()); + } + + public void test_radix() throws Exception { + SequenceValueGenerator generator = new SequenceValueGenerator(mRepository, "goo"); + + for (int i=1; i<=1000; i++) { + assertEquals(Integer.toString(i, 36), generator.nextNumericalValue(36, 1)); + } + } + + public void test_pad() throws Exception { + SequenceValueGenerator generator = new SequenceValueGenerator(mRepository, "goo"); + + for (int i=1; i<=2000; i++) { + String next = generator.nextNumericalValue(10, 3); + assertTrue(next.length() >= 3); + int value = Integer.parseInt(next); + assertEquals(i, value); + } + } + + public void test_concurrentAccess() throws Exception { + // Simple test ensuring that values are reserved properly even when + // multiple processes may be sharing the sequence. + + SequenceValueGenerator g1 = new SequenceValueGenerator(mRepository, "goo", 1, 1, 100); + SequenceValueGenerator g2 = new SequenceValueGenerator(mRepository, "goo", 1, 1, 100); + + for (int i=1; i<=100; i++) { + assertEquals(i, g1.nextLongValue()); + assertEquals(i + 100, g2.nextLongValue()); + } + + for (int i=201; i<=300; i++) { + assertEquals(i, g2.nextLongValue()); + assertEquals(i + 100, g1.nextLongValue()); + } + + assertTrue(g1.returnReservedValues()); + assertFalse(g2.returnReservedValues()); + } + + // FIXME: move this test somewhere else + /* Takes too long + public void test_heavyConcurrentAccess() throws Exception { + // Heavy test with multiple processes sharing the sequence. + + final Storage storage = + mRepository.storageFor(StorableTestBasic.class); + final Random rnd = new Random(376296292); + final int loopCount = 10000; + + Thread[] threads = new Thread[10]; + for (int i=0; i