1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.store

File XWikiHibernateStoreTest.java

 

Code metrics

0
139
14
1
361
254
15
0.11
9.93
14
1.07

Classes

Class Line # Actions
XWikiHibernateStoreTest 66 139 0% 15 1
0.9934640599.3%
 

Contributing tests

This file is covered by 12 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 com.xpn.xwiki.store;
21   
22    import java.sql.SQLException;
23    import java.sql.Statement;
24    import java.util.Arrays;
25    import java.util.Collections;
26    import java.util.List;
27    import java.util.Locale;
28   
29    import org.hibernate.FlushMode;
30    import org.hibernate.HibernateException;
31    import org.hibernate.Query;
32    import org.hibernate.SQLQuery;
33    import org.hibernate.Session;
34    import org.hibernate.dialect.Dialect;
35    import org.hibernate.engine.SessionFactoryImplementor;
36    import org.hibernate.id.SequenceGenerator;
37    import org.junit.Before;
38    import org.junit.Rule;
39    import org.junit.Test;
40    import org.mockito.ArgumentCaptor;
41    import org.xwiki.bridge.event.ActionExecutingEvent;
42    import org.xwiki.model.reference.DocumentReference;
43    import org.xwiki.model.reference.EntityReferenceSerializer;
44    import org.xwiki.observation.EventListener;
45    import org.xwiki.observation.ObservationManager;
46    import org.xwiki.query.QueryManager;
47    import org.xwiki.test.mockito.MockitoComponentMockingRule;
48   
49    import com.xpn.xwiki.doc.XWikiDocument;
50    import com.xpn.xwiki.objects.BaseObject;
51    import com.xpn.xwiki.objects.BaseProperty;
52    import com.xpn.xwiki.objects.LargeStringProperty;
53    import com.xpn.xwiki.objects.StringProperty;
54    import com.xpn.xwiki.store.hibernate.HibernateSessionFactory;
55    import com.xpn.xwiki.store.migration.DataMigrationManager;
56   
57    import static org.junit.Assert.*;
58    import static org.mockito.ArgumentMatchers.*;
59    import static org.mockito.Mockito.*;
60   
61    /**
62    * Unit tests for the {@link XWikiHibernateStore} class.
63    *
64    * @version $Id: a3f4772efa804b74301766d5afce4f225f73ec4d $
65    */
 
