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; 203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Arrays; 213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Random; 223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.zip.DeflaterOutputStream; 233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.zip.Inflater; 243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Test; 253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertEquals; 273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.fail; 283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic final class InflaterSourceTest { 303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflate() throws Exception { 313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer deflated = decodeBase64("eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tK" 323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "tYDAF6CD5s="); 333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer inflated = inflate(deflated); 343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("God help us, we're in the hands of engineers.", readUtf8(inflated)); 353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflateTruncated() throws Exception { 383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer deflated = decodeBase64("eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tK" 393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "tYDAF6CDw=="); 403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller inflate(deflated); 423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller fail(); 433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (EOFException expected) { 443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflateWellCompressed() throws Exception { 483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer deflated = decodeBase64("eJztwTEBAAAAwqCs61/CEL5AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 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 + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8B" 643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller + "tFeWvE=\n"); 653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller String original = repeat('a', 1024 * 1024); 663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer inflated = inflate(deflated); 673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(original, readUtf8(inflated)); 683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inflatePoorlyCompressed() throws Exception { 713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller ByteString original = randomBytes(1024 * 1024); 723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer deflated = deflate(original); 733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer inflated = inflate(deflated); 743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(original, inflated.readByteString(inflated.size())); 753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private OkBuffer decodeBase64(String s) { 783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return new OkBuffer().write(ByteString.decodeBase64(s)); 793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private String readUtf8(OkBuffer buffer) { 823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return buffer.readUtf8(buffer.size()); 833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** Use DeflaterOutputStream to deflate source. */ 863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private OkBuffer deflate(ByteString source) throws IOException { 873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer result = new OkBuffer(); 883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Sink sink = Okio.sink(new DeflaterOutputStream(result.outputStream())); 893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.write(new OkBuffer().write(source), source.size()); 903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.close(); 913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return result; 923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** Returns a new buffer containing the inflated contents of {@code deflated}. */ 953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private OkBuffer inflate(OkBuffer deflated) throws IOException { 963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OkBuffer result = new OkBuffer(); 973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InflaterSource source = new InflaterSource(deflated, new Inflater()); 983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller while (source.read(result, Integer.MAX_VALUE) != -1) { 993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return result; 1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private ByteString randomBytes(int length) { 1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Random random = new Random(0); 1053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller byte[] randomBytes = new byte[length]; 1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller random.nextBytes(randomBytes); 1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return ByteString.of(randomBytes); 1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private String repeat(char c, int count) { 1113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller char[] array = new char[count]; 1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Arrays.fill(array, c); 1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return new String(array); 1143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller} 116