Fix EOLConvertingOutputStream + add test

Add test for another EOLConvertingOutputStream edge case

Fix bug in EOLConvertingOutputStream

Swap order

Simplify
This commit is contained in:
Jan Berkel 2014-12-17 01:08:51 +01:00
parent 7c79e7c6b5
commit ac33de6310
2 changed files with 86 additions and 13 deletions

View File

@ -5,8 +5,11 @@ import java.io.IOException;
import java.io.OutputStream;
public class EOLConvertingOutputStream extends FilterOutputStream {
private static final int CR = '\r';
private static final int LF = '\n';
private int lastChar;
private boolean ignoreNextIfLF = false;
private static final int IGNORE_LF = Integer.MIN_VALUE;
public EOLConvertingOutputStream(OutputStream out) {
super(out);
@ -14,26 +17,27 @@ public class EOLConvertingOutputStream extends FilterOutputStream {
@Override
public void write(int oneByte) throws IOException {
if (!ignoreNextIfLF) {
if ((oneByte == '\n') && (lastChar != '\r')) {
super.write('\r');
}
super.write(oneByte);
lastChar = oneByte;
if (oneByte == LF && lastChar == IGNORE_LF) {
lastChar = LF;
return;
}
ignoreNextIfLF = false;
if (oneByte == LF && lastChar != CR) {
super.write(CR);
} else if (oneByte != LF && lastChar == CR) {
super.write(LF);
}
super.write(oneByte);
lastChar = oneByte;
}
@Override
public void flush() throws IOException {
if (lastChar == '\r') {
super.write('\n');
lastChar = '\n';
if (lastChar == CR) {
super.write(LF);
// We have to ignore the next character if it is <LF>. Otherwise it
// will be expanded to an additional <CR><LF> sequence although it
// belongs to the one just completed.
ignoreNextIfLF = true;
lastChar = IGNORE_LF;
}
super.flush();
}

View File

@ -0,0 +1,69 @@
package com.fsck.k9.mail.filter;
import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
public class EOLConvertingOutputStreamTest extends TestCase {
private EOLConvertingOutputStream subject;
private ByteArrayOutputStream out;
@Override
public void setUp() throws Exception {
super.setUp();
out = new ByteArrayOutputStream();
subject = new EOLConvertingOutputStream(out);
}
public void testFilterWithoutCRorLF() throws Exception {
subject.write("Unchanged".getBytes());
subject.flush();
assertEquals("Unchanged", out.toString());
}
public void testFilterWithCRLF() throws Exception {
subject.write("Filter\r\nNext Line".getBytes());
subject.flush();
assertEquals("Filter\r\nNext Line", out.toString());
}
public void testFilterWithJustCR() throws Exception {
subject.write("\n\n\n".getBytes());
subject.flush();
assertEquals("\r\n\r\n\r\n", out.toString());
}
public void testFilterWithCR() throws Exception {
subject.write("Filter\rNext Line".getBytes());
subject.flush();
assertEquals("Filter\r\nNext Line", out.toString());
}
public void testFilterWithLF() throws Exception {
subject.write("Filter\nNext Line".getBytes());
subject.flush();
assertEquals("Filter\r\nNext Line", out.toString());
}
public void testFlushWithCR() throws Exception {
subject.write("Flush\r".getBytes());
subject.flush();
assertEquals("Flush\r\n", out.toString());
subject.write("\n\n\n".getBytes());
assertEquals("Flush\r\n\r\n\r\n", out.toString());
}
public void testFlushWithCRNotFollowedByLF() throws Exception {
subject.write("Flush\r".getBytes());
subject.flush();
subject.write("Next line".getBytes());
assertEquals("Flush\r\nNext line", out.toString());
}
public void testFlushWithLF() throws Exception {
subject.write("Flush\n".getBytes());
subject.flush();
subject.write("\n".getBytes());
assertEquals("Flush\r\n\r\n", out.toString());
}
}