blob: 8c3926524a1c1627459ec9e01faeba2fb2c1db09 [file] [log] [blame]
/*
Derby - Class org.apache.derbyTesting.functionTests.tests.store.PositionedStoreStreamTest
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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 org.apache.derbyTesting.functionTests.tests.store;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import junit.framework.Test;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.impl.jdbc.PositionedStoreStream;
import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
import org.apache.derbyTesting.junit.BaseTestCase;
import org.apache.derbyTesting.junit.BaseTestSuite;
/**
* Tests of the repositioning logic in {@link PositionedStoreStream}.
*/
public class PositionedStoreStreamTest
extends BaseTestCase {
public PositionedStoreStreamTest(String name) {
super(name);
}
/**
* Verifies that reading after EOF doesn't change the position.
*/
public void testPositionAfterEOFRead()
throws IOException, StandardException {
InputStream in = new LoopingAlphabetStream(10);
PositionedStoreStream pss = new PositionedStoreStream(in);
assertEquals(0, pss.getPosition());
for (int i=0; i < 10; i++) {
pss.read();
assertEquals(i +1, pss.getPosition());
}
assertEquals(10, pss.getPosition());
assertEquals(-1, pss.read());
assertEquals(10, pss.getPosition());
assertEquals(-1, pss.read());
assertEquals(0, pss.skip(199));
assertEquals(10, pss.getPosition());
pss.resetStream();
assertEquals(0, pss.getPosition());
}
/**
* Verifies that reading after EOF doesn't change the position.
*/
public void testPositionAfterEOFReadArray()
throws IOException, StandardException {
InputStream in = new LoopingAlphabetStream(10);
PositionedStoreStream pss = new PositionedStoreStream(in);
assertEquals(0, pss.getPosition());
byte[] two = new byte[2];
for (int i=0; i < 10; i += 2) {
assertEquals(2, pss.read(two, 0, 2));
assertEquals(i +2, pss.getPosition());
}
assertEquals(10, pss.getPosition());
assertEquals(-1, pss.read(two, 0, 2));
assertEquals(10, pss.getPosition());
assertEquals(-1, pss.read(two, 0, 2));
assertEquals(0, pss.skip(21));
assertEquals(-1, pss.read());
assertEquals(10, pss.getPosition());
pss.resetStream();
assertEquals(0, pss.getPosition());
}
/**
* Reads the whole stream repeatedly in one go, and resets it after each
* read.
*/
public void testReadEverythingInOneGo()
throws IOException, StandardException {
InputStream in = new LoopingAlphabetStream(127);
PositionedStoreStream pss = new PositionedStoreStream(in);
byte[] b = new byte[256];
for (int i=0; i < 3; i++) {
Arrays.fill(b, (byte)-1);
assertEquals(127, pss.read(b, 0, 256));
assertEquals(-1, pss.read(b, 127, 10));
assertEquals(-1, b[127]);
assertTrue( -1 != b[126]);
assertEquals('a', b[0]);
pss.reposition(0);
}
}
public void testRepositionForwards()
throws IOException, StandardException {
final long length = 20L;
InputStream in = new LoopingAlphabetStream(length);
PositionedStoreStream pss = new PositionedStoreStream(in);
assertEquals(0, pss.getPosition());
// Position forwards one by one.
for (int i=0; i < length; i++) {
InputStream inComp = new LoopingAlphabetStream(length);
pss.reposition(i);
inComp.skip(i);
assertEquals(inComp.read(), pss.read());
}
// Position forwards two by two.
for (int i=1; i < length; i += 2) {
InputStream inComp = new LoopingAlphabetStream(length);
pss.reposition(i);
inComp.skip(i);
assertEquals(inComp.read(), pss.read());
}
}
public void testRepositionBackwards()
throws IOException, StandardException {
final long length = 20L;
InputStream in = new LoopingAlphabetStream(length);
PositionedStoreStream pss = new PositionedStoreStream(in);
assertEquals(0, pss.getPosition());
// Position backwards one by one.
for (int i=(int)length; i >= 0; i--) {
InputStream inComp = new LoopingAlphabetStream(length);
pss.reposition(i);
inComp.skip(i);
assertEquals(inComp.read(), pss.read());
}
// Position backwards two by two.
for (int i=(int)length -1; i >= 0; i -= 2) {
InputStream inComp = new LoopingAlphabetStream(length);
pss.reposition(i);
inComp.skip(i);
assertEquals(inComp.read(), pss.read());
}
}
/**
* Executes a simple read sequence against the lower case modern latin
* alphabet, which involves some repositioning.
*/
public void testSimpleReadSequence()
throws IOException, StandardException {
InputStream in = new LoopingAlphabetStream(26);
PositionedStoreStream pss = new PositionedStoreStream(in);
assertEquals('a', pss.read());
pss.reposition(9);
assertEquals('j', pss.read());
pss.reposition(10);
assertEquals('k', pss.read());
pss.reposition(9);
assertEquals('j', pss.read());
pss.reposition(25);
assertEquals('z', pss.read());
assertEquals(-1, pss.read());
pss.reposition(1);
assertEquals('b', pss.read());
pss.reposition(1);
assertEquals('b', pss.read());
}
/**
* A regression test for DERBY-3735.
* <p>
* If the bug is present, the repositioning will cause an EOF-exception to
* be thrown in {@code skipFully}.
*/
public void testDerby3735()
throws IOException, StandardException {
InputStream in = new LoopingAlphabetStream(2);
PositionedStoreStream pss = new PositionedStoreStream(in);
byte[] b = new byte[2];
for (int i=0; i < 10; i++) {
// After the first iteration, the position will be decreased and
// eventually become negative.
pss.read(b);
println("Position at iteration " + i + ": " + pss.getPosition());
}
// This failed, because we tried skipping more bytes than there are in
// the stream to get to position 0.
pss.reposition(0);
}
/**
* Tests that trying to move past the end of the stream leaves the stream
* object in a consistent state, and can be repositioned again after the
* failed reposition attempt.
* <p>
* Issue logged in Jira as DERBY-3781
*
* @throws IOException if reading the stream fails unexpectedly
* @throws StandardException will never happen
*/
public void testDerby3781()
throws IOException, StandardException {
final long size = 10;
InputStream in = new LoopingAlphabetStream(size);
PositionedStoreStream pss = new PositionedStoreStream(in);
assertEquals("Invalid initial position", 0L, pss.getPosition());
pss.reposition(size -1); // Goto end.
assertEquals(size -1, pss.getPosition());
assertEquals('j', pss.read());
assertEquals(size, pss.getPosition());
assertEquals(-1, pss.read());
// This step is crucial, position must be different than zero when the
// first exception below is thrown.
pss.reposition(size / 2); // Goto middle.
assertEquals(size / 2, pss.getPosition());
try {
pss.reposition(size *2); // Try to go past end.
fail("Should have failed with EOFException");
} catch (EOFException eofe) {
// Ignore this exception
}
// Failed here before, because internal state was inconsistent.
// Assumed: pos = 5, underlying stream at pos 5, skipped (size -1 - pos)
// Actual: pos = 5, underlying stream at pos (size -1)
pss.reposition(size -1); // Goto end.
assertEquals(size -1, pss.getPosition());
assertEquals('j', pss.read());
}
public static Test suite() {
return new BaseTestSuite(
PositionedStoreStreamTest.class, "PositionedStoreStreamTest");
}
}