Skip to content

Commit

Permalink
SieveScript/test: Copy conversations into ctx so we can use it
Browse files Browse the repository at this point in the history
Without this, and jmapquerys that depend on the conversations db don't
work.

Also, we need to configure Cassandane::Cyrus::JMAPSieve to allow specific
flags to be counted so we can use SomeInThreadHaveKeyword in our tests.
  • Loading branch information
wolfsage committed Dec 20, 2024
1 parent 453bc9b commit adcd55c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 34 deletions.
1 change: 1 addition & 0 deletions cassandane/Cassandane/Cyrus/JMAPSieve.pm
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ sub new
}

$config->set(caldav_realm => 'Cassandane',
conversations_counted_flags => "\\Draft \\Flagged \$IsMailingList \$IsNotification \$HasAttachment \$muted",
conversations => 'yes',
httpmodules => 'carddav caldav jmap',
httpallowcompress => 'no',
Expand Down
115 changes: 82 additions & 33 deletions cassandane/tiny-tests/JMAPSieve/sieve-test-extensive
Original file line number Diff line number Diff line change
Expand Up @@ -80,67 +80,98 @@ add_sieve_tests(
[ ['keep', {}, [] ] ],
);

sub add_sieve_tests {
my (@tests) = @_;
sub test_sieve_test_extensive_some_in_thread_have_keyword
:min_version_3_3 :JMAPExtensions
{
my ($self) = @_;

my $leftover = @tests % 3;
# Create two messages, where the first is muted and the second is in
# the same conversation
my $mid = '<[email protected]>';

if ($leftover) {
die "We expected multiple sets of 3 test specifications, but after parsing we'd have $leftover extra items... something is wrong!\n";
}
my (undef, $email1) = $self->new_email_blob({
'keywords' => { '$muted' => JSON::true },
'header:Message-Id' => $mid,
});

my ($email2_blob_id, $email2) = $self->new_email_blob({
'header:inReplyTo' => $mid,
'header:references' => $mid,
});

$self->assert_str_equals($email1->{threadId}, $email2->{threadId});

my $sieve_blob_id = $self->new_sieve_blob(
'if jmapquery "{\"someInThreadHaveKeyword\":\"$muted\"}" {
fileinto "muted";
}',
);

$self->run_sieve_test(
$sieve_blob_id,
$email2_blob_id,
[ ['fileinto', {}, ['muted'] ] ],
);
}

sub add_sieve_tests {
my (@tests) = @_;

while (@tests) {
add_sieve_test(
my ($name, $sieve, $expect) = (
shift @tests,
shift @tests,
shift @tests,
);

if (! $expect) {
die "Expected at least 3 arguments, but didn't get it. Bad test spec?! "
. Dumper({
name => $name,
sieve => $sieve,
});
}

my $opts;

if (@tests && ref $tests[0] eq 'HASH') {
$opts = shift @tests;
}

add_sieve_test($name, $sieve, $expect, $opts);
}
}

sub add_sieve_test {
my ($name, $sieve, $expect, $variables) = @_;
my ($name, $sieve, $expect, $opts) = @_;

unless ($name =~ /^[a-zA-Z][a-zA-Z0-9_]+$/) {
die "Test name '$name' invalid. Must look like a perl subroutine name (start with a letter, a-zA-Z0-9_ only after that...\n";
}

Sub::Install::install_sub({
code => sub :min_version_3_3 :JMAPExtensions {
shift->_do_test($sieve, $expect, $variables);
shift->_do_test($sieve, $expect, $opts);
},
as => "test_sieve_test_extensive_$name",
});
}

sub _do_test {
my ($self, $sieve, $expect, $variables) = @_;
my ($self, $sieve, $expect, $opts) = @_;

my $variables = $opts->{variables};
my $email_set_params = $opts->{email_set_params};

my $sieve_blob_id = $self->new_sieve_blob($sieve);
my $email_blob_id = $self->new_email_blob;
my $email_blob_id = $self->new_email_blob($email_set_params);

my $res = $self->run_sieve_test(
$self->run_sieve_test(
$sieve_blob_id,
$email_blob_id,
$expect,
$variables,
);

eval {
$self->assert_deep_equals(
$expect,
$res->[0][1]{completed}{$email_blob_id},
);
};

if ($@) {
my $err = $@;

warn "Wanted: " . Dumper($expect);
warn "Got: " . Dumper($res->[0][1]{completed}{$email_blob_id});

# Rethrow for Test::Unit's sake
die $@;
}
}

sub new_sieve_blob {
Expand Down Expand Up @@ -181,7 +212,7 @@ EOF
}

sub new_email_blob {
my ($self) = @_;
my ($self, $email_set_params) = @_;

my $jmap = $self->{jmap};

Expand All @@ -200,7 +231,8 @@ sub new_email_blob {
to => [ { name => "Bugs Bunny", email => "bugs\@acme.local" }, ],
subject => "Memo",
textBody => [{ partId => '1' }],
bodyValues => { '1' => { value => "Whoa!" }}
bodyValues => { '1' => { value => "Whoa!" }},
( $email_set_params ? ( %$email_set_params ) : () ),
};

$res = $jmap->CallMethods([
Expand All @@ -210,11 +242,11 @@ sub new_email_blob {
my $email_blob_id = $res->[0][1]{created}{"1"}{blobId};
$self->assert_not_null($email_blob_id);

return $email_blob_id;
return wantarray ? ($email_blob_id, $res->[0][1]{created}{"1"}) : $email_blob_id;
}

sub run_sieve_test {
my ($self, $sieve_blob_id, $email_blob_id, $variables) = @_;
my ($self, $sieve_blob_id, $email_blob_id, $expect, $variables) = @_;

my $jmap = $self->{jmap};

Expand All @@ -232,5 +264,22 @@ sub run_sieve_test {
$self->assert_not_null($res->[0][1]{completed});
$self->assert_null($res->[0][1]{notCompleted});

eval {
$self->assert_deep_equals(
$expect,
$res->[0][1]{completed}{$email_blob_id},
);
};

if ($@) {
my $err = $@;

warn "Wanted: " . Dumper($expect);
warn "Got: " . Dumper($res->[0][1]{completed}{$email_blob_id});

# Rethrow for Test::Unit's sake
die $@;
}

return $res;
}
3 changes: 2 additions & 1 deletion imap/jmap_sieve.c
Original file line number Diff line number Diff line change
Expand Up @@ -2166,6 +2166,8 @@ static int jmap_sieve_test(struct jmap_req *req)
goto done;
}

interp_ctx.cstate = req->cstate;

/* create interpreter */
interp = sieve_interp_alloc(&interp_ctx);
sieve_register_header(interp, getheader);
Expand Down Expand Up @@ -2257,7 +2259,6 @@ static int jmap_sieve_test(struct jmap_req *req)
}
}

if (interp_ctx.cstate) conversations_commit(&interp_ctx.cstate);
if (interp_ctx.carddavdb) carddav_close(interp_ctx.carddavdb);

/* Build response */
Expand Down

0 comments on commit adcd55c

Please sign in to comment.