1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.notifications.sources.internal

File QueryGeneratorTest.java

 

Code metrics

0
138
10
1
428
320
10
0.07
13.8
10
1

Classes

Class Line # Actions
QueryGeneratorTest 71 138 0% 10 0
1.0100%
 

Contributing tests

This file is covered by 9 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.notifications.sources.internal;
21   
22    import java.util.Arrays;
23    import java.util.Collection;
24    import java.util.Collections;
25    import java.util.Date;
26   
27    import org.junit.Before;
28    import org.junit.Rule;
29    import org.junit.Test;
30    import org.xwiki.bridge.DocumentAccessBridge;
31    import org.xwiki.model.internal.reference.DefaultStringEntityReferenceSerializer;
32    import org.xwiki.model.internal.reference.DefaultSymbolScheme;
33    import org.xwiki.model.reference.DocumentReference;
34    import org.xwiki.model.reference.EntityReferenceSerializer;
35    import org.xwiki.notifications.NotificationFormat;
36    import org.xwiki.notifications.filters.NotificationFilter;
37    import org.xwiki.notifications.filters.NotificationFilterManager;
38    import org.xwiki.notifications.filters.NotificationFilterPreference;
39    import org.xwiki.notifications.filters.expression.EmptyNode;
40    import org.xwiki.notifications.filters.expression.EventProperty;
41    import org.xwiki.notifications.filters.expression.ExpressionNode;
42    import org.xwiki.notifications.preferences.NotificationPreference;
43    import org.xwiki.notifications.preferences.NotificationPreferenceProperty;
44    import org.xwiki.notifications.sources.NotificationParameters;
45    import org.xwiki.query.Query;
46    import org.xwiki.query.QueryManager;
47    import org.xwiki.test.annotation.ComponentList;
48    import org.xwiki.test.mockito.MockitoComponentMockingRule;
49    import org.xwiki.wiki.descriptor.WikiDescriptorManager;
50   
51    import org.apache.commons.codec.digest.DigestUtils;
52   
53    import static org.junit.Assert.assertEquals;
54    import static org.mockito.ArgumentMatchers.any;
55    import static org.mockito.ArgumentMatchers.anyCollection;
56    import static org.mockito.ArgumentMatchers.anyString;
57    import static org.mockito.ArgumentMatchers.eq;
58    import static org.mockito.Mockito.mock;
59    import static org.mockito.Mockito.verify;
60    import static org.mockito.Mockito.when;
61    import static org.xwiki.notifications.filters.expression.generics.ExpressionBuilder.value;
62   
63    /**
64    * @version $Id: 1a82a5a8ae0cc3ea07d57abba43bbb44a8cfa2b4 $
65    */
66    @ComponentList({
67    ExpressionNodeToHQLConverter.class,
68    DefaultStringEntityReferenceSerializer.class,
69    DefaultSymbolScheme.class
70    })
 
