1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.mail.internal.thread

File PrepareMailRunnableTest.java

 

Code metrics

2
102
9
1
290
208
10
0.1
11.33
9
1.11

Classes

Class Line # Actions
PrepareMailRunnableTest 70 102 0% 10 1
0.9911504499.1%
 

Contributing tests

This file is covered by 2 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.mail.internal.thread;
21   
22    import java.util.Arrays;
23    import java.util.Iterator;
24    import java.util.Properties;
25    import java.util.UUID;
26   
27    import javax.inject.Provider;
28    import javax.mail.Session;
29    import javax.mail.internet.MimeMessage;
30   
31    import org.junit.Before;
32    import org.junit.Rule;
33    import org.junit.Test;
34    import org.mockito.Mockito;
35    import org.mockito.invocation.InvocationOnMock;
36    import org.mockito.stubbing.Answer;
37    import org.xwiki.component.util.DefaultParameterizedType;
38    import org.xwiki.context.ExecutionContext;
39    import org.xwiki.mail.ExtendedMimeMessage;
40    import org.xwiki.mail.MailContentStore;
41    import org.xwiki.mail.MailListener;
42    import org.xwiki.mail.MailState;
43    import org.xwiki.mail.MailStatus;
44    import org.xwiki.mail.MailStatusResult;
45    import org.xwiki.mail.MailStoreException;
46    import org.xwiki.mail.internal.MemoryMailListener;
47    import org.xwiki.mail.internal.UpdateableMailStatusResult;
48    import org.xwiki.test.AllLogRule;
49    import org.xwiki.test.annotation.ComponentList;
50    import org.xwiki.test.mockito.MockitoComponentMockingRule;
51   
52    import com.xpn.xwiki.XWikiContext;
53   
54    import static org.junit.Assert.assertEquals;
55    import static org.junit.Assert.assertFalse;
56    import static org.junit.Assert.assertNotNull;
57    import static org.junit.Assert.assertTrue;
58    import static org.mockito.ArgumentMatchers.any;
59    import static org.mockito.Mockito.doAnswer;
60    import static org.mockito.Mockito.doThrow;
61    import static org.mockito.Mockito.when;
62   
63    /**
64    * Unit tests for {@link org.xwiki.mail.internal.thread.PrepareMailRunnable}.
65    *
66    * @version $Id: 1a5167ee5ada7327ae1a09243ae207cf5a7162f1 $
67    * @since 6.4
68    */
69    @ComponentList({MemoryMailListener.class, PrepareMailQueueManager.class})
 
