View Javadoc
1   /*
2    * #%L
3    * ToPIA :: Service Replication
4    * $Id$
5    * $HeadURL$
6    * %%
7    * Copyright (C) 2004 - 2014 CodeLutin
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as 
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  package org.nuiton.topia.replication;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.junit.After;
30  import org.junit.AfterClass;
31  import org.junit.Before;
32  import org.junit.BeforeClass;
33  import org.junit.Test;
34  import org.nuiton.topia.TestHelper;
35  import org.nuiton.topia.TopiaContext;
36  import org.nuiton.topia.TopiaContextFactory;
37  import org.nuiton.topia.TopiaException;
38  import org.nuiton.topia.TopiaTestDAOHelper.TopiaTestEntityEnum;
39  import org.nuiton.topia.framework.TopiaContextImplementor;
40  import org.nuiton.topia.persistence.TopiaEntityEnum;
41  import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
42  import org.nuiton.topia.replication.model.ReplicationModel;
43  import org.nuiton.topia.replication.operation.AttachAssociation;
44  import org.nuiton.topia.replication.operation.DettachAssociation;
45  import org.nuiton.topia.replication.operation.Duplicate;
46  import org.nuiton.topia.replication.operation.FakeOperation;
47  import org.nuiton.topia.replication.operation.UncreatableOperation;
48  import org.nuiton.topia.replication.operation.UnregistredOperation;
49  import org.nuiton.topia.test.entities.Person;
50  import org.nuiton.topia.test.entities.PersonImpl;
51  import org.nuiton.topia.test.entities.Pet;
52  import org.nuiton.topia.test.entities.PetImpl;
53  import org.nuiton.topia.test.entities.Race;
54  import org.nuiton.topia.test.entities.RaceImpl;
55  
56  import java.io.File;
57  import java.io.IOException;
58  import java.util.Properties;
59  
60  /**
61   * TopiaReplicationServiceImplTest on model TopiaTest
62   * 
63   * Created: 07 jun. 09 17:14:22
64   *
65   * @author tchemit &lt;chemit@codelutin.com&gt;
66   * @since 2.2.0
67   */
68  public class TopiaReplicationServiceImplTest extends AbstractTopiaReplicationServiceTest {
69  
70      /** Logger */
71      private static final Log log =
72              LogFactory.getLog(TopiaReplicationServiceImplTest.class);
73  
74      protected static final TopiaEntityEnum[] contracts = {TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race};
75  
76      protected static final String entitiesList = PersonImpl.class.getName() + "," + PetImpl.class.getName() + "," + RaceImpl.class.getName();
77  
78      static protected Person person, person2;
79  
80      static protected Pet pet, pet2, pet3;
81  
82      static protected Race race, race2, race3;
83  
84      protected static File tesDir;
85  
86      @BeforeClass
87      public static void beforeClass() throws IOException {
88          tesDir = TestHelper.getTestBasedir(
89                  TopiaReplicationServiceImplTest.class);
90      }
91  
92      @AfterClass
93      public static void after() throws Exception {
94          AbstractTopiaReplicationServiceTest.after();
95      }
96  
97      @Before
98      @Override
99      public void setUp() throws Exception {
100 
101         super.setUp();
102 
103         person = update(person);
104         person2 = update(person2);
105         pet = update(pet);
106         pet2 = update(pet2);
107         race = update(race);
108         race2 = update(race2);
109         race3 = update(race3);
110     }
111 
112     @After
113     @Override
114     public void tearDown() throws Exception {
115         super.tearDown();
116         if (dstCtxt != null && !dstCtxt.isClosed()) {
117             dstCtxt.closeContext();
118         }
119     }
120 
121     @Test
122     @Override
123     public void testDetectTypes() throws Exception {
124 
125         detectTypes(race, Race.class);
126         detectTypes(pet, Pet.class, Person.class, Race.class);
127         detectTypes(person, Pet.class, Person.class, Race.class);
128 
129         detectTypes(pet2, Pet.class);
130         detectTypes(person2, Person.class);
131         detectTypes(race2, Race.class);
132 
133         detectTypes(race3, Race.class);
134         detectTypes(pet3, Pet.class, Race.class);
135     }
136 
137     @Test
138     @Override
139     public void testGetOperation() throws Exception {
140 
141         getOperation(UnregistredOperation.class, false);
142         getOperation(UncreatableOperation.class, true);
143         getOperation(FakeOperation.class, true);
144         getOperation(Duplicate.class, true);
145         getOperation(AttachAssociation.class, true);
146         getOperation(DettachAssociation.class, true);
147     }
148 
149     @Test
150     @Override
151     public void testDetectAssociations() throws Exception {
152 
153         detectAssociations(person, TopiaTestEntityEnum.Person, Person.PROPERTY_PET);
154         detectAssociations(race);
155         detectAssociations(pet);
156 
157         detectAssociations(person2);
158         detectAssociations(race2);
159         detectAssociations(pet2);
160     }
161 
162     @Test
163     @Override
164     public void testDetectDirectDependencies() throws Exception {
165 
166         detectDirectDependencies(person);
167         detectDirectDependencies(race);
168         detectDirectDependencies(pet, TopiaTestEntityEnum.Pet, Pet.PROPERTY_PERSON, TopiaTestEntityEnum.Pet, Pet.PROPERTY_RACE);
169 
170         detectDirectDependencies(person2);
171         detectDirectDependencies(race2);
172         detectDirectDependencies(pet2);
173     }
174 
175     @Test
176     @Override
177     public void testDetectShell() throws Exception {
178 
179         detectShell(person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
180         detectShell(race);
181         detectShell(pet, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
182         detectShell(person2);
183         detectShell(race2);
184         detectShell(pet2);
185     }
186 
187     @Test
188     @Override
189     public void testDetectDependencies() throws Exception {
190 
191         detectDependencies(person, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
192         detectDependencies(race, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race});
193         detectDependencies(pet, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
194 
195         detectDependencies(person2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person});
196         detectDependencies(race2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race});
197         detectDependencies(pet2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
198     }
199 
200     @Test
201     @Override
202     public void testDetectObjectsToDettach() throws Exception {
203 
204         detectObjectsToDettach(person, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
205         detectObjectsToDettach(race);
206         detectObjectsToDettach(pet, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
207 
208         detectObjectsToDettach(person2);
209         detectObjectsToDettach(race2);
210         detectObjectsToDettach(pet2);
211 
212         detectObjectsToDettach(race3);
213         detectObjectsToDettach(pet3);
214     }
215 
216     @Test
217     @Override
218     public void testDetectOperations() throws Exception {
219 
220         //TODO Make some real test on detected operations...
221 
222         detectOperations(person);
223         detectOperations(pet);
224         detectOperations(race);
225 
226         detectOperations(person2);
227         detectOperations(pet2);
228         detectOperations(race2);
229 
230         detectOperations(race3);
231         detectOperations(pet3);
232     }
233 
234     @Test
235     @Override
236     public void testDoReplicate() throws Exception {
237 
238         doReplicate(TopiaTestEntityEnum.Person, person);
239         doReplicate(TopiaTestEntityEnum.Person, person2);
240         doReplicate(TopiaTestEntityEnum.Person, person, person2);
241 
242         doReplicate(TopiaTestEntityEnum.Pet, pet);
243         doReplicate(TopiaTestEntityEnum.Pet, pet2);
244         doReplicate(TopiaTestEntityEnum.Pet, pet, pet2, pet3);
245         doReplicate(TopiaTestEntityEnum.Pet, person2, pet3);
246 
247         doReplicate(TopiaTestEntityEnum.Race, race);
248         doReplicate(TopiaTestEntityEnum.Race, race2);
249         doReplicate(TopiaTestEntityEnum.Race, race, race2);
250 
251     }
252 
253     /**
254      * Cette methode montre pourquoi la simple replication ne peut pas
255      * fonctionne :)
256      * 
257      * Le replicateur ne deplique pas dans le bon ordre et on a donc des
258      * violations de clef etrangeres...
259      *
260      * @throws Exception pour toute erreur
261      */
262     @Test(expected = TopiaException.class)
263     public void testSimpleReplicateFailed() throws Exception {
264 
265         TopiaContext dstRootCtxt = createDb2("testSimpleReplicateFailed");
266 
267         //model = service.prepare(contracts, pet.getTopiaId());
268 
269         TopiaContext srcCtxt = ctxt.beginTransaction();
270         dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
271 
272         try {
273 
274             srcCtxt.replicateEntity(dstCtxt, pet);
275 
276             dstCtxt.commitTransaction();
277 
278         } finally {
279             srcCtxt.rollbackTransaction();
280             srcCtxt.closeContext();
281             dstCtxt.closeContext();
282         }
283     }
284 
285     /**
286      * Cette methode montre comment manuellement on peut effectuer la
287      * replication (en dettachant les dependances qui forment des cycles)
288      * 
289      * La methode utilisee ici peut ne pas fonctionner : si une clef metier est
290      * posee sur une dependance alors cela ne fonctionne pas.
291      *
292      * @throws Exception pour toute erreur
293      */
294     @Test
295     public void testSimpleReplicateNotSure() throws Exception {
296 
297         TopiaContext dstRootCtxt = createDb2("testSimpleReplicateNotSure");
298 
299         //model = service.prepare(contracts, pet.getTopiaId());
300 
301         TopiaContext srcCtxt = ctxt;
302         dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
303 
304         try {
305 
306 
307             srcCtxt.replicateEntity(dstCtxt, race);
308 
309             // on dettache l'entite qui pose probleme
310 
311             pet.setPerson(null);
312             srcCtxt.replicateEntity(dstCtxt, pet);
313             srcCtxt.rollbackTransaction();
314 
315             srcCtxt.replicateEntity(dstCtxt, person);
316 
317             dstCtxt.commitTransaction();
318             ((Pet) dstCtxt.findByTopiaId(pet.getTopiaId())).setPerson((Person) dstCtxt.findByTopiaId(person.getTopiaId()));
319             dstCtxt.commitTransaction();
320 
321             srcCtxt.rollbackTransaction();
322             person = update(person);
323 
324             assertEntityEquals(person, dstCtxt.findByTopiaId(person.getTopiaId()), null);
325         } finally {
326             srcCtxt.rollbackTransaction();
327             //srcCtxt.closeContext();
328             dstCtxt.closeContext();
329         }
330     }
331 
332     /**
333      * Cette methode montre comment manuellement on peut effectuer la
334      * replication (en dettachant les associations qui forment des cycles)
335      * 
336      * La methode utilisee ici fonctionne mieux que la precedante : il parrait
337      * dificille de pose une une clef metier sur une association :).
338      * 
339      * On remarque que l'on dettache l'assocation qui forme un cycle et que l'on
340      * est pas obligee de la reattachee car elle est bi-directionnelle.
341      * 
342      * On doit optimiser l'algorithme dans la methode {@link
343      * ReplicationModel#adjustOperations(TopiaEntityIdsMap)}.
344      *
345      * @throws Exception pour toute erreur
346      */
347     @Test
348     public void testSimpleReplicateSure() throws Exception {
349 
350         TopiaContext dstRootCtxt = createDb2("testSimpleReplicateSure");
351 
352         //model = service.prepare(contracts, pet.getTopiaId());
353 
354         TopiaContext srcCtxt = ctxt;
355         dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
356 
357         try {
358 
359             srcCtxt.replicateEntity(dstCtxt, race);
360             // on dettache l'association qui pose probleme
361             person.setPet(null);
362             srcCtxt.replicateEntity(dstCtxt, person);
363 
364             srcCtxt.replicateEntity(dstCtxt, pet);
365             srcCtxt.rollbackTransaction();
366             dstCtxt.commitTransaction();
367 
368             //((Person) dstCtxt.findByTopiaId(person.getTopiaId())).addPet(((Pet) dstCtxt.findByTopiaId(pet.getTopiaId())));
369             //dstCtxt.commitTransaction();
370 
371             srcCtxt.rollbackTransaction();
372 
373             srcCtxt.closeContext();
374             dstCtxt.closeContext();
375 
376             ctxt = context.beginTransaction();
377             dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
378 
379             person = update(person);
380 
381             assertEntityEquals(person, dstCtxt.findByTopiaId(person.getTopiaId()), null);
382 
383         } finally {
384             dstCtxt.closeContext();
385         }
386     }
387 
388     @Override
389     protected TopiaContext createDb(String name) throws Exception {
390 
391 //        File localDB = new File(getTestDir(getClass()), "db_" + name);
392 
393         Properties config = getH2Properties(name);
394 
395         context = TopiaContextFactory.getContext(config);
396 
397         TopiaContextImplementor tx = (TopiaContextImplementor) context.beginTransaction();
398 
399         person = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding master");
400         race = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race I");
401         pet = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding", Pet.PROPERTY_PERSON, person, Pet.PROPERTY_RACE, race);
402 
403         person2 = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding II master");
404         pet2 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding II");
405         race2 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race II");
406 
407         race3 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race III");
408         pet3 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding III", Pet.PROPERTY_RACE, race3);
409 
410         tx.commitTransaction();
411         tx.closeContext();
412         return context;
413     }
414 
415     @Override
416     protected TopiaContext createDb2(String name) throws Exception {
417 
418 //        File localDB = new File(getTestDir(getClass()), "db_" + name);
419 //
420 //        log.info("db dir :\n" + localDB.getAbsolutePath());
421 
422         Properties config = getH2Properties(name);
423 
424         return TopiaContextFactory.getContext(config);
425     }
426 
427     @Override
428     protected TopiaEntityEnum[] getContracts() {
429         return contracts;
430     }
431 
432     @Override
433     protected Log getLog() {
434         return log;
435     }
436 
437     protected Properties getH2Properties(String dbName) throws IOException {
438 
439 
440         Properties config = TestHelper.initTopiaContextConfiguration(tesDir, dbName);
441 
442 //        config.setProperty("hibernate.show_sql", "false");
443 //        config.setProperty("hibernate.hbm2ddl.auto", "create");
444 
445         config.setProperty("topia.persistence.classes", entitiesList);
446 //        config.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
447 //        config.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
448 //        config.setProperty("hibernate.connection.url", "jdbc:h2:file:" + f.getAbsolutePath() + "/db;create=true");
449 //        config.setProperty("hibernate.connection.username", "sa");
450 //        config.setProperty("hibernate.connection.password", "");
451 
452         config.setProperty(TopiaReplicationServiceImpl.TOPIA_SERVICE_NAME, TopiaReplicationServiceImpl.class.getName());
453 
454         return config;
455     }
456 }
457 
458