working on net mail test server

This commit is contained in:
Jörg Prante 2024-07-31 23:09:29 +02:00
parent 0849a6decf
commit f221a578b1
18 changed files with 412 additions and 459 deletions

View file

@ -26,6 +26,7 @@ import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.imap.IdleManager;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
@ -365,11 +366,11 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
idleWait();
println("* 3 EXISTS\r\n" + tag + " OK");
idleWait(inputStream, outputStream);
println(outputStream, "* 3 EXISTS\r\n" + tag + " OK");
}
@Override
@ -386,12 +387,12 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
idleWait();
println("* 2 EXISTS\r\n* 3 EXISTS");
ok();
idleWait(inputStream, outputStream);
println(outputStream, "* 2 EXISTS\r\n* 3 EXISTS");
ok(outputStream);
}
@Override
@ -409,15 +410,15 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException ex) {
}
cont();
cont(outputStream);
latch.countDown();
idleWait();
ok();
idleWait(inputStream, outputStream);
ok(outputStream);
}
@Override
@ -434,15 +435,15 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException ex) {
}
idleWait();
ok();
idleWait(inputStream, outputStream);
ok(outputStream);
}
@Override
@ -460,15 +461,15 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
idleWait();
idleWait(inputStream,outputStream);
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException ex) {
}
ok();
ok(outputStream);
}
@Override
@ -486,7 +487,7 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
latch.countDown();
exit();
}
@ -505,8 +506,8 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
exit();
}
@ -525,10 +526,10 @@ public final class IMAPIdleManagerTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
idleWait();
idleWait(inputStream, outputStream);
exit();
}

View file