70    public class PrepareMailRunnableTest
71    {
72    @Rule
73    public AllLogRule logRule = new AllLogRule();
74   
75    @Rule
76    public MockitoComponentMockingRule<PrepareMailRunnable> mocker = new MockitoComponentMockingRule<>(
77    PrepareMailRunnable.class);
78   
 
79  2 toggle @Before
80    public void setUp() throws Exception
81    {
82  2 Provider<XWikiContext> xwikiContextProvider = this.mocker.registerMockComponent(XWikiContext.TYPE_PROVIDER);
83  2 when(xwikiContextProvider.get()).thenReturn(Mockito.mock(XWikiContext.class));
84    }
85   
 
86  1 toggle @Test
87    public void prepareMailWhenContentStoreFails() throws Exception
88    {
89  1 Properties properties = new Properties();
90  1 Session session = Session.getDefaultInstance(properties);
91   
92  1 MimeMessage message1 = new MimeMessage(session);
93  1 message1.setText("Content1");
94   
95  1 MimeMessage message2 = new MimeMessage(session);
96  1 message2.setText("Content2");
97   
98  1 String batchId1 = UUID.randomUUID().toString();
99  1 String batchId2 = UUID.randomUUID().toString();
100   
101  1 ExecutionContext context1 = new ExecutionContext();
102  1 XWikiContext xContext1 = new XWikiContext();
103  1 xContext1.setWikiId("wiki1");
104  1 context1.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, xContext1);
105   
106  1 ExecutionContext context2 = new ExecutionContext();
107  1 XWikiContext xContext2 = new XWikiContext();
108  1 xContext2.setWikiId("wiki2");
109  1 context2.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, xContext2);
110   
111  1 MemoryMailListener listener1 = this.mocker.getInstance(MailListener.class, "memory");
112  1 PrepareMailQueueItem item1 =
113    new PrepareMailQueueItem(Arrays.asList(message1), session, listener1, batchId1, context1);
114  1 MemoryMailListener listener2 = this.mocker.getInstance(MailListener.class, "memory");
115  1 PrepareMailQueueItem item2 =
116    new PrepareMailQueueItem(Arrays.asList(message2), session, listener2, batchId2, context2);
117   
118  1 MailQueueManager mailQueueManager =
119    this.mocker.getInstance(new DefaultParameterizedType(null, MailQueueManager.class,
120    PrepareMailQueueItem.class));
121   
122    // Make the content store save fail
123  1 MailContentStore contentStore = this.mocker.getInstance(MailContentStore.class, "filesystem");
124  1 doThrow(new MailStoreException("error")).when(contentStore).save(any(String.class), any(ExtendedMimeMessage.class));
125   
126    // Prepare 2 mails. Both will fail but we want to verify that the second one is processed even though the first
127    // one failed.
128  1 mailQueueManager.addToQueue(item1);
129  1 mailQueueManager.addToQueue(item2);
130   
131  1 MailRunnable runnable = this.mocker.getComponentUnderTest();
132  1 Thread thread = new Thread(runnable);
133  1 thread.start();
134   
135    // Wait for the mails to have been processed.
136  1 try {
137  1 listener1.getMailStatusResult().waitTillProcessed(10000L);
138  1 listener2.getMailStatusResult().waitTillProcessed(10000L);
139    } finally {
140  1 runnable.stopProcessing();
141  1 thread.interrupt();
142  1 thread.join();
143    }
144   
145  1 MailStatusResult result1 = listener1.getMailStatusResult();
146  1 MailStatusResult result2 = listener2.getMailStatusResult();
147   
148    // Despite the errors, both process should be ended with known total number of mails
149  1 assertTrue(result1.isProcessed());
150  1 assertTrue(result2.isProcessed());
151   
152    // This is the real test: we verify that there's been an error while sending each email.
153  1 MailStatus status1 = result1.getByState(MailState.PREPARE_ERROR).next();
154  1 assertEquals("MailStoreException: error", status1.getErrorSummary());
155  1 MailStatus status2 = result2.getByState(MailState.PREPARE_ERROR).next();
156  1 assertEquals("MailStoreException: error", status2.getErrorSummary());
157    }
158   
 
