This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit d65b1a08178cbec530adfdeb3d6763e05518427a Author: Benoit Tellier <[email protected]> AuthorDate: Thu Feb 24 09:18:44 2022 +0700 JAMES-3715 Adds tests for IMAP partial fetch over Netty transport Under some circumstances those broke with Netty4 and the little test suite introduced here reliably demonstrates this. Furthermore, we identified an issue regarding partial fetch when only the offset is specified. This is due to the usage of Long.MAX_VALUE to represent absence, and that causes some mis-calculations down the line. --- .../fetch/PartialFetchBodyElementTest.java | 35 +++++++--- .../james/imapserver/netty/IMAPServerTest.java | 79 ++++++++++++++++++++++ .../org/apache/james/utils/TestIMAPClient.java | 2 +- 3 files changed, 106 insertions(+), 10 deletions(-) diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java index 5a8f2d4..a35226d 100644 --- a/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java +++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.when; import org.apache.james.imap.message.response.FetchResponse.BodyElement; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class PartialFetchBodyElementTest { @@ -39,8 +40,7 @@ class PartialFetchBodyElementTest { } @Test - void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZero() - throws Exception { + void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZero() throws Exception { final long moreThanNumberOfOctets = NUMBER_OF_OCTETS + 1; PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, NUMBER_OF_OCTETS); when(mockBodyElement.size()).thenReturn(moreThanNumberOfOctets); @@ -49,8 +49,7 @@ class PartialFetchBodyElementTest { } @Test - void testSizeShouldBeSizeWhenNumberOfOctetsMoreWhenStartIsZero() - throws Exception { + void testSizeShouldBeSizeWhenNumberOfOctetsMoreWhenStartIsZero() throws Exception { final long lessThanNumberOfOctets = NUMBER_OF_OCTETS - 1; PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, NUMBER_OF_OCTETS); when(mockBodyElement.size()).thenReturn(lessThanNumberOfOctets); @@ -59,8 +58,7 @@ class PartialFetchBodyElementTest { } @Test - void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStart() - throws Exception { + void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStart() throws Exception { final long size = 60; PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, NUMBER_OF_OCTETS); when(mockBodyElement.size()).thenReturn(size); @@ -70,7 +68,7 @@ class PartialFetchBodyElementTest { @Test void testWhenStartPlusNumberOfOctetsIsLessThanSizeSizeShouldBeNumberOfOctetsMinusStart() - throws Exception { + throws Exception { final long size = 100; PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, NUMBER_OF_OCTETS); when(mockBodyElement.size()).thenReturn(size); @@ -88,12 +86,31 @@ class PartialFetchBodyElementTest { } @Test - void testSizeShouldBeNumberOfOctetsWhenStartMoreThanOctets() - throws Exception { + void testSizeShouldBeNumberOfOctetsWhenStartMoreThanOctets() throws Exception { final long size = 2000; PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 1000, NUMBER_OF_OCTETS); when(mockBodyElement.size()).thenReturn(size); assertThat(element.size()).describedAs("Content size is less than start. Size should be zero.").isEqualTo(NUMBER_OF_OCTETS); } + + @Test + void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZeroAndNoLimitSpecified() throws Exception { + PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, Long.MAX_VALUE); + when(mockBodyElement.size()).thenReturn(NUMBER_OF_OCTETS); + + assertThat(element.size()).describedAs("Size is more than number of octets so should be number of octets") + .isEqualTo(NUMBER_OF_OCTETS); + } + + @Disabled("JAMES-3715 A bug due to usage of Long.MAX to represent a value that is absent prevents this" + + "from working decently. Returns 9223372036854775807L which cannot be parsed nor handled by IMAP clients.") + @Test + void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStartAndNoLimitSpecified() throws Exception { + final long size = 60; + PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, Long.MAX_VALUE); + when(mockBodyElement.size()).thenReturn(size); + + assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(50); + } } diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java index 6222c4d..4094f8d 100644 --- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java +++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java @@ -141,6 +141,85 @@ class IMAPServerTest { } @Nested + class PartialFetch { + IMAPServer imapServer; + private int port; + + @BeforeEach + void beforeEach() throws Exception { + imapServer = createImapServer("imapServer.xml"); + port = imapServer.getListenAddresses().get(0).getPort(); + } + + @AfterEach + void tearDown() { + imapServer.destroy(); + } + + @Test + void fetchShouldRetrieveMessage() throws Exception { + testIMAPClient.connect("127.0.0.1", port) + .login(USER.asString(), USER_PASS) + .append("INBOX", SMALL_MESSAGE); + + assertThat(testIMAPClient + .select("INBOX") + .readFirstMessage()) + .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[] {21}\r\nheader: value\r\n\r\nBODY)\r\n"); + } + + @Test + void fetchShouldRetrieveMessageWhenOffsetAndLimitExceedingMessageSize() throws Exception { + testIMAPClient.connect("127.0.0.1", port) + .login(USER.asString(), USER_PASS) + .append("INBOX", SMALL_MESSAGE); + + assertThat(testIMAPClient + .select("INBOX") + .readFirstMessageInMailbox("BODY[]<8.20>")) + .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {13}\r\nvalue\r\n\r\nBODY)\r\n"); + } + + @Test + void fetchShouldRetrieveMessageWhenOffsetAndLimitEqualMessageSize() throws Exception { + testIMAPClient.connect("127.0.0.1", port) + .login(USER.asString(), USER_PASS) + .append("INBOX", SMALL_MESSAGE); + + assertThat(testIMAPClient + .select("INBOX") + .readFirstMessageInMailbox("BODY[]<8.13>")) + .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {13}\r\nvalue\r\n\r\nBODY)\r\n"); + } + + @Test + void fetchShouldRetrieveMessageWhenOffsetAndLimitBelowMessageSize() throws Exception { + testIMAPClient.connect("127.0.0.1", port) + .login(USER.asString(), USER_PASS) + .append("INBOX", SMALL_MESSAGE); + + assertThat(testIMAPClient + .select("INBOX") + .readFirstMessageInMailbox("BODY[]<8.12>")) + .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {12}\r\nvalue\r\n\r\nBOD)\r\n"); + } + + @Disabled("JAMES-3715 A bug due to usage of Long.MAX to represent a value that is absent prevents this" + + "from working decently.") + @Test + void fetchShouldRetrieveMessageWhenOffsetAndNoLimitSpecified() throws Exception { + testIMAPClient.connect("127.0.0.1", port) + .login(USER.asString(), USER_PASS) + .append("INBOX", SMALL_MESSAGE); + + assertThat(testIMAPClient + .select("INBOX") + .readFirstMessageInMailbox("BODY[]<8>")) + .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {13}\r\nvalue\r\n\r\nBODY)\r\n"); + } + } + + @Nested class NoLimit { IMAPServer imapServer; private int port; diff --git a/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java b/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java index 72f1c79..25041a5 100644 --- a/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java +++ b/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java @@ -220,7 +220,7 @@ public class TestIMAPClient extends ExternalResource implements Closeable, After return imapClient.getReplyString(); } - private String readFirstMessageInMailbox(String parameters) throws IOException { + public String readFirstMessageInMailbox(String parameters) throws IOException { imapClient.fetch("1:1", parameters); return imapClient.getReplyString(); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