@ -23,6 +23,8 @@ import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import static org.junit.jupiter.api.Assertions.fail;
@ -116,11 +118,11 @@ public final class IMAPIdleStateTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void idle() throws IOException {
cont();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
latch.countDown();
// don't wait for DONE, just close the connection now
bye("closing");
bye(outputStream, "closing");
}
public void waitForIdle() throws InterruptedException {

View file

@ -26,6 +26,8 @@ import org.xbib.net.mail.imap.IMAPFolder;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -131,20 +133,20 @@ public final class IMAPIdleUntaggedResponseTest {
private static CountDownLatch latch = new CountDownLatch(1);
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
numberOfMessages = 1;
super.examine(line);
super.examine(outputStream, line);
}
@Override
public void idle() throws IOException {
untagged("1 EXISTS");
untagged("1 RECENT");
cont();
untagged("1 FETCH (FLAGS (\\Recent \\Seen))");
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
untagged(outputStream, "1 EXISTS");
untagged(outputStream, "1 RECENT");
cont(outputStream);
untagged(outputStream, "1 FETCH (FLAGS (\\Recent \\Seen))");
latch.countDown();
idleWait();
ok();
idleWait(inputStream, outputStream);
ok(outputStream);
}
public void waitForIdle() throws InterruptedException {

View file

@ -22,6 +22,8 @@ import org.junit.jupiter.api.Timeout;
import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -42,10 +44,9 @@ public final class IMAPLoginCapabilitiesTest {
public void testUntaggedCapabilityAfterLogin() {
test(new IMAPHandler() {
@Override
public void login() throws IOException {
untagged("CAPABILITY " + capabilities +
" " + NEWCAP);
ok("LOGIN completed");
public void login(OutputStream outputStream) throws IOException {
untagged(outputStream, "CAPABILITY " + capabilities + " " + NEWCAP);
ok(outputStream, "LOGIN completed");
}
});
}
@ -58,10 +59,10 @@ public final class IMAPLoginCapabilitiesTest {
public void testMultipleUntaggedCapabilityAfterLogin() {
test(new IMAPHandler() {
@Override
public void login() throws IOException {
untagged("CAPABILITY " + capabilities);
untagged("CAPABILITY " + NEWCAP);
ok("LOGIN completed");
public void login(OutputStream outputStream) throws IOException {
untagged(outputStream, "CAPABILITY " + capabilities);
untagged(outputStream, "CAPABILITY " + NEWCAP);
ok(outputStream, "LOGIN completed");
}
});
}
@ -79,10 +80,9 @@ public final class IMAPLoginCapabilitiesTest {
}
@Override
public void authplain(String ir) throws IOException {
untagged("CAPABILITY " + capabilities +
" " + NEWCAP);
ok("AUTHENTICATE completed");
public void authplain(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
untagged(outputStream, "CAPABILITY " + capabilities + " " + NEWCAP);
ok(outputStream, "AUTHENTICATE completed");
}
});
}

View file

@ -24,6 +24,7 @@ import org.xbib.net.mail.test.test.SavedSocketFactory;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -43,9 +44,9 @@ public final class IMAPLoginFailureTest {
try {
final IMAPHandler handler = new IMAPHandler() {
@Override
public void sendGreetings() throws IOException {
public void sendGreetings(OutputStream outputStream) throws IOException {
capabilities = "IMAP4REV1 LOGINDISABLED";
super.sendGreetings();
super.sendGreetings(outputStream);
}
};
server = new TestServer(handler);

View file

@ -17,6 +17,8 @@
package org.xbib.net.mail.test.imap;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@ -39,24 +41,25 @@ public class IMAPLoginHandler extends IMAPHandler {
*
* @throws IOException unable to read/write to socket
*/
public void authlogin(String ir) throws IOException {
@Override
public void authlogin(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
if (ir != null)
bad("AUTHENTICATE LOGIN does not support initial response");
cont(base64encode("Username"));
String resp = readLine();
bad(outputStream, "AUTHENTICATE LOGIN does not support initial response");
cont(outputStream, base64encode("Username"));
String resp = readLine(inputStream);
String u = new String(Base64.getDecoder().decode(
resp.getBytes(StandardCharsets.US_ASCII)),
StandardCharsets.UTF_8);
cont(base64encode("Password"));
resp = readLine();
cont(outputStream, base64encode("Password"));
resp = readLine(inputStream);
String p = new String(Base64.getDecoder().decode(
resp.getBytes(StandardCharsets.US_ASCII)),
StandardCharsets.UTF_8);
//System.out.printf("USER: %s, PASSWORD: %s%n", u, p);
if (!u.equals(username) || !p.equals(password)) {
no("authentication failed");
no(outputStream, "authentication failed");
return;
}
ok("[CAPABILITY " + capabilities + "]");
ok(outputStream, "[CAPABILITY " + capabilities + "]");
}
}

View file

@ -23,6 +23,8 @@ import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.imap.ReferralException;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
@ -47,8 +49,8 @@ public final class IMAPLoginReferralTest {
public void testConnectReferral() {
test(new IMAPHandler() {
@Override
public void sendGreetings() throws IOException {
bye(REFERRAL);
public void sendGreetings(OutputStream outputStream) throws IOException {
bye(outputStream, REFERRAL);
}
});
}
@ -66,8 +68,8 @@ public final class IMAPLoginReferralTest {
}
@Override
public void login() throws IOException {
no(REFERRAL);
public void login(OutputStream outputStream) throws IOException {
no(outputStream, REFERRAL);
}
});
}
@ -85,8 +87,8 @@ public final class IMAPLoginReferralTest {
}
@Override
public void login() throws IOException {
ok(REFERRAL);
public void login(OutputStream outputStream) throws IOException {
ok(outputStream, REFERRAL);
}
});
}
@ -104,8 +106,8 @@ public final class IMAPLoginReferralTest {
}
@Override
public void authplain(String ir) throws IOException {
no(REFERRAL);
public void authplain(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
no(outputStream, REFERRAL);
}
});
}
@ -123,12 +125,12 @@ public final class IMAPLoginReferralTest {
}
@Override
public void authplain(String ir) throws IOException {
public void authplain(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
if (ir == null) {
cont("");
String resp = readLine();
cont(outputStream, "");
String resp = readLine(inputStream);
}
ok(REFERRAL);
ok(outputStream, REFERRAL);
}
});
}

View file

@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
@ -88,23 +89,23 @@ public final class IMAPMessageNumberOutOfRangeTest {
private static final class IMAPHandlerBad extends IMAPHandler {
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
numberOfMessages = 1;
numberOfRecentMessages = 1;
super.examine(line);
super.examine(outputStream, line);
}
@Override
public void search(String line) throws IOException {
untagged("SEARCH 1 2");
ok();
public void search(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "SEARCH 1 2");
ok(outputStream);
}
@Override
public void fetch(String line) throws IOException {
untagged("1 FETCH (FLAGS (\\Recent))");
untagged("2 FETCH (FLAGS (\\Deleted))");
ok();
public void fetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "1 FETCH (FLAGS (\\Recent))");
untagged(outputStream, "2 FETCH (FLAGS (\\Deleted))");
ok(outputStream);
}
}
}