71    public class QueryGeneratorTest
72    {
73    @Rule
74    public final MockitoComponentMockingRule<QueryGenerator> mocker =
75    new MockitoComponentMockingRule<>(QueryGenerator.class);
76   
77    private QueryManager queryManager;
78    private EntityReferenceSerializer<String> serializer;
79    private WikiDescriptorManager wikiDescriptorManager;
80    private NotificationFilterManager notificationFilterManager;
81    private DocumentAccessBridge documentAccessBridge;
82    private RecordableEventDescriptorHelper recordableEventDescriptorHelper;
83   
84    private DocumentReference userReference = new DocumentReference("xwiki", "XWiki", "UserA");
85    private Query query;
86    private Date startDate;
87    private String startDateParamName;
88    private Date pref1StartDate;
89    private String pref1StartDateParamName;
90   
91    private NotificationFilterPreference fakeFilterPreference;
92    private NotificationPreference pref1;
93   
 
94  9 toggle @Before
95    public void setUp() throws Exception
96    {
97  9 queryManager = mocker.getInstance(QueryManager.class);
98  9 serializer = mocker.getInstance(EntityReferenceSerializer.TYPE_STRING);
99  9 wikiDescriptorManager = mocker.getInstance(WikiDescriptorManager.class);
100  9 notificationFilterManager = mocker.getInstance(NotificationFilterManager.class);
101  9 documentAccessBridge = mocker.getInstance(DocumentAccessBridge.class);
102  9 recordableEventDescriptorHelper = mocker.getInstance(RecordableEventDescriptorHelper.class);
103   
104  9 startDate = new Date(10);
105  9 this.startDateParamName = String.format("date_%s", DigestUtils.sha256Hex(this.startDate.toString()));
106   
107  9 query = mock(Query.class);
108  9 when(queryManager.createQuery(anyString(), anyString())).thenReturn(query);
109   
110  9 pref1StartDate = new Date(100000000);
111  9 this.pref1StartDateParamName = String.format("date_%s", DigestUtils.sha256Hex(this.pref1StartDate.toString()));
112   
113  9 pref1 = mock(NotificationPreference.class);
114  9 when(pref1.getProperties()).thenReturn(Collections.singletonMap(
115    NotificationPreferenceProperty.EVENT_TYPE, "create"));
116  9 when(pref1.getFormat()).thenReturn(NotificationFormat.ALERT);
117  9 when(pref1.getStartDate()).thenReturn(pref1StartDate);
118  9 when(pref1.isNotificationEnabled()).thenReturn(true);
119   
120  9 fakeFilterPreference = mock(NotificationFilterPreference.class);
121  9 when(fakeFilterPreference.isActive()).thenReturn(true);
122   
123  9 when(documentAccessBridge.getProperty(userReference,
124    new DocumentReference("xwiki", "XWiki", "XWikiUsers"),
125    "displayHiddenDocuments")).thenReturn(0);
126   
127  9 when(wikiDescriptorManager.getMainWikiId()).thenReturn("xwiki");
128   
129  9 when(recordableEventDescriptorHelper.hasDescriptor(anyString(), any(DocumentReference.class))).thenReturn(true);
130    }
131   
 
132  1 toggle @Test
133    public void generateQueryExpression() throws Exception
134    {
135    // Test
136  1 NotificationParameters parameters = new NotificationParameters();
137  1 parameters.user = userReference;
138  1 parameters.format = NotificationFormat.ALERT;
139  1 parameters.fromDate = startDate;
140  1 parameters.preferences = Arrays.asList(pref1);
141  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
142  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
143   
144    // Verify
145  1 assertEquals("((DATE >= \"" + this.startDate.toString() + "\" " +
146    "AND (TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\")) AND HIDDEN <> true) " +
147    "ORDER BY DATE DESC",
148    node.toString());
149   
150    // Test 2
151  1 mocker.getComponentUnderTest().generateQuery(parameters);
152   
153  1 verify(this.queryManager).createQuery(
154    "where ((" +
155    "event.date >= :" + this.startDateParamName + ") " +
156    "AND ((event.type = :value_fa8847b0c33183273f5945508b31c3208a9e4ece58ca47233a05628d8dba3799) " +
157    "AND (event.date >= :" + this.pref1StartDateParamName + "))) " +
158    "AND (event.hidden <> true) " +
159    "ORDER BY event.date DESC",
160    Query.HQL);
161  1 verify(this.query).bindValue(this.startDateParamName, this.startDate);
162  1 verify(this.query).bindValue(this.pref1StartDateParamName, this.pref1StartDate);
163  1 verify(this.query).bindValue(eq("value_fa8847b0c33183273f5945508b31c3208a9e4ece58ca47233a05628d8dba3799"),
164    eq("create"));
165   
166    }
167   
 
168  1 toggle @Test
169    public void generateQueryWhenHiddenDocsAreEnabled() throws Exception
170    {
171    // Mock
172  1 when(documentAccessBridge.getProperty(userReference,
173    new DocumentReference("xwiki", "XWiki", "XWikiUsers"),
174    "displayHiddenDocuments")).thenReturn(1);
175   
176    // Test
177  1 NotificationParameters parameters = new NotificationParameters();
178  1 parameters.user = userReference;
179  1 parameters.format = NotificationFormat.ALERT;
180  1 parameters.fromDate = startDate;
181  1 parameters.preferences = Arrays.asList(pref1);
182  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
183  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
184   
185    // Verify
186  1 assertEquals("(DATE >= \"" + this.startDate.toString() + "\" " +
187    "AND (TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\")) " +
188    "ORDER BY DATE DESC", node.toString());
189   
190    // Test 2
191  1 mocker.getComponentUnderTest().generateQuery(parameters);
192   
193  1 verify(this.queryManager).createQuery(
194    "where (" +
195    "event.date >= :" + this.startDateParamName + ") " +
196    "AND ((event.type = :value_fa8847b0c33183273f5945508b31c3208a9e4ece58ca47233a05628d8dba3799) " +
197    "AND (event.date >= :" + this.pref1StartDateParamName + ")) " +
198    "ORDER BY event.date DESC",
199    Query.HQL);
200  1 verify(this.query).bindValue(eq(this.startDateParamName), eq(this.startDate));
201  1 verify(this.query).bindValue(eq("value_fa8847b0c33183273f5945508b31c3208a9e4ece58ca47233a05628d8dba3799"),
202    eq("create"));
203  1 verify(this.query).bindValue(this.pref1StartDateParamName, this.pref1StartDate);
204    }
205   
 
206  1 toggle @Test
207    public void generateQueryWithNotOnlyUnread() throws Exception
208    {
209    // Test
210  1 NotificationParameters parameters = new NotificationParameters();
211  1 parameters.user = userReference;
212  1 parameters.format = NotificationFormat.ALERT;
213  1 parameters.fromDate = startDate;
214  1 parameters.preferences = Arrays.asList(pref1);
215  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
216  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
217   
218    // Verify
219  1 assertEquals("((DATE >= \"" + this.startDate.toString() + "\" " +
220    "AND (TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\")) AND HIDDEN <> true) " +
221    "ORDER BY DATE DESC", node.toString());
222   
223    // Test 2
224  1 mocker.getComponentUnderTest().generateQuery(parameters);
225   
226  1 verify(this.queryManager).createQuery(
227    "where ((" +
228    "event.date >= :" + this.startDateParamName + ") " +
229    "AND ((event.type = :value_fa8847b0c33183273f5945508b31c3208a9e4ece58ca47233a05628d8dba3799) " +
230    "AND (event.date >= :" + this.pref1StartDateParamName + "))) " +
231    "AND (event.hidden <> true) " +
232    "ORDER BY event.date DESC",
233    Query.HQL);
234    }
235   
 
236  1 toggle @Test
237    public void generateQueryWithUntilDate() throws Exception
238    {
239  1 Date untilDate = new Date(1000000000000L);
240  1 String untilDateParamName = String.format("date_%s", DigestUtils.sha256Hex(untilDate.toString()));
241   
242    // Test
243  1 NotificationParameters parameters = new NotificationParameters();
244  1 parameters.user = userReference;
245  1 parameters.format = NotificationFormat.ALERT;
246  1 parameters.fromDate = startDate;
247  1 parameters.endDate = untilDate;
248  1 parameters.preferences = Arrays.asList(pref1);
249  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
250  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
251   
252    // Verify
253  1 assertEquals("(((DATE >= \"" + this.startDate.toString() + "\" " +
254    "AND (TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\")) " +
255    "AND DATE <= \"" + untilDate.toString() + "\") AND HIDDEN <> true) " +
256    "ORDER BY DATE DESC", node.toString());
257   
258    // Test 2
259  1 mocker.getComponentUnderTest().generateQuery(parameters);
260   
261  1 verify(this.queryManager).createQuery(
262    "where (((" +
263    "event.date >= :" + this.startDateParamName + ") " +
264    "AND ((event.type = :value_fa8847b0c33183273f5945508b31c3208a9e4ece58ca47233a05628d8dba3799) " +
265    "AND (event.date >= :" + this.pref1StartDateParamName + "))) " +
266    "AND (event.date <= :" + untilDateParamName + ")) " +
267    "AND (event.hidden <> true) " +
268    "ORDER BY event.date DESC",
269    Query.HQL);
270  1 verify(this.query).bindValue(this.startDateParamName, this.startDate);
271  1 verify(this.query).bindValue(this.pref1StartDateParamName, this.pref1StartDate);
272  1 verify(this.query).bindValue(untilDateParamName, untilDate);
273   
274    }
275   
 
276  1 toggle @Test
277    public void generateQueryWithUntilDateAndBlackList() throws Exception
278    {
279  1 Date untilDate = new Date(1000000000000L);
280   
281    // Test
282  1 NotificationParameters parameters = new NotificationParameters();
283  1 parameters.user = userReference;
284  1 parameters.format = NotificationFormat.ALERT;
285  1 parameters.endDate = untilDate;
286  1 parameters.blackList = Arrays.asList("event1", "event2");
287  1 parameters.preferences = Arrays.asList(pref1);
288  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
289  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
290   
291    // Verify
292  1 assertEquals("((((TYPE = \"create\" " +
293    "AND DATE >= \"" + this.pref1StartDate.toString() + "\") " +
294    "AND NOT (ID IN (\"event1\", \"event2\"))) " +
295    "AND DATE <= \"" + untilDate.toString() + "\") " +
296    "AND HIDDEN <> true) " +
297    "ORDER BY DATE DESC",
298    node.toString());
299    }
300   
 
301  1 toggle @Test
302    public void generateQueryWithLocalUser() throws Exception
303    {
304    // Test
305  1 when(wikiDescriptorManager.getMainWikiId()).thenReturn("mainWiki");
306  1 NotificationParameters parameters = new NotificationParameters();
307  1 parameters.user = userReference;
308  1 parameters.format = NotificationFormat.ALERT;
309  1 parameters.fromDate = startDate;
310  1 parameters.preferences = Arrays.asList(pref1);
311  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
312  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
313   
314    // Verify
315  1 assertEquals("(((DATE >= \"" + this.startDate.toString() + "\" "
316    + "AND (TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\")) AND HIDDEN <> true) "
317    + "AND WIKI = \"Wiki xwiki\") "
318    + "ORDER BY DATE DESC",
319    node.toString());
320    }
321   
 
322  1 toggle @Test
323    public void generateQueryWithFilters() throws Exception
324    {
325    // Mocks
326  1 NotificationFilter notificationFilter1 = mock(NotificationFilter.class);
327  1 NotificationFilter notificationFilter2 = mock(NotificationFilter.class);
328   
329  1 when(notificationFilter1.filterExpression(any(DocumentReference.class), any(Collection.class),
330    any(NotificationPreference.class)))
331    .thenReturn(value(EventProperty.PAGE).eq(value("someValue1")).and(value("1").eq(value("1"))));
332   
333  1 when(notificationFilter2.filterExpression(any(DocumentReference.class), any(Collection.class),
334    any(NotificationPreference.class)))
335    .thenReturn(value(EventProperty.TYPE).eq(value("someValue2")).and(value("2").eq(value("2"))));
336   
337  1 when(notificationFilter1.matchesPreference(any(NotificationPreference.class))).thenReturn(true);
338  1 when(notificationFilter2.matchesPreference(any(NotificationPreference.class))).thenReturn(true);
339  1 when(notificationFilterManager.getFiltersRelatedToNotificationPreference(anyCollection(),
340    any(NotificationPreference.class))).thenAnswer(
341    invocationOnMock -> ((Collection)invocationOnMock.getArgument(0)).stream());
342   
343    // Test
344  1 NotificationParameters parameters = new NotificationParameters();
345  1 parameters.user = userReference;
346  1 parameters.format = NotificationFormat.ALERT;
347  1 parameters.fromDate = startDate;
348  1 parameters.blackList = Arrays.asList("event1", "event2");
349  1 parameters.filters = Arrays.asList(notificationFilter1, notificationFilter2);
350  1 parameters.preferences = Arrays.asList(pref1);
351  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
352  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
353   
354  1 assertEquals("(((DATE >= \"" + this.startDate.toString() + "\" " +
355    "AND (((TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\") " +
356    "AND (PAGE = \"someValue1\" AND \"1\" = \"1\")) " +
357    "AND (TYPE = \"someValue2\" AND \"2\" = \"2\"))) " +
358    "AND NOT (ID IN (\"event1\", \"event2\"))) " +
359    "AND HIDDEN <> true) " +
360    "ORDER BY DATE DESC", node.toString());
361    }
362   
 
363  1 toggle @Test
364    public void generateQueryWithNoRelevantFilters() throws Exception
365    {
366   
367    // Mocks
368  1 NotificationFilter notificationFilter1 = mock(NotificationFilter.class);
369   
370  1 when(notificationFilter1.filterExpression(any(DocumentReference.class), any(Collection.class),
371    any(NotificationPreference.class)))
372    .thenReturn(new EmptyNode());
373   
374  1 when(notificationFilter1.matchesPreference(any(NotificationPreference.class))).thenReturn(true);
375   
376    // Test
377  1 NotificationParameters parameters = new NotificationParameters();
378  1 parameters.user = userReference;
379  1 parameters.format = NotificationFormat.ALERT;
380  1 parameters.fromDate = startDate;
381  1 parameters.blackList = Arrays.asList("event1", "event2");
382  1 parameters.filters = Collections.singleton(notificationFilter1);
383  1 parameters.preferences = Arrays.asList(pref1);
384  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
385  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
386   
387  1 assertEquals("(((DATE >= \"" + this.startDate.toString() + "\" " +
388    "AND (TYPE = \"create\" AND DATE >= \"" + this.pref1StartDate.toString() + "\")) " +
389    "AND NOT (ID IN (\"event1\", \"event2\"))) " +
390    "AND HIDDEN <> true) " +
391    "ORDER BY DATE DESC",
392    node.toString());
393    }
394   
 
395  1 toggle @Test
396    public void generateQueryWithEventTypesThatHasNoDescriptor() throws Exception
397    {
398    // Mocks
399  1 NotificationFilter notificationFilter1 = mock(NotificationFilter.class);
400   
401  1 when(notificationFilter1.filterExpression(any(DocumentReference.class), any(Collection.class),
402    any(NotificationPreference.class)))
403    .thenReturn(value(EventProperty.PAGE).eq(value("someValue1")).and(value("1").eq(value("1"))));
404   
405  1 when(notificationFilter1.matchesPreference(any(NotificationPreference.class))).thenReturn(true);
406  1 when(notificationFilterManager.getFiltersRelatedToNotificationPreference(anyCollection(),
407    any(NotificationPreference.class))).thenAnswer(
408    invocationOnMock -> ((Collection)invocationOnMock.getArgument(0)).stream());
409   
410    // No matching descriptor
411  1 when(recordableEventDescriptorHelper.hasDescriptor("create", userReference)).thenReturn(false);
412   
413    // Test
414  1 NotificationParameters parameters = new NotificationParameters();
415  1 parameters.user = userReference;
416  1 parameters.format = NotificationFormat.ALERT;
417  1 parameters.fromDate = startDate;
418  1 parameters.filters = Arrays.asList(notificationFilter1);
419  1 parameters.preferences = Arrays.asList(pref1);
420  1 parameters.filterPreferences = Arrays.asList(fakeFilterPreference);
421  1 ExpressionNode node = mocker.getComponentUnderTest().generateQueryExpression(parameters);
422   
423    // Expectation: no filters on "create" event type because it has no descriptor
424  1 assertEquals("(DATE >= \"" + this.startDate.toString() + "\" AND HIDDEN <> true) ORDER BY DATE DESC",
425    node.toString());
426    }
427   
428    }