r3891 - in trunk: . pollen-rest-api pollen-rest-api/src/test/java/org/chorem/pollen/rest/api pollen-rest-api/src/test/resources pollen-services pollen-services/src/main/java/org/chorem/pollen/services pollen-services/src/main/java/org/chorem/pollen/services/config pollen-services/src/main/java/org/chorem/pollen/services/test pollen-services/src/main/resources pollen-services/src/test/java/org/chorem/pollen/service pollen-services/src/test/resources
Author: tchemit Date: 2014-04-30 13:26:00 +0200 (Wed, 30 Apr 2014) New Revision: 3891 Url: http://forge.chorem.org/projects/pollen/repository/revisions/3891 Log: improve tests Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/ trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenServiceContext.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/PollenApplication.java trunk/pollen-services/src/test/resources/pollen-services.properties Removed: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenRestApiApplicationContext.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenServiceContext.java trunk/pollen-services/src/test/java/org/chorem/pollen/service/FakePollenServiceContext.java Modified: trunk/pollen-rest-api/pom.xml trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollServiceTest.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java trunk/pollen-rest-api/src/test/resources/log4j.properties trunk/pollen-services/pom.xml trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java trunk/pollen-services/src/main/resources/fixtures.yaml trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java trunk/pom.xml Modified: trunk/pollen-rest-api/pom.xml =================================================================== --- trunk/pollen-rest-api/pom.xml 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/pom.xml 2014-04-30 11:26:00 UTC (rev 3891) @@ -47,6 +47,20 @@ <dependency> <groupId>org.debux.webmotion</groupId> <artifactId>webmotion-unittest</artifactId> + <exclusions> + <exclusion> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jdt.core.compiler</groupId> + <artifactId>ecj</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> @@ -99,6 +113,21 @@ </dependency> <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-log4j</artifactId> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -23,16 +23,22 @@ * #L% */ +import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; -import org.chorem.pollen.services.PollenFixtures; +import org.chorem.pollen.persistence.PollenPersistenceContext; import org.chorem.pollen.services.PollenServiceContext; -import org.chorem.pollen.services.service.FixturesService; -import org.debux.webmotion.unittest.WebMotionJUnit; +import org.chorem.pollen.services.config.PollenServiceConfig; +import org.chorem.pollen.services.test.FakePollenServiceContext; +import org.chorem.pollen.services.test.PollenApplication; +import org.debux.webmotion.unittest.WebMotionTest; import org.junit.After; import org.junit.Before; +import org.junit.Rule; +import org.nuiton.util.DateUtil; +import java.io.File; +import java.io.IOException; import java.util.Locale; /** @@ -41,25 +47,54 @@ * @author tchemit <chemit@codelutin.com> * @since 2.0 */ -public class AbstractPollenRestApiTest extends WebMotionJUnit { +public class AbstractPollenRestApiTest extends WebMotionTest { /** Logger. */ private static final Log log = LogFactory.getLog(AbstractPollenRestApiTest.class); - protected PollenFixtures fixtures; + @Rule + public final PollenApplication application = new PollenApplication("pollen-rest-api.properties"); + protected void loadFixtures(String fixturesSetName) { + + PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(); + + PollenServiceContext serviceContext = applicationContext.newServiceContext(applicationContext.newPersistenceContext(), Locale.FRANCE); + + application.loadFixtures(serviceContext, fixturesSetName); + } + + protected <E> E fixture(String id) { + + return application.fixture(id); + } + @Before - public void launchServer() throws Exception { + public void startServer() throws Exception { - PollenRestApiApplicationContext applicationContext = FakePollenRestApiApplicationContext.newFakeApplicationContext(); + PollenRestApiApplicationContext applicationContext = + new PollenRestApiApplicationContext(application.getConfiguration(), + application.getApplicationContext()) { + @Override + public PollenServiceContext newServiceContext(PollenPersistenceContext persistenceContext, Locale locale) { + + FakePollenServiceContext serviceContext = FakePollenServiceContext.newServiceContext( + DateUtil.createDate(1, 1, 2014), + Locale.FRANCE, + application.getConfiguration(), + application.getApplicationContext(), + application.newPersistenceContext()); + return serviceContext; + } + }; applicationContext.init(); PollenRestApiApplicationContext.setApplicationContext(applicationContext); - super.launchServer(); + super.startServer(); } @After - public void tearDown() { + public void stopServer() throws Exception { PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(); @@ -70,23 +105,20 @@ } applicationContext.close(); } + server.stop(); + server.destroy(); } - protected void loadFixtures(String fixturesSetName) { + protected void saveTestResult(String content) throws IOException { + String testName = application.getMethodName(); - PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(); - PollenTopiaPersistenceContext entityManager = applicationContext.newPersistenceContext(); - PollenServiceContext pollenServiceContext = applicationContext.newServiceContext(entityManager, Locale.FRANCE); - - FixturesService fixturesService = pollenServiceContext.newService(FixturesService.class); - fixtures = fixturesService.loadFixtures(fixturesSetName); - + PollenServiceConfig applicationConfig = PollenRestApiApplicationContext.getApplicationContext().getApplicationConfig(); + File dataDirectory = applicationConfig.getDataDirectory(); + File resultFile = new File(dataDirectory, testName); + FileUtils.write(resultFile, content); + if (log.isInfoEnabled()) { + log.info("ResultFile: " + resultFile); + } } - protected <E> E fixture(String id) { - - return fixtures.fixture(id); - - } - } Deleted: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenRestApiApplicationContext.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenRestApiApplicationContext.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenRestApiApplicationContext.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -1,146 +0,0 @@ -package org.chorem.pollen.rest.api; - -/* - * #%L - * Pollen :: Rest Api - * %% - * Copyright (C) 2009 - 2014 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ - -import org.apache.commons.lang3.SystemUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.persistence.PollenPersistenceContext; -import org.chorem.pollen.persistence.PollenTopiaApplicationContext; -import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; -import org.chorem.pollen.services.PollenServiceContext; -import org.chorem.pollen.services.config.PollenServiceConfig; -import org.hibernate.cfg.Environment; -import org.nuiton.util.DateUtil; - -import java.io.File; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Created on 4/27/14. - * - * @author Tony Chemit <chemit@codelutin.com> - * @since 2.0 - */ -public class FakePollenRestApiApplicationContext extends PollenRestApiApplicationContext { - - /** Logger. */ - private static final Log log = LogFactory.getLog(FakePollenRestApiApplicationContext.class); - - protected List<PollenTopiaPersistenceContext> openedTransactions = new LinkedList<>(); - - public static PollenRestApiApplicationContext newFakeApplicationContext() { - PollenServiceConfig applicationConfig = new PollenServiceConfig("pollen-rest-api.properties"); - PollenTopiaApplicationContext pollenTopiaApplicationContext = newTopiaApplicationContext(applicationConfig, UUID.randomUUID().toString()); - PollenRestApiApplicationContext result = new FakePollenRestApiApplicationContext(applicationConfig, pollenTopiaApplicationContext); - return result; - } - - public FakePollenRestApiApplicationContext(PollenServiceConfig applicationConfig, PollenTopiaApplicationContext pollenTopiaApplicationContext) { - - super(applicationConfig, pollenTopiaApplicationContext); - } - - @Override - public PollenServiceContext newServiceContext(PollenPersistenceContext persistenceContext, Locale locale) { - - FakePollenServiceContext serviceContext = new FakePollenServiceContext(); - serviceContext.setPersistenceContext(persistenceContext); - serviceContext.setPollenServiceConfig(getApplicationConfig()); - serviceContext.setTopiaApplicationContext(getTopiaApplicationContext()); - serviceContext.setLocale(locale); - serviceContext.setDate(DateUtil.createDate(1, 1, 2014)); - - return serviceContext; - } - - @Override - public PollenTopiaPersistenceContext newPersistenceContext() { - PollenTopiaPersistenceContext pollenTopiaPersistenceContext = super.newPersistenceContext(); - openedTransactions.add(pollenTopiaPersistenceContext); - return pollenTopiaPersistenceContext; - } - - @Override - public void close() { - if (!closed.get()) { - - for (PollenTopiaPersistenceContext openedTransaction : openedTransactions) { - - if (log.isTraceEnabled()) { - log.trace("closing transaction " + openedTransaction); - } - - if (!openedTransaction.isClosed()) { - openedTransaction.closeContext(); - } - } - openedTransactions.clear(); - } - super.close(); - } - - protected static PollenTopiaApplicationContext newTopiaApplicationContext(PollenServiceConfig applicationConfig, String dataBase) { - - Map<String, String> hibernateH2Config = new HashMap<>(); - - hibernateH2Config.putAll(applicationConfig.getTopiaProperties()); - - hibernateH2Config.put(Environment.DRIVER, org.h2.Driver.class.getName()); - hibernateH2Config.put(Environment.DIALECT, org.hibernate.dialect.H2Dialect.class.getName()); - hibernateH2Config.put(Environment.USER, "sa"); - hibernateH2Config.put(Environment.PASS, "sa"); - hibernateH2Config.put(Environment.HBM2DDL_AUTO, "update"); - - File tempDirFile = SystemUtils.getJavaIoTmpDir(); - - File databaseFile = new File(tempDirFile, dataBase); - - String h2dataPath = databaseFile.getAbsolutePath() + File.separator + "h2data"; - - String jdbcUrl = "jdbc:h2:file:" + h2dataPath; - - hibernateH2Config.put(Environment.URL, jdbcUrl); - - if (log.isTraceEnabled()) { - log.trace("will store H2 data in " + h2dataPath); - log.trace("allTopiaParameters = " + hibernateH2Config); - } - - if (log.isDebugEnabled()) { - log.debug("jdbc url is\n" + jdbcUrl); - } - - PollenTopiaApplicationContext applicationContext = new PollenTopiaApplicationContext(hibernateH2Config); - - if (log.isTraceEnabled()) { - log.trace("created root context " + applicationContext); - } - - return applicationContext; - } -} Deleted: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenServiceContext.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenServiceContext.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/FakePollenServiceContext.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -1,53 +0,0 @@ -package org.chorem.pollen.rest.api; - -/* - * #%L - * Pollen :: Service - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2009 - 2013 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ - -import com.google.common.base.Preconditions; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.services.DefaultPollenServiceContext; - -import java.util.Date; - -public class FakePollenServiceContext extends DefaultPollenServiceContext { - - private static final Log log = - LogFactory.getLog(FakePollenServiceContext.class); - - protected Date date; - - @Override - public Date getNow() { - Preconditions.checkState(date != null, "you must provide a date before running service test"); - if (log.isTraceEnabled()) { - log.trace("injecting fake date in service: " + date); - } - return date; - } - - public void setDate(Date date) { - this.date = date; - } - -} Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollServiceTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollServiceTest.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollServiceTest.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -1,6 +1,7 @@ package org.chorem.pollen.rest.api; import org.apache.http.client.fluent.Request; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -18,10 +19,17 @@ @Ignore public class PollServiceTest extends AbstractPollenRestApiTest { + @Before + public void setUp() throws Exception { + + loadFixtures("fixtures"); + } + @Test public void getPollsNew() throws URISyntaxException, IOException { Request request = createRequest("/v1/polls/new").Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } @@ -29,6 +37,7 @@ public void getPolls() throws URISyntaxException, IOException { Request request = createRequest("/v1/polls").Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } @@ -36,6 +45,7 @@ public void getPollsCreated() throws URISyntaxException, IOException { Request request = createRequest("/v1/polls/created").Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } @@ -43,6 +53,7 @@ public void getPollsInvited() throws URISyntaxException, IOException { Request request = createRequest("/v1/polls/invited").Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } @@ -50,61 +61,75 @@ public void getPollsParticipated() throws URISyntaxException, IOException { Request request = createRequest("/v1/polls/participated").Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } @Test public void getPoll() throws URISyntaxException, IOException { - String pollId = ""; + String pollId = "iioi"; Request request = createRequest("/v1/polls/" + pollId).Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } + @Ignore @Test public void postPoll() throws URISyntaxException, IOException { Request request = createRequest("/v1/polls").Post(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } + @Ignore @Test public void putPoll() throws URISyntaxException, IOException { String pollId = ""; Request request = createRequest("/v1/polls/" + pollId).Put(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } + @Ignore @Test public void deletePoll() throws URISyntaxException, IOException { String pollId = ""; Request request = createRequest("/v1/polls/" + pollId).Delete(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } + @Ignore @Test public void clonePoll() throws URISyntaxException, IOException { String pollId = ""; Request request = createRequest("/v1/polls/" + pollId).Post(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } + @Ignore @Test public void exportPoll() throws URISyntaxException, IOException { String pollId = ""; Request request = createRequest("/v1/polls/" + pollId + "/export").Get(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } + @Ignore @Test public void closePoll() throws URISyntaxException, IOException { String pollId = ""; Request request = createRequest("/v1/polls/" + pollId + "/close").Post(); String content = request.execute().returnContent().asString(); + saveTestResult(content); assertNotNull(content); } } Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -39,7 +39,6 @@ @Ignore public class PollenUserServiceTest extends AbstractPollenRestApiTest { - @Before public void setUp() throws Exception { @@ -50,50 +49,57 @@ public void getUsers() throws Exception { Request request = createRequest("/v1/users").Get(); - String result = request.execute().returnContent().asString(); - - assertTrue(result.contains("email")); + String content = request.execute().returnContent().asString(); + saveTestResult(content); + assertTrue(content.contains("email")); } @Test public void getUser() throws Exception { String userId = ""; Request request = createRequest("/v1/users/" + userId).Get(); - String result = request.execute().returnContent().asString(); - - assertTrue(result.contains("email")); + String content = request.execute().returnContent().asString(); + saveTestResult(content); + assertTrue(content.contains("email")); } + @Ignore @Test public void postUser() throws Exception { Request request = createRequest("/v1/users").Post(); - String result = request.execute().returnContent().asString(); - - assertTrue(result.contains("email2")); + String content = request.execute().returnContent().asString(); + saveTestResult(content); + assertTrue(content.contains("email2")); } + @Ignore @Test public void putUser() throws Exception { String userId = ""; Request request = createRequest("/v1/users/" + userId).Get(); - String result = request.execute().returnContent().asString(); - assertTrue(result.contains("email3")); + String content = request.execute().returnContent().asString(); + saveTestResult(content); + assertTrue(content.contains("email3")); } + @Ignore @Test public void deleteUser() throws Exception { String userId = ""; Request request = createRequest("/v1/users/" + userId).Delete(); - String result = request.execute().returnContent().asString(); - assertTrue(result.contains("OK!")); + String content = request.execute().returnContent().asString(); + saveTestResult(content); + assertTrue(content.contains("OK!")); } + @Ignore @Test public void validateUserEmail() throws Exception { String userId = ""; String token = ""; Request request = createRequest("/v1/users/" + userId + "?token=" + token).Put(); - String result = request.execute().returnContent().asString(); - assertTrue(result.contains("OK!")); + String content = request.execute().returnContent().asString(); + saveTestResult(content); + assertTrue(content.contains("OK!")); } } Modified: trunk/pollen-rest-api/src/test/resources/log4j.properties =================================================================== --- trunk/pollen-rest-api/src/test/resources/log4j.properties 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-rest-api/src/test/resources/log4j.properties 2014-04-30 11:26:00 UTC (rev 3891) @@ -26,7 +26,7 @@ log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{hh:mm:ss} %5p (%F:%L) %m%n -log4j.logger.org.chorem.pollen=TRACE +log4j.logger.org.chorem.pollen=INFO log4j.logger.org.debux=INFO # log4j.logger.org.hibernate.tool.hbm2ddl.SchemaExport=FATAL Modified: trunk/pollen-services/pom.xml =================================================================== --- trunk/pollen-services/pom.xml 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/pom.xml 2014-04-30 11:26:00 UTC (rev 3891) @@ -26,10 +26,10 @@ <groupId>org.nuiton.topia</groupId> <artifactId>topia-persistence</artifactId> </dependency> - <!--dependency> + <dependency> <groupId>org.nuiton.topia</groupId> <artifactId>topia-junit</artifactId> - </dependency--> + </dependency> <dependency> <groupId>org.hibernate</groupId> @@ -88,6 +88,7 @@ <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> + <scope>provided</scope> </dependency> <dependency> Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -53,13 +53,23 @@ protected ApplicationConfig applicationConfig; public PollenServiceConfig() { - this("pollen.properties"); + this("pollen.properties", null); } public PollenServiceConfig(String filename) { + this(filename, null); + } + + public PollenServiceConfig(String filename, Properties defaultValues) { applicationConfig = new ApplicationConfig(); applicationConfig.loadDefaultOptions(PollenServiceConfigOption.values()); applicationConfig.setConfigFileName(filename); + if (defaultValues != null) { + for (Map.Entry<Object, Object> entry : defaultValues.entrySet()) { + + applicationConfig.setOption((String) entry.getKey(), (String) entry.getValue()); + } + } try { applicationConfig.parse(); } catch (ArgumentsParserException e) { @@ -74,7 +84,7 @@ option.getKey(), applicationConfig.getOption(option))); } - log.info( builder.toString()); + log.info(builder.toString()); } } Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenServiceContext.java (from rev 3890, trunk/pollen-services/src/test/java/org/chorem/pollen/service/FakePollenServiceContext.java) =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenServiceContext.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenServiceContext.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -0,0 +1,73 @@ +package org.chorem.pollen.services.test; + +/* + * #%L + * Pollen :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.chorem.pollen.persistence.PollenTopiaApplicationContext; +import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; +import org.chorem.pollen.services.DefaultPollenServiceContext; +import org.chorem.pollen.services.config.PollenServiceConfig; + +import java.util.Date; +import java.util.Locale; + +public class FakePollenServiceContext extends DefaultPollenServiceContext { + + private static final Log log = + LogFactory.getLog(FakePollenServiceContext.class); + + protected Date date; + + + public static FakePollenServiceContext newServiceContext(Date now, + Locale locale, + PollenServiceConfig serviceConfig, + PollenTopiaApplicationContext applicationcontext, + PollenTopiaPersistenceContext persistenceContext) { + FakePollenServiceContext serviceContext = new FakePollenServiceContext(); + serviceContext.setPersistenceContext(persistenceContext); + serviceContext.setPollenServiceConfig(serviceConfig); + serviceContext.setTopiaApplicationContext(applicationcontext); + serviceContext.setLocale(locale); + serviceContext.setDate(now); + return serviceContext; + } + + @Override + public Date getNow() { + Preconditions.checkState(date != null, "you must provide a date before running service test"); + if (log.isTraceEnabled()) { + log.trace("injecting fake date in service: " + date); + } + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + +} Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/PollenApplication.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/PollenApplication.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/PollenApplication.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -0,0 +1,170 @@ +package org.chorem.pollen.services.test; + +/* + * #%L + * ToPIA :: JUnit + * $Id$ + * $HeadURL: http://svn.nuiton.org/svn/topia/trunk/topia-junit/src/main/java/org/nuiton/t... $ + * %% + * Copyright (C) 2004 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.chorem.pollen.persistence.PollenTopiaApplicationContext; +import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; +import org.chorem.pollen.services.PollenFixtures; +import org.chorem.pollen.services.PollenServiceContext; +import org.chorem.pollen.services.config.PollenServiceConfig; +import org.chorem.pollen.services.config.PollenServiceConfigOption; +import org.chorem.pollen.services.service.FixturesService; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +import org.nuiton.topia.junit.ConfigurationHelper; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.0 + */ +public class PollenApplication extends TestWatcher { + + /** Logger. */ + private static final Log log = LogFactory.getLog(PollenApplication.class); + + private File testBasedir; + + protected List<PollenTopiaPersistenceContext> openedTransactions = new LinkedList<>(); + + private PollenTopiaApplicationContext applicationContext; + + private PollenServiceConfig configuration; + + private final String configurationPath; + + + protected PollenFixtures fixtures; + + protected String methodName; + + public PollenApplication(String configurationPath) { + this.configurationPath = configurationPath; + } + + @Override + protected void starting(Description description) { + + methodName = description.getMethodName(); + + // get test directory + testBasedir = ConfigurationHelper.getTestSpecificDirectory( + description.getTestClass(), + description.getMethodName()); + + if (log.isDebugEnabled()) { + log.debug("testBasedir: " + testBasedir); + } + + // create configuration + + Properties defaultvalues = new Properties(); + defaultvalues.put(PollenServiceConfigOption.DATA_DIRECTORY.getKey(), testBasedir.getAbsolutePath()); + + configuration = new PollenServiceConfig(configurationPath, defaultvalues); + + Map<String, String> topiaProperties = configuration.getTopiaProperties(); + applicationContext = new PollenTopiaApplicationContext(topiaProperties); + + } + + @Override + public void finished(Description description) { + + for (PollenTopiaPersistenceContext openedTransaction : openedTransactions) { + + if (log.isTraceEnabled()) { + log.trace("closing transaction " + openedTransaction); + } + + openedTransaction.closeContext(); + + } + + if (applicationContext != null && !applicationContext.isClosed()) { + + if (log.isTraceEnabled()) { + log.trace("closing transaction " + applicationContext); + } + + applicationContext.closeContext(); + + } + } + + public File getTestBasedir() { + return testBasedir; + } + + public PollenTopiaApplicationContext getApplicationContext() { + return applicationContext; + } + + public PollenServiceConfig getConfiguration() { + return configuration; + } + + public String getMethodName() { + return methodName; + } + + public PollenTopiaPersistenceContext newPersistenceContext() { + + PollenTopiaPersistenceContext persistenceContext; + + persistenceContext = applicationContext.newPersistenceContext(); + + if (log.isTraceEnabled()) { + log.trace("opened transaction " + persistenceContext); + } + + openedTransactions.add(persistenceContext); + + return persistenceContext; + + } + + public void loadFixtures(PollenServiceContext serviceContext, String fixturesSetName) { + + FixturesService fixturesService = serviceContext.newService(FixturesService.class); + + fixtures = fixturesService.loadFixtures(fixturesSetName); + + } + + public <E> E fixture(String id) { + + return fixtures.fixture(id); + + } + +} Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/PollenApplication.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/pollen-services/src/main/resources/fixtures.yaml =================================================================== --- trunk/pollen-services/src/main/resources/fixtures.yaml 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/src/main/resources/fixtures.yaml 2014-04-30 11:26:00 UTC (rev 3891) @@ -1,4 +1,4 @@ -tony: +user_tony: &tony !user login: tony password: fake @@ -6,7 +6,7 @@ email: tony@pollen.fake administrator: false -jean: +user_jean: &jean !user login: jean password: fake @@ -14,7 +14,7 @@ email: jean@pollen.fake administrator: true -julien: +user_julien: &julien !user login: julien password: fake Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -24,173 +24,49 @@ */ import com.google.common.collect.Multimap; -import org.apache.commons.lang3.SystemUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.persistence.PollenTopiaApplicationContext; -import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; -import org.chorem.pollen.services.PollenFixtures; import org.chorem.pollen.services.PollenService; -import org.chorem.pollen.services.config.PollenServiceConfig; import org.chorem.pollen.services.exception.AbstractInvalidFormException; -import org.chorem.pollen.services.service.FixturesService; -import org.hibernate.cfg.Environment; -import org.junit.After; +import org.chorem.pollen.services.test.FakePollenServiceContext; +import org.chorem.pollen.services.test.PollenApplication; import org.junit.Assert; +import org.junit.Rule; import org.nuiton.util.DateUtil; -import java.io.File; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.Locale; public abstract class AbstractPollenServiceTest { - private static final Log log = LogFactory.getLog(AbstractPollenServiceTest.class); - protected static final double DELTA = 0.0001; - protected static PollenServiceConfig applicationConfig; + @Rule + public final PollenApplication application = new PollenApplication("pollen-services.properties"); - protected PollenTopiaApplicationContext applicationContext; - - protected List<PollenTopiaPersistenceContext> openedTransactions = new LinkedList<>(); - protected FakePollenServiceContext serviceContext; - protected PollenFixtures fixtures; + public void loadFixtures(String fixturesSetName) { - @After - public void tearDown() { - - for (PollenTopiaPersistenceContext openedTransaction : openedTransactions) { - - if (log.isTraceEnabled()) { - log.trace("closing transaction " + openedTransaction); - } - - openedTransaction.closeContext(); - - } - - if (applicationContext != null) { - - if (log.isTraceEnabled()) { - log.trace("closing transaction " + applicationContext); - } - - applicationContext.closeContext(); - - } - + application.loadFixtures(getServiceContext(), fixturesSetName); } - protected PollenTopiaApplicationContext newApplicationContext(String dataBase) { + public <E> E fixture(String id) { - Map<String, String> hibernateH2Config = new HashMap<>(); - - hibernateH2Config.putAll(getApplicationConfig().getTopiaProperties()); - - hibernateH2Config.put(Environment.DRIVER, org.h2.Driver.class.getName()); - hibernateH2Config.put(Environment.DIALECT, org.hibernate.dialect.H2Dialect.class.getName()); - hibernateH2Config.put(Environment.USER, "sa"); - hibernateH2Config.put(Environment.PASS, "sa"); - hibernateH2Config.put(Environment.HBM2DDL_AUTO, "update"); - - File tempDirFile = SystemUtils.getJavaIoTmpDir(); - - File databaseFile = new File(tempDirFile, dataBase); - - String h2dataPath = databaseFile.getAbsolutePath() + File.separator + "h2data"; - - String jdbcUrl = "jdbc:h2:file:" + h2dataPath; - - hibernateH2Config.put(Environment.URL, jdbcUrl); - - if (log.isTraceEnabled()) { - log.trace("will store H2 data in " + h2dataPath); - log.trace("allTopiaParameters = " + hibernateH2Config); - } - - if (log.isDebugEnabled()) { - log.debug("jdbc url is\n" + jdbcUrl); - } - - PollenTopiaApplicationContext topiaApplicationContext = new PollenTopiaApplicationContext(hibernateH2Config); - - if (log.isTraceEnabled()) { - log.trace("created root context " + topiaApplicationContext); - } - - return topiaApplicationContext; + return application.fixture(id); } - protected PollenTopiaApplicationContext getApplicationContext() { - - String databaseName = UUID.randomUUID().toString(); - - return newApplicationContext(databaseName); - } - - protected PollenTopiaPersistenceContext newPersistenceContext() { - - if (applicationContext == null) { - - applicationContext = getApplicationContext(); - } - - PollenTopiaPersistenceContext persistenceContext; - - persistenceContext = applicationContext.newPersistenceContext(); - - if (log.isTraceEnabled()) { - log.trace("opened transaction " + persistenceContext); - } - - openedTransactions.add(persistenceContext); - - return persistenceContext; - - } - - protected static PollenServiceConfig getApplicationConfig() { - - if (applicationConfig == null) { - - applicationConfig = new PollenServiceConfig("pollen-services.properties"); - } - - return applicationConfig; - } - protected FakePollenServiceContext getServiceContext() { if (serviceContext == null) { - serviceContext = new FakePollenServiceContext(); - serviceContext.setPollenServiceConfig(getApplicationConfig()); - PollenTopiaPersistenceContext persistenceContext = newPersistenceContext(); - serviceContext.setPersistenceContext(persistenceContext); - serviceContext.setDate(DateUtil.createDate(2, 11, 2009)); - serviceContext.setTopiaApplicationContext(getApplicationContext()); + serviceContext = FakePollenServiceContext.newServiceContext( + DateUtil.createDate(1, 1, 2014), + Locale.FRANCE, + application.getConfiguration(), + application.getApplicationContext(), + application.newPersistenceContext()); } return serviceContext; } - protected void loadFixtures(String fixturesSetName) { - - FixturesService fixturesService = getServiceContext().newService(FixturesService.class); - - fixtures = fixturesService.loadFixtures(fixturesSetName); - } - - protected <E> E fixture(String id) { - - return fixtures.fixture(id); - } - protected <E extends PollenService> E newService(Class<E> serviceClass) { return getServiceContext().newService(serviceClass); Deleted: trunk/pollen-services/src/test/java/org/chorem/pollen/service/FakePollenServiceContext.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/FakePollenServiceContext.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/FakePollenServiceContext.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -1,53 +0,0 @@ -package org.chorem.pollen.service; - -/* - * #%L - * Pollen :: Service - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2009 - 2013 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ - -import com.google.common.base.Preconditions; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.services.DefaultPollenServiceContext; - -import java.util.Date; - -public class FakePollenServiceContext extends DefaultPollenServiceContext { - - private static final Log log = - LogFactory.getLog(FakePollenServiceContext.class); - - protected Date date; - - @Override - public Date getNow() { - Preconditions.checkState(date != null, "you must provide a date before running service test"); - if (log.isTraceEnabled()) { - log.trace("injecting fake date in service: " + date); - } - return date; - } - - public void setDate(Date date) { - this.date = date; - } - -} Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -61,11 +61,11 @@ loadFixtures("fixtures"); - service = getServiceContext().newService(PollService.class); + service = newService(PollService.class); - serviceContext.setDate(new Date(1363948427576l)); + getServiceContext().setDate(new Date(1363948427576l)); - serviceContext.setSecurityContext(PollenSecurityContext.newContext(null)); + getServiceContext().setSecurityContext(PollenSecurityContext.newContext(null)); } @Test @@ -127,12 +127,12 @@ Assert.assertNotNull(createdPoll); Assert.assertNotNull(createdPoll.getTopiaId()); - serviceContext.newService(SecurityService.class).prepareSubject(createdPoll.getCreator().getTopiaId()); + newService(SecurityService.class).prepareSubject(createdPoll.getCreator().getTopiaId()); Poll reloadedPoll = service.getPoll(createdPoll.getTopiaId()); Assert.assertEquals(createdPoll, reloadedPoll); - Assert.assertEquals(serviceContext.getNow(), createdPoll.getBeginDate()); + Assert.assertEquals(getServiceContext().getNow(), createdPoll.getBeginDate()); Assert.assertNotNull(createdPoll.getCreator()); Assert.assertNotNull(createdPoll.getCreator().getTopiaId()); @@ -150,7 +150,7 @@ Assert.assertNotNull(createdChoice1); Assert.assertNotNull(createdChoice1.getTopiaId()); - ChoiceService choiceService = serviceContext.newService(ChoiceService.class); + ChoiceService choiceService = newService(ChoiceService.class); Choice reloadedChoice1 = choiceService.getChoice(createdPoll.getTopiaId(), createdChoice1.getTopiaId()); Assert.assertEquals(createdChoice1, reloadedChoice1); @@ -265,7 +265,7 @@ Poll reloadedPoll = service.getPoll(createdPoll.getTopiaId()); Assert.assertEquals(createdPoll, reloadedPoll); - Assert.assertEquals(serviceContext.getNow(), createdPoll.getBeginDate()); + Assert.assertEquals(getServiceContext().getNow(), createdPoll.getBeginDate()); Assert.assertNotNull(createdPoll.getCreator()); Assert.assertNotNull(createdPoll.getCreator().getTopiaId()); @@ -281,7 +281,7 @@ Assert.assertNotNull(createdChoice1); Assert.assertNotNull(createdChoice1.getTopiaId()); - ChoiceService choiceService = serviceContext.newService(ChoiceService.class); + ChoiceService choiceService = newService(ChoiceService.class); Choice reloadedChoice1 = choiceService.getChoice(createdPoll.getTopiaId(), createdChoice1.getTopiaId()); Assert.assertEquals(createdChoice1, reloadedChoice1); @@ -306,7 +306,7 @@ Assert.assertNotNull(createdVoterList); Assert.assertNotNull(createdVoterList.getTopiaId()); - VoterListService voterListService = serviceContext.newService(VoterListService.class); + VoterListService voterListService = newService(VoterListService.class); VoterList reloadedVoterList = voterListService.getVoterList(createdPoll.getTopiaId(), createdVoterList.getTopiaId()); Assert.assertEquals(createdVoterList, reloadedVoterList); Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java 2014-04-30 11:26:00 UTC (rev 3891) @@ -56,11 +56,11 @@ loadFixtures("fixtures"); - service = getServiceContext().newService(PollenUserService.class); + service = newService(PollenUserService.class); - serviceContext.setDate(new Date(1363948427576l)); + getServiceContext().setDate(new Date(1363948427576l)); - user = fixture("tony"); + user = application.fixture("user_tony"); } @Test @@ -143,7 +143,7 @@ Assert.assertNotNull(user); Assert.assertNull(user.getEmailActivationToken()); - serviceContext.getPersistenceContext().getHibernateSupport().getHibernateSession().evict(user); + getServiceContext().getPersistenceContext().getHibernateSupport().getHibernateSession().evict(user); String originalLogin = user.getLogin(); @@ -174,7 +174,7 @@ Assert.assertNotNull(user); Assert.assertNull(user.getEmailActivationToken()); - serviceContext.getPersistenceContext().getHibernateSupport().getHibernateSession().evict(user); + getServiceContext().getPersistenceContext().getHibernateSupport().getHibernateSession().evict(user); String email = "tony@pollen.org"; user.setEmail(email); Added: trunk/pollen-services/src/test/resources/pollen-services.properties =================================================================== --- trunk/pollen-services/src/test/resources/pollen-services.properties (rev 0) +++ trunk/pollen-services/src/test/resources/pollen-services.properties 2014-04-30 11:26:00 UTC (rev 3891) @@ -0,0 +1,6 @@ +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.connection.url=jdbc:h2:file:${pollen.data.directory}/db/pollen-rest-api +hibernate.connection.username=sa +hibernate.connection.password=sa +hibernate.connection.driver_class=org.h2.Driver +hibernate.hbm2ddl.auto=update Property changes on: trunk/pollen-services/src/test/resources/pollen-services.properties ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2014-04-30 10:05:11 UTC (rev 3890) +++ trunk/pom.xml 2014-04-30 11:26:00 UTC (rev 3891) @@ -177,6 +177,7 @@ <shiroVersion>1.2.2</shiroVersion> <slf4jVersion>1.7.6</slf4jVersion> <jettyVersion>9.0.3.v20130506</jettyVersion> + <tomcatEmbedVersion>7.0.47</tomcatEmbedVersion> <hibernateVersion>4.3.5.Final</hibernateVersion> <seleniumVersion>2.33.0</seleniumVersion> <mockitoVersion>1.9.5</mockitoVersion> @@ -313,12 +314,6 @@ <scope>test</scope> </dependency> - <dependency> - <groupId>org.debux.webmotion</groupId> - <artifactId>webmotion-extra-jpa</artifactId> - <version>${webmotionVersion}</version> - </dependency> - <!-- Nuiton libs --> <dependency> @@ -458,11 +453,32 @@ <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> - <version>7.0.41</version> + <version>${tomcatEmbedVersion}</version> <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-log4j</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version>
participants (1)
-
tchemit@users.chorem.org