/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.jersey.jdk.connector;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.TestCase.fail;
/**
* @author Petr Janouch (petr.janouch at oracle.com)
*/
public class ChunkedBodyOutputStreamTest {
@Test
public void testBasic() throws IOException {
AsynchronousBodyInputStream responseBody = new AsynchronousBodyInputStream();
ChunkedBodyOutputStream chunkedStream = getOutputStream(responseBody, 21);
String sentBody = TestUtils.generateBody(500);
byte[] sentBytes = sentBody.getBytes();
for (byte b : sentBytes) {
chunkedStream.write(b);
}
chunkedStream.close();
verifyReceivedMessage(sentBody, responseBody);
}
@Test
public void testChunkSize() throws IOException {
doTestChunkSize(1);
}
@Test
public void testChunkSizeWithArray() throws IOException {
doTestChunkSize(8);
}
private void doTestChunkSize(int batchSize) throws IOException {
final int chunkSize = 21;
AsynchronousBodyInputStream responseBody = new AsynchronousBodyInputStream() {
private boolean receivedLess = false;
@Override
synchronized void notifyDataAvailable(ByteBuffer availableData) {
if (availableData.remaining() > chunkSize) {
fail();
}
if (availableData.remaining() < chunkSize) {
assertFalse(receivedLess);
receivedLess = true;
}
super.notifyDataAvailable(availableData);
}
};
ChunkedBodyOutputStream chunkedStream = getOutputStream(responseBody, chunkSize);
String sentBody = TestUtils.generateBody(100);
byte[] sentBytes = sentBody.getBytes();
if (batchSize > 1) {
for (int i = 0; i < sentBytes.length; i += 8) {
chunkedStream.write(sentBytes, i, Math.min(sentBytes.length - i, 8));
}
} else {
for (byte b : sentBytes) {
chunkedStream.write(b);
}
}
chunkedStream.close();
verifyReceivedMessage(sentBody, responseBody);
}
private ChunkedBodyOutputStream getOutputStream(AsynchronousBodyInputStream responseBody, int chunkSize) {
ChunkedBodyOutputStream chunkedStream = new ChunkedBodyOutputStream(chunkSize);
Filter<ByteBuffer, ?, ?, ?> mockTransportFilter = createMockTransportFilter(responseBody);
chunkedStream.open(mockTransportFilter);
return chunkedStream;
}
private void verifyReceivedMessage(String sentBody, AsynchronousBodyInputStream responseBody) throws IOException {
byte[] sentBytes = sentBody.getBytes();
byte[] receivedBytes = new byte[sentBytes.length];
for (int i = 0; i < sentBytes.length; i++) {
int b = responseBody.tryRead();
if (b == -1) {
fail();
}
receivedBytes[i] = (byte) b;
}
if (responseBody.tryRead() != -1) {
fail();
}
String receivedBody = new String(receivedBytes);
assertEquals(sentBody, receivedBody);
}
Filter<ByteBuffer, ?, ?, ?> createMockTransportFilter(final AsynchronousBodyInputStream responseBody) {
HttpParser parser = new HttpParser(Integer.MAX_VALUE, Integer.MAX_VALUE);
parser.reset(true);
final TransferEncodingParser transferEncodingParser = TransferEncodingParser
.createChunkParser(responseBody, parser, 1000);
return new Filter<ByteBuffer, Void, Void, Void>(null) {
@Override
public void write(ByteBuffer chunk, CompletionHandler<ByteBuffer> completionHandler) {
try {
if (transferEncodingParser.parse(chunk)) {
responseBody.notifyAllDataRead();
}
completionHandler.completed(chunk);
} catch (ParseException e) {
completionHandler.failed(e);
}
}
};
}
}