commit 8f39d06015c7491c81f40a35703cfe78529b868f
parent 882c9825cd41ce88ce22f3c3a37f679d61f200df
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date: Tue, 22 Feb 2022 16:42:22 +0100
fix mixing MaxMessages with MaxSize
this is actually a useful combination for resource-constrained devices.
Diffstat:
M | NEWS | | | 2 | ++ |
M | src/run-tests.pl | | | 125 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/sync.c | | | 28 | +++++++++++++++++++++++++--- |
3 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
@@ -9,6 +9,8 @@ is now the file's containing directory.
Placeholders will be now created for messages exceeding MaxSize even if
they are flagged on the source side.
+MaxMessages and MaxSize can be used together now.
+
The unfiltered list of mailboxes in each Store can be printed now.
A proper summary is now printed prior to exiting.
diff --git a/src/run-tests.pl b/src/run-tests.pl
@@ -1313,6 +1313,131 @@ my @X38 = (
);
test("max messages + expunge", \@x38, \@X38, \@O38);
+# Expiration with size restriction tests
+
+my @x40 = (
+ P, 0, P,
+
+ A, "**", "*>", "*?",
+ B, "**", "*>", "*S?",
+ C, "**", "*>S", "*S?",
+ D, "*S*", "*>S", "*S?",
+ E, "*S*", "*>", "*S?",
+ F, "*S*", "*>S", "*?",
+ G, "*S*", "*>", "*?",
+ H, "**", "*>S", "*?",
+
+ I, "*F*", "*>", "*?",
+ J, "*F*", "*>", "*S?",
+ K, "*F*", "*>S", "*S?",
+ L, "*FS*", "*>S", "*S?",
+ M, "*FS*", "*>", "*S?",
+ N, "*FS*", "*>S", "*?",
+ O, "*FS*", "*>", "*?",
+ P, "*F*", "*>S", "*?",
+
+ Q, "**", "", "",
+ R, "*FS*", "", "",
+ S, "*S*", "", "",
+
+ T, "**", "", "",
+ U, "*FS*", "", "",
+ V, "*S*", "", "",
+);
+
+my @O41 = ("", "", "MaxSize 1k\nMaxMessages 3\nExpireUnread no\n");
+my @X41 = (
+ V, S, V,
+
+ C, "", "-S", "-S",
+ D, "", "+~", "+T",
+ E, "", "+~S", "+T",
+ F, "-S", "-S", "",
+ G, "", "+~S", "+ST",
+ H, "", "-S", "",
+
+ K, "", "-S", "-S",
+ M, "", "+S", "",
+ N, "-S", "-S", "",
+ O, "", "+S", "+S",
+ P, "", "-S", "",
+
+ Q, "", "*>", "*?",
+ R, "", "*>S", "*S?",
+
+ T, "", "*>", "*?",
+ U, "", "*>S", "*S?",
+ V, "", "*>S", "*S?",
+);
+test("max size without upgrade + max messages", \@x40, \@X41, \@O41);
+
+my @x42 = (
+ T, Q, T,
+
+ A, "**", "*>", "*F?",
+ B, "**", "*>", "*FS?",
+ C, "**", "*>S", "*FS?",
+ D, "*S*", "*>S", "*FS?",
+ E, "*S*", "*>", "*FS?",
+ F, "*S*", "*>S", "*F?",
+ G, "*S*", "*>", "*F?",
+ H, "**", "*>S", "*F?",
+
+ I, "*F*", "*>", "*F?",
+ J, "*F*", "*>", "*FS?",
+ K, "*F*", "*>S", "*FS?",
+ L, "*FS*", "*>S", "*FS?",
+ M, "*FS*", "*>", "*FS?",
+ N, "*FS*", "*>S", "*F?",
+ O, "*FS*", "*>", "*F?",
+ P, "*F*", "*>S", "*F?",
+
+ Q, "*S", "", "",
+
+ R, "*", "*", "*",
+ S, "*", "*", "*",
+ T, "*", "*", "*",
+);
+
+my @X43 = (
+ T, Q, P,
+
+ A, "", ">->", "^*",
+ A, "&", "^", "&1+T",
+ B, "", ">->", "^*",
+ B, "&", "^", "&1+T",
+ C, "", ">->S", "^*",
+ C, "&", "^", "&1+T",
+ D, "", "/", "",
+ D, "&", "^", "&1+T",
+ E, "", "/", "",
+ E, "&", "^", "&1+T",
+ F, "-S", ">->S", "^*",
+ F, "&", "^", "&1+T",
+ G, "", "/", "",
+ G, "&", "^", "&1+T",
+ H, "", ">->S", "^*",
+ H, "&", "^", "&1+T",
+
+ I, "", ">->+F", "^F*",
+ I, "&", "^", "&1+T",
+ J, "", ">->+F", "^F*",
+ J, "&", "^", "&1+T",
+ K, "", ">->S+F", "^F*",
+ K, "&", "^", "&1+T",
+ L, "", ">->+F", "^FS*",
+ L, "&", "^", "&1+T",
+ M, "", ">->+FS", "^FS*",
+ M, "&", "^", "&1+T",
+ N, "-S", ">->S+F", "^F*",
+ N, "&", "^", "&1+T",
+ O, "", ">->+FS", "^FS*",
+ O, "&", "^", "&1+T",
+ P, "", ">->S+F", "^F*",
+ P, "&", "^", "&1+T",
+);
+test("max size with upgrade + max messages", \@x42, \@X43, \@O41);
+
# Test for legacy/tampered states with inaccurate maxuid tracking
# Joined post-push & post-pull state to have just one test -
diff --git a/src/sync.c b/src/sync.c
@@ -799,7 +799,9 @@ box_opened2( sync_vars_t *svars, int t )
svars->any_expiring = 1;
if (svars->any_expiring) {
opts[N] |= OPEN_OLD | OPEN_FLAGS;
- if (chan->ops[N] & (OP_NEW | OP_RENEW))
+ if (any_dummies[N])
+ opts[F] |= OPEN_OLD | OPEN_FLAGS;
+ else if (chan->ops[N] & (OP_NEW | OP_RENEW))
opts[F] |= OPEN_FLAGS;
}
svars->opts[F] = svars->drv[F]->prepare_load_box( ctx[F], opts[F] );
@@ -1284,9 +1286,29 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
// to expire in the first place.
if (!srec->msg[N])
continue;
- nflags = (srec->msg[N]->flags | srec->aflags[N]) & ~srec->dflags[N];
+ nflags = srec->msg[N]->flags;
+ if (srec->status & S_DUMMY(N)) {
+ if (!srec->msg[F])
+ continue;
+ // We need to pull in the real Flagged and Seen even if flag
+ // propagation was not requested, as the placeholder's ones are
+ // useless (except for un-seeing).
+ // This results in the somewhat weird situation that messages
+ // which are not visibly flagged remain unexpired.
+ sflags = srec->msg[F]->flags;
+ aflags = (sflags & ~srec->flags) & (F_SEEN | F_FLAGGED);
+ dflags = (~sflags & srec->flags) & F_SEEN;
+ nflags = (nflags & (~(F_SEEN | F_FLAGGED) | (srec->flags & F_SEEN)) & ~dflags) | aflags;
+ }
+ nflags = (nflags | srec->aflags[N]) & ~srec->dflags[N];
} else {
- nflags = srec->msg[F]->flags;
+ if (srec->status & S_UPGRADE) {
+ // The dummy's F & S flags are mostly masked out anyway,
+ // but we may be pulling in the real ones.
+ nflags = (srec->pflags | srec->aflags[N]) & ~srec->dflags[N];
+ } else {
+ nflags = srec->msg[F]->flags;
+ }
}
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE | S_EXPIRED))) {
// The message is not deleted, or it is, but only due to being expired.