blob: 1248a5b1bd037ff5368efcd842c590b5aa0b684f [file] [log] [blame]
/*
* 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.jackrabbit.oak.commons;
import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Test the utility classes.
*/
public class IOUtilsTest extends TestCase {
public void testReadFully() throws IOException {
final Random r = new Random(1);
byte[] data = new byte[1000];
final AtomicInteger readCount = new AtomicInteger();
r.nextBytes(data);
FilterInputStream in = new FilterInputStream(new ByteArrayInputStream(data)) {
@Override
public int read(byte[] buffer, int off, int max) throws IOException {
readCount.incrementAndGet();
if (r.nextInt(10) == 0) {
return 0;
}
return in.read(buffer, off, Math.min(10, max));
}
};
in.mark(10000);
byte[] test = new byte[1000];
// readFully is not supposed to call read when reading 0 bytes
assertEquals(0, IOUtils.readFully(in, test, 0, 0));
assertEquals(0, readCount.get());
assertEquals(1000, IOUtils.readFully(in, test, 0, 1000));
IOUtilsTest.assertEquals(data, test);
test = new byte[1001];
in.reset();
in.mark(10000);
assertEquals(1000, IOUtils.readFully(in, test, 0, 1001));
assertEquals(0, IOUtils.readFully(in, test, 0, 0));
}
public void testSkipFully() throws IOException {
final Random r = new Random(1);
byte[] data = new byte[1000];
r.nextBytes(data);
FilterInputStream in = new FilterInputStream(new ByteArrayInputStream(data)) {
@Override
public int read(byte[] buffer, int off, int max) throws IOException {
return in.read(buffer, off, Math.min(10, max));
}
};
in.mark(10000);
IOUtils.skipFully(in, 1000);
assertEquals(-1, in.read());
in.reset();
try {
IOUtils.skipFully(in, 1001);
fail();
} catch (EOFException e) {
// expected
}
}
public void testStringReadWrite() throws IOException {
final Random r = new Random(1);
for (int i = 0; i < 100000; i += i / 10 + 1) {
String s = "";
for (int j = 0; j < 10; j++) {
String p = new String(new char[i]).replace((char) 0, 'a');
s += p;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.writeString(out, s);
byte[] data = out.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(data) {
@Override
public int read(byte[] b, int off, int len) {
if (r.nextBoolean()) {
len = r.nextInt(len);
}
return super.read(b, off, len);
}
};
String t = IOUtils.readString(in);
assertEquals(s, t);
assertEquals(-1, in.read());
}
try {
InputStream in = new ByteArrayInputStream(new byte[]{1});
IOUtils.readString(in);
fail();
} catch (EOFException e) {
// expected
}
}
public void testBytesReadWrite() throws IOException {
final Random r = new Random();
int iterations = 1000;
while (iterations-- > 0) {
int n = Math.abs(r.nextInt()) % 0x40000;
byte[] buf = new byte[n];
r.nextBytes(buf);
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.writeBytes(out, buf);
byte[] buf1 = IOUtils.readBytes(new ByteArrayInputStream(out.toByteArray()));
assertEquals(buf, buf1);
}
}
public void testVarInt() throws IOException {
testVarInt(0, 1);
testVarInt(0x7f, 1);
testVarInt(0x80, 2);
testVarInt(0x3fff, 2);
testVarInt(0x4000, 3);
testVarInt(0x1fffff, 3);
testVarInt(0x200000, 4);
testVarInt(0xfffffff, 4);
testVarInt(0x10000000, 5);
testVarInt(-1, 5);
for (int x = 0; x < 0x20000; x++) {
testVarInt(x, 0);
testVarInt(Integer.MIN_VALUE + x, 0);
testVarInt(Integer.MAX_VALUE - x, 5);
testVarInt(0x200000 + x - 100, 0);
testVarInt(0x10000000 + x - 100, 0);
}
Random r = new Random(1);
for (int i = 0; i < 100000; i++) {
testVarInt(r.nextInt(), 0);
testVarInt(r.nextInt(10000000), 0);
}
// trailing 0s are never written, but are an alternative way to encode a value
InputStream in = new ByteArrayInputStream(new byte[]{(byte) 0x80, 0});
assertEquals(0, IOUtils.readVarInt(in));
assertEquals(-1, in.read());
}
public void testVarLong() throws IOException {
testVarLong(0, 1);
testVarLong(0x7f, 1);
testVarLong(0x80, 2);
testVarLong(0x3fff, 2);
testVarLong(0x4000, 3);
testVarLong(0x1fffff, 3);
testVarLong(0x200000, 4);
testVarLong(0xfffffff, 4);
testVarLong(0x10000000, 5);
testVarLong(0x1fffffffL, 5);
testVarLong(0x2000000000L, 6);
testVarLong(0x3ffffffffffL, 6);
testVarLong(0x40000000000L, 7);
testVarLong(0x1ffffffffffffL, 7);
testVarLong(0x2000000000000L, 8);
testVarLong(0xffffffffffffffL, 8);
testVarLong(0x100000000000000L, 9);
testVarLong(-1, 10);
for (int x = 0; x < 0x20000; x++) {
testVarLong(x, 0);
testVarLong(Long.MIN_VALUE + x, 0);
testVarLong(Long.MAX_VALUE - x, 9);
testVarLong(0x200000 + x - 100, 0);
testVarLong(0x10000000 + x - 100, 0);
}
Random r = new Random(1);
for (int i = 0; i < 100000; i++) {
testVarLong(r.nextLong(), 0);
testVarLong(r.nextInt(Integer.MAX_VALUE), 0);
}
// trailing 0s are never written, but are an alternative way to encode a value
InputStream in = new ByteArrayInputStream(new byte[]{(byte) 0x80, 0});
assertEquals(0, IOUtils.readVarLong(in));
assertEquals(-1, in.read());
}
public void testVarEOF() throws IOException {
try {
IOUtils.readVarInt(new ByteArrayInputStream(new byte[0]));
fail();
} catch (EOFException e) {
// expected
}
try {
IOUtils.readVarLong(new ByteArrayInputStream(new byte[0]));
fail();
} catch (EOFException e) {
// expected
}
}
private static void testVarInt(int x, int expectedLen) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.writeVarInt(out, x);
byte[] data = out.toByteArray();
assertTrue(data.length <= 5);
if (expectedLen > 0) {
assertEquals(expectedLen, data.length);
}
ByteArrayInputStream in = new ByteArrayInputStream(data);
int x2 = IOUtils.readVarInt(in);
assertEquals(x, x2);
assertEquals(-1, in.read());
}
private static void testVarLong(long x, int expectedLen) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.writeVarLong(out, x);
byte[] data = out.toByteArray();
assertTrue(data.length <= 10);
if (expectedLen > 0) {
assertEquals(expectedLen, data.length);
}
ByteArrayInputStream in = new ByteArrayInputStream(data);
long x2 = IOUtils.readVarLong(in);
assertEquals(x, x2);
assertEquals(-1, in.read());
}
public static void assertEquals(byte[] expected, byte[] got) {
assertEquals(expected.length, got.length);
for (int i = 0; i < got.length; i++) {
assertEquals(expected[i], got[i]);
}
}
}