summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/db/gloda/test/unit/base_index_junk.js
blob: 8529f24a566a710d164c0b3e3e34eb57dc98960a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * Test indexing in the face of junk classification and junk folders.  It is
 *  gloda policy not to index junk mail.
 *
 * A similar test that moving things to the trash folder is deletion happens in
 *  base_index_messages.js.
 */

var { MailServices } = ChromeUtils.import(
  "resource:///modules/MailServices.jsm"
);
var { Gloda } = ChromeUtils.import("resource:///modules/gloda/GlodaPublic.jsm");
var { GlodaConstants } = ChromeUtils.import(
  "resource:///modules/gloda/GlodaConstants.jsm"
);
var { GlodaMsgIndexer } = ChromeUtils.import(
  "resource:///modules/gloda/IndexMsg.jsm"
);
var { queryExpect } = ChromeUtils.import(
  "resource://testing-common/gloda/GlodaQueryHelper.jsm"
);
var { assertExpectedMessagesIndexed, waitForGlodaIndexer } = ChromeUtils.import(
  "resource://testing-common/gloda/GlodaTestHelper.jsm"
);
var { MessageInjection } = ChromeUtils.import(
  "resource://testing-common/mailnews/MessageInjection.jsm"
);

var messageInjection;

const SPAM_BODY = { body: "superspam superspam superspam eevil eevil eevil" };
const HAM_BODY = { body: "ham ham ham nice nice nice happy happy happy" };

/**
 * Make SPAM_BODY be known as spammy and HAM_BODY be known as hammy.
 */
async function setup_spam_filter() {
  let [, spamSet, hamSet] = await messageInjection.makeFoldersWithSets(1, [
    { count: 1, body: SPAM_BODY },
    { count: 1, body: HAM_BODY },
  ]);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([spamSet, hamSet], []));
  let promiseResolve;
  let promise = new Promise(resolve => {
    promiseResolve = resolve;
  });
  let junkListener = {
    onMessageClassified() {
      promiseResolve();
    },
  };

  // Ham.
  dump(`Marking message: ${hamSet.getMsgHdr(0)} as ham.`);
  MailServices.junk.setMessageClassification(
    hamSet.getMsgURI(0),
    null, // no old classification
    MailServices.junk.GOOD,
    null,
    junkListener
  );
  await promise;

  // Reset promise for junkListener.
  promise = new Promise(resolve => {
    promiseResolve = resolve;
  });

  // Spam.
  dump(`Marking message: ${spamSet.getMsgHdr(0)} as spam.`);
  MailServices.junk.setMessageClassification(
    spamSet.getMsgURI(0),
    null, // No old classification.
    MailServices.junk.JUNK,
    null,
    junkListener
  );
  await promise;
}

/**
 * Because gloda defers indexing until after junk, we should never index a
 *  message that gets marked as junk.  So if we inject a message that will
 *  definitely be marked as junk (thanks to use of terms that guarantee it),
 *  the indexer should never index it.
 *
 * ONLY THIS TEST ACTUALLY RELIES ON THE BAYESIAN CLASSIFIER.
 */
async function test_never_indexes_a_message_marked_as_junk() {
  // Event-driven does not index junk.

  // Make a message that will be marked as junk from the get-go.
  await messageInjection.makeFoldersWithSets(1, [
    { count: 1, body: SPAM_BODY },
  ]);
  // Since the message is junk, gloda should not index it!
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([]));

  // Folder sweep does not index junk.
  GlodaMsgIndexer.indexingSweepNeeded = true;
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([]));
}

/**
 * Reset the training data so the bayesian classifier stops doing things.
 */
function reset_spam_filter() {
  MailServices.junk.resetTrainingData();
}

/**
 * Marking a message as junk is equivalent to deleting the message, un-mark it
 *  and it should go back to being a happy message (with the same gloda-id!).
 *
 * THIS TEST DOES NOT RELY ON THE BAYESIAN CLASSIFIER.
 */

async function test_mark_as_junk_is_deletion_mark_as_not_junk_is_exposure() {
  // Mark as junk is deletion.
  // Create a message; it should get indexed.
  let [, msgSet] = await messageInjection.makeFoldersWithSets(1, [
    { count: 1 },
  ]);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([msgSet], { augment: true }));
  let glodaId = msgSet.glodaMessages[0].id;
  // Mark it as junk.
  msgSet.setJunk(true);
  // It will appear deleted after the event.
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([], { deleted: [msgSet] }));
  // Mark as non-junk gets indexed.
  msgSet.setJunk(false);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([msgSet], { augment: true }));
  // We should have reused the existing gloda message so it should keep the id.
  Assert.equal(glodaId, msgSet.glodaMessages[0].id);
}

/**
 * Moving a message to the junk folder is equivalent to deletion.  Gloda does
 *  not index junk folders at all, which is why this is an important and
 *  independent determination from marking a message directly as junk.
 *
 * The move to the junk folder is performed without using any explicit junk
 *  support code.  This ends up being effectively the same underlying logic test
 *  as base_index_messages' test of moving a message to the trash folder.
 */
async function test_message_moving_to_junk_folder_is_deletion() {
  // Create and index two messages in a conversation.
  let [, msgSet] = await messageInjection.makeFoldersWithSets(1, [
    { count: 2, msgsPerThread: 2 },
  ]);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([msgSet], { augment: true }));

  let convId = msgSet.glodaMessages[0].conversation.id;
  let firstGlodaId = msgSet.glodaMessages[0].id;
  let secondGlodaId = msgSet.glodaMessages[1].id;

  // Move them to the junk folder.
  await messageInjection.moveMessages(
    msgSet,
    await messageInjection.getJunkFolder()
  );

  // They will appear deleted after the events.
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([], { deleted: [msgSet] }));

  // We do not index the junk folder so this should actually make them appear
  //  deleted to an unprivileged query.
  let msgQuery = Gloda.newQuery(GlodaConstants.NOUN_MESSAGE);
  msgQuery.id(firstGlodaId, secondGlodaId);
  await queryExpect(msgQuery, []);

  // Force a sweep.
  GlodaMsgIndexer.indexingSweepNeeded = true;
  // There should be no apparent change as the result of this pass.
  // (Well, the conversation will die, but we can't see that.)
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([]));

  // The conversation should be gone.
  let convQuery = Gloda.newQuery(GlodaConstants.NOUN_CONVERSATION);
  convQuery.id(convId);
  await queryExpect(convQuery, []);

  // The messages should be entirely gone.
  let msgPrivQuery = Gloda.newQuery(GlodaConstants.NOUN_MESSAGE, {
    noDbQueryValidityConstraints: true,
  });
  msgPrivQuery.id(firstGlodaId, secondGlodaId);
  await queryExpect(msgPrivQuery, []);
}

function test_sanity_test_environment() {
  Assert.ok(messageInjection, "Sanity that messageInjection is set.");
  Assert.ok(messageInjection.messageGenerator, "Sanity that msgGen is set.");
}

/* exported tests */
var base_index_junk_tests = [
  test_sanity_test_environment,
  setup_spam_filter,
  test_never_indexes_a_message_marked_as_junk,
  reset_spam_filter,
  test_mark_as_junk_is_deletion_mark_as_not_junk_is_exposure,
  test_message_moving_to_junk_folder_is_deletion,
];