1 package org.brotli.wrapper.enc;
2 
3 import static org.junit.Assert.assertEquals;
4 
5 import org.brotli.integration.BrotliJniTestBase;
6 import org.brotli.integration.BundleHelper;
7 import org.brotli.wrapper.dec.BrotliInputStream;
8 import java.io.ByteArrayInputStream;
9 import java.io.ByteArrayOutputStream;
10 import java.io.FileInputStream;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.nio.Buffer;
14 import java.nio.ByteBuffer;
15 import java.nio.channels.Channels;
16 import java.nio.channels.WritableByteChannel;
17 import java.util.List;
18 import junit.framework.TestCase;
19 import junit.framework.TestSuite;
20 import org.junit.runner.RunWith;
21 import org.junit.runners.AllTests;
22 
23 /** Tests for {@link org.brotli.wrapper.enc.BrotliEncoderChannel}. */
24 @RunWith(AllTests.class)
25 public class BrotliEncoderChannelTest extends BrotliJniTestBase {
26 
27   private enum TestMode {
28     WRITE_ALL,
29     WRITE_CHUNKS
30   }
31 
32   private static final int CHUNK_SIZE = 256;
33 
getBundle()34   static InputStream getBundle() throws IOException {
35     return new FileInputStream(System.getProperty("TEST_BUNDLE"));
36   }
37 
38   /** Creates a test suite. */
suite()39   public static TestSuite suite() throws IOException {
40     TestSuite suite = new TestSuite();
41     InputStream bundle = getBundle();
42     try {
43       List<String> entries = BundleHelper.listEntries(bundle);
44       for (String entry : entries) {
45         suite.addTest(new ChannleTestCase(entry, TestMode.WRITE_ALL));
46         suite.addTest(new ChannleTestCase(entry, TestMode.WRITE_CHUNKS));
47       }
48     } finally {
49       bundle.close();
50     }
51     return suite;
52   }
53 
54   /** Test case with a unique name. */
55   static class ChannleTestCase extends TestCase {
56     final String entryName;
57     final TestMode mode;
ChannleTestCase(String entryName, TestMode mode)58     ChannleTestCase(String entryName, TestMode mode) {
59       super("BrotliEncoderChannelTest." + entryName + "." + mode.name());
60       this.entryName = entryName;
61       this.mode = mode;
62     }
63 
64     @Override
runTest()65     protected void runTest() throws Throwable {
66       BrotliEncoderChannelTest.run(entryName, mode);
67     }
68   }
69 
run(String entryName, TestMode mode)70   private static void run(String entryName, TestMode mode) throws Throwable {
71     InputStream bundle = getBundle();
72     byte[] original;
73     try {
74       original = BundleHelper.readEntry(bundle, entryName);
75     } finally {
76       bundle.close();
77     }
78     if (original == null) {
79       throw new RuntimeException("Can't read bundle entry: " + entryName);
80     }
81 
82     if ((mode == TestMode.WRITE_CHUNKS) && (original.length <= CHUNK_SIZE)) {
83       return;
84     }
85 
86     ByteArrayOutputStream dst = new ByteArrayOutputStream();
87     WritableByteChannel encoder = new BrotliEncoderChannel(Channels.newChannel(dst));
88     ByteBuffer src = ByteBuffer.wrap(original);
89     try {
90       switch (mode) {
91         case WRITE_ALL:
92           encoder.write(src);
93           break;
94 
95         case WRITE_CHUNKS:
96           while (src.hasRemaining()) {
97             int limit = Math.min(CHUNK_SIZE, src.remaining());
98             ByteBuffer slice = src.slice();
99             ((Buffer) slice).limit(limit);
100             ((Buffer) src).position(src.position() + limit);
101             encoder.write(slice);
102           }
103           break;
104       }
105     } finally {
106       encoder.close();
107     }
108 
109     InputStream decoder = new BrotliInputStream(new ByteArrayInputStream(dst.toByteArray()));
110     try {
111       long originalCrc = BundleHelper.fingerprintStream(new ByteArrayInputStream(original));
112       long crc = BundleHelper.fingerprintStream(decoder);
113       assertEquals(originalCrc, crc);
114     } finally {
115       decoder.close();
116     }
117   }
118 }
119