diff --git a/src/test/java/io/ebean/BaseTestCase.java b/src/test/java/io/ebean/BaseTestCase.java index da3c31218..f6d9f7c29 100644 --- a/src/test/java/io/ebean/BaseTestCase.java +++ b/src/test/java/io/ebean/BaseTestCase.java @@ -5,12 +5,14 @@ import io.ebeaninternal.api.SpiEbeanServer; import io.ebeaninternal.server.deploy.BeanDescriptor; import org.tests.model.basic.Country; import org.avaje.agentloader.AgentLoader; +import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Types; -public class BaseTestCase { +@RunWith(ConditionalTestRunner.class) +public abstract class BaseTestCase { protected static Logger logger = LoggerFactory.getLogger(BaseTestCase.class); @@ -75,6 +77,10 @@ public class BaseTestCase { return Platform.ORACLE == platform(); } + public boolean isDb2() { + return Platform.DB2 == platform(); + } + public boolean isPostgres() { return Platform.POSTGRES == platform(); } diff --git a/src/test/java/io/ebean/ConditionalTestRunner.java b/src/test/java/io/ebean/ConditionalTestRunner.java new file mode 100644 index 000000000..55f27f287 --- /dev/null +++ b/src/test/java/io/ebean/ConditionalTestRunner.java @@ -0,0 +1,48 @@ +package io.ebean; + +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; + +import io.ebean.annotation.ForPlatform; +import io.ebean.annotation.IgnorePlatform; + +/** + * This testrunner checks for an {@link IgnorePlatform} annotation and ignores the test. + * + * @author Roland Praml, FOCONIS AG + */ +public class ConditionalTestRunner extends BlockJUnit4ClassRunner { + public ConditionalTestRunner(Class klass) throws InitializationError { + super(klass); + } + @Override + public void runChild(FrameworkMethod method, RunNotifier notifier) { + ForPlatform forPlatform = method.getAnnotation(ForPlatform.class); + if (forPlatform != null) { + if (!platformMath(forPlatform.value())) { + notifier.fireTestIgnored(describeChild(method)); + return; + } + } + + IgnorePlatform ignore = method.getAnnotation(IgnorePlatform.class); + + if (ignore == null || !platformMath(ignore.value())) { + super.runChild(method, notifier); + } else { + notifier.fireTestIgnored(describeChild(method)); + } + + } + private boolean platformMath(Platform[] platforms) { + Platform current = Ebean.getDefaultServer().getPluginApi().getDatabasePlatform().getPlatform(); + for (Platform p : platforms) { + if (p.equals(current)) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/src/test/java/io/ebean/PrimaryServerTest.java b/src/test/java/io/ebean/PrimaryServerTest.java index 67e6ea46f..998afd9a5 100644 --- a/src/test/java/io/ebean/PrimaryServerTest.java +++ b/src/test/java/io/ebean/PrimaryServerTest.java @@ -1,14 +1,15 @@ package io.ebean; import io.ebean.PrimaryServer; -import org.junit.Ignore; +import io.ebean.annotation.ForPlatform; + import org.junit.Test; import java.util.Properties; import static org.junit.Assert.*; -public class PrimaryServerTest { +public class PrimaryServerTest extends BaseTestCase { @Test @@ -19,8 +20,8 @@ public class PrimaryServerTest { assertFalse(PrimaryServer.isSkip()); } - @Ignore @Test + @ForPlatform(Platform.H2) public void testGetPrimaryServerName() throws Exception { String primaryServerName = PrimaryServer.getDefaultServerName(); diff --git a/src/test/java/io/ebean/UpdateQueryTest.java b/src/test/java/io/ebean/UpdateQueryTest.java index c8689d608..126ae8100 100644 --- a/src/test/java/io/ebean/UpdateQueryTest.java +++ b/src/test/java/io/ebean/UpdateQueryTest.java @@ -2,6 +2,9 @@ package io.ebean; import org.tests.model.basic.Country; import org.tests.model.basic.Customer; + +import io.ebean.annotation.IgnorePlatform; + import org.junit.Test; import java.sql.Timestamp; @@ -30,6 +33,7 @@ public class UpdateQueryTest extends BaseTestCase { } @Test + @IgnorePlatform(Platform.SQLSERVER) public void withTableAlias() { EbeanServer server = server(); diff --git a/src/test/java/io/ebean/annotation/ForPlatform.java b/src/test/java/io/ebean/annotation/ForPlatform.java new file mode 100644 index 000000000..b150c94bb --- /dev/null +++ b/src/test/java/io/ebean/annotation/ForPlatform.java @@ -0,0 +1,17 @@ +package io.ebean.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.ebean.Platform; +/** + * Annotation to run a test for a certain platform. + * @author Roland Praml, FOCONIS AG + */ +@Target(ElementType.METHOD ) +@Retention(RetentionPolicy.RUNTIME) +public @interface ForPlatform { + Platform[] value(); +} diff --git a/src/test/java/io/ebean/annotation/IgnorePlatform.java b/src/test/java/io/ebean/annotation/IgnorePlatform.java new file mode 100644 index 000000000..bb788fc01 --- /dev/null +++ b/src/test/java/io/ebean/annotation/IgnorePlatform.java @@ -0,0 +1,17 @@ +package io.ebean.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.ebean.Platform; +/** + * Annotation to ignore a test for a certain platform. + * @author Roland Praml, FOCONIS AG + */ +@Target(ElementType.METHOD ) +@Retention(RetentionPolicy.RUNTIME) +public @interface IgnorePlatform { + Platform[] value(); +} diff --git a/src/test/java/io/ebeaninternal/server/cache/DefaultServerCache_RunEvictionTest.java b/src/test/java/io/ebeaninternal/server/cache/DefaultServerCache_RunEvictionTest.java index cc2c20601..4ba1d82a4 100644 --- a/src/test/java/io/ebeaninternal/server/cache/DefaultServerCache_RunEvictionTest.java +++ b/src/test/java/io/ebeaninternal/server/cache/DefaultServerCache_RunEvictionTest.java @@ -30,7 +30,7 @@ public class DefaultServerCache_RunEvictionTest { this.cache = createCache(); } - @Ignore + @Ignore("test takes long time") @Test public void runEvict() throws InterruptedException { diff --git a/src/test/java/io/ebeaninternal/server/core/DefaultBackgroundExecutorTest.java b/src/test/java/io/ebeaninternal/server/core/DefaultBackgroundExecutorTest.java index bd9234318..647d95613 100644 --- a/src/test/java/io/ebeaninternal/server/core/DefaultBackgroundExecutorTest.java +++ b/src/test/java/io/ebeaninternal/server/core/DefaultBackgroundExecutorTest.java @@ -6,7 +6,7 @@ import org.junit.Test; public class DefaultBackgroundExecutorTest { @Test - @Ignore + @Ignore("test takes long time") public void shutdown_when_running_expect_waitAndNiceShutdown() throws Exception { DefaultBackgroundExecutor es = new DefaultBackgroundExecutor(1, 20, "test"); @@ -19,7 +19,7 @@ public class DefaultBackgroundExecutorTest { } @Test - @Ignore + @Ignore("test takes long time") public void shutdown_when_rougeRunnable_expect_InterruptedException() throws Exception { DefaultBackgroundExecutor es = new DefaultBackgroundExecutor(1, 10, "test"); diff --git a/src/test/java/org/tests/basic/TestMetaAnnotation.java b/src/test/java/org/tests/basic/TestMetaAnnotation.java index 8ce5c2441..1c3700763 100644 --- a/src/test/java/org/tests/basic/TestMetaAnnotation.java +++ b/src/test/java/org/tests/basic/TestMetaAnnotation.java @@ -2,6 +2,8 @@ package org.tests.basic; import io.ebean.BaseTestCase; import io.ebean.Ebean; +import io.ebean.Platform; +import io.ebean.annotation.IgnorePlatform; import org.tests.model.basic.Address; import org.tests.model.basic.metaannotation.SizeMedium; import org.junit.Test; @@ -9,6 +11,7 @@ import org.junit.Test; import javax.persistence.PersistenceException; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * Very simple test case to check if Ebean recognizes meta-annotation correctly. @@ -46,17 +49,16 @@ public class TestMetaAnnotation extends BaseTestCase { * This test writes 101 spaces to "line1" which is annotated with @Size(max=100). */ @Test + @IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL}) // pg & mssql does not fail if string is too long. public void testWrite101SpacesToLine1() { - if (isH2()) { - Address address = new Address(); - address.setLine1(spaces101); - try { - Ebean.save(address); - assertTrue("H2 fails this insert", false); - } catch (PersistenceException e) { - assertTrue(true); - } + Address address = new Address(); + address.setLine1(spaces101); + try { + Ebean.save(address); + fail("Test failed, Could insert a too long string"); + } catch (PersistenceException e) { + assertTrue(true); } } @@ -64,17 +66,16 @@ public class TestMetaAnnotation extends BaseTestCase { * This test writes 101 spaces to "line1" which is meta-annotated with {@link SizeMedium}. */ @Test + @IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL}) public void testWrite101SpacesToLine2() { - if (isH2()) { - Address address = new Address(); - address.setLine2(spaces101); - try { - Ebean.save(address); - assertTrue("H2 fails this insert", false); - } catch (PersistenceException e) { - assertTrue(true); - } + Address address = new Address(); + address.setLine2(spaces101); + try { + Ebean.save(address); + fail("Test failed, Could insert a too long string"); + } catch (PersistenceException e) { + assertTrue(true); } } diff --git a/src/test/java/org/tests/basic/TestQueryForUpdate.java b/src/test/java/org/tests/basic/TestQueryForUpdate.java index aa4b357a8..0a3ada27f 100644 --- a/src/test/java/org/tests/basic/TestQueryForUpdate.java +++ b/src/test/java/org/tests/basic/TestQueryForUpdate.java @@ -4,8 +4,11 @@ import io.ebean.AcquireLockException; import io.ebean.BaseTestCase; import io.ebean.Ebean; import io.ebean.EbeanServer; +import io.ebean.Platform; import io.ebean.Query; import io.ebean.Transaction; +import io.ebean.annotation.ForPlatform; + import org.junit.Test; import org.tests.model.basic.Customer; import org.tests.model.basic.ResetBasicData; @@ -17,37 +20,38 @@ import static org.junit.Assert.assertTrue; public class TestQueryForUpdate extends BaseTestCase { - private boolean isSupportLocking() { - return isH2() || isOracle() || isPostgres() || isSqlServer() || isMySql(); - } - + @Test + @ForPlatform({ + Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL + }) public void testForUpdate() { - if (isSupportLocking()) { - ResetBasicData.reset(); + ResetBasicData.reset(); - Query query = Ebean.find(Customer.class) + Query query = Ebean.find(Customer.class) .forUpdate() .setMaxRows(1) .order().desc("id"); query.findList(); - if (isSqlServer()) { - assertThat(sqlOf(query)).contains("with (updlock)"); - } else { - assertThat(sqlOf(query)).contains("for update"); - } + if (isSqlServer()) { + assertThat(sqlOf(query)).contains("with (updlock)"); + } else { + assertThat(sqlOf(query)).contains("for update"); } } @Test + @ForPlatform({ + Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER + }) public void testForUpdate_noWait() { - if (isSupportLocking()) { - ResetBasicData.reset(); + ResetBasicData.reset(); - EbeanServer server = Ebean.getDefaultServer(); + + EbeanServer server = Ebean.getDefaultServer(); Ebean.beginTransaction(); try { @@ -83,9 +87,8 @@ public class TestQueryForUpdate extends BaseTestCase { txn2.end(); } - } finally { - Ebean.endTransaction(); - } + } finally { + Ebean.endTransaction(); } } } diff --git a/src/test/java/org/tests/basic/encrypt/TestEncrypt.java b/src/test/java/org/tests/basic/encrypt/TestEncrypt.java index b51b1b125..a92e71cc8 100644 --- a/src/test/java/org/tests/basic/encrypt/TestEncrypt.java +++ b/src/test/java/org/tests/basic/encrypt/TestEncrypt.java @@ -2,15 +2,16 @@ package org.tests.basic.encrypt; import io.ebean.BaseTestCase; import io.ebean.Ebean; +import io.ebean.Platform; import io.ebean.SqlQuery; import io.ebean.SqlRow; import io.ebean.Update; +import io.ebean.annotation.ForPlatform; import io.ebean.config.dbplatform.DbEncrypt; import io.ebeaninternal.api.SpiEbeanServer; import org.tests.model.basic.EBasicEncrypt; import org.ebeantest.LoggedSqlCollector; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import java.sql.Date; @@ -22,13 +23,9 @@ public class TestEncrypt extends BaseTestCase { @Test + @ForPlatform(Platform.H2) // only run this on H2 - PGCrypto not happy on CI server public void testQueryBind() { - if (!isH2()) { - // only run this on H2 - PGCrypto not happy on CI server - return; - } - LoggedSqlCollector.start(); Ebean.find(EBasicEncrypt.class) .where().startsWith("description", "Rob") @@ -39,8 +36,8 @@ public class TestEncrypt extends BaseTestCase { assertThat(loggedSql.get(0)).contains("; --bind(****,Rob%)"); } - @Ignore @Test + @ForPlatform(Platform.H2) public void test() { Update deleteAll = Ebean.createUpdate(EBasicEncrypt.class, "delete from EBasicEncrypt"); diff --git a/src/test/java/org/tests/idkeys/TestGeneratedKeys.java b/src/test/java/org/tests/idkeys/TestGeneratedKeys.java index 809dc5712..12b307b81 100644 --- a/src/test/java/org/tests/idkeys/TestGeneratedKeys.java +++ b/src/test/java/org/tests/idkeys/TestGeneratedKeys.java @@ -1,7 +1,9 @@ package org.tests.idkeys; import io.ebean.BaseTestCase; +import io.ebean.Platform; import io.ebean.Transaction; +import io.ebean.annotation.ForPlatform; import io.ebean.config.dbplatform.IdType; import io.ebeaninternal.api.SpiEbeanServer; import org.junit.Test; @@ -17,6 +19,7 @@ import static org.junit.Assert.*; public class TestGeneratedKeys extends BaseTestCase { @Test + @ForPlatform(Platform.H2) // readSequenceValue is H2 specific public void testSequence() throws SQLException { SpiEbeanServer server = spiEbeanServer(); IdType idType = server.getDatabasePlatform().getDbIdentity().getIdType(); @@ -24,10 +27,6 @@ public class TestGeneratedKeys extends BaseTestCase { // only run this test when SEQUENCE is being used return; } - if (!isH2()) { - // readSequenceValue is H2 specific - return; - } Transaction tx = server.beginTransaction(); diff --git a/src/test/java/org/tests/model/m2o/TestManyToOneAsOne.java b/src/test/java/org/tests/model/m2o/TestManyToOneAsOne.java index 77ec50a05..63060696e 100644 --- a/src/test/java/org/tests/model/m2o/TestManyToOneAsOne.java +++ b/src/test/java/org/tests/model/m2o/TestManyToOneAsOne.java @@ -2,6 +2,8 @@ package org.tests.model.m2o; import io.ebean.BaseTestCase; import io.ebean.Ebean; +import io.ebean.Platform; +import io.ebean.annotation.IgnorePlatform; import io.ebean.annotation.Transactional; import org.junit.Test; @@ -16,12 +18,14 @@ public class TestManyToOneAsOne extends BaseTestCase { @Transactional(batchSize = 20) @Test + @IgnorePlatform(Platform.SQLSERVER) // probably due the use of sequences - Empl has already an ID and Addr refers to it. public void test_when_jdbcBatch() { runInserts(); } + private void runInserts() { - if (isSqlServer()) return; // probably due the use of sequences - Empl has already an ID and Addr refers to it. + Addr junk = new Addr(); junk.setName("junk"); Ebean.save(junk); diff --git a/src/test/java/org/tests/rawsql/nativesql/TestNativeSqlBasic.java b/src/test/java/org/tests/rawsql/nativesql/TestNativeSqlBasic.java index 82c295321..a368b8dde 100644 --- a/src/test/java/org/tests/rawsql/nativesql/TestNativeSqlBasic.java +++ b/src/test/java/org/tests/rawsql/nativesql/TestNativeSqlBasic.java @@ -4,7 +4,10 @@ import io.ebean.BaseTestCase; import io.ebean.BeanState; import io.ebean.Ebean; import io.ebean.EbeanServer; +import io.ebean.Platform; import io.ebean.Query; +import io.ebean.annotation.IgnorePlatform; + import org.tests.model.basic.Customer; import org.tests.model.basic.Order; import org.tests.model.basic.ResetBasicData; @@ -106,6 +109,7 @@ public class TestNativeSqlBasic extends BaseTestCase { } @Test + @IgnorePlatform(Platform.SQLSERVER) // does only work in 'cursor' mode! public void partialAssoc() { ResetBasicData.reset(); diff --git a/src/test/java/org/tests/transaction/TestBatchPersistCascade.java b/src/test/java/org/tests/transaction/TestBatchPersistCascade.java index b2d5c69ea..734b3f6d1 100644 --- a/src/test/java/org/tests/transaction/TestBatchPersistCascade.java +++ b/src/test/java/org/tests/transaction/TestBatchPersistCascade.java @@ -23,8 +23,6 @@ public class TestBatchPersistCascade extends BaseTestCase { @Test public void test() { - if (isSqlServer()) return; - EbeanServer ebeanServer = Ebean.getServer(null); LoggedSqlCollector.start(); diff --git a/src/test/java/org/tests/transaction/TestCommitAndContinue.java b/src/test/java/org/tests/transaction/TestCommitAndContinue.java index 057b03bb1..d8cb67364 100644 --- a/src/test/java/org/tests/transaction/TestCommitAndContinue.java +++ b/src/test/java/org/tests/transaction/TestCommitAndContinue.java @@ -3,7 +3,9 @@ package org.tests.transaction; import io.ebean.BaseTestCase; import io.ebean.Ebean; import io.ebean.EbeanServer; +import io.ebean.Platform; import io.ebean.Transaction; +import io.ebean.annotation.IgnorePlatform; import io.ebean.annotation.Transactional; import org.tests.model.m2m.MnyB; import org.junit.Test; @@ -19,8 +21,8 @@ public class TestCommitAndContinue extends BaseTestCase { @Test @Transactional + @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB}) // they will dead lock public void transactional_partialSuccess() { - if (isHSqlDb()) return; // HSQL will lock up here MnyB a = new MnyB("a100"); MnyB b = new MnyB("b200"); @@ -45,10 +47,8 @@ public class TestCommitAndContinue extends BaseTestCase { try (Transaction anotherTxn = server.createTransaction()) { // success prior to commitAndContinue assertNotNull(server.find(MnyB.class, a.getId(), anotherTxn)); - if (!isSqlServer()) { - // insert failed after commitAndContinue - sqlserver dead locks here - assertNull(server.find(MnyB.class, b.getId(), anotherTxn)); - } + // insert failed after commitAndContinue - sqlserver dead locks here + assertNull(server.find(MnyB.class, b.getId(), anotherTxn)); } } } @@ -57,6 +57,7 @@ public class TestCommitAndContinue extends BaseTestCase { * The @Transactional is nicer to me. */ @Test + @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB}) // they will dead lock public void tryFinally_partialSuccess() { MnyB a = new MnyB("a100"); @@ -80,15 +81,13 @@ public class TestCommitAndContinue extends BaseTestCase { txn.setRollbackOnly(); // use a different transaction to assert - if (!isSqlServer() && !isHSqlDb()) { // sqlServer & HSQL dead locks here... - try (Transaction anotherTxn = server.createTransaction()) { - // success prior to commitAndContinue - assertNotNull(server.find(MnyB.class, a.getId(), anotherTxn)); - // insert failed after commitAndContinue - assertNull(server.find(MnyB.class, b.getId(), anotherTxn)); - } - //anotherTxn.end(); + try (Transaction anotherTxn = server.createTransaction()) { + // success prior to commitAndContinue + assertNotNull(server.find(MnyB.class, a.getId(), anotherTxn)); + // insert failed after commitAndContinue + assertNull(server.find(MnyB.class, b.getId(), anotherTxn)); } + //anotherTxn.end(); } // does not commit due to the txn.setRollbackOnly(); @@ -102,9 +101,8 @@ public class TestCommitAndContinue extends BaseTestCase { @Test @Transactional + @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB}) // they will dead lock public void transactional_partialSuccess_secondTransactionInsert() { - - if (isHSqlDb()) return; // HSQL will lock up here MnyB a = new MnyB("a100"); MnyB b = new MnyB("b200"); @@ -143,10 +141,9 @@ public class TestCommitAndContinue extends BaseTestCase { // success prior to commitAndContinue assertNotNull(server.find(MnyB.class, a.getId(), txnForAssert)); - if (!isSqlServer()) { - // insert failed after commitAndContinue - assertNull(server.find(MnyB.class, b.getId(), txnForAssert)); - } + // insert failed after commitAndContinue + assertNull(server.find(MnyB.class, b.getId(), txnForAssert)); + // successful insert using txn2 assertNotNull(server.find(MnyB.class, c.getId(), txnForAssert)); } diff --git a/src/test/java/org/tests/transaction/TestTransactionTryResources.java b/src/test/java/org/tests/transaction/TestTransactionTryResources.java index f9aa15445..24b96662e 100644 --- a/src/test/java/org/tests/transaction/TestTransactionTryResources.java +++ b/src/test/java/org/tests/transaction/TestTransactionTryResources.java @@ -3,7 +3,10 @@ package org.tests.transaction; import io.ebean.BaseTestCase; import io.ebean.DuplicateKeyException; import io.ebean.Ebean; +import io.ebean.Platform; import io.ebean.Transaction; +import io.ebean.annotation.IgnorePlatform; + import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +38,7 @@ public class TestTransactionTryResources extends BaseTestCase { } @Test + @IgnorePlatform(Platform.ORACLE) // does not support uncommited reads public void tryWithResources_catch() { try (Transaction transaction = Ebean.beginTransaction()) {