git clone of logicmail with some fixes/features added
1/*-
2 * Copyright (c) 2009, Derek Konigsberg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31package org.logicprobe.LogicMail.model;
32
33import java.util.Date;
34
35import org.logicprobe.LogicMail.mail.FakeMessageToken;
36import org.logicprobe.LogicMail.mail.FolderExpungedEvent;
37import org.logicprobe.LogicMail.mail.FolderMessagesEvent;
38import org.logicprobe.LogicMail.mail.FolderTreeItem;
39import org.logicprobe.LogicMail.mail.MessageToken;
40import org.logicprobe.LogicMail.message.FolderMessage;
41import org.logicprobe.LogicMail.message.MessageEnvelope;
42
43import j2meunit.framework.Test;
44import j2meunit.framework.TestCase;
45import j2meunit.framework.TestMethod;
46import j2meunit.framework.TestSuite;
47
48public class MailboxNodeTest extends TestCase {
49 private MailboxNode instance;
50
51 /** Creates a new instance of MailboxNodeTest */
52 public MailboxNodeTest() {
53 }
54
55 public MailboxNodeTest(String testName, TestMethod testMethod) {
56 super(testName, testMethod);
57 }
58
59 public void setUp() {
60 instance = new MailboxNode(new FolderTreeItem("INBOX", "INBOX", "."));
61 }
62
63 public void tearDown() {
64 instance = null;
65 }
66
67 public void testAddMessage() {
68 MessageNode message1 = new MessageNode(createFolderMessage(1, 1, 1));
69 MessageNode message2 = new MessageNode(createFolderMessage(2, 2, 2));
70 MessageNode message3 = new MessageNode(createFolderMessage(3, 3, 3));
71 MessageNode message4 = new MessageNode(createFolderMessage(4, 4, 4));
72
73 // Add messages in-order
74 instance.addMessage(message1);
75 instance.addMessage(message2);
76 instance.addMessage(message3);
77 instance.addMessage(message4);
78
79 MessageNode[] messageNodes = instance.getMessages();
80 assertEquals(4, messageNodes.length);
81 assertEquals(message1, messageNodes[0]);
82 assertEquals(message2, messageNodes[1]);
83 assertEquals(message3, messageNodes[2]);
84 assertEquals(message4, messageNodes[3]);
85
86 // Clear the messages
87 instance.clearMessages();
88 messageNodes = instance.getMessages();
89 assertEquals(0, messageNodes.length);
90
91 // Add messages out-of-order
92 instance.addMessage(message4);
93 instance.addMessage(message1);
94 instance.addMessage(message3);
95 instance.addMessage(message2);
96
97 messageNodes = instance.getMessages();
98 assertEquals(4, messageNodes.length);
99 assertEquals(message1, messageNodes[0]);
100 assertEquals(message2, messageNodes[1]);
101 assertEquals(message3, messageNodes[2]);
102 assertEquals(message4, messageNodes[3]);
103 }
104
105 public void testAddMessagesFromEvent() {
106 FolderMessage message1 = createFolderMessage(1, 1, 1);
107 FolderMessage message2 = createFolderMessage(2, 2, 2);
108 FolderMessage message3 = createFolderMessage(3, 3, 3);
109 FolderMessage message4 = createFolderMessage(4, 4, 4);
110
111 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
112 this, instance.getFolderTreeItem(), new FolderMessage[] {
113 message1, message2, message3, message4
114 }));
115
116 MessageNode[] messageNodes = instance.getMessages();
117 assertEquals(4, messageNodes.length);
118 assertEquals(message1.getMessageToken(), messageNodes[0].getMessageToken());
119 assertEquals(message2.getMessageToken(), messageNodes[1].getMessageToken());
120 assertEquals(message3.getMessageToken(), messageNodes[2].getMessageToken());
121 assertEquals(message4.getMessageToken(), messageNodes[3].getMessageToken());
122 }
123
124 public void testHasMoreLoadableMessages() {
125 assertTrue("Empty mailbox", instance.hasMoreLoadableMessages());
126
127 // Initial set of messages, assuming no more loadable
128 FolderMessage message1 = createFolderMessage(1, 1, 1);
129 FolderMessage message2 = createFolderMessage(2, 2, 2);
130 FolderMessage message3 = createFolderMessage(3, 3, 3);
131 FolderMessage message4 = createFolderMessage(4, 4, 4);
132
133 // Need to add from event, since this is the only place where the
134 // mailbox is able to directly read FolderMessage properties
135 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
136 this, instance.getFolderTreeItem(), new FolderMessage[] {
137 message1, message2, message3, message4
138 }));
139
140 assertTrue("No more loadable", !instance.hasMoreLoadableMessages());
141
142 // Fake an event to remove the first message
143 instance.mailStoreFolderExpunged(new FolderExpungedEvent(
144 this, instance.getFolderTreeItem(),
145 new MessageToken[] { new FakeMessageToken(1) },
146 new MessageToken[0]));
147
148 assertTrue("Removed and has more loadable", instance.hasMoreLoadableMessages());
149
150 instance.clearMessages();
151
152 // Set of messages, assuming more are loadable
153 message1 = createFolderMessage(1, 11, 1);
154 message2 = createFolderMessage(2, 12, 2);
155 message3 = createFolderMessage(3, 13, 3);
156 message4 = createFolderMessage(4, 14, 4);
157
158 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
159 this, instance.getFolderTreeItem(), new FolderMessage[] {
160 message1, message2, message3, message4
161 }));
162
163 assertTrue("Has more loadable", instance.hasMoreLoadableMessages());
164 }
165
166 public void testFindMessageNodeGaps() {
167 // Empty mailbox test
168 MessageNode[][] result = instance.findMessageNodeGaps();
169 String msg = "Empty mailbox";
170 assertNotNull(msg, result);
171 assertEquals(msg, 0, result.length);
172
173 // Initial set of messages, assuming no more loadable
174 FolderMessage message1 = createFolderMessage(1, 1, 1);
175 FolderMessage message2 = createFolderMessage(2, 2, 2);
176 FolderMessage message3 = createFolderMessage(3, 3, 3);
177 FolderMessage message4 = createFolderMessage(4, 4, 4);
178
179 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
180 this, instance.getFolderTreeItem(), new FolderMessage[] {
181 message1, message2, message3, message4
182 }));
183
184 result = instance.findMessageNodeGaps();
185 msg = "No gaps";
186 assertNotNull(msg, result);
187 assertEquals(msg, 0, result.length);
188
189 instance.clearMessages();
190
191 message1 = createFolderMessage(1, 11, 1);
192 message2 = createFolderMessage(2, 12, 2);
193 message3 = createFolderMessage(3, 13, 3);
194 message4 = createFolderMessage(4, 14, 4);
195
196 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
197 this, instance.getFolderTreeItem(), new FolderMessage[] {
198 message1, message2, message3, message4
199 }));
200
201 result = instance.findMessageNodeGaps();
202 msg = "Gap at start";
203 assertNotNull(msg, result);
204 assertEquals(msg, 1, result.length);
205 MessageNode[] gap = result[0];
206 assertNotNull(msg, gap);
207 assertEquals(msg, 2, gap.length);
208 assertNull(msg, gap[0]);
209 assertEquals(msg, new FakeMessageToken(1), gap[1].getMessageToken());
210
211 instance.clearMessages();
212
213 message1 = createFolderMessage(1, 1, 1);
214 message2 = createFolderMessage(2, 2, 2);
215 message3 = createFolderMessage(3, 5, 3);
216 message4 = createFolderMessage(4, 6, 4);
217
218 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
219 this, instance.getFolderTreeItem(), new FolderMessage[] {
220 message1, message2, message3, message4
221 }));
222
223 result = instance.findMessageNodeGaps();
224 msg = "Gap in middle";
225 assertNotNull(msg, result);
226 assertEquals(msg, 1, result.length);
227 gap = result[0];
228 assertNotNull(msg, gap);
229 assertEquals(msg, 2, gap.length);
230 assertEquals(msg, new FakeMessageToken(2), gap[0].getMessageToken());
231 assertEquals(msg, new FakeMessageToken(3), gap[1].getMessageToken());
232 }
233
234 public void testFindMessageNodeGapsMultiple() {
235 // Two gaps in the middle
236 FolderMessage message1 = createFolderMessage(10, 1, 1);
237 FolderMessage message2 = createFolderMessage(20, 5, 2);
238 FolderMessage message3 = createFolderMessage(30, 6, 3);
239 FolderMessage message4 = createFolderMessage(40, 10, 4);
240
241 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
242 this, instance.getFolderTreeItem(), new FolderMessage[] {
243 message1, message2, message3, message4
244 }));
245
246 MessageNode[][] result = instance.findMessageNodeGaps();
247 String msg = "Gaps between 10-20 and 30-40";
248 assertNotNull(msg, result);
249 assertEquals(msg, 2, result.length);
250 boolean found1 = false;
251 boolean found2 = false;
252 for(int i=0; i<result.length; i++) {
253 MessageNode[] gap = result[i];
254 assertNotNull(msg, gap);
255 assertNotNull(msg, gap[0]);
256 assertNotNull(msg, gap[1]);
257 if(gap[0].getMessageToken().getUniqueId() == 10
258 && gap[1].getMessageToken().getUniqueId() == 20) {
259 found1 = true;
260 }
261 else if(gap[0].getMessageToken().getUniqueId() == 30
262 && gap[1].getMessageToken().getUniqueId() == 40) {
263 found2 = true;
264 }
265 }
266 assertTrue(msg, found1 && found2);
267 }
268
269 public void testFolderExpunged() {
270 // Create our initial set of messages
271 FolderMessage message1 = createFolderMessage(1, 1, 1);
272 FolderMessage message2 = createFolderMessage(2, 2, 2);
273 FolderMessage message3 = createFolderMessage(3, 3, 3);
274 FolderMessage message4 = createFolderMessage(4, 4, 4);
275
276 // These tests all verify correct expunge handling, which includes
277 // the removal of messages without gap creation.
278
279 String msg = "Two at the end";
280 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
281 this, instance.getFolderTreeItem(), new FolderMessage[] {
282 message1, message2, message3, message4
283 }));
284
285 instance.mailStoreFolderExpunged(new FolderExpungedEvent(
286 this, instance.getFolderTreeItem(),
287 new MessageToken[] {
288 message3.getMessageToken(), message4.getMessageToken()
289 },
290 new MessageToken[0]));
291
292 MessageNode[] messageNodes = instance.getMessages();
293 assertEquals(msg, 2, messageNodes.length);
294 assertEquals(msg, message1.getMessageToken(), messageNodes[0].getMessageToken());
295 assertEquals(msg, message2.getMessageToken(), messageNodes[1].getMessageToken());
296 MessageNode[][] messageGaps = instance.findMessageNodeGaps();
297 assertEquals(msg, 0, messageGaps.length);
298 instance.clearMessages();
299
300 msg = "Two at the beginning";
301 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
302 this, instance.getFolderTreeItem(), new FolderMessage[] {
303 message1, message2, message3, message4
304 }));
305
306 MessageToken updatedToken3 = message3.getMessageToken().clone();
307 updatedToken3.updateMessageIndex(1);
308 MessageToken updatedToken4 = message4.getMessageToken().clone();
309 updatedToken4.updateMessageIndex(2);
310
311 instance.mailStoreFolderExpunged(new FolderExpungedEvent(
312 this, instance.getFolderTreeItem(),
313 new MessageToken[] {
314 message1.getMessageToken(), message2.getMessageToken()
315 },
316 new MessageToken[] { updatedToken3, updatedToken4 }));
317
318 messageNodes = instance.getMessages();
319 assertEquals(msg, 2, messageNodes.length);
320 assertEquals(msg, message3.getMessageToken(), messageNodes[0].getMessageToken());
321 assertEquals(msg, message4.getMessageToken(), messageNodes[1].getMessageToken());
322 messageGaps = instance.findMessageNodeGaps();
323 assertEquals(msg, 0, messageGaps.length);
324 instance.clearMessages();
325
326 msg = "One in the middle";
327 instance.mailStoreFolderMessagesAvailable(new FolderMessagesEvent(
328 this, instance.getFolderTreeItem(), new FolderMessage[] {
329 message1, message2, message3, message4
330 }));
331
332 updatedToken4 = message4.getMessageToken().clone();
333 updatedToken4.updateMessageIndex(3);
334
335 instance.mailStoreFolderExpunged(new FolderExpungedEvent(
336 this, instance.getFolderTreeItem(),
337 new MessageToken[] {
338 message3.getMessageToken()
339 },
340 new MessageToken[] { updatedToken4 }));
341
342 messageNodes = instance.getMessages();
343 assertEquals(msg, 3, messageNodes.length);
344 assertEquals(msg, message1.getMessageToken(), messageNodes[0].getMessageToken());
345 assertEquals(msg, message2.getMessageToken(), messageNodes[1].getMessageToken());
346 assertEquals(msg, message4.getMessageToken(), messageNodes[2].getMessageToken());
347
348 messageGaps = instance.findMessageNodeGaps();
349 assertEquals(msg, 0, messageGaps.length);
350 }
351
352 private static FolderMessage createFolderMessage(int uid, int index, int sortOrder) {
353 MessageEnvelope envelope = new MessageEnvelope();
354 envelope.subject = "Test " + uid;
355 envelope.date = new Date(1286920000 + sortOrder);
356 FakeMessageToken token = new FakeMessageToken(uid);
357 token.updateMessageIndex(index);
358 FolderMessage message = new FolderMessage(token, envelope, index, uid, -1);
359 return message;
360 }
361
362 public Test suite() {
363 TestSuite suite = new TestSuite("MailboxNode");
364
365 suite.addTest(new MailboxNodeTest("addMessage", new TestMethod()
366 { public void run(TestCase tc) {((MailboxNodeTest)tc).testAddMessage(); } }));
367 suite.addTest(new MailboxNodeTest("addMessagesFromEvent", new TestMethod()
368 { public void run(TestCase tc) {((MailboxNodeTest)tc).testAddMessagesFromEvent(); } }));
369 suite.addTest(new MailboxNodeTest("hasMoreLoadableMessages", new TestMethod()
370 { public void run(TestCase tc) {((MailboxNodeTest)tc).testHasMoreLoadableMessages(); } }));
371 suite.addTest(new MailboxNodeTest("findMessageNodeGaps", new TestMethod()
372 { public void run(TestCase tc) {((MailboxNodeTest)tc).testFindMessageNodeGaps(); } }));
373 suite.addTest(new MailboxNodeTest("findMessageNodeGapsMultiple", new TestMethod()
374 { public void run(TestCase tc) {((MailboxNodeTest)tc).testFindMessageNodeGapsMultiple(); } }));
375 suite.addTest(new MailboxNodeTest("folderExpunged", new TestMethod()
376 { public void run(TestCase tc) {((MailboxNodeTest)tc).testFolderExpunged(); } }));
377
378 return suite;
379 }
380}