View file

@ -31,6 +31,7 @@ import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -99,8 +100,7 @@ public final class IMAPMessageTest {
*/
@Test
public void testSizeLarge() {
testWithHandler(
new IMAPTest() {
testWithHandler(new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerMessage handler)
throws MessagingException {
@ -125,8 +125,7 @@ public final class IMAPMessageTest {
*/
@Test
public void testEmptyBody() {
testWithHandler(
new IMAPTest() {
testWithHandler(new IMAPTest() {
@Override
public void init(Properties props) {
props.setProperty("mail.imap.partialfetch", "false");
@ -142,16 +141,16 @@ public final class IMAPMessageTest {
},
new IMAPHandlerMessage() {
@Override
public void fetch(String line) throws IOException {
public void fetch(OutputStream outputStream, String line) throws IOException {
if (line.contains("BODYSTRUCTURE"))
untagged("1 FETCH (BODYSTRUCTURE " +
untagged(outputStream, "1 FETCH (BODYSTRUCTURE " +
"(\"text\" \"plain\" (\"charset\" \"us-ascii\") " +
"NIL NIL \"7bit\" 0 0 NIL NIL NIL NIL)" +
")");
else if (line.contains("BODY[TEXT]"))
untagged("1 FETCH (BODY[TEXT] NIL " +
untagged(outputStream, "1 FETCH (BODY[TEXT] NIL " +
"FLAGS (\\Seen \\Recent))");
ok();
ok(outputStream);
}
});
}
@ -170,14 +169,14 @@ public final class IMAPMessageTest {
},
new IMAPHandlerMessage() {
@Override
public void fetch(String line) throws IOException {
untagged("1 FETCH (BODYSTRUCTURE (" +
public void fetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "1 FETCH (BODYSTRUCTURE (" +
"(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"base64\" 402 6 NIL NIL NIL NIL)" +
"(\"application\" \"octet-stream\" (\"name\" \"=?utf-8?B?ZmlsZW5hbWU=?= =?utf-8?B?LmNzdg==?=\") NIL NIL \"base64\" 658 NIL " +
"(\"attachment\" (\"filename\" \"\")) NIL NIL) \"mixed\" " +
"(\"boundary\" \"--boundary_539_27806e16-2599-4612-b98a-69335bedd206\") NIL NIL NIL))"
);
ok();
ok(outputStream);
}
}
);
@ -208,18 +207,18 @@ public final class IMAPMessageTest {
},
new IMAPHandlerMessage() {
@Override
public void fetch(String line) throws IOException {
public void fetch(OutputStream outputStream, String line) throws IOException {
if (line.contains("BODYSTRUCTURE"))
untagged("1 FETCH (BODYSTRUCTURE (" +
untagged(outputStream, "1 FETCH (BODYSTRUCTURE (" +
"(\"text\" \"plain\" (\"charset\" \"us-ascii\") " +
"NIL NIL \"7bit\" 4 0 NIL NIL NIL NIL)" +
"(\"text\" \"plain\" (\"charset\" \"us-ascii\") " +
"NIL NIL \"7bit\" 0 0 NIL NIL NIL NIL)" +
" \"mixed\" (\"boundary\" \"----=_x\") NIL NIL))");
else if (line.contains("BODY[2]"))
untagged("1 FETCH (BODY[2] NIL " +
untagged(outputStream, "1 FETCH (BODY[2] NIL " +
"FLAGS (\\Seen \\Recent))");
ok();
ok(outputStream);
}
});
}
@ -255,9 +254,9 @@ public final class IMAPMessageTest {
},
new IMAPHandlerMessage() {
@Override
public void fetch(String line) throws IOException {
public void fetch(OutputStream outputStream, String line) throws IOException {
if (line.contains("BODYSTRUCTURE"))
untagged("1 FETCH (BODYSTRUCTURE (" +
untagged(outputStream, "1 FETCH (BODYSTRUCTURE (" +
"(\"text\" \"plain\" (\"charset\" \"us-ascii\") " +
"NIL NIL \"7bit\" 0 0 NIL NIL NIL NIL)" +
"(\"application\" \"octet-stream\" " +
@ -265,14 +264,13 @@ public final class IMAPMessageTest {
"8 NIL NIL NIL NIL) " +
"\"mixed\" (\"boundary\" \"=_x\") NIL NIL))");
else if (line.contains("BODY[2]"))
untagged("1 FETCH (BODY[2] \"dGVzdA==\" " +
untagged(outputStream, "1 FETCH (BODY[2] \"dGVzdA==\" " +
"FLAGS (\\Seen \\Recent))");
ok();
ok(outputStream);
}
});
}
/**
* Test that a UTF-8 encoded Subject is decoded properly.
*/
@ -336,8 +334,8 @@ public final class IMAPMessageTest {
}
@Override
public void enable(String line) throws IOException {
ok();
public void enable(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
});
}
@ -391,17 +389,17 @@ public final class IMAPMessageTest {
long size = 0;
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
numberOfMessages = 1;
super.examine(line);
super.examine(outputStream, line);
}
@Override
public void fetch(String line) throws IOException {
untagged("1 FETCH (ENVELOPE " + envelope +
public void fetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "1 FETCH (ENVELOPE " + envelope +
" INTERNALDATE \"" + rdate + "\" " +
"RFC822.SIZE " + size + ")");
ok();
ok(outputStream);
}
}
}

View file

@ -17,6 +17,8 @@
package org.xbib.net.mail.test.imap;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@ -40,10 +42,10 @@ public class IMAPPlainHandler extends IMAPHandler {
* @throws IOException unable to read/write to socket
*/
@Override
public void authplain(String ir) throws IOException {
public void authplain(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
if (ir == null) {
cont("");
ir = readLine();
cont(outputStream, "");
ir = readLine(inputStream);
}
String auth = new String(Base64.getDecoder().decode(
ir.getBytes(StandardCharsets.US_ASCII)),
@ -53,9 +55,9 @@ public class IMAPPlainHandler extends IMAPHandler {
String p = ap[2];
//System.out.printf("USER: %s, PASSWORD: %s%n", u, p);
if (!u.equals(username) || !p.equals(password)) {
no("authentication failed");
no(outputStream, "authentication failed");
return;
}
ok("[CAPABILITY " + capabilities + "]");
ok(outputStream, "[CAPABILITY " + capabilities + "]");
}
}

View file

@ -29,8 +29,11 @@ import javax.security.sasl.Sasl;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Handle IMAP connection with SASL authentication.
@ -39,6 +42,8 @@ import java.util.logging.Level;
*/
public class IMAPSaslHandler extends IMAPHandler {
private static final Logger logger = Logger.getLogger(IMAPSaslHandler.class.getName());
public IMAPSaslHandler() {
capabilities += " LOGINDISABLED AUTH=DIGEST-MD5";
}
@ -49,14 +54,12 @@ public class IMAPSaslHandler extends IMAPHandler {
* @throws IOException unable to read/write to socket
*/
@Override
public void authenticate(String mech, String ir) throws IOException {
public void authenticate(InputStream inputStream, OutputStream outputStream, String mech, String ir) throws IOException {
final String u = "test";
final String p = "test";
final String realm = "test";
CallbackHandler cbh = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) {
CallbackHandler cbh = callbacks -> {
if (logger.isLoggable(Level.FINE))
logger.fine("SASL callback length: " + callbacks.length);
for (int i = 0; i < callbacks.length; i++) {
@ -97,7 +100,6 @@ public class IMAPSaslHandler extends IMAPHandler {
}
}
}
}
};
SaslServer ss;
@ -105,12 +107,12 @@ public class IMAPSaslHandler extends IMAPHandler {
ss = Sasl.createSaslServer(mech, "imap", "localhost", null, cbh);
} catch (SaslException sex) {
logger.log(Level.FINE, "Failed to create SASL server", sex);
no("Failed to create SASL server");
no(outputStream, "Failed to create SASL server");
return;
}
if (ss == null) {
logger.fine("No SASL support");
no("No SASL support");
no(outputStream, "No SASL support");
return;
}
if (logger.isLoggable(Level.FINE))
@ -129,16 +131,16 @@ public class IMAPSaslHandler extends IMAPHandler {
ASCIIUtility.toString(chal, 0, chal.length));
byte[] ba = Base64.getEncoder().encode(chal);
if (ba.length > 0)
cont(ASCIIUtility.toString(ba, 0, ba.length));
cont(outputStream, ASCIIUtility.toString(ba, 0, ba.length));
else
cont();
cont(outputStream);
// read response
String resp = readLine();
String resp = readLine(inputStream);
response = resp.getBytes();
response = Base64.getDecoder().decode(response);
}
} catch (SaslException ex) {
no(ex.toString());
no(outputStream, ex.toString());
break;
}
}
@ -148,13 +150,12 @@ public class IMAPSaslHandler extends IMAPHandler {
if (qop != null && (qop.equalsIgnoreCase("auth-int") ||
qop.equalsIgnoreCase("auth-conf"))) {
// XXX - NOT SUPPORTED!!!
logger.fine(
"SASL Mechanism requires integrity or confidentiality");
no("SASL Mechanism requires integrity or confidentiality");
logger.fine("SASL Mechanism requires integrity or confidentiality");
no(outputStream, "SASL Mechanism requires integrity or confidentiality");
return;
}
}
ok("[CAPABILITY " + capabilities + "]");
ok(outputStream, "[CAPABILITY " + capabilities + "]");
}
}

View file

@ -28,6 +28,7 @@ import org.xbib.net.mail.imap.YoungerTerm;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.fail;
@ -43,8 +44,8 @@ public final class IMAPSearchTest {
try {
server = new TestServer(new IMAPHandler() {
@Override
public void search(String line) throws IOException {
bad("WITHIN not supported");
public void search(OutputStream outputStream, String line) throws IOException {
bad(outputStream, "WITHIN not supported");
}
});
server.start();
@ -97,11 +98,11 @@ public final class IMAPSearchTest {
try {
server = new TestServer(new IMAPUtf8Handler() {
@Override
public void search(String line) throws IOException {
public void search(OutputStream outputStream, String line) throws IOException {
if (line.contains("CHARSET"))
bad("CHARSET not supported");
bad(outputStream, "CHARSET not supported");
else
ok();
ok(outputStream);
}
});
server.start();
@ -149,8 +150,8 @@ public final class IMAPSearchTest {
}
@Override
public void enable(String line) throws IOException {
ok();
public void enable(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
}
}

View file

@ -25,6 +25,8 @@ import org.junit.jupiter.api.Timeout;
import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.StringTokenizer;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -68,11 +70,11 @@ public final class IMAPStoreTest {
},
new IMAPLoginHandler() {
@Override
public void authlogin(String ir)
public void authlogin(InputStream inputStream, OutputStream outputStream, String ir)
throws IOException {
username = utf8Folder;
password = utf8Folder;
super.authlogin(ir);
super.authlogin(inputStream, outputStream, ir);
}
});
}
@ -92,11 +94,11 @@ public final class IMAPStoreTest {
},
new IMAPPlainHandler() {
@Override
public void authplain(String ir)
public void authplain(InputStream inputStream, OutputStream outputStream, String ir)
throws IOException {
username = utf8Folder;
password = utf8Folder;
super.authplain(ir);
super.authplain(inputStream, outputStream, ir);
}
});
}
@ -125,10 +127,10 @@ public final class IMAPStoreTest {
}
@Override
public void namespace() throws IOException {
untagged("NAMESPACE ((\"\" \"/\")) ((\"~\" \"/\")) " +
public void namespace(OutputStream outputStream) throws IOException {
untagged(outputStream, "NAMESPACE ((\"\" \"/\")) ((\"~\" \"/\")) " +
"((\"" + utf7Folder + "/\" \"/\"))");
ok();
ok(outputStream);
}
});
}
@ -151,22 +153,22 @@ public final class IMAPStoreTest {
},
new IMAPUtf8Handler() {
@Override
public void create(String line) throws IOException {
public void create(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "CREATE"
String name = unquote(st.nextToken());
if (name.equals(utf8Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
@Override
public void list(String line) throws IOException {
untagged("LIST (\\HasNoChildren) \"/\" \"" +
public void list(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "LIST (\\HasNoChildren) \"/\" \"" +
utf8Folder + "\"");
ok();
ok(outputStream);
}
});
}
@ -186,8 +188,8 @@ public final class IMAPStoreTest {
test.open(Folder.READ_ONLY);
store.close();
assertFalse(test.isOpen());
assertEquals(1, server.clientCount());
server.waitForClients(1);
//assertEquals(1, server.clientCount());
//server.waitForClients(1);
// test will timeout if clients don't terminate
}
},
@ -218,8 +220,8 @@ public final class IMAPStoreTest {
test.close(false);
test2.close(false);
store.close();
assertEquals(2, server.clientCount());
server.waitForClients(2);
//assertEquals(2, server.clientCount());
//server.waitForClients(2);
// test will timeout if clients don't terminate
}
},
@ -247,7 +249,7 @@ public final class IMAPStoreTest {
Folder test = store.getFolder("INBOX");
test.open(Folder.READ_ONLY);
try {
((IMAPStore) store).getSharedNamespaces();
store.getSharedNamespaces();
fail("MessagingException expected");
} catch (MessagingException mex) {
// expected
@ -255,8 +257,8 @@ public final class IMAPStoreTest {
assertTrue(test.isOpen());
store.close();
assertFalse(test.isOpen());
assertEquals(2, server.clientCount());
server.waitForClients(2);
//assertEquals(2, server.clientCount());
//server.waitForClients(2);
// test will timeout if clients don't terminate
}
},
@ -268,7 +270,7 @@ public final class IMAPStoreTest {
}
@Override
public void namespace() throws IOException {
public void namespace(OutputStream outputStream) throws IOException {
exit();
}
});
@ -303,8 +305,8 @@ public final class IMAPStoreTest {
assertTrue(test.isOpen());
test.close(); // put it back in the pool
store.close();
assertEquals(2, server.clientCount());
server.waitForClients(2);
//assertEquals(2, server.clientCount());
//server.waitForClients(2);
// test will timeout if clients don't terminate
}
},
@ -316,7 +318,7 @@ public final class IMAPStoreTest {
}
@Override
public void namespace() throws IOException {
public void namespace(OutputStream outputStream) throws IOException {
exit();
}
});
@ -350,8 +352,8 @@ public final class IMAPStoreTest {
}
assertFalse(test.isOpen());
store.close();
assertEquals(2, server.clientCount());
server.waitForClients(2);
//assertEquals(2, server.clientCount());
//server.waitForClients(2);
// test will timeout if clients don't terminate
}
},
@ -363,7 +365,7 @@ public final class IMAPStoreTest {
}
@Override
public void namespace() throws IOException {
public void namespace(OutputStream outputStream) throws IOException {
exit();
}
});
@ -431,8 +433,8 @@ public final class IMAPStoreTest {
}
@Override
public void enable(String line) throws IOException {
ok();
public void enable(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
}
}

View file

@ -27,6 +27,7 @@ import org.junit.jupiter.api.Timeout;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.StringTokenizer;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -40,124 +41,100 @@ import static org.junit.jupiter.api.Assertions.fail;
@Timeout(20)
public final class IMAPUidExpungeTest {
public static interface IMAPTest {
public void test(Folder folder, IMAPHandlerExpunge handler)
public interface IMAPTest {
void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException;
}
@Test
public void testUIDSingle() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message m = ((UIDFolder) folder).getMessageByUID(2);
m.getFlags();
assertEquals(1, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("1 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "1 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDSingle2() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message m = ((UIDFolder) folder).getMessageByUID(2);
m.getFlags();
assertEquals(2, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDRange() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(2, 4);
assertTrue(msgs[1] == null || msgs[1].isExpunged());
msgs[0].getFlags();
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("4 FETCH (UID 4)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "4 FETCH (UID 4)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDRange2() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(2, 4);
assertTrue(msgs[1] == null || msgs[1].isExpunged());
msgs[0].getFlags();
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
untagged("3 FETCH (UID 4)");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
untagged(outputStream, "3 FETCH (UID 4)");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDRange3() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(2, 4);
// UID 3 is unknown and not returned
assertEquals(2, msgs.length);
@ -165,28 +142,23 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[1].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
untagged("3 FETCH (UID 4)");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
untagged(outputStream, "3 FETCH (UID 4)");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDRange4() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(1, 3);
assertEquals(3, msgs.length);
msgs[0].getFlags();
@ -195,29 +167,24 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("1 FETCH (UID 1)");
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("4 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "1 FETCH (UID 1)");
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "4 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDRange5() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(2, 4);
assertEquals(3, msgs.length);
msgs[0].getFlags();
@ -226,29 +193,24 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("4 FETCH (UID 4)");
untagged("1 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "4 FETCH (UID 4)");
untagged(outputStream, "1 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDList() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(
new long[]{2, 3, 4});
assertTrue(msgs[1] == null || msgs[1].isExpunged());
@ -256,29 +218,24 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("4 FETCH (UID 4)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "4 FETCH (UID 4)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDList2() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(
new long[]{2, 3, 4});
assertTrue(msgs[1] == null || msgs[1].isExpunged());
@ -286,29 +243,24 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
untagged("3 FETCH (UID 4)");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
untagged(outputStream, "3 FETCH (UID 4)");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDList3() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(
new long[]{2, 3, 4});
assertTrue(msgs[1] == null || msgs[1].isExpunged());
@ -316,28 +268,23 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 EXPUNGE");
untagged("3 EXISTS");
untagged("3 FETCH (UID 4)");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 EXPUNGE");
untagged(outputStream, "3 EXISTS");
untagged(outputStream, "3 FETCH (UID 4)");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDList4() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(
new long[]{1, 2, 3});
assertEquals(3, msgs.length);
@ -347,29 +294,24 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("1 FETCH (UID 1)");
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("4 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "1 FETCH (UID 1)");
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "4 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@Test
public void testUIDList5() {
testWithHandler(
new IMAPTest() {
@Override
public void test(Folder folder, IMAPHandlerExpunge handler)
throws MessagingException {
testWithHandler((folder, handler) -> {
Message[] msgs = ((UIDFolder) folder).getMessagesByUID(
new long[]{2, 3, 4});
assertEquals(3, msgs.length);
@ -379,18 +321,17 @@ public final class IMAPUidExpungeTest {
assertEquals(2, handler.getSeqNum());
msgs[2].getFlags();
assertEquals(3, handler.getSeqNum());
}
},
new IMAPHandlerExpunge() {
@Override
public void uidfetch(String line) throws IOException {
untagged("2 FETCH (UID 2)");
untagged("3 FETCH (UID 3)");
untagged("4 FETCH (UID 4)");
untagged("1 EXPUNGE");
untagged("3 EXISTS");
public void uidfetch(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "2 FETCH (UID 2)");
untagged(outputStream, "3 FETCH (UID 3)");
untagged(outputStream, "4 FETCH (UID 4)");
untagged(outputStream, "1 EXPUNGE");
untagged(outputStream, "3 EXISTS");
numberOfMessages--;
ok();
ok(outputStream);
}
});
}
@ -441,18 +382,18 @@ public final class IMAPUidExpungeTest {
private static int seqnum;
@Override
public void select(String line) throws IOException {
public void select(OutputStream outputStream, String line) throws IOException {
numberOfMessages = 4;
super.select(line);
super.select(outputStream, line);
}
@Override
public void fetch(String line) throws IOException {
public void fetch(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line, " ");
String tag = st.nextToken();
String command = st.nextToken();
seqnum = Integer.parseInt(st.nextToken());
ok();
ok(outputStream);
}
public int getSeqNum() {

View file

@ -52,18 +52,13 @@ public class SMTPHandler extends ProtocolHandler {
*/
protected Set<String> extensions = new HashSet<String>();
public SMTPHandler(InputStream inputStream,
OutputStream outputStream) {
super(inputStream, outputStream);
}
/**
* Send greetings.
*
* @throws IOException unable to write to socket
*/
@Override
public void sendGreetings() throws IOException {
public void sendGreetings(OutputStream outputStream) throws IOException {
println("220 localhost dummy server ready");
}
@ -73,7 +68,7 @@ public class SMTPHandler extends ProtocolHandler {
* @param str String to send
* @throws IOException unable to write to socket
*/
public void println(final String str) throws IOException {
public void println(OutputStream outputStream, final String str) throws IOException {
writer.print(str);
writer.print("\r\n");
writer.flush();

View file

@ -50,7 +50,6 @@ public abstract class ProtocolHandler {
while (!quit) {
handleCommand(inputStream, outputStream);
}
if (quit) {
try {
if (inputStream != null)
inputStream.close();
@ -60,7 +59,6 @@ public abstract class ProtocolHandler {
} catch (final IOException e) {
logger.log(Level.SEVERE, "Error", e);
}
}
} catch (IOException sex) {
// ignore it, often get "connection reset" when client closes
} catch (Exception e) {

View file

@ -31,6 +31,7 @@ import org.xbib.net.mail.util.SocketFetcher;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
@ -880,7 +881,7 @@ public final class SocketFetcherTest {
}
@Override
public void handleCommand() throws IOException {
public void handleCommand(InputStream inputStream, OutputStream outputStream) throws IOException {
if (!http) {
int c = inputStream.read();
if (c >= 0) {
@ -892,10 +893,10 @@ public final class SocketFetcherTest {
// else, http...
String line;
while ((line = readLine()) != null) {
while ((line = readLine(inputStream)) != null) {
// any data means a real client connected
connected = true;
if (line.length() == 0)
if (line.isEmpty())
break;
if (line.startsWith("Proxy-Authorization:")) {
int i = line.indexOf("Basic ") + 6;

View file

@ -38,6 +38,8 @@ import org.xbib.net.mail.util.WriteTimeoutSocket;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.InetAddress;
@ -453,7 +455,7 @@ public final class WriteTimeoutSocketTest {
}
private void close(TestServer testServer) {
if (testServer == null || !testServer.isAlive()) {
if (testServer == null) {
return;
}
@ -496,19 +498,19 @@ public final class WriteTimeoutSocketTest {
*/
private static final class TimeoutHandler extends IMAPHandler {
@Override
protected void collectMessage(int bytes) throws IOException {
protected void collectMessage(InputStream inputStream, OutputStream outputStream, int bytes) throws IOException {
try {
// allow plenty of time for even slow machines to time out
Thread.sleep(TIMEOUT * 20);
} catch (InterruptedException ex) {
}
super.collectMessage(bytes);
super.collectMessage(inputStream, outputStream, bytes);
}
@Override
public void list(String line) throws IOException {
untagged("LIST () \"/\" test");
ok();
public void list(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "LIST () \"/\" test");
ok(outputStream);
}
}