package org.eclipse.jetty.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import org.eclipse.jetty.http.AbstractGenerator; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.SimpleBuffers; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.Utf8StringBuilder; import org.junit.Before; import org.junit.Test; public class HttpWriterTest { private HttpWriter _writer; private ByteArrayBuffer _bytes; @Before public void init() throws Exception { _bytes = new ByteArrayBuffer(2048); Buffers buffers = new SimpleBuffers(new ByteArrayBuffer(1024),new ByteArrayBuffer(1024)); ByteArrayEndPoint endp = new ByteArrayEndPoint(); AbstractGenerator generator = new AbstractGenerator(buffers,endp) { @Override public boolean isRequest() { return false; } @Override public boolean isResponse() { return true; } @Override public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException { } @Override public int flushBuffer() throws IOException { return 0; } @Override public int prepareUncheckedAddContent() throws IOException { return 1024; } public void addContent(Buffer content, boolean last) throws IOException { _bytes.put(content); content.clear(); } public boolean addContent(byte b) throws IOException { return false; } }; AbstractHttpConnection connection = new AbstractHttpConnection(null,endp,new Server(),null,generator,null) { @Override public Connection handle() throws IOException { return null; } }; endp.setMaxIdleTime(60000); HttpOutput httpOut = new HttpOutput(connection); _writer = new HttpWriter(httpOut); } @Test public void testSimpleUTF8() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); _writer.write("Now is the time"); assertArrayEquals("Now is the time".getBytes(StringUtil.__UTF8),_bytes.asArray()); } @Test public void testUTF8() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); _writer.write("How now \uFF22rown cow"); assertArrayEquals("How now \uFF22rown cow".getBytes(StringUtil.__UTF8),_bytes.asArray()); } @Test public void testNotCESU8() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); String data="xxx\uD801\uDC00xxx"; _writer.write(data); assertEquals("787878F0909080787878",TypeUtil.toHexString(_bytes.asArray())); assertArrayEquals(data.getBytes(StringUtil.__UTF8),_bytes.asArray()); assertEquals(3+4+3,_bytes.length()); Utf8StringBuilder buf = new Utf8StringBuilder(); buf.append(_bytes.asArray(),0,_bytes.length()); assertEquals(data,buf.toString()); } @Test public void testMultiByteOverflowUTF8() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); final String singleByteStr = "a"; final String multiByteDuplicateStr = "\uFF22"; int remainSize = 1; int multiByteStrByteLength = multiByteDuplicateStr.getBytes("UTF-8").length; StringBuilder sb = new StringBuilder(); for (int i = 0; i < HttpWriter.MAX_OUTPUT_CHARS - multiByteStrByteLength; i++) { sb.append(singleByteStr); } sb.append(multiByteDuplicateStr); for (int i = 0; i < remainSize; i++) { sb.append(singleByteStr); } char[] buf = new char[HttpWriter.MAX_OUTPUT_CHARS * 3]; int length = HttpWriter.MAX_OUTPUT_CHARS - multiByteStrByteLength + remainSize + 1; sb.toString().getChars(0, length, buf, 0); _writer.write(buf, 0, length); assertEquals(sb.toString(),new String(_bytes.asArray(),StringUtil.__UTF8)); } @Test public void testISO8859() throws Exception { _writer.setCharacterEncoding(StringUtil.__ISO_8859_1); _writer.write("How now \uFF22rown cow"); assertEquals("How now ?rown cow",new String(_bytes.asArray(),StringUtil.__ISO_8859_1)); } @Test public void testOutput() throws Exception { Buffer sb=new ByteArrayBuffer(1500); Buffer bb=new ByteArrayBuffer(8096); HttpFields fields = new HttpFields(); ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096); HttpGenerator hb = new HttpGenerator(new SimpleBuffers(sb,bb),endp); hb.setResponse(200,"OK"); AbstractHttpConnection connection = new AbstractHttpConnection(null,endp,new Server(),null,hb,null) { @Override public Connection handle() throws IOException { return null; } }; endp.setMaxIdleTime(10000); hb.setSendServerVersion(false); HttpOutput output = new HttpOutput(connection); HttpWriter writer = new HttpWriter(output); writer.setCharacterEncoding(StringUtil.__UTF8); char[] chars = new char[1024]; for (int i=0;i<chars.length;i++) chars[i]=(char)('0'+(i%10)); chars[0]='\u0553'; writer.write(chars); hb.completeHeader(fields,true); hb.flush(10000); String response = new String(endp.getOut().asArray(),StringUtil.__UTF8); assertTrue(response.startsWith("HTTP/1.1 200 OK\r\nContent-Length: 1025\r\n\r\n\u05531234567890")); } @Test public void testUTF16x2() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); String source = "\uD842\uDF9F"; byte[] bytes = source.getBytes(StringUtil.__UTF8); _writer.write(source.toCharArray(),0,source.toCharArray().length); java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(baos ,StringUtil.__UTF8 ); osw.write(source.toCharArray(),0,source.toCharArray().length); osw.flush(); myReportBytes(bytes); myReportBytes(baos.toByteArray()); myReportBytes(_bytes.asArray()); assertArrayEquals(bytes,_bytes.asArray()); assertArrayEquals(baos.toByteArray(),_bytes.asArray()); } @Test public void testMultiByteOverflowUTF16x2() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); final String singleByteStr = "a"; int remainSize = 1; final String multiByteDuplicateStr = "\uD842\uDF9F"; int adjustSize = -1; StringBuilder sb = new StringBuilder(); for (int i = 0; i < HttpWriter.MAX_OUTPUT_CHARS + adjustSize; i++) { sb.append(singleByteStr); } sb.append(multiByteDuplicateStr); for (int i = 0; i < remainSize; i++) { sb.append(singleByteStr); } String source = sb.toString(); byte[] bytes = source.getBytes(StringUtil.__UTF8); _writer.write(source.toCharArray(),0,source.toCharArray().length); java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(baos ,StringUtil.__UTF8); osw.write(source.toCharArray(),0,source.toCharArray().length); osw.flush(); myReportBytes(bytes); myReportBytes(baos.toByteArray()); myReportBytes(_bytes.asArray()); assertArrayEquals(bytes,_bytes.asArray()); assertArrayEquals(baos.toByteArray(),_bytes.asArray()); } @Test public void testMultiByteOverflowUTF16x2_2() throws Exception { _writer.setCharacterEncoding(StringUtil.__UTF8); final String singleByteStr = "a"; int remainSize = 1; final String multiByteDuplicateStr = "\uD842\uDF9F"; int adjustSize = -2; StringBuilder sb = new StringBuilder(); for (int i = 0; i < HttpWriter.MAX_OUTPUT_CHARS + adjustSize; i++) { sb.append(singleByteStr); } sb.append(multiByteDuplicateStr); for (int i = 0; i < remainSize; i++) { sb.append(singleByteStr); } String source = sb.toString(); byte[] bytes = source.getBytes(StringUtil.__UTF8); _writer.write(source.toCharArray(),0,source.toCharArray().length); java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(baos,StringUtil.__UTF8); osw.write(source.toCharArray(),0,source.toCharArray().length); osw.flush(); myReportBytes(bytes); myReportBytes(baos.toByteArray()); myReportBytes(_bytes.asArray()); assertArrayEquals(bytes,_bytes.asArray()); assertArrayEquals(baos.toByteArray(),_bytes.asArray()); } private void myReportBytes(byte[] bytes) throws Exception { for (int i = 0; i < bytes.length; i++) { // System.err.format("%s%x",(i == 0)?"[":(i % (HttpWriter.MAX_OUTPUT_CHARS) == 0)?"][":",",bytes[i]); } // System.err.format("]->%s\n",new String(bytes,StringUtil.__UTF8)); } private void assertArrayEquals(byte[] b1, byte[] b2) { String test=new String(b1)+"=="+new String(b2); assertEquals(test,b1.length,b2.length); for (int i=0;i<b1.length;i++) assertEquals(test,b1[i],b2[i]); } }