66    public class XWikiHibernateStoreTest extends AbstractXWikiHibernateStoreTest<XWikiStoreInterface>
67    {
68    /**
69    * A special component manager that mocks automatically all the dependencies of the component under test.
70    */
71    @Rule
72    public MockitoComponentMockingRule<XWikiStoreInterface> mocker =
73    new MockitoComponentMockingRule<XWikiStoreInterface>(XWikiHibernateStore.class);
74   
75    /**
76    * The component being tested.
77    */
78    private XWikiHibernateStore store;
79   
 
80  37 toggle @Override
81    protected MockitoComponentMockingRule<XWikiStoreInterface> getMocker()
82    {
83  37 return mocker;
84    }
85   
 
86  12 toggle @Before
87    public void setUp() throws Exception
88    {
89  12 super.setUp();
90   
91  12 store = (XWikiHibernateStore) mocker.getComponentUnderTest();
92    }
93   
 
94  1 toggle @Test
95    public void testGetColumnsForSelectStatement() throws Exception
96    {
97  1 assertEquals(", doc.date", store.getColumnsForSelectStatement("where 1=1 order by doc.date desc"));
98  1 assertEquals(", doc.date", store.getColumnsForSelectStatement("where 1=1 order by doc.date asc"));
99  1 assertEquals(", doc.date", store.getColumnsForSelectStatement("where 1=1 order by doc.date"));
100  1 assertEquals(", description", store.getColumnsForSelectStatement("where 1=1 order by description desc"));
101  1 assertEquals(", ascendent", store.getColumnsForSelectStatement("where 1=1 order by ascendent asc"));
102  1 assertEquals(", doc.date, doc.name",
103    store.getColumnsForSelectStatement("where 1=1 order by doc.date, doc.name"));
104  1 assertEquals(", doc.date, doc.name",
105    store.getColumnsForSelectStatement("where 1=1 order by doc.date ASC, doc.name DESC"));
106  1 assertEquals("", store.getColumnsForSelectStatement(", BaseObject as obj where obj.name=doc.fullName"));
107    }
108   
 
109  1 toggle @Test
110    public void testCreateSQLQuery()
111    {
112  1 assertEquals("select distinct doc.space, doc.name from XWikiDocument as doc",
113    store.createSQLQuery("select distinct doc.space, doc.name", ""));
114  1 assertEquals("select distinct doc.space, doc.name, doc.date from XWikiDocument as doc "
115    + "where 1=1 order by doc.date desc",
116    store.createSQLQuery("select distinct doc.space, doc.name", "where 1=1 order by doc.date desc"));
117    }
118   
 
119  1 toggle @Test
120    public void testEndTransactionWhenSQLBatchUpdateExceptionThrown() throws Exception
121    {
122  1 SQLException sqlException2 = new SQLException("sqlexception2");
123  1 sqlException2.setNextException(new SQLException("nextexception2"));
124   
125  1 SQLException sqlException1 = new SQLException("sqlexception1");
126  1 sqlException1.initCause(sqlException2);
127  1 sqlException1.setNextException(new SQLException("nextexception1"));
128   
129    // Assume the transaction is already created.
130  1 when(context.get("hibtransaction")).thenReturn(transaction);
131  1 doThrow(new HibernateException("exception1", sqlException1)).when(transaction).commit();
132   
133  1 try {
134  1 store.endTransaction(context, true);
135  0 fail("Should have thrown an exception here");
136    } catch (HibernateException e) {
137  1 assertEquals("Failed to commit or rollback transaction. Root cause [\n"
138    + "SQL next exception = [java.sql.SQLException: nextexception1]\n"
139    + "SQL next exception = [java.sql.SQLException: nextexception2]]", e.getMessage());
140    }
141    }
142   
 
143  1 toggle @Test
144    public void executeDeleteWikiStatementForPostgreSQLWhenInSchemaMode() throws Exception
145    {
146  1 HibernateSessionFactory sessionFactory = mocker.getInstance(HibernateSessionFactory.class);
147  1 when(sessionFactory.getConfiguration().getProperty("xwiki.virtual_mode")).thenReturn("schema");
148   
149  1 Statement statement = mock(Statement.class);
150  1 DatabaseProduct databaseProduct = DatabaseProduct.POSTGRESQL;
151   
152  1 store.executeDeleteWikiStatement(statement, databaseProduct, "schema");
153   
154  1 verify(statement).execute("DROP SCHEMA schema CASCADE");
155    }
156   
 
157  1 toggle @Test
158    public void executeDeleteWikiStatementForPostgreSQLWhenInDatabaseMode() throws Exception
159    {
160  1 HibernateSessionFactory sessionFactory = mocker.getInstance(HibernateSessionFactory.class);
161  1 when(sessionFactory.getConfiguration().getProperty("xwiki.virtual_mode")).thenReturn("database");
162   
163  1 Statement statement = mock(Statement.class);
164  1 DatabaseProduct databaseProduct = DatabaseProduct.POSTGRESQL;
165   
166  1 store.executeDeleteWikiStatement(statement, databaseProduct, "schema");
167   
168  1 verify(mocker.getMockedLogger()).warn("Subwiki deletion not yet supported in Database mode for PostgreSQL");
169  1 verify(statement, never()).execute(any(String.class));
170    }
171   
 
172  1 toggle @Test
173    public void testLocksAreReleasedOnLogout() throws Exception
174    {
175    // Capture the event listener.
176  1 ObservationManager observationManager = getMocker().getInstance(ObservationManager.class);
177  1 ArgumentCaptor<EventListener> eventListenerCaptor = ArgumentCaptor.forClass(EventListener.class);
178  1 verify(observationManager).addListener(eventListenerCaptor.capture());
179  1 assertEquals("deleteLocksOnLogoutListener", eventListenerCaptor.getValue().getName());
180   
181  1 Query query = mock(Query.class);
182  1 when(session.createQuery("delete from XWikiLock as lock where lock.userName=:userName")).thenReturn(query);
183  1 when(context.getUserReference()).thenReturn(new DocumentReference("xwiki", "XWiki", "LoggerOutter"));
184  1 when(context.getUser()).thenReturn("XWiki.LoggerOutter");
185   
186    // Fire the logout event.
187  1 eventListenerCaptor.getValue().onEvent(new ActionExecutingEvent("logout"), null, context);
188   
189  1 verify(session, times(2)).setFlushMode(FlushMode.COMMIT);
190  1 verify(query).setString("userName", "XWiki.LoggerOutter");
191  1 verify(query).executeUpdate();
192  1 verify(transaction).commit();
193  1 verify(session).close();
194   
195    // setDatabase() is called for each transaction and that calls checkDatabase().
196  1 DataMigrationManager dataMigrationManager = mocker.getInstance(DataMigrationManager.class, "hibernate");
197  1 verify(dataMigrationManager).checkDatabase();
198    }
199   
 
200  1 toggle @Test
201    public void createHibernateSequenceIfRequiredWhenNotInUpdateCommands() throws Exception
202    {
203  1 Session session = mock(Session.class);
204  1 SessionFactoryImplementor sessionFactory = mock(SessionFactoryImplementor.class);
205  1 Dialect dialect = mock(Dialect.class);
206  1 when(session.getSessionFactory()).thenReturn(sessionFactory);
207  1 when(sessionFactory.getDialect()).thenReturn(dialect);
208  1 when(dialect.getNativeIdentifierGeneratorClass()).thenReturn(SequenceGenerator.class);
209  1 SQLQuery sqlQuery = mock(SQLQuery.class);
210  1 when(session.createSQLQuery("create sequence schema.hibernate_sequence")).thenReturn(sqlQuery);
211  1 when(sqlQuery.executeUpdate()).thenReturn(0);
212   
213  1 this.store.createHibernateSequenceIfRequired(new String[] {}, "schema", session);
214   
215  1 verify(session).createSQLQuery("create sequence schema.hibernate_sequence");
216  1 verify(sqlQuery).executeUpdate();
217    }
218   
219    /**
220    * We verify that the sequence is not created if it's already in the update script.
221    */
 
222  1 toggle @Test
223    public void createHibernateSequenceIfRequiredWhenInUpdateCommands() throws Exception
224    {
225  1 Session session = mock(Session.class);
226  1 SessionFactoryImplementor sessionFactory = mock(SessionFactoryImplementor.class);
227  1 Dialect dialect = mock(Dialect.class);
228  1 when(session.getSessionFactory()).thenReturn(sessionFactory);
229  1 when(sessionFactory.getDialect()).thenReturn(dialect);
230  1 when(dialect.getNativeIdentifierGeneratorClass()).thenReturn(SequenceGenerator.class);
231  1 SQLQuery sqlQuery = mock(SQLQuery.class);
232  1 when(session.createSQLQuery("create sequence schema.hibernate_sequence")).thenReturn(sqlQuery);
233  1 when(sqlQuery.executeUpdate()).thenReturn(0);
234   
235  1 this.store.createHibernateSequenceIfRequired(
236    new String[] {"whatever", "create sequence schema.hibernate_sequence"}, "schema", session);
237   
238  1 verify(session, never()).createSQLQuery("create sequence schema.hibernate_sequence");
239  1 verify(sqlQuery, never()).executeUpdate();
240    }
241   
242    /**
243    * Save an object that has a property whose type has changed.
244    *
245    * @see "XWIKI-9716: Error while migrating SearchSuggestConfig page from 4.1.4 to 5.2.1 with DW"
246    */
 
247  1 toggle @Test
248    public void saveObjectWithPropertyTypeChange() throws Exception
249    {
250    // The class must be local.
251  1 DocumentReference classReference = new DocumentReference("myWiki", "mySpace", "myClass");
252  1 when(context.getWikiId()).thenReturn(classReference.getWikiReference().getName());
253  1 BaseObject object = mock(BaseObject.class);
254  1 when(object.getXClassReference()).thenReturn(classReference);
255   
256    // Query to check if the object exists already (save versus update).
257  1 when(context.get("hibsession")).thenReturn(session);
258  1 when(session.createQuery("select obj.id from BaseObject as obj where obj.id = :id")).thenReturn(
259    mock(Query.class));
260   
261    // Save each object property.
262  1 String propertyName = "query";
263  1 long propertyId = 1234567890L;
264  1 when(object.getPropertyList()).thenReturn(Collections.singleton(propertyName));
265   
266    // The property name must match the key in the property list.
267  1 BaseProperty property = mock(BaseProperty.class);
268  1 when(object.getField(propertyName)).thenReturn(property);
269  1 when(property.getId()).thenReturn(propertyId);
270  1 when(property.getName()).thenReturn(propertyName);
271  1 when(property.getClassType()).thenReturn(LargeStringProperty.class.getName());
272   
273  1 Query oldClassTypeQuery = mock(Query.class);
274  1 when(session.createQuery("select prop.classType from BaseProperty as prop "
275    + "where prop.id.id = :id and prop.id.name= :name")).thenReturn(oldClassTypeQuery);
276    // The old value has a different type (String -> TextArea).
277  1 when(oldClassTypeQuery.uniqueResult()).thenReturn(StringProperty.class.getName());
278   
279    // The old property must be loaded from the corresponding table.
280  1 Query oldPropertyQuery = mock(Query.class);
281  1 when(session.createQuery("select prop from " + StringProperty.class.getName()
282    + " as prop where prop.id.id = :id and prop.id.name= :name")).thenReturn(oldPropertyQuery);
283  1 BaseProperty oldProperty = mock(BaseProperty.class);
284  1 when(oldPropertyQuery.uniqueResult()).thenReturn(oldProperty);
285   
286  1 store.saveXWikiCollection(object, context, false);
287   
288  1 verify(oldClassTypeQuery).setLong("id", propertyId);
289  1 verify(oldClassTypeQuery).setString("name", propertyName);
290   
291  1 verify(oldPropertyQuery).setLong("id", propertyId);
292  1 verify(oldPropertyQuery).setString("name", propertyName);
293   
294    // Delete the old property value and then save the new one.
295  1 verify(session).delete(oldProperty);
296  1 verify(session).save(property);
297    }
298   
 
299  1 toggle @Test
300    public void existsWithRootLocale() throws Exception
301    {
302  1 String fullName = "foo";
303  1 XWikiDocument doc = mock(XWikiDocument.class);
304  1 when(doc.getLocale()).thenReturn(Locale.ROOT);
305  1 when(doc.getFullName()).thenReturn(fullName);
306   
307  1 Query query = mock(Query.class);
308  1 when(session.createQuery("select doc.fullName from XWikiDocument as doc where doc.fullName=:fullName"))
309    .thenReturn(query);
310  1 when(query.list()).thenReturn(Collections.singletonList(fullName));
311   
312  1 assertTrue(store.exists(doc, context));
313   
314  1 verify(query).setString("fullName", fullName);
315    }
316   
 
317  1 toggle @Test
318    public void existsWithNonRootLocale() throws Exception
319    {
320  1 String fullName = "bar";
321  1 XWikiDocument doc = mock(XWikiDocument.class);
322  1 when(doc.getLocale()).thenReturn(Locale.ENGLISH);
323  1 when(doc.getFullName()).thenReturn(fullName);
324   
325  1 Query query = mock(Query.class);
326  1 String statement = "select doc.fullName from XWikiDocument as doc where doc.fullName=:fullName"
327    + " and doc.language=:language";
328  1 when(session.createQuery(statement)).thenReturn(query);
329  1 when(query.list()).thenReturn(Collections.singletonList(fullName));
330   
331  1 assertTrue(store.exists(doc, context));
332   
333  1 verify(query).setString("fullName", fullName);
334  1 verify(query).setString("language", Locale.ENGLISH.toString());
335    }
336   
 
337  1 toggle @Test
338    public void getTranslationList() throws Exception
339    {
340  1 DocumentReference documentReference = new DocumentReference("chess", Arrays.asList("Path", "To"), "Success");
341  1 XWikiDocument doc = mock(XWikiDocument.class);
342  1 when(doc.getDocumentReference()).thenReturn(documentReference);
343   
344  1 org.xwiki.query.Query query = mock(org.xwiki.query.Query.class);
345  1 List<Object> translationList = Arrays.<Object>asList("fr", "ro");
346  1 when(query.execute()).thenReturn(translationList);
347   
348  1 QueryManager queryManager = this.mocker.getInstance(QueryManager.class);
349  1 when(queryManager.createQuery(any(String.class), eq(org.xwiki.query.Query.HQL))).thenReturn(query);
350   
351  1 EntityReferenceSerializer<String> localEntityReferenceSerialzier =
352    this.mocker.getInstance(EntityReferenceSerializer.TYPE_STRING, "local");
353  1 when(localEntityReferenceSerialzier.serialize(documentReference.getParent())).thenReturn("Path.To");
354   
355  1 assertEquals(translationList, store.getTranslationList(doc, context));
356   
357  1 verify(query).setWiki(documentReference.getWikiReference().getName());
358  1 verify(query).bindValue("space", "Path.To");
359  1 verify(query).bindValue("name", documentReference.getName());
360    }
361    }