From 010b65e34fc7bb9e0aa144734f807c115a5f29bd Mon Sep 17 00:00:00 2001 From: rmpestano Date: Sun, 29 May 2016 19:39:39 -0300 Subject: [PATCH 1/6] - adds support for scriptable datasets; - removes windows special characters; --- .../script/ScriptExecutorTest.java | 4 +- dbunit/pom.xml | 6 + .../persistence/dbunit/DBUnitDataHandler.java | 11 +- .../configuration/DBUnitConfiguration.java | 15 +++ .../dataset/scriptable/ScriptableDataSet.java | 25 ++++ .../scriptable/ScriptableDataSetIterator.java | 53 ++++++++ .../dataset/scriptable/ScriptableTable.java | 118 ++++++++++++++++++ .../deployment/DBUnitArchiveAppender.java | 17 ++- .../scriptable/ScriptableDataSetTest.java | 86 +++++++++++++ .../persistence/testutils/TableAssert.java | 4 +- dbunit/src/test/resources/scriptable.json | 21 ++++ dbunit/src/test/resources/scriptable.xml | 4 + dbunit/src/test/resources/scriptable.yml | 14 +++ int-tests/pom.xml | 40 ++++++ .../SeedingUsingScriptableDataSetTest.java | 64 ++++++++++ .../datasets/expected-users-scriptable.yml | 7 ++ .../test/resources-jboss-7.0.2/arquillian.xml | 1 + .../test/resources-tomee-1.5/arquillian.xml | 1 + .../resources-wildfly-8.1.0/arquillian.xml | 9 ++ pom.xml | 10 +- 20 files changed, 500 insertions(+), 10 deletions(-) create mode 100644 dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSet.java create mode 100644 dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetIterator.java create mode 100644 dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java create mode 100644 dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java create mode 100644 dbunit/src/test/resources/scriptable.json create mode 100644 dbunit/src/test/resources/scriptable.xml create mode 100644 dbunit/src/test/resources/scriptable.yml create mode 100644 int-tests/src/test/java/org/jboss/arquillian/integration/persistence/test/seeding/SeedingUsingScriptableDataSetTest.java create mode 100644 int-tests/src/test/resources-datasets/datasets/expected-users-scriptable.yml diff --git a/core/src/test/java/org/jboss/arquillian/persistence/script/ScriptExecutorTest.java b/core/src/test/java/org/jboss/arquillian/persistence/script/ScriptExecutorTest.java index 8a6dd08e..7228396b 100644 --- a/core/src/test/java/org/jboss/arquillian/persistence/script/ScriptExecutorTest.java +++ b/core/src/test/java/org/jboss/arquillian/persistence/script/ScriptExecutorTest.java @@ -264,7 +264,9 @@ public void should_insert_special_entities_with_custom_end_line() throws Excepti verify(connection.createStatement(), times(1)).execute(statementsCaptor.capture()); assertThat(statementsCaptor.getAllValues()).containsSequence( "insert into useraccount (id, firstname, lastname, username, password)" + - " values (1, 'John', 'Smith & Company', 'doovde;;', '&test©')\nGO" + " values (1, 'John', 'Smith & Company', 'doovde;;', '&test©')" + + System.getProperty("line.separator") + + "GO" ); } diff --git a/dbunit/pom.xml b/dbunit/pom.xml index 2110f1fb..7f272c6c 100644 --- a/dbunit/pom.xml +++ b/dbunit/pom.xml @@ -192,6 +192,12 @@ test + + org.codehaus.groovy + groovy-all + 2.4.6 + + diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java index 616fe8f3..0aadfa84 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java @@ -39,6 +39,7 @@ import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitConfiguration; import org.jboss.arquillian.persistence.dbunit.configuration.DBUnitDataSeedStrategyProvider; import org.jboss.arquillian.persistence.dbunit.dataset.DataSetRegister; +import org.jboss.arquillian.persistence.dbunit.dataset.scriptable.ScriptableDataSet; import org.jboss.arquillian.persistence.dbunit.event.CompareDBUnitData; import org.jboss.arquillian.persistence.dbunit.event.PrepareDBUnitData; import org.jboss.arquillian.persistence.dbunit.exception.DBUnitConnectionException; @@ -95,7 +96,11 @@ public void compare(@Observes CompareDBUnitData compareDataEvent) { if (excludeTables.length != 0) { currentDataSet = new FilteredDataSet(new ExcludeTableFilter(excludeTables), currentDataSet); } - final IDataSet expectedDataSet = mergeDataSets(dataSetRegister.get().getExpected()); + IDataSet expectedDataSet = mergeDataSets(dataSetRegister.get().getExpected()); + + if (dbunitConfigurationInstance.get().isScriptableDataSets()) { + expectedDataSet = new ScriptableDataSet(expectedDataSet); + } final DataSetComparator dataSetComparator = new DataSetComparator(compareDataEvent.getSortByColumns(), compareDataEvent.getColumnsToExclude(), compareDataEvent.getCustomColumnFilters()); dataSetComparator.compare(currentDataSet, expectedDataSet, assertionErrorCollector.get()); @@ -143,6 +148,10 @@ private void seedDatabase() throws Exception { final ITableFilter databaseSequenceFilter = sequenceFilterProvider.provide(connection, initialDataSet.getTableNames()); initialDataSet = new FilteredDataSet(databaseSequenceFilter, initialDataSet); } + + if(dbunitConfigurationInstance.get().isScriptableDataSets()){ + initialDataSet = new ScriptableDataSet(initialDataSet); + } seedingStrategy().execute(connection, initialDataSet); } diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/configuration/DBUnitConfiguration.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/configuration/DBUnitConfiguration.java index 675c3e7f..dcaedc11 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/configuration/DBUnitConfiguration.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/configuration/DBUnitConfiguration.java @@ -114,6 +114,9 @@ public class DBUnitConfiguration extends Configuration { private String customTableFilter; + private boolean scriptableDataSets = false; + + public DBUnitConfiguration() { super("persistence-dbunit", "arquillian.extension.persistence.dbunit."); } @@ -436,4 +439,16 @@ public String getCustomTableFilter() { public void setCustomTableFilter(String customTableFilter) { this.customTableFilter = customTableFilter; } + + public boolean isScriptableDataSets() { + return scriptableDataSets; + } + + /** + * @param scriptableDataSets Enable or disable usage of script language in datasets. + * Default value is false + */ + public void setScriptableDataSets(boolean scriptableDataSets) { + this.scriptableDataSets = scriptableDataSets; + } } diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSet.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSet.java new file mode 100644 index 00000000..baebfdf3 --- /dev/null +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSet.java @@ -0,0 +1,25 @@ +package org.jboss.arquillian.persistence.dbunit.dataset.scriptable; + +import org.dbunit.dataset.AbstractDataSet; +import org.dbunit.dataset.DataSetException; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITableIterator; + +/** + * @author Rafael Pestano + * + */ +public class ScriptableDataSet extends AbstractDataSet { + + private IDataSet delegate; + + public ScriptableDataSet(IDataSet delegate) { + this.delegate = delegate; + } + + @Override + protected ITableIterator createIterator(boolean reversed) throws DataSetException { + return new ScriptableDataSetIterator(reversed ? delegate.reverseIterator() : delegate.iterator()); + } + +} diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetIterator.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetIterator.java new file mode 100644 index 00000000..efe1f1e2 --- /dev/null +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetIterator.java @@ -0,0 +1,53 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.arquillian.persistence.dbunit.dataset.scriptable; + +import org.dbunit.dataset.DataSetException; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ITableIterator; +import org.dbunit.dataset.ITableMetaData; + +/** + * @author Rafael Pestano + * + */ +public class ScriptableDataSetIterator implements ITableIterator{ + + private ITableIterator delegate; + + public ScriptableDataSetIterator(ITableIterator delegate) { + this.delegate = delegate; + } + + @Override + public boolean next() throws DataSetException { + return delegate.next(); + } + + @Override + public ITableMetaData getTableMetaData() throws DataSetException { + return delegate.getTableMetaData(); + } + + @Override + public ITable getTable() throws DataSetException { + return new ScriptableTable(delegate.getTable()); + } + + + +} diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java new file mode 100644 index 00000000..2b904493 --- /dev/null +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java @@ -0,0 +1,118 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.arquillian.persistence.dbunit.dataset.scriptable; + +import org.dbunit.dataset.DataSetException; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ITableMetaData; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +/** + * @author Rafael Pestano + *

+ * Adds support for script language (JSR 223) in table values. + */ +public class ScriptableTable implements ITable { + + //any non digit char followed by ':' followed by 1 or more chars e.g: js: new Date().toString() + private final Pattern scriptEnginePattern = Pattern.compile(".*\\D.*:.+"); + + private static Logger log = Logger.getLogger(ScriptableTable.class.getName()); + + private Map engines; + + private ScriptEngineManager manager; + + private ITable delegate; + + + public ScriptableTable(ITable delegate) { + this.delegate = delegate; + engines = new HashMap(); + manager = new ScriptEngineManager(); + } + + @Override + public ITableMetaData getTableMetaData() { + return delegate.getTableMetaData(); + } + + @Override + public int getRowCount() { + return delegate.getRowCount(); + } + + @Override + public Object getValue(int row, String column) throws DataSetException { + Object value = delegate.getValue(row, column); + if (value != null && scriptEnginePattern.matcher(value.toString()).matches()) { + ScriptEngine engine = getScriptEngine(value.toString().trim()); + if (engine != null) { + Object scriptResult = getScriptResult(value.toString(), engine); + if (scriptResult != null) { + value = scriptResult; + } else { + throw new RuntimeException(String.format("Could not evaluate script expression for table '%s', column '%s'.", getTableMetaData().getTableName(), column)); + } + } + } + return value; + } + + /** + * Parses table cell to get script engine + * + * @param value the table cell + * @return scriptEngine + */ + private ScriptEngine getScriptEngine(String value) { + String engineName = value.substring(0, value.indexOf(":")); + if (engines.containsKey(engineName)) { + return engines.get(engineName); + } else { + ScriptEngine engine = manager.getEngineByName(engineName); + if (engine != null) { + engines.put(engineName, engine); + } else { + log.warning(String.format("Could not find script engine with name %s in classpath", engineName)); + } + return engine; + } + + } + + /** + * Evaluates the script expression + * + * @return script expression result or null if any evaluation error + */ + private Object getScriptResult(String script, ScriptEngine engine) { + String scriptToExecute = script.substring(script.indexOf(":") + 1); + try { + return engine.eval(scriptToExecute); + } catch (Exception e) { + return null; + } + } + +} diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/deployment/DBUnitArchiveAppender.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/deployment/DBUnitArchiveAppender.java index 75d477f6..fb477a89 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/deployment/DBUnitArchiveAppender.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/deployment/DBUnitArchiveAppender.java @@ -16,6 +16,7 @@ */ package org.jboss.arquillian.persistence.dbunit.deployment; +import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; import org.jboss.arquillian.container.test.spi.RemoteLoadableExtension; import org.jboss.arquillian.container.test.spi.client.deployment.AuxiliaryArchiveAppender; import org.jboss.arquillian.core.api.Instance; @@ -25,13 +26,13 @@ import org.jboss.arquillian.persistence.dbunit.container.RemoteDBUnitExtension; import org.jboss.arquillian.persistence.dbunit.filter.DefaultDatabaseSequenceFilterProvider; import org.jboss.arquillian.persistence.dbunit.filter.OracleDatabaseSequenceFilterProvider; -import org.jboss.arquillian.persistence.dbunit.filter.TableFilterResolver; import org.jboss.arquillian.persistence.spi.dbunit.filter.TableFilterProvider; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.Filters; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; +import javax.script.ScriptEngineFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -62,6 +63,20 @@ public Archive createAuxiliaryArchive() { .addAsServiceProvider(RemoteLoadableExtension.class, RemoteDBUnitExtension.class) .addAsServiceProvider(TableFilterProvider.class, DefaultDatabaseSequenceFilterProvider.class, OracleDatabaseSequenceFilterProvider.class); + if(dbunitConfigurationInstance.get().isScriptableDataSets()){ + dbUnitExtensionArchive.addPackages(true, + Filters.exclude(".*/package-info.*"), + "groovy", + "org.codehaus.groovy", + "groovyjarjarcommonscli", + "groovyjarjarasm.asm", + "groovyjarjarantlr" + ); + dbUnitExtensionArchive. + addAsServiceProvider(ScriptEngineFactory.class, GroovyScriptEngineFactory.class) + .addAsManifestResource("META-INF/dgminfo", "dgminfo") + .addAsManifestResource("META-INF/groovy-release-info.properties", "groovy-release-info.properties"); + } return dbUnitExtensionArchive; } diff --git a/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java b/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java new file mode 100644 index 00000000..9947082d --- /dev/null +++ b/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java @@ -0,0 +1,86 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.arquillian.persistence.dbunit.dataset.scriptable; + +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.jboss.arquillian.persistence.dbunit.dataset.json.JsonDataSet; +import org.jboss.arquillian.persistence.dbunit.dataset.yaml.YamlDataSet; +import org.jboss.arquillian.persistence.testutils.FileLoader; +import org.jboss.arquillian.persistence.testutils.TableAssert; +import org.junit.After; +import org.junit.Test; + +import java.io.InputStream; +import java.util.Date; + +public class ScriptableDataSetTest { + + InputStream input; + + @After + public void closeStream() { + FileLoader.close(input); + } + + @Test + public void should_load_all_rows_with_script_content_from_yaml_file() throws Exception { + // given + input = FileLoader.load("scriptable.yml"); + + // when + IDataSet yamlDataSet = new YamlDataSet(input); + yamlDataSet = new ScriptableDataSet(yamlDataSet); + + // then + TableAssert.assertThat(yamlDataSet.getTable("useraccount")) + .hasRow("id: 1", "firstname: John", "lastname: Smith", "username: doovde", "password: password", "age: 42.0") + .hasRow("id: 2", "firstname: Clark", "lastname: Kent", "username: superman", "password: kryptonite", "email: arquillian@jboss.org", "birthdate: "+new Date()); + } + + @Test + public void should_load_all_rows_with_script_content_from_json_file() throws Exception { + // given + input = FileLoader.load("scriptable.json"); + + // when + IDataSet jsonDataSet = new JsonDataSet(input); + jsonDataSet = new ScriptableDataSet(jsonDataSet); + + // then + TableAssert.assertThat(jsonDataSet.getTable("useraccount")) + .hasRow("id: 1", "firstname: John", "lastname: Smith", "username: doovde", "password: password", "age: 42.0") + .hasRow("id: 2", "firstname: Clark", "lastname: Kent", "username: superman", "password: kryptonite", "email: arquillian@jboss.org", "birthdate: "+new Date()); + } + + @Test + public void should_load_all_rows_with_script_content_from_xml_file() throws Exception { + // given + input = FileLoader.load("scriptable.xml"); + + // when + IDataSet xmlDataSet = new FlatXmlDataSetBuilder().build(input); + xmlDataSet = new ScriptableDataSet(xmlDataSet); + + // then + TableAssert.assertThat(xmlDataSet.getTable("useraccount")) + .hasRow("id: 1", "firstname: John", "lastname: Smith", "username: doovde", "password: password", "age: 42.0", "email: \"\" ", "birthdate: \"\" ") + .hasRow("id: 2", "firstname: Clark", "lastname: Kent", "username: superman", "password: kryptonite", "age: \"\" ", "email: arquillian@jboss.org", "birthdate: "+new Date()); + } + +} diff --git a/dbunit/src/test/java/org/jboss/arquillian/persistence/testutils/TableAssert.java b/dbunit/src/test/java/org/jboss/arquillian/persistence/testutils/TableAssert.java index 3f45874a..8b953ace 100644 --- a/dbunit/src/test/java/org/jboss/arquillian/persistence/testutils/TableAssert.java +++ b/dbunit/src/test/java/org/jboss/arquillian/persistence/testutils/TableAssert.java @@ -93,9 +93,9 @@ private List extractRows() { private Map extractRow(int rowIndex, final List columnNames) throws DataSetException { final Map cells = new HashMap(); for (String columnName : columnNames) { - String value = (String) actual.getValue(rowIndex, columnName); + Object value = actual.getValue(rowIndex, columnName); if (value != null) { - cells.put(columnName, value); + cells.put(columnName, value.toString()); } } return cells; diff --git a/dbunit/src/test/resources/scriptable.json b/dbunit/src/test/resources/scriptable.json new file mode 100644 index 00000000..61f55f8f --- /dev/null +++ b/dbunit/src/test/resources/scriptable.json @@ -0,0 +1,21 @@ +{ + "useraccount": [ + { + "id": 1, + "firstname": "John", + "lastname": "Smith", + "username": "doovde", + "password": "password", + "age": "js:var a=1;var b=1; 40 + a + b" + }, + { + "id": 2, + "firstname": "Clark", + "lastname": "Kent", + "username": "superman", + "password": "kryptonite", + "email": "arquillian@jboss.org", + "birthdate": "groovy: new Date()" + } + ] +} \ No newline at end of file diff --git a/dbunit/src/test/resources/scriptable.xml b/dbunit/src/test/resources/scriptable.xml new file mode 100644 index 00000000..413c580b --- /dev/null +++ b/dbunit/src/test/resources/scriptable.xml @@ -0,0 +1,4 @@ + + + + diff --git a/dbunit/src/test/resources/scriptable.yml b/dbunit/src/test/resources/scriptable.yml new file mode 100644 index 00000000..a1f85f4d --- /dev/null +++ b/dbunit/src/test/resources/scriptable.yml @@ -0,0 +1,14 @@ +useraccount: + - id: 1 + firstname: John + lastname: Smith + username: doovde + password: password + age: "js:var a=1;var b=1; 40 + a + b" + - id: 2 + firstname: Clark + lastname: Kent + username: superman + password: kryptonite + email: arquillian@jboss.org + birthdate: "groovy: new Date()" diff --git a/int-tests/pom.xml b/int-tests/pom.xml index cb2c5246..7f7fcd00 100644 --- a/int-tests/pom.xml +++ b/int-tests/pom.xml @@ -1073,6 +1073,46 @@ + + wildfly-remote + + + org.jboss.arquillian.extension + arquillian-transaction-jta + test + + + org.wildfly + wildfly-arquillian-container-remote + test + 8.2.0.Final + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + wildfly-remote + + + + + + + src/test/resources-datasets + + + src/test/resources-scripts + + + src/test/resources-wildfly-8.1.0 + + + + diff --git a/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/test/seeding/SeedingUsingScriptableDataSetTest.java b/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/test/seeding/SeedingUsingScriptableDataSetTest.java new file mode 100644 index 00000000..71633afe --- /dev/null +++ b/int-tests/src/test/java/org/jboss/arquillian/integration/persistence/test/seeding/SeedingUsingScriptableDataSetTest.java @@ -0,0 +1,64 @@ +package org.jboss.arquillian.integration.persistence.test.seeding; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.integration.persistence.example.UserAccount; +import org.jboss.arquillian.integration.persistence.util.Query; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.persistence.ShouldMatchDataSet; +import org.jboss.arquillian.persistence.UsingDataSet; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(Arquillian.class) +public class SeedingUsingScriptableDataSetTest { + + @Deployment + public static Archive createDeploymentPackage() { + WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war") + .addPackage(UserAccount.class.getPackage()) + .addClass(Query.class) + .addPackages(true, "org.assertj.core") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") + .addAsResource("test-persistence.xml", "META-INF/persistence.xml"); + return war; + } + + @PersistenceContext + EntityManager em; + + @Test + @UsingDataSet("expected-users-scriptable.yml") + @ShouldMatchDataSet(value = "expected-users-scriptable.yml",excludeColumns = "id") + public void should_seed_dataset_using_groovy_and_javascript() throws Exception { + // given + int expectedAmountOfUserEntries = 1; + + // when + @SuppressWarnings("unchecked") + List userAccounts = em.createQuery(Query.selectAllInJPQL(UserAccount.class)).getResultList(); + + // then + assertThat(userAccounts).hasSize(expectedAmountOfUserEntries); + + UserAccount userAccount = userAccounts.get(0); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Date now = sdf.parse(sdf.format(new Date())); + + assertThat(userAccount.getUsername()).isEqualTo("superman"); + assertThat(userAccount.getOpenDate()).isEqualTo(now); + + } + +} diff --git a/int-tests/src/test/resources-datasets/datasets/expected-users-scriptable.yml b/int-tests/src/test/resources-datasets/datasets/expected-users-scriptable.yml new file mode 100644 index 00000000..f54d8de7 --- /dev/null +++ b/int-tests/src/test/resources-datasets/datasets/expected-users-scriptable.yml @@ -0,0 +1,7 @@ +useraccount: + - id: "js: Math.floor(Math.random() * 6) + 1;" + firstname: Clark + lastname: Kent + username: "js: 'super'.concat('man')" + password: kryptonite + openDate: "groovy: new Date().clearTime()" diff --git a/int-tests/src/test/resources-jboss-7.0.2/arquillian.xml b/int-tests/src/test/resources-jboss-7.0.2/arquillian.xml index fae9a270..e36544b6 100644 --- a/int-tests/src/test/resources-jboss-7.0.2/arquillian.xml +++ b/int-tests/src/test/resources-jboss-7.0.2/arquillian.xml @@ -28,6 +28,7 @@ org.dbunit.ext.h2.H2DataTypeFactory + true diff --git a/int-tests/src/test/resources-tomee-1.5/arquillian.xml b/int-tests/src/test/resources-tomee-1.5/arquillian.xml index 837f08f2..03889fcf 100644 --- a/int-tests/src/test/resources-tomee-1.5/arquillian.xml +++ b/int-tests/src/test/resources-tomee-1.5/arquillian.xml @@ -29,6 +29,7 @@ openjpa_sequence_table org.dbunit.ext.hsqldb.HsqldbDataTypeFactory + true openjpa_sequence_table diff --git a/int-tests/src/test/resources-wildfly-8.1.0/arquillian.xml b/int-tests/src/test/resources-wildfly-8.1.0/arquillian.xml index e6d87e27..20877b2b 100644 --- a/int-tests/src/test/resources-wildfly-8.1.0/arquillian.xml +++ b/int-tests/src/test/resources-wildfly-8.1.0/arquillian.xml @@ -35,6 +35,14 @@ + + + + 127.0.0.1 + 9990 + + + java:jboss/UserTransaction @@ -46,6 +54,7 @@ org.dbunit.ext.h2.H2DataTypeFactory + true diff --git a/pom.xml b/pom.xml index 7c2f3a32..6bb344de 100644 --- a/pom.xml +++ b/pom.xml @@ -89,9 +89,9 @@ 1.10 - 1.5 - 1.5 - 1.5 + 1.6 + 1.6 + 1.6 @@ -210,8 +210,8 @@ org.codehaus.mojo.signature - java15 - 1.0 + java16 + 1.1 From 8977d21320b7bc800ce94c854dc6d3b7f6d447ad Mon Sep 17 00:00:00 2001 From: rmpestano Date: Sun, 29 May 2016 19:46:47 -0300 Subject: [PATCH 2/6] - code format --- .../jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java index 0aadfa84..f4a4b69e 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/DBUnitDataHandler.java @@ -149,7 +149,7 @@ private void seedDatabase() throws Exception { initialDataSet = new FilteredDataSet(databaseSequenceFilter, initialDataSet); } - if(dbunitConfigurationInstance.get().isScriptableDataSets()){ + if (dbunitConfigurationInstance.get().isScriptableDataSets()) { initialDataSet = new ScriptableDataSet(initialDataSet); } seedingStrategy().execute(connection, initialDataSet); From 35f988e52a4f9322398d3efef833ceeb7540b187 Mon Sep 17 00:00:00 2001 From: rmpestano Date: Sat, 4 Jun 2016 08:23:13 -0300 Subject: [PATCH 3/6] adds notes to jsr223 support. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 78ac873e..70d7233a 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ It comes with following features: * Seeding database using: * [DBUnit](http://dbunit.sourceforge.net/) with **XML**, **XLS**, **YAML** and **JSON** supported as data sets format. * Custom SQL scripts. + * Script from [JSR 223](http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/) languages. * Comparing database state at the end of the test using given data sets (with column exclusion). * Eviction JPA second level cache between test method invocation, see `@JpaCacheEviction`. From 47de511c2319052f381d8f3652aa1e613fb2be65 Mon Sep 17 00:00:00 2001 From: rmpestano Date: Sat, 4 Jun 2016 09:09:32 -0300 Subject: [PATCH 4/6] - script result exception handling should not rely on null result. - adds ScriptableDataSetEngineException and ScriptableDataSetEvalutationException. --- .../ScriptableDataSetEngineException.java | 38 +++++++++++++++++++ .../ScriptableDataSetEvaluationException.java | 38 +++++++++++++++++++ .../dataset/scriptable/ScriptableTable.java | 33 ++++++++-------- .../scriptable/ScriptableDataSetTest.java | 30 +++++++++++++++ .../scriptable_with_evaluation_error.yml | 7 ++++ .../scriptable_with_unknown_engine.yml | 7 ++++ 6 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEngineException.java create mode 100644 core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEvaluationException.java create mode 100644 dbunit/src/test/resources/scriptable_with_evaluation_error.yml create mode 100644 dbunit/src/test/resources/scriptable_with_unknown_engine.yml diff --git a/core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEngineException.java b/core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEngineException.java new file mode 100644 index 00000000..9247ef4f --- /dev/null +++ b/core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEngineException.java @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.arquillian.persistence.core.exception; + +public class ScriptableDataSetEngineException extends RuntimeException { + + private static final long serialVersionUID = 508713667493794528L; + + public ScriptableDataSetEngineException() { + } + + public ScriptableDataSetEngineException(String message) { + super(message); + } + + public ScriptableDataSetEngineException(Throwable cause) { + super(cause); + } + + public ScriptableDataSetEngineException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEvaluationException.java b/core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEvaluationException.java new file mode 100644 index 00000000..207c5804 --- /dev/null +++ b/core/src/main/java/org/jboss/arquillian/persistence/core/exception/ScriptableDataSetEvaluationException.java @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.arquillian.persistence.core.exception; + +public class ScriptableDataSetEvaluationException extends RuntimeException { + + private static final long serialVersionUID = 508713667493794528L; + + public ScriptableDataSetEvaluationException() { + } + + public ScriptableDataSetEvaluationException(String message) { + super(message); + } + + public ScriptableDataSetEvaluationException(Throwable cause) { + super(cause); + } + + public ScriptableDataSetEvaluationException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java index 2b904493..2987425d 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java @@ -22,15 +22,19 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; +import javax.script.ScriptException; import java.util.HashMap; import java.util.Map; +import org.jboss.arquillian.persistence.core.exception.ScriptableDataSetEvaluationException; +import org.jboss.arquillian.persistence.core.exception.ScriptableDataSetEngineException; + import java.util.logging.Logger; import java.util.regex.Pattern; /** + * Adds support for script language (JSR 223) in table values. + * * @author Rafael Pestano - *

- * Adds support for script language (JSR 223) in table values. */ public class ScriptableTable implements ITable { @@ -68,17 +72,20 @@ public Object getValue(int row, String column) throws DataSetException { if (value != null && scriptEnginePattern.matcher(value.toString()).matches()) { ScriptEngine engine = getScriptEngine(value.toString().trim()); if (engine != null) { - Object scriptResult = getScriptResult(value.toString(), engine); - if (scriptResult != null) { - value = scriptResult; - } else { - throw new RuntimeException(String.format("Could not evaluate script expression for table '%s', column '%s'.", getTableMetaData().getTableName(), column)); + try { + Object scriptResult = getScriptResult(value.toString(), engine); + if (scriptResult != null) { + value = scriptResult; + } + }catch (Exception e){ + throw new ScriptableDataSetEvaluationException(String.format("Could not evaluate script expression for table '%s', column '%s'.", getTableMetaData().getTableName(), column)); } } } return value; } + /** * Parses table cell to get script engine * @@ -94,7 +101,7 @@ private ScriptEngine getScriptEngine(String value) { if (engine != null) { engines.put(engineName, engine); } else { - log.warning(String.format("Could not find script engine with name %s in classpath", engineName)); + throw new ScriptableDataSetEngineException(String.format("Could not find script engine with name %s in classpath", engineName)); } return engine; } @@ -104,15 +111,11 @@ private ScriptEngine getScriptEngine(String value) { /** * Evaluates the script expression * - * @return script expression result or null if any evaluation error + * @return script expression result */ - private Object getScriptResult(String script, ScriptEngine engine) { + private Object getScriptResult(String script, ScriptEngine engine) throws ScriptException { String scriptToExecute = script.substring(script.indexOf(":") + 1); - try { - return engine.eval(scriptToExecute); - } catch (Exception e) { - return null; - } + return engine.eval(scriptToExecute); } } diff --git a/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java b/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java index 9947082d..0d274529 100644 --- a/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java +++ b/dbunit/src/test/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableDataSetTest.java @@ -17,8 +17,11 @@ */ package org.jboss.arquillian.persistence.dbunit.dataset.scriptable; +import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.jboss.arquillian.persistence.core.exception.ScriptableDataSetEngineException; +import org.jboss.arquillian.persistence.core.exception.ScriptableDataSetEvaluationException; import org.jboss.arquillian.persistence.dbunit.dataset.json.JsonDataSet; import org.jboss.arquillian.persistence.dbunit.dataset.yaml.YamlDataSet; import org.jboss.arquillian.persistence.testutils.FileLoader; @@ -38,6 +41,33 @@ public void closeStream() { FileLoader.close(input); } + + @Test(expected = ScriptableDataSetEngineException.class) + public void should_not_load_rows_with_unknown_script_engine() throws DataSetException { + input = FileLoader.load("scriptable_with_unknown_engine.yml"); + + // when + IDataSet yamlDataSet = new YamlDataSet(input); + yamlDataSet = new ScriptableDataSet(yamlDataSet); + + // then + TableAssert.assertThat(yamlDataSet.getTable("useraccount")) + .hasRow("id: 1", "firstname: John", "lastname: Smith", "username: doovde", "password: password", "age: 42.0"); + } + + @Test(expected = ScriptableDataSetEvaluationException.class) + public void should_not_load_rows_with_script_evaluation_error() throws DataSetException { + input = FileLoader.load("scriptable_with_evaluation_error.yml"); + + // when + IDataSet yamlDataSet = new YamlDataSet(input); + yamlDataSet = new ScriptableDataSet(yamlDataSet); + + // then + TableAssert.assertThat(yamlDataSet.getTable("useraccount")) + .hasRow("id: 1", "firstname: John", "lastname: Smith", "username: doovde", "password: password", "age: 42.0"); + } + @Test public void should_load_all_rows_with_script_content_from_yaml_file() throws Exception { // given diff --git a/dbunit/src/test/resources/scriptable_with_evaluation_error.yml b/dbunit/src/test/resources/scriptable_with_evaluation_error.yml new file mode 100644 index 00000000..b1d7fc6a --- /dev/null +++ b/dbunit/src/test/resources/scriptable_with_evaluation_error.yml @@ -0,0 +1,7 @@ +useraccount: + - id: 1 + firstname: John + lastname: Smith + username: doovde + password: password + age: "js:var a=0;var b=0; return abcdefg" \ No newline at end of file diff --git a/dbunit/src/test/resources/scriptable_with_unknown_engine.yml b/dbunit/src/test/resources/scriptable_with_unknown_engine.yml new file mode 100644 index 00000000..3b2a452b --- /dev/null +++ b/dbunit/src/test/resources/scriptable_with_unknown_engine.yml @@ -0,0 +1,7 @@ +useraccount: + - id: 1 + firstname: John + lastname: Smith + username: doovde + password: password + age: "kotlin:var a=1;var b=1; 40 + a + b" From c9719465ca197de1cfa659040e4c12ae1c961a4a Mon Sep 17 00:00:00 2001 From: rmpestano Date: Sat, 4 Jun 2016 09:17:08 -0300 Subject: [PATCH 5/6] - removed unnecessary null check --- .../dbunit/dataset/scriptable/ScriptableTable.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java index 2987425d..3048ff5c 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java @@ -73,11 +73,8 @@ public Object getValue(int row, String column) throws DataSetException { ScriptEngine engine = getScriptEngine(value.toString().trim()); if (engine != null) { try { - Object scriptResult = getScriptResult(value.toString(), engine); - if (scriptResult != null) { - value = scriptResult; - } - }catch (Exception e){ + return getScriptResult(value.toString(), engine); + } catch (Exception e) { throw new ScriptableDataSetEvaluationException(String.format("Could not evaluate script expression for table '%s', column '%s'.", getTableMetaData().getTableName(), column)); } } From d7fd3b1d6a96297d4a6ffed49b95fa9e175b5b1b Mon Sep 17 00:00:00 2001 From: rmpestano Date: Sun, 19 Jun 2016 14:04:42 -0300 Subject: [PATCH 6/6] simplified script engine regex pattern --- .../persistence/dbunit/dataset/scriptable/ScriptableTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java index 3048ff5c..7796c14f 100644 --- a/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java +++ b/dbunit/src/main/java/org/jboss/arquillian/persistence/dbunit/dataset/scriptable/ScriptableTable.java @@ -39,7 +39,7 @@ public class ScriptableTable implements ITable { //any non digit char followed by ':' followed by 1 or more chars e.g: js: new Date().toString() - private final Pattern scriptEnginePattern = Pattern.compile(".*\\D.*:.+"); + private final Pattern scriptEnginePattern = Pattern.compile("^[a-zA-Z]+:.+"); private static Logger log = Logger.getLogger(ScriptableTable.class.getName());