159  1 toggle @Test
160    public void prepareMailWhenIteratorFails() throws Exception
161    {
162  1 Properties properties = new Properties();
163  1 Session session = Session.getDefaultInstance(properties);
164   
165  1 final MimeMessage message1 = new MimeMessage(session);
166  1 message1.setText("Content1");
167   
168  1 MimeMessage message2 = new MimeMessage(session);
169  1 message2.setText("Content2");
170   
171  1 String batchId1 = UUID.randomUUID().toString();
172  1 String batchId2 = UUID.randomUUID().toString();
173   
174  1 ExecutionContext context1 = new ExecutionContext();
175  1 XWikiContext xContext1 = new XWikiContext();
176  1 xContext1.setWikiId("wiki1");
177  1 context1.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, xContext1);
178   
179  1 ExecutionContext context2 = new ExecutionContext();
180  1 XWikiContext xContext2 = new XWikiContext();
181  1 xContext2.setWikiId("wiki2");
182  1 context2.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, xContext2);
183   
184  1 MemoryMailListener listener1 = this.mocker.getInstance(MailListener.class, "memory");
185  1 PrepareMailQueueItem item1 =
186    new PrepareMailQueueItem(new Iterable<MimeMessage>()
187    {
 
188  1 toggle @Override
189    public Iterator<MimeMessage> iterator()
190    {
191  1 return new Iterator<MimeMessage>()
192    {
193    int index = 0;
194   
 
195  2 toggle @Override
196    public boolean hasNext()
197    {
198  2 return true;
199    }
200   
 
201  2 toggle @Override
202    public MimeMessage next()
203    {
204  2 if (index++ == 0) {
205  1 return message1;
206    }
207  1 throw new RuntimeException("Iterator failure");
208    }
209   
 
210  0 toggle @Override
211    public void remove()
212    {
213   
214    }
215    };
216    }
217    }, session, listener1, batchId1, context1);
218  1 MemoryMailListener listener2 = this.mocker.getInstance(MailListener.class, "memory");
219  1 PrepareMailQueueItem item2 =
220    new PrepareMailQueueItem(Arrays.asList(message2), session, listener2, batchId2, context2);
221   
222  1 MailQueueManager prepareMailQueueManager =
223    this.mocker.getInstance(new DefaultParameterizedType(null, MailQueueManager.class,
224    PrepareMailQueueItem.class));
225   
226  1 MailQueueManager sendMailQueueManager =
227    this.mocker.getInstance(new DefaultParameterizedType(null, MailQueueManager.class,
228    SendMailQueueItem.class));
229   
230  1 MailContentStore contentStore = this.mocker.getInstance(MailContentStore.class, "filesystem");
231  1 doAnswer(new Answer<Object>()
232    {
 
233  2 toggle @Override
234    public Object answer(InvocationOnMock invocationOnMock) throws Throwable
235    {
236  2 Object[] args = invocationOnMock.getArguments();
237  2 MimeMessage message = (MimeMessage) args[1];
238  2 message.saveChanges();
239  2 return null;
240    }
241    }).when(contentStore).save(any(String.class), any(ExtendedMimeMessage.class));
242   
243  1 doAnswer(new Answer<Object>()
244    {
 
245  2 toggle @Override
246    public Object answer(InvocationOnMock invocationOnMock) throws Throwable
247    {
248  2 Object[] args = invocationOnMock.getArguments();
249  2 SendMailQueueItem item = (SendMailQueueItem) args[0];
250  2 ((UpdateableMailStatusResult)item.getListener().getMailStatusResult()).incrementCurrentSize();
251  2 return null;
252    }
253    }).when(sendMailQueueManager).addToQueue(any(SendMailQueueItem.class));
254   
255   
256    // Prepare 2 mails. Both will fail but we want to verify that the second one is processed even though the first
257    // one failed.
258  1 prepareMailQueueManager.addToQueue(item1);
259  1 prepareMailQueueManager.addToQueue(item2);
260   
261  1 MailRunnable runnable = this.mocker.getComponentUnderTest();
262  1 Thread thread = new Thread(runnable);
263  1 thread.start();
264   
265    // Wait for the mails to have been processed.
266  1 try {
267  1 listener1.getMailStatusResult().waitTillProcessed(10000L);
268  1 listener2.getMailStatusResult().waitTillProcessed(10000L);
269    } finally {
270  1 runnable.stopProcessing();
271  1 thread.interrupt();
272  1 thread.join();
273    }
274   
275  1 MailStatusResult result1 = listener1.getMailStatusResult();
276  1 MailStatusResult result2 = listener2.getMailStatusResult();
277   
278    // Despite the errors, both process should be ended with known total number of mails
279  1 assertTrue(result1.isProcessed());
280  1 assertTrue(result2.isProcessed());
281   
282    // This is the real test: we verify that there's been an error while sending each email.
283  1 assertNotNull(listener1.getMailStatusResult().getByState(MailState.PREPARE_SUCCESS).next());
284  1 assertNotNull(listener2.getMailStatusResult().getByState(MailState.PREPARE_SUCCESS).next());
285  1 assertFalse(listener1.getMailStatusResult().getByState(MailState.PREPARE_ERROR).hasNext());
286  1 assertFalse(listener2.getMailStatusResult().getByState(MailState.PREPARE_ERROR).hasNext());
287   
288  1 assertEquals("Failure during preparation phase of thread [" + batchId1 + "]", logRule.getMessage(0));
289    }
290    }