package com.tngtech.archunit.junit;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import com.google.common.base.Joiner;
import com.google.common.io.Files;
import com.tngtech.archunit.core.domain.Dependency;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.domain.SourceTest;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.testutil.ArchConfigurationRule;
import org.junit.Rule;
import org.junit.Test;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.System.lineSeparator;
import static org.assertj.core.api.Assertions.assertThat;
public class ProGuardTest {
@Rule
public final ArchConfigurationRule configurationRule = new ArchConfigurationRule()
.resolveAdditionalDependenciesFromClassPath(false);
private static final boolean PRINT_EXPECTED_RESULT = false;
/**
* We have to make sure, that all Guava targets used by archunit-junit are left alone by ProGuard,
* so no necessary methods, etc., are removed from the byte code while optimizing the relocated
* classes within archunit.
*/
@Test
public void all_guava_targets_are_configured() throws Exception {
JavaClasses archunitJunitClasses = new ClassFileImporter().importUrl(rootOf(ArchTest.class));
Set<String> guavaDependencies = findGuavaDependenciesIn(archunitJunitClasses);
if (PRINT_EXPECTED_RESULT) {
System.out.println(Joiner.on(lineSeparator()).join(guavaDependencies));
}
List<String> keptTargets = read("proguard-keepclassmembers.txt");
assertThat(guavaDependencies).as("Guava dependencies of archunit-junit").containsOnlyElementsOf(keptTargets);
}
private Set<String> findGuavaDependenciesIn(JavaClasses archunitJunitClasses) {
Set<String> guavaDependencies = new TreeSet<>();
for (JavaClass javaClass : archunitJunitClasses) {
for (Dependency dependency : javaClass.getDirectDependencies()) {
if (dependency.getTargetClass().getPackage().startsWith("com.google")) {
guavaDependencies.add(dependency.getTargetClass().getName().replaceAll("\\$.*", ""));
}
}
}
return guavaDependencies;
}
private List<String> read(String fileName) throws IOException {
File currentAttempt = new File(new File("."), fileName).getCanonicalFile();
while (!currentAttempt.exists() && currentAttempt.getParentFile() != null) {
currentAttempt = new File(currentAttempt.getParentFile().getParentFile(), fileName);
}
checkState(currentAttempt.exists(), "Couldn't find %s in any parent dir", fileName);
return Files.readLines(currentAttempt, StandardCharsets.UTF_8);
}
private URL rootOf(Class<?> clazz) throws MalformedURLException {
URL url = SourceTest.urlOf(clazz);
String root = url.toString().replaceAll("/com/tngtech/archunit/.*", "/com/tngtech/archunit");
return new URL(root);
}
}