vttranlina commented on a change in pull request #909:
URL: https://github.com/apache/james-project/pull/909#discussion_r830795564



##########
File path: 
server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
##########
@@ -1276,12 +1258,250 @@ void 
selectShouldReturnDeletedMessagesWhenNoSubsequentModification() throws Exce
             server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
             readBytes(server);
             server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
+            server.write(ByteBuffer.wrap(String.format("I00104 SELECT INBOX 
(QRESYNC (%d %d 2:37 (1,10,28 2,11,29)))\r\n", uidValidity.asLong(), 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
+
+            assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
[READ-WRITE] SELECT completed.")))
+                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 10"))
+                .hasSize(1);
+        }
+
+        @Test
+        void selectShouldCombineIntoRangesWhenRespondingVanished() throws 
Exception {
+            inbox.delete(ImmutableList.of(MessageUid.MIN_VALUE), 
mailboxSession);
+
+            ModSeq highestModSeq = 
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .getMetaData(false, mailboxSession, 
MessageManager.MailboxMetaData.FetchGroup.NO_COUNT)
+                .getHighestModSeq();
+
+            UidValidity uidValidity = 
memoryIntegrationResources.getMailboxManager()
+                .getMailbox(MailboxPath.inbox(USER), mailboxSession)
+                .getMailboxEntity().getUidValidity();
+
+            inbox.delete(ImmutableList.of(MessageUid.of(10), 
MessageUid.of(11), MessageUid.of(12),
+                    MessageUid.of(25), MessageUid.of(26),
+                    MessageUid.of(32)), mailboxSession);
+
+            SocketChannel server = SocketChannel.open();
+            server.connect(new InetSocketAddress(LOCALHOST_IP, port));
             readBytes(server);
+
+            server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
             readBytes(server);
+            server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
             server.write(ByteBuffer.wrap(String.format("I00104 SELECT INBOX 
(QRESYNC (%d %d 2:37 (1,10,28 2,11,29)))\r\n", uidValidity.asLong(), 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
 
             assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
[READ-WRITE] SELECT completed.")))
-                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 10"))
+                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 
10:12,25:26,32"))
+                .hasSize(1);
+        }
+
+        private void setUpTestingData() {
+            IntStream.range(0, 37)
+                .forEach(Throwing.intConsumer(i -> 
inbox.appendMessage(MessageManager.AppendCommand.builder()
+                    .build("MIME-Version: 1.0\r\n\r\nCONTENT\r\n"), 
mailboxSession)));
+        }
+
+        @Test
+        void fetchShouldAllowChangedSinceModifier() throws Exception {
+            SocketChannel server = SocketChannel.open();
+            server.connect(new InetSocketAddress(LOCALHOST_IP, port));
+            readBytes(server);
+
+            server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
+            readBytes(server);
+            server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
+            server.write(ByteBuffer.wrap(("a2 SELECT 
INBOX\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a2 OK [READ-WRITE] SELECT 
completed."));
+
+            
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .setFlags(new Flags(Flags.Flag.ANSWERED), 
MessageManager.FlagsUpdateMode.REPLACE, MessageRange.one(MessageUid.of(10)), 
mailboxSession);
+
+            ModSeq highestModSeq = 
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .getMetaData(false, mailboxSession, 
MessageManager.MailboxMetaData.FetchGroup.NO_COUNT)
+                .getHighestModSeq();
+            server.write(ByteBuffer.wrap(String.format("I00104 UID FETCH 1:37 
(FLAGS) (CHANGEDSINCE %d)\r\n", 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
+
+            assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
FETCH completed.")))
+                .filteredOn(s -> s.contains("* 10 FETCH (MODSEQ (39) FLAGS 
(\\Answered \\Recent) UID 10)"))
+                .hasSize(1);
+        }
+
+        @Test
+        void fetchShouldNotReturnChangedItemsOutOfRange() throws Exception {
+            SocketChannel server = SocketChannel.open();
+            server.connect(new InetSocketAddress(LOCALHOST_IP, port));
+            readBytes(server);
+
+            server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
+            readBytes(server);
+            server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
+            server.write(ByteBuffer.wrap(("a2 SELECT 
INBOX\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a2 OK [READ-WRITE] SELECT 
completed."));
+
+            inbox.setFlags(new Flags(Flags.Flag.ANSWERED), 
MessageManager.FlagsUpdateMode.REPLACE, MessageRange.one(MessageUid.of(10)), 
mailboxSession);
+
+            ModSeq highestModSeq = 
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .getMetaData(false, mailboxSession, 
MessageManager.MailboxMetaData.FetchGroup.NO_COUNT)
+                .getHighestModSeq();
+            server.write(ByteBuffer.wrap(String.format("I00104 UID FETCH 12:37 
(FLAGS) (CHANGEDSINCE %d)\r\n", 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
+
+            assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
FETCH completed.")))
+                .filteredOn(s -> s.contains("FLAGS")) // No FLAGS FETCH 
responses
+                .hasSize(1);
+        }
+
+        @Disabled("JAMES-3722 IMAP stack failed to parse FETCH command with 
two modifiers and thus do" +
+            "not conform to the example of the RFC-5162")
+        @Test
+        void fetchShouldSupportVanishedModifiedWithEarlierTag() throws 
Exception {
+            inbox.delete(ImmutableList.of(MessageUid.of(14)), mailboxSession);
+
+            SocketChannel server = SocketChannel.open();
+            server.connect(new InetSocketAddress(LOCALHOST_IP, port));
+            readBytes(server);
+
+            server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
+            readBytes(server);
+            server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
+            server.write(ByteBuffer.wrap(("a2 SELECT 
INBOX\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a2 OK [READ-WRITE] SELECT 
completed."));
+
+            
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .setFlags(new Flags(Flags.Flag.ANSWERED), 
MessageManager.FlagsUpdateMode.REPLACE, MessageRange.one(MessageUid.of(10)), 
mailboxSession);
+            
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .setFlags(new Flags(Flags.Flag.ANSWERED), 
MessageManager.FlagsUpdateMode.REPLACE, MessageRange.one(MessageUid.of(25)), 
mailboxSession);
+
+            ModSeq highestModSeq = 
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .getMetaData(false, mailboxSession, 
MessageManager.MailboxMetaData.FetchGroup.NO_COUNT)
+                .getHighestModSeq();
+            server.write(ByteBuffer.wrap(String.format("I00104 UID FETCH 12:37 
(FLAGS) (CHANGEDSINCE %d VANISHED)\r\n", 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
+
+            assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
FETCH completed.")))
+                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 14"))
+                .hasSize(1);
+        }
+
+        @Test
+        void unsolicitedNotificationsShouldBeSent() throws Exception {
+            SocketChannel server = SocketChannel.open();
+            server.connect(new InetSocketAddress(LOCALHOST_IP, port));
+            readBytes(server);
+
+            server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
+            readBytes(server);
+            server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
+            server.write(ByteBuffer.wrap(("a2 SELECT 
INBOX\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a2 OK [READ-WRITE] SELECT 
completed."));
+
+            
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .setFlags(new Flags(Flags.Flag.ANSWERED), 
MessageManager.FlagsUpdateMode.REPLACE, MessageRange.one(MessageUid.of(10)), 
mailboxSession);
+            
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .setFlags(new Flags(Flags.Flag.ANSWERED), 
MessageManager.FlagsUpdateMode.REPLACE, MessageRange.one(MessageUid.of(25)), 
mailboxSession);
+
+            inbox.delete(ImmutableList.of(MessageUid.of(14)), mailboxSession);
+
+            ModSeq highestModSeq = 
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .getMetaData(false, mailboxSession, 
MessageManager.MailboxMetaData.FetchGroup.NO_COUNT)
+                .getHighestModSeq();
+            server.write(ByteBuffer.wrap(String.format("I00104 NOOP\r\n", 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));

Review comment:
       missing `%d` in String.format

##########
File path: 
protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
##########
@@ -278,21 +280,28 @@ private void respondVanished(ImapSession session, 
Responder responder, IdRange[]
             .reduce((t3_1, t3_2) -> t3_2)
             .orElse(MessageUid.MIN_VALUE);
 
-        // Ok now its time to filter out the IdRanges which we are not 
interested in
-        List<UidRange> filteredUidSet = new ArrayList<>();
-        for (UidRange r : uidSet) {
-            if (r.getLowVal().compareTo(firstKnownUid) < 0) {
-                if (r.getHighVal().compareTo(firstKnownUid) > 0) {
-                    filteredUidSet.add(new UidRange(firstKnownUid, 
r.getHighVal()));
-                }
+        return filter(uidSet, firstKnownUid);
+    }
+
+    private UidRange[] filter(UidRange[] uidSet, MessageUid lowerBound) {
+        return Arrays.stream(uidSet)
+            .flatMap(range -> filter(range, lowerBound))
+            .collect(ImmutableList.toImmutableList())

Review comment:
       Why do we need to convert it to ImmutableList in middle?
   
   ```
   return Arrays.stream(uidSet)
               .flatMap(range -> filter(range, lowerBound))
               .toArray(UidRange[]::new);
   ``` 
   is better?
   

##########
File path: 
server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
##########
@@ -1323,7 +1324,83 @@ void selectShouldReturnDeletedMessagesWhenKnownUidSet() 
throws Exception {
             server.write(ByteBuffer.wrap(String.format("I00104 SELECT INBOX 
(QRESYNC (%d %d 5:11,28:36 (1,10,28 2,11,29)))\r\n", uidValidity.asLong(), 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
 
             assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
[READ-WRITE] SELECT completed.")))
-                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 10"))
+                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 10:11,32"))
+                .hasSize(1);
+        }
+
+        @Disabled("JAMES-3722 Known sequence sets are buggy and never restrict 
vanished replies." +
+            "Known sequence sets are a way to restrict the scope of vanished 
responses for servers " +
+            "not storing deletion sequences.")
+        @Test
+        void knownUidSetShouldBeUsedToRestrictVanishedResponses() throws 
Exception {
+            inbox.delete(ImmutableList.of(MessageUid.MIN_VALUE), 
mailboxSession);
+
+            ModSeq highestModSeq = 
memoryIntegrationResources.getMailboxManager().getMailbox(MailboxPath.inbox(USER),
 mailboxSession)
+                .getMetaData(false, mailboxSession, 
MessageManager.MailboxMetaData.FetchGroup.NO_COUNT)
+                .getHighestModSeq();
+
+            UidValidity uidValidity = 
memoryIntegrationResources.getMailboxManager()
+                .getMailbox(MailboxPath.inbox(USER), mailboxSession)
+                .getMailboxEntity().getUidValidity();
+
+            inbox.delete(ImmutableList.of(MessageUid.of(10), 
MessageUid.of(11), MessageUid.of(12),
+                MessageUid.of(25), MessageUid.of(26),
+                MessageUid.of(32)), mailboxSession);
+
+            SocketChannel server = SocketChannel.open();
+            server.connect(new InetSocketAddress(LOCALHOST_IP, port));
+            readBytes(server);
+
+            server.write(ByteBuffer.wrap(String.format("a0 LOGIN %s %s\r\n", 
USER.asString(), USER_PASS).getBytes(StandardCharsets.UTF_8)));
+            readBytes(server);
+            server.write(ByteBuffer.wrap(("a1 ENABLE 
QRESYNC\r\n").getBytes(StandardCharsets.UTF_8)));
+            readStringUntil(server, s -> s.contains("a1 OK ENABLE 
completed."));
+            // MSN 1 => UID 2 MATCH
+            // MSN 13 => UID 17 MATCH
+            // MSN 28 => UID 30 MISMATCH stored value is 34
+            // Thus we know we can skip resynchronisation for UIDs up to 17
+            server.write(ByteBuffer.wrap(String.format("I00104 SELECT INBOX 
(QRESYNC (%d %d 1:37 (1,13,28 2,17,30)))\r\n", uidValidity.asLong(), 
highestModSeq.asLong()).getBytes(StandardCharsets.UTF_8)));
+
+            assertThat(readStringUntil(server, s -> s.contains("I00104 OK 
[READ-WRITE] SELECT completed.")))
+                .filteredOn(s -> s.contains("* VANISHED (EARLIER) 25:26,32"))
+                .hasSize(1);
+        }
+
+        @Disabled("JAMES-3722 Known sequence sets are buggy and never restrict 
vanished replies." +
+            "Known sequence sets are a way to restrict the scope of vanished 
responses for servers " +
+            "not storing deletion sequences.")
+        @Test
+        void knownUidSetShouldTorelateDeletedMessages() throws Exception {

Review comment:
       Torelate -> Tolerate ?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to