AjBuildConfigTest.java
/* *******************************************************************
* Copyright (c) 2018 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
* ******************************************************************/
package org.aspectj.ajdt.internal.core.builder;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.aspectj.ajdt.ajc.BuildArgParser;
import org.aspectj.bridge.AbortException;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessage.Kind;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import junit.framework.TestCase;
/**
* @author Andy Clement
*/
public class AjBuildConfigTest extends TestCase {
@Override
public void setUp() throws Exception {
super.setUp();
testHandler.clear();
}
public void testBasicJar() {
// There should be only one reference to foo.jar in the checked classpaths
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
AjBuildConfig buildConfig = buildArgParser.genBuildConfig(toArgs("-classpath foo.jar"));
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
checkOccurrencesOf(checkedClasspaths, "foo.jar",1);
checkMessages();
}
public void testBasicDir() {
// Directory on classpath
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
AjBuildConfig buildConfig = buildArgParser.genBuildConfig(toArgs("-classpath /madeup/location"));
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
checkOccurrencesOf(checkedClasspaths, "madeup/location",0);
checkMessages();
}
public void testBasicDir2() {
// Non existent directory on classpath
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
AjBuildConfig buildConfig = new AjBuildConfig(buildArgParser);
buildArgParser.populateBuildConfig(buildConfig, toArgs("-classpath /madeup/location"), true, null);
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
checkOccurrencesOf(checkedClasspaths, "madeup/location",0);
// There is no message about the location not existing in the set that is going to be checked
// but the message is routed to the internal logger setup inside the JDT Main class. By default
// that is a string logger but when built through AspectJ Main.main() it will route that message
// to System.out/System.err
checkMessages();
}
public void testAspectPath() {
// There should be only one reference to foo.jar in the checked classpaths
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
AjBuildConfig buildConfig = buildArgParser.genBuildConfig(toArgs("-classpath foo.jar -aspectpath bar.jar"));
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
checkOccurrencesOf(checkedClasspaths, "foo.jar", 1);
checkOccurrencesOf(checkedClasspaths, "bar.jar", 0);
checkMessages("skipping missing, empty or corrupt aspectpath entry: bar.jar");
}
public void testInPath() {
// There should be only one reference to foo.jar in the checked classpaths
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
AjBuildConfig buildConfig = buildArgParser.genBuildConfig(toArgs("-classpath foo.jar -inpath bar.jar"));
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
checkOccurrencesOf(checkedClasspaths, "foo.jar", 1);
checkOccurrencesOf(checkedClasspaths, "bar.jar", 0);
checkMessages("skipping missing, empty or corrupt aspectpath entry: bar.jar");
}
public void testInJars() {
// There should be only one reference to foo.jar in the checked classpaths
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
AjBuildConfig buildConfig = buildArgParser.genBuildConfig(toArgs("-classpath foo.jar -injars bar.jar"));
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
checkOccurrencesOf(checkedClasspaths, "foo.jar", 1);
checkOccurrencesOf(checkedClasspaths, "bar.jar", 0);
checkMessages("skipping missing, empty or corrupt aspectpath entry: bar.jar");
}
// TODO why does this misbehave on java8? (It doesn't remove the duplicate jar references when normalizing the classpath)
public void xtestClashingJars() {
File tempJar = createTempJar("foo");
try {
BuildArgParser buildArgParser = new BuildArgParser(testHandler);
String[] args = toArgs("-classpath "+tempJar.getAbsolutePath()+
" -inpath "+tempJar.getAbsolutePath()+" -aspectpath "+tempJar.getAbsolutePath());
AjBuildConfig buildConfig = buildArgParser.genBuildConfig(args);
Classpath[] checkedClasspaths = buildConfig.getCheckedClasspaths();
System.out.println(Arrays.toString(checkedClasspaths));
checkOccurrencesOf(checkedClasspaths, "/foo", 1);
checkMessages();
} finally {
tempJar.delete();
}
}
// ---
private File createTempJar(String jarname) {
try {
File file = File.createTempFile(jarname, ".jar");
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream jos = new JarOutputStream(new FileOutputStream(file),manifest);
JarEntry je = new JarEntry("foo");
je.setSize(0);
jos.putNextEntry(je);
jos.close();
return file;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
private void checkMessages(String... expectedMessageSubstrings) {
List<IMessage> messages = testHandler.getMessages();
if (expectedMessageSubstrings.length == 0 && messages.size() != 0) {
fail("Expected no messages but found:\n" + messages);
}
if (expectedMessageSubstrings.length != messages.size()) {
fail("Incompatible number of actual messages (" + messages.size() + ") vs expected messages ("
+ expectedMessageSubstrings + ")\n" + "expected:\n" + Arrays.toString(expectedMessageSubstrings)
+ "\nactual:\n" + messages);
}
}
private void checkOccurrencesOf(Classpath[] classpath, String string, int expectedCount) {
int count = 0;
for (Classpath cpentry : classpath) {
// Example: /Users/aclement/gits/org.aspectj/org.aspectj.ajdt.core/foo.jar
String path = cpentry.getPath();
if (path.contains(string)) {
count++;
}
}
if (count != expectedCount) {
fail("Did not find expected " + expectedCount + " occurrences of " + string + " in classpaths: "
+ Arrays.toString(classpath));
}
}
TestMessageHandler testHandler = new TestMessageHandler();
static class TestMessageHandler implements IMessageHandler {
List<IMessage> messages = new ArrayList<>();
@Override
public boolean isIgnoring(Kind kind) {
return false;
}
public List<IMessage> getMessages() {
return messages;
}
@Override
public void ignore(Kind kind) {
}
@Override
public boolean handleMessage(IMessage message) throws AbortException {
messages.add(message);
return true;
}
@Override
public void dontIgnore(Kind kind) {
}
public void clear() {
messages.clear();
}
};
private String[] toArgs(String commandLine) {
return commandLine.split(" ");
}
}