summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/db/gloda/test/unit/test_index_messages_local.js
blob: 5441a3062c8a64a01f9cbd24a41a01dd71e240a7 (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
/* 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 support for local messages.
 */

var {
  glodaTestHelperInitialize,
  assertExpectedMessagesIndexed,
  waitForGlodaIndexer,
  messageInjection,
  nukeGlodaCachesAndCollections,
} = ChromeUtils.import("resource://testing-common/gloda/GlodaTestHelper.jsm");
var { waitForGlodaDBFlush } = ChromeUtils.import(
  "resource://testing-common/gloda/GlodaTestHelperFunctions.jsm"
);
var { MessageGenerator, MessageScenarioFactory } = ChromeUtils.import(
  "resource://testing-common/mailnews/MessageGenerator.jsm"
);
var { MessageInjection } = ChromeUtils.import(
  "resource://testing-common/mailnews/MessageInjection.jsm"
);

/* import-globals-from base_index_messages.js */
load("base_index_messages.js");

add_setup(async function () {
  msgGen = new MessageGenerator();
  scenarios = new MessageScenarioFactory(msgGen);
  messageInjection = new MessageInjection({ mode: "local" }, msgGen);
  glodaTestHelperInitialize(messageInjection);
});

/**
 * Make sure that if we have to reparse a local folder we do not hang or
 *  anything.  (We had a regression where we would hang.)
 */
add_task(async function test_reparse_of_local_folder_works() {
  // Index a folder.
  let [[folder], msgSet] = await messageInjection.makeFoldersWithSets(1, [
    { count: 1 },
  ]);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([msgSet]));

  // Force a db flush so we do not have any outstanding references to the
  //  folder or its headers.
  await waitForGlodaDBFlush();

  // Mark the summary invalid.
  folder.msgDatabase.summaryValid = false;
  // Clear the database so next time we have to reparse.
  folder.msgDatabase.forceClosed();

  // Force gloda to re-parse the folder again.
  GlodaMsgIndexer.indexFolder(folder);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([]));
});

/**
 * Ensure that fromJSON for a non-singular attribute properly filters out
 *  "undefined" return values, specifically as it relates to tags.  When the
 *  user removes them Gloda doesn't actually re-index the messages so the
 *  values will still be there when we next load the message.
 *
 * We directly monkey with the state of NounTag for no really good reason, but
 *  maybe it cuts down on disk I/O because we don't have to touch prefs.
 */
add_task(async function test_fromjson_of_removed_tag() {
  // -- Inject
  let [, msgSet] = await messageInjection.makeFoldersWithSets(1, [
    { count: 1 },
  ]);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([msgSet], { augment: true }));
  let gmsg = msgSet.glodaMessages[0];

  // -- Tag
  let tag = TagNoun.getTag("$label4");
  msgSet.addTag(tag.key);
  await waitForGlodaIndexer();
  Assert.ok(...assertExpectedMessagesIndexed([msgSet]));
  Assert.equal(gmsg.tags.length, 1);
  Assert.equal(gmsg.tags[0].key, tag.key);

  // -- Forget about the tag, TagNoun!
  delete TagNoun._tagMap[tag.key];
  // This also means we have to replace the tag service with a liar.
  let realTagService = TagNoun._msgTagService;
  TagNoun._msgTagService = {
    isValidKey() {
      return false;
    }, // Lies!
  };

  // -- Forget about the message, gloda!
  let glodaId = gmsg.id;
  nukeGlodaCachesAndCollections();

  // -- Re-load the message.
  let query = Gloda.newQuery(GlodaConstants.NOUN_MESSAGE);
  query.id(glodaId);
  let coll = await queryExpect(query, msgSet);

  // -- Put the tag back in TagNoun before we check and possibly explode.
  TagNoun._tagMap[tag.key] = tag;
  TagNoun._msgTagService = realTagService;

  // -- Verify the message apparently has no tags (despite no reindex).
  gmsg = coll.items[0];
  Assert.equal(gmsg.tags.length, 0);
});

/**
 * Test that we are using hasOwnProperty or a properly guarding dict for
 *  NounTag so that if someone created a tag called "watch" and then deleted
 *  it, we don't end up exposing the watch function as the tag.
 *
 * Strictly speaking, this does not really belong here, but it's a matched set
 *  with the previous test.
 */
add_task(
  function test_nountag_does_not_think_it_has_watch_tag_when_it_does_not() {
    Assert.equal(TagNoun.fromJSON("watch"), undefined);
  }
);

base_index_messages_tests.forEach(e => {
  add_task(e);
});