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