250 lines
8.6 KiB
Java
250 lines
8.6 KiB
Java
/*
|
|
* Copyright (C) 2012 The Guava Authors
|
|
*
|
|
* 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.google.common.io;
|
|
|
|
import static com.google.common.io.SourceSinkFactory.ByteSourceFactory;
|
|
import static com.google.common.io.SourceSinkFactory.CharSourceFactory;
|
|
import static org.junit.Assert.assertArrayEquals;
|
|
|
|
import com.google.common.base.Charsets;
|
|
import com.google.common.base.Optional;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.hash.HashCode;
|
|
import com.google.common.hash.Hashing;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.lang.reflect.Method;
|
|
import java.util.Map.Entry;
|
|
import java.util.Random;
|
|
import junit.framework.TestSuite;
|
|
|
|
/**
|
|
* A generator of {@code TestSuite} instances for testing {@code ByteSource} implementations.
|
|
* Generates tests of a all methods on a {@code ByteSource} given various inputs the source is
|
|
* expected to contain as well as sub-suites for testing the {@code CharSource} view and {@code
|
|
* slice()} views in the same way.
|
|
*
|
|
* @author Colin Decker
|
|
*/
|
|
@AndroidIncompatible // Android doesn't understand tests that lack default constructors.
|
|
public class ByteSourceTester extends SourceSinkTester<ByteSource, byte[], ByteSourceFactory> {
|
|
|
|
private static final ImmutableList<Method> testMethods = getTestMethods(ByteSourceTester.class);
|
|
|
|
static TestSuite tests(String name, ByteSourceFactory factory, boolean testAsCharSource) {
|
|
TestSuite suite = new TestSuite(name);
|
|
for (Entry<String, String> entry : TEST_STRINGS.entrySet()) {
|
|
if (testAsCharSource) {
|
|
suite.addTest(suiteForString(factory, entry.getValue(), name, entry.getKey()));
|
|
} else {
|
|
suite.addTest(
|
|
suiteForBytes(
|
|
factory, entry.getValue().getBytes(Charsets.UTF_8), name, entry.getKey(), true));
|
|
}
|
|
}
|
|
return suite;
|
|
}
|
|
|
|
static TestSuite suiteForString(
|
|
ByteSourceFactory factory, String string, String name, String desc) {
|
|
TestSuite suite = suiteForBytes(factory, string.getBytes(Charsets.UTF_8), name, desc, true);
|
|
CharSourceFactory charSourceFactory = SourceSinkFactories.asCharSourceFactory(factory);
|
|
suite.addTest(
|
|
CharSourceTester.suiteForString(
|
|
charSourceFactory, string, name + ".asCharSource[Charset]", desc));
|
|
return suite;
|
|
}
|
|
|
|
static TestSuite suiteForBytes(
|
|
ByteSourceFactory factory, byte[] bytes, String name, String desc, boolean slice) {
|
|
TestSuite suite = new TestSuite(name + " [" + desc + "]");
|
|
for (Method method : testMethods) {
|
|
suite.addTest(new ByteSourceTester(factory, bytes, name, desc, method));
|
|
}
|
|
|
|
if (slice && bytes.length > 0) {
|
|
// test a random slice() of the ByteSource
|
|
Random random = new Random();
|
|
byte[] expected = factory.getExpected(bytes);
|
|
// if expected.length == 0, off has to be 0 but length doesn't matter--result will be empty
|
|
int off = expected.length == 0 ? 0 : random.nextInt(expected.length);
|
|
int len = expected.length == 0 ? 4 : random.nextInt(expected.length - off);
|
|
|
|
ByteSourceFactory sliced = SourceSinkFactories.asSlicedByteSourceFactory(factory, off, len);
|
|
suite.addTest(suiteForBytes(sliced, bytes, name + ".slice[long, long]", desc, false));
|
|
|
|
// test a slice() of the ByteSource starting at a random offset with a length of
|
|
// Long.MAX_VALUE
|
|
ByteSourceFactory slicedLongMaxValue =
|
|
SourceSinkFactories.asSlicedByteSourceFactory(factory, off, Long.MAX_VALUE);
|
|
suite.addTest(
|
|
suiteForBytes(
|
|
slicedLongMaxValue, bytes, name + ".slice[long, Long.MAX_VALUE]", desc, false));
|
|
|
|
// test a slice() of the ByteSource starting at an offset greater than its size
|
|
ByteSourceFactory slicedOffsetPastEnd =
|
|
SourceSinkFactories.asSlicedByteSourceFactory(
|
|
factory, expected.length + 2, expected.length + 10);
|
|
suite.addTest(
|
|
suiteForBytes(slicedOffsetPastEnd, bytes, name + ".slice[size + 2, long]", desc, false));
|
|
}
|
|
|
|
return suite;
|
|
}
|
|
|
|
private ByteSource source;
|
|
|
|
public ByteSourceTester(
|
|
ByteSourceFactory factory, byte[] bytes, String suiteName, String caseDesc, Method method) {
|
|
super(factory, bytes, suiteName, caseDesc, method);
|
|
}
|
|
|
|
@Override
|
|
public void setUp() throws IOException {
|
|
source = factory.createSource(data);
|
|
}
|
|
|
|
public void testOpenStream() throws IOException {
|
|
InputStream in = source.openStream();
|
|
try {
|
|
byte[] readBytes = ByteStreams.toByteArray(in);
|
|
assertExpectedBytes(readBytes);
|
|
} finally {
|
|
in.close();
|
|
}
|
|
}
|
|
|
|
public void testOpenBufferedStream() throws IOException {
|
|
InputStream in = source.openBufferedStream();
|
|
try {
|
|
byte[] readBytes = ByteStreams.toByteArray(in);
|
|
assertExpectedBytes(readBytes);
|
|
} finally {
|
|
in.close();
|
|
}
|
|
}
|
|
|
|
public void testRead() throws IOException {
|
|
byte[] readBytes = source.read();
|
|
assertExpectedBytes(readBytes);
|
|
}
|
|
|
|
public void testCopyTo_outputStream() throws IOException {
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
source.copyTo(out);
|
|
assertExpectedBytes(out.toByteArray());
|
|
}
|
|
|
|
public void testCopyTo_byteSink() throws IOException {
|
|
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
// HERESY! but it's ok just for this I guess
|
|
source.copyTo(
|
|
new ByteSink() {
|
|
@Override
|
|
public OutputStream openStream() throws IOException {
|
|
return out;
|
|
}
|
|
});
|
|
assertExpectedBytes(out.toByteArray());
|
|
}
|
|
|
|
public void testIsEmpty() throws IOException {
|
|
assertEquals(expected.length == 0, source.isEmpty());
|
|
}
|
|
|
|
public void testSize() throws IOException {
|
|
assertEquals(expected.length, source.size());
|
|
}
|
|
|
|
public void testSizeIfKnown() throws IOException {
|
|
Optional<Long> sizeIfKnown = source.sizeIfKnown();
|
|
if (sizeIfKnown.isPresent()) {
|
|
assertEquals(expected.length, (long) sizeIfKnown.get());
|
|
}
|
|
}
|
|
|
|
public void testContentEquals() throws IOException {
|
|
assertTrue(
|
|
source.contentEquals(
|
|
new ByteSource() {
|
|
@Override
|
|
public InputStream openStream() throws IOException {
|
|
return new RandomAmountInputStream(
|
|
new ByteArrayInputStream(expected), new Random());
|
|
}
|
|
}));
|
|
}
|
|
|
|
public void testRead_usingByteProcessor() throws IOException {
|
|
byte[] readBytes =
|
|
source.read(
|
|
new ByteProcessor<byte[]>() {
|
|
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
|
@Override
|
|
public boolean processBytes(byte[] buf, int off, int len) throws IOException {
|
|
out.write(buf, off, len);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public byte[] getResult() {
|
|
return out.toByteArray();
|
|
}
|
|
});
|
|
|
|
assertExpectedBytes(readBytes);
|
|
}
|
|
|
|
public void testHash() throws IOException {
|
|
HashCode expectedHash = Hashing.md5().hashBytes(expected);
|
|
assertEquals(expectedHash, source.hash(Hashing.md5()));
|
|
}
|
|
|
|
public void testSlice_illegalArguments() {
|
|
try {
|
|
source.slice(-1, 0);
|
|
fail("expected IllegalArgumentException for call to slice with offset -1: " + source);
|
|
} catch (IllegalArgumentException expected) {
|
|
}
|
|
|
|
try {
|
|
source.slice(0, -1);
|
|
fail("expected IllegalArgumentException for call to slice with length -1: " + source);
|
|
} catch (IllegalArgumentException expected) {
|
|
}
|
|
}
|
|
|
|
// Test that you can not expand the readable data in a previously sliced ByteSource.
|
|
public void testSlice_constrainedRange() throws IOException {
|
|
long size = source.read().length;
|
|
if (size >= 2) {
|
|
ByteSource sliced = source.slice(1, size - 2);
|
|
assertEquals(size - 2, sliced.read().length);
|
|
ByteSource resliced = sliced.slice(0, size - 1);
|
|
assertTrue(sliced.contentEquals(resliced));
|
|
}
|
|
}
|
|
|
|
private void assertExpectedBytes(byte[] readBytes) {
|
|
assertArrayEquals(expected, readBytes);
|
|
}
|
|
}
|