Feature/contitional test runner (#1132)

* FIX: warnings (add generics, overrides, fix imports) - should be no effecive code change

* replaced deprecated methods by default methods

* FIX: more compiler warnings

* FIX more warnings - no code changes

* FIX: deprecated call to JsonParseException

* Remove unused code, check unused variables

* ADD: ContitonaltestRunner to skip tests for certain platforms

* Use annotations to control on which platforms a test shoud run

* FIX: compile errors
This commit is contained in:
Roland Praml
2017-09-15 21:03:03 +12:00
committed by Rob Bygrave
parent f3e4696498
commit 8d334ff2e8
17 changed files with 176 additions and 76 deletions
+7 -1
View File
@@ -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();
}
@@ -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;
}
}
@@ -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();
@@ -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();
@@ -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();
}
@@ -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();
}
@@ -30,7 +30,7 @@ public class DefaultServerCache_RunEvictionTest {
this.cache = createCache();
}
@Ignore
@Ignore("test takes long time")
@Test
public void runEvict() throws InterruptedException {
@@ -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");
@@ -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 &#64;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);
}
}
@@ -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<Customer> query = Ebean.find(Customer.class)
Query<Customer> 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();
}
}
}
@@ -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<EBasicEncrypt> deleteAll = Ebean.createUpdate(EBasicEncrypt.class, "delete from EBasicEncrypt");
@@ -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();
@@ -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);
@@ -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();
@@ -23,8 +23,6 @@ public class TestBatchPersistCascade extends BaseTestCase {
@Test
public void test() {
if (isSqlServer()) return;
EbeanServer ebeanServer = Ebean.getServer(null);
LoggedSqlCollector.start();
@@ -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));
}
@@ -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()) {