blob: b6cafb214619ac5870788357058154fe8dbf08d5 [file] [log] [blame]
/*
* Copyright (C) 2014 Square, Inc.
*
* 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 okio;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.junit.Test;
import static okio.TestUtil.randomBytes;
import static okio.TestUtil.repeat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public final class DeflaterSinkTest {
@Test public void deflateWithClose() throws Exception {
Buffer data = new Buffer();
String original = "They're moving in herds. They do move in herds.";
data.writeUtf8(original);
Buffer sink = new Buffer();
DeflaterSink deflaterSink = new DeflaterSink(sink, new Deflater());
deflaterSink.write(data, data.size());
deflaterSink.close();
Buffer inflated = inflate(sink);
assertEquals(original, inflated.readUtf8());
}
@Test public void deflateWithSyncFlush() throws Exception {
String original = "Yes, yes, yes. That's why we're taking extreme precautions.";
Buffer data = new Buffer();
data.writeUtf8(original);
Buffer sink = new Buffer();
DeflaterSink deflaterSink = new DeflaterSink(sink, new Deflater());
deflaterSink.write(data, data.size());
deflaterSink.flush();
Buffer inflated = inflate(sink);
assertEquals(original, inflated.readUtf8());
}
@Test public void deflateWellCompressed() throws IOException {
String original = repeat('a', 1024 * 1024);
Buffer data = new Buffer();
data.writeUtf8(original);
Buffer sink = new Buffer();
DeflaterSink deflaterSink = new DeflaterSink(sink, new Deflater());
deflaterSink.write(data, data.size());
deflaterSink.close();
Buffer inflated = inflate(sink);
assertEquals(original, inflated.readUtf8());
}
@Test public void deflatePoorlyCompressed() throws IOException {
ByteString original = randomBytes(1024 * 1024);
Buffer data = new Buffer();
data.write(original);
Buffer sink = new Buffer();
DeflaterSink deflaterSink = new DeflaterSink(sink, new Deflater());
deflaterSink.write(data, data.size());
deflaterSink.close();
Buffer inflated = inflate(sink);
assertEquals(original, inflated.readByteString());
}
@Test public void multipleSegmentsWithoutCompression() throws IOException {
Buffer buffer = new Buffer();
Deflater deflater = new Deflater();
deflater.setLevel(Deflater.NO_COMPRESSION);
DeflaterSink deflaterSink = new DeflaterSink(buffer, deflater);
int byteCount = Segment.SIZE * 4;
deflaterSink.write(new Buffer().writeUtf8(repeat('a', byteCount)), byteCount);
deflaterSink.close();
assertEquals(repeat('a', byteCount), inflate(buffer).readUtf8(byteCount));
}
@Test public void deflateIntoNonemptySink() throws Exception {
String original = "They're moving in herds. They do move in herds.";
// Exercise all possible offsets for the outgoing segment.
for (int i = 0; i < Segment.SIZE; i++) {
Buffer data = new Buffer().writeUtf8(original);
Buffer sink = new Buffer().writeUtf8(repeat('a', i));
DeflaterSink deflaterSink = new DeflaterSink(sink, new Deflater());
deflaterSink.write(data, data.size());
deflaterSink.close();
sink.skip(i);
Buffer inflated = inflate(sink);
assertEquals(original, inflated.readUtf8());
}
}
/**
* This test deflates a single segment of without compression because that's
* the easiest way to force close() to emit a large amount of data to the
* underlying sink.
*/
@Test public void closeWithExceptionWhenWritingAndClosing() throws IOException {
MockSink mockSink = new MockSink();
mockSink.scheduleThrow(0, new IOException("first"));
mockSink.scheduleThrow(1, new IOException("second"));
Deflater deflater = new Deflater();
deflater.setLevel(Deflater.NO_COMPRESSION);
DeflaterSink deflaterSink = new DeflaterSink(mockSink, deflater);
deflaterSink.write(new Buffer().writeUtf8(repeat('a', Segment.SIZE)), Segment.SIZE);
try {
deflaterSink.close();
fail();
} catch (IOException expected) {
assertEquals("first", expected.getMessage());
}
mockSink.assertLogContains("close()");
}
/**
* Uses streaming decompression to inflate {@code deflated}. The input must
* either be finished or have a trailing sync flush.
*/
private Buffer inflate(Buffer deflated) throws IOException {
InputStream deflatedIn = deflated.inputStream();
Inflater inflater = new Inflater();
InputStream inflatedIn = new InflaterInputStream(deflatedIn, inflater);
Buffer result = new Buffer();
byte[] buffer = new byte[8192];
while (!inflater.needsInput() || deflated.size() > 0 || deflatedIn.available() > 0) {
int count = inflatedIn.read(buffer, 0, buffer.length);
if (count != -1) {
result.write(buffer, 0, count);
}
}
return result;
}
}