Skip to content

Commit

Permalink
reintroduced field-clearing on Spring test classes, moved to superclass
Browse files Browse the repository at this point in the history
model-intest were indeed very slow, hopefully this helps (again)
  • Loading branch information
virgo47 committed Mar 1, 2020
1 parent 7e9a9aa commit b392821
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 44 deletions.
Expand Up @@ -6,9 +6,13 @@
*/
package com.evolveum.midpoint.test.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.jetbrains.annotations.NotNull;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.ITestResult;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;

Expand Down Expand Up @@ -64,4 +68,48 @@ public String contextName() {
public String getTestNameShort() {
return TEST_CONTEXT_THREAD_LOCAL.get().getMethod().getMethodName();
}

/**
* This method null all fields which are not static, final or primitive type.
* <p>
* All this is just to make GC work during DirtiesContext after every test class,
* because test class instances are not GCed immediately.
* If they hold autowired fields like sessionFactory (for example
* through SqlRepositoryService impl), their memory footprint is getting big.
* <p>
* Note that this does not work for components injected through constructor into
* final fields - if we need this cleanup, make the field non-final.
*/
@AfterClass(alwaysRun = true)
protected void clearClassFields() throws Exception {
logger.trace("Clearing all fields for test class {}", getClass().getName());
clearClassFields(this, getClass());
}

private void clearClassFields(Object object, Class<?> forClass) throws Exception {
if (forClass.getSuperclass() != null) {
clearClassFields(object, forClass.getSuperclass());
}

for (Field field : forClass.getDeclaredFields()) {
if (Modifier.isFinal(field.getModifiers())
|| Modifier.isStatic(field.getModifiers())
|| field.getType().isPrimitive()) {
continue;
}

nullField(object, field);
}
}

private void nullField(Object obj, Field field) throws Exception {
logger.info("Setting {} to null on {}.", field.getName(), obj.getClass().getSimpleName());
boolean accessible = field.isAccessible();
// boolean accessible = field.canAccess(obj); // TODO: after ditching JDK 8
if (!accessible) {
field.setAccessible(true);
}
field.set(obj, null);
field.setAccessible(accessible);
}
}
Expand Up @@ -37,8 +37,6 @@

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
Expand All @@ -48,7 +46,6 @@

/**
* @author semancik
*
*/
public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegrationTest {

Expand Down Expand Up @@ -613,47 +610,6 @@ protected PrismObject<UserType> getDefaultActor() {
return userAdministrator;
}

// TODO inttest: let's try it without this after 6 years
// @AfterClass(alwaysRun = true)
public void clearClassFields() throws Exception {
logger.trace("Clearing all fields for test class {}", getClass().getName());
nullAllFields(this, getClass());
}

/**
* This method null all fields which are not static, final or primitive type.
*
* All this is just to make GC work during DirtiesContext after every test class,
* because memory consumption is too big. Test class instances can't be GCed
* immediately. If they holds autowired fields like sessionFactory (for example
* through SqlRepositoryService impl), their memory footprint is getting big.
*/
public void nullAllFields(Object object, Class<?> forClass) throws Exception {
if (forClass.getSuperclass() != null) {
nullAllFields(object, forClass.getSuperclass());
}

for (Field field : forClass.getDeclaredFields()) {
if (Modifier.isFinal(field.getModifiers())
|| Modifier.isStatic(field.getModifiers())
|| field.getType().isPrimitive()) {
continue;
}

nullField(object, field);
}
}

private void nullField(Object obj, Field field) throws Exception {
logger.info("Setting {} to null on {}.", new Object[]{field.getName(), obj.getClass().getSimpleName()});
boolean accessible = field.isAccessible();
if (!accessible) {
field.setAccessible(true);
}
field.set(obj, null);
field.setAccessible(accessible);
}

protected PrismSchema getPiracySchema() {
return prismContext.getSchemaRegistry().findSchemaByNamespace(NS_PIRACY);
}
Expand Down

0 comments on commit b392821

Please sign in to comment.