blob: 8216986cc10f0c8d67e1169c54d133f5c56dafdb [file] [log] [blame]
/*
* Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
package org.eclipse.scout.rt.dataobject.testing;
import static org.junit.Assert.fail;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.scout.rt.dataobject.migration.AbstractDoStructureMigrationHandlerTest;
import org.eclipse.scout.rt.dataobject.migration.IDoStructureMigrationHandler;
import org.eclipse.scout.rt.platform.IgnoreBean;
import org.eclipse.scout.rt.platform.inventory.ClassInventory;
import org.eclipse.scout.rt.platform.inventory.IClassInfo;
import org.eclipse.scout.rt.platform.util.StringUtility;
import org.junit.Test;
/**
* Completeness test to check that for all {@link IDoStructureMigrationHandler} a corresponding
* {@link AbstractDoStructureMigrationHandlerTest} exists.
*/
public abstract class AbstractDoStructureMigrationHandlerCompletenessTest {
/**
* @return the package name prefix within this completeness tests looks for {@link IDoStructureMigrationHandler}
*/
protected abstract String getPackageNamePrefix();
/**
* @return a list of classes/test classes that will be excluded from completeness checking. This may be used if there
* is a very special case where a successful standard test cannot be implemented.
*/
protected Set<Class<?>> getExclusionList() {
return Collections.emptySet();
}
@Test
public void testCompleteness() {
// Convention: migration handler naming contains version number: LoremMigrationHandler_1_2_0
// Naming of test class: LoremMigrationHandler_1_2_0_Test
Set<Class<?>> excludedMigrationHandlers = getExclusionList();
Set<String> expectedTestClassNames = findClasses(IDoStructureMigrationHandler.class)
.filter(clazz -> !excludedMigrationHandlers.contains(clazz))
.map(Class::getName)
.map(className -> className + "_Test")
.collect(Collectors.toSet());
Set<String> actualTestClassNames = findClasses(AbstractDoStructureMigrationHandlerTest.class)
.map(Class::getName)
.collect(Collectors.toSet());
Set<String> missingTestClassNames = new HashSet<>(expectedTestClassNames);
missingTestClassNames.removeAll(actualTestClassNames);
Set<String> unknownTestClassNames = new HashSet<>(actualTestClassNames);
unknownTestClassNames.removeAll(expectedTestClassNames);
if (!missingTestClassNames.isEmpty()) {
StringBuilder builder = new StringBuilder();
builder.append("There are missing test classes:\n");
builder.append(StringUtility.join("\n", missingTestClassNames));
if (!unknownTestClassNames.isEmpty()) {
builder.append("\n");
builder.append("Maybe the name of one of these is wrong :\n");
builder.append(StringUtility.join("\n", unknownTestClassNames));
}
fail(builder.toString());
}
}
@SuppressWarnings("unchecked")
protected <T> Stream<Class<T>> findClasses(Class<T> clazz) {
return ClassInventory.get().getAllKnownSubClasses(clazz).stream()
.filter(this::acceptClass)
.map(classInfo -> (Class<T>) classInfo.resolveClass())
.filter(resolvedClass -> !Modifier.isStatic(resolvedClass.getModifiers()));
}
protected boolean acceptClass(IClassInfo ci) {
if (!ci.isInstanciable()) {
return false;
}
if (ci.hasAnnotation(IgnoreBean.class)) {
return false; // e.g. test migration handlers
}
String className = ci.name();
return className.startsWith(getPackageNamePrefix());
}
}