13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/* 23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc. 33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License. 63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at 73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software 113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and 143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License. 153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage okio; 173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.EOFException; 193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.IOException; 20a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fullerimport java.util.zip.Deflater; 213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.zip.DeflaterOutputStream; 223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.zip.Inflater; 233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Test; 243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static okio.TestUtil.randomBytes; 26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static okio.TestUtil.repeat; 273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertEquals; 283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.fail; 293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic final class InflaterSourceTest { 313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflate() throws Exception { 32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer deflated = decodeBase64("eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tK" 333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "tYDAF6CD5s="); 34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer inflated = inflate(deflated); 35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("God help us, we're in the hands of engineers.", inflated.readUtf8()); 363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflateTruncated() throws Exception { 39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer deflated = decodeBase64("eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tK" 403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "tYDAF6CDw=="); 413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller inflate(deflated); 433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller fail(); 443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (EOFException expected) { 453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflateWellCompressed() throws Exception { 49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer deflated = decodeBase64("eJztwTEBAAAAwqCs61/CEL5AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8B" 653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "tFeWvE=\n"); 663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller String original = repeat('a', 1024 * 1024); 67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer inflated = inflate(deflated); 68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(original, inflated.readUtf8()); 693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflatePoorlyCompressed() throws Exception { 723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller ByteString original = randomBytes(1024 * 1024); 73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer deflated = deflate(original); 74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer inflated = inflate(deflated); 75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(original, inflated.readByteString()); 763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 78a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller @Test public void inflateIntoNonemptySink() throws Exception { 79a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller for (int i = 0; i < Segment.SIZE; i++) { 80a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller Buffer inflated = new Buffer().writeUtf8(repeat('a', i)); 81a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller Buffer deflated = decodeBase64( 82a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller "eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s="); 83a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller InflaterSource source = new InflaterSource(deflated, new Inflater()); 84a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller while (source.read(inflated, Integer.MAX_VALUE) != -1) { 85a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 86a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller inflated.skip(i); 87a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller assertEquals("God help us, we're in the hands of engineers.", inflated.readUtf8()); 88a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 89a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 90a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller 91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private Buffer decodeBase64(String s) { 92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return new Buffer().write(ByteString.decodeBase64(s)); 933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** Use DeflaterOutputStream to deflate source. */ 96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private Buffer deflate(ByteString source) throws IOException { 97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer result = new Buffer(); 983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Sink sink = Okio.sink(new DeflaterOutputStream(result.outputStream())); 99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller sink.write(new Buffer().write(source), source.size()); 1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.close(); 1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return result; 1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** Returns a new buffer containing the inflated contents of {@code deflated}. */ 105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private Buffer inflate(Buffer deflated) throws IOException { 106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer result = new Buffer(); 1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InflaterSource source = new InflaterSource(deflated, new Inflater()); 1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller while (source.read(result, Integer.MAX_VALUE) != -1) { 1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return result; 1113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller} 113