/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2017 the original authors or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sarl.examples.tests;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import com.google.inject.Injector;
import org.apache.log4j.Level;
import org.arakhne.afc.vmutil.ClasspathUtil;
import org.arakhne.afc.vmutil.FileSystem;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.util.Strings;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.ComparisonFailure;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import io.sarl.lang.SARLStandaloneSetup;
import io.sarl.lang.SARLVersion;
import io.sarl.lang.compiler.batch.SarlBatchCompiler;
import io.sarl.tests.api.AbstractSarlTest;
/** Class for testing the examples.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
@RunWith(Parameterized.class)
@SuppressWarnings("all")
public class ExamplesTest extends AbstractSarlTest {
/** Name of the property that contains the root path for the project to test.
*/
public static final String ROOT_TEST_FOLDER_PROPERTY = "io.sarl.examples.test.rootDir"; //$NON-NLS-1$
private static final File DEFAULT_RELATIVE_PATH = FileSystem.convertStringToFile("file:../io.sarl.examples.plugin"); //$NON-NLS-1$
private static final String PROJECTS_FOLDER_NAME = "projects"; //$NON-NLS-1$
/** Replies the archives for the examples.
*
* @return the archive locations.
* @throws Exception in case of error.
*/
@Parameters(name = "Example {1}")
public static Collection<Object[]> getExampleArchives() throws Exception {
final Set<String> names = new TreeSet<>();
final Map<String, File> rawSources = new TreeMap<>();
File rootPath = null;
final String projectdir = System.getProperty(ROOT_TEST_FOLDER_PROPERTY);
if (!Strings.isEmpty(projectdir)) {
rootPath = FileSystem.convertStringToFile(projectdir);
}
if (rootPath == null) {
rootPath = DEFAULT_RELATIVE_PATH;
}
final File projectFolder = new File(rootPath, PROJECTS_FOLDER_NAME);
if (projectFolder.isDirectory()) {
for (File child : projectFolder.listFiles()) {
if (child.isDirectory()) {
final String basename = child.getName();
rawSources.putIfAbsent(basename, child);
names.add(basename);
}
}
}
if (names.isEmpty()) {
throw new Exception("no test found"); //$NON-NLS-1$
}
final List<Object[]> list = new ArrayList<>();
for (final String name : names) {
final File folder = rawSources.get(name);
list.add(new Object[] {name, folder});
}
return list;
}
private final String name;
private final File exampleFolder;
static SarlBatchCompiler compiler;
/** Constructor.
*
* @param name the name of the test.
* @param exampleFolder the folder to open.
*/
public ExamplesTest(String name, File exampleFolder) {
this.name = name;
this.exampleFolder = exampleFolder.getAbsoluteFile();
}
@BeforeClass
public static void setupClass() throws Exception {
Injector injector = SARLStandaloneSetup.doSetup();
compiler = injector.getInstance(SarlBatchCompiler.class);
}
@Override
public String toString() {
return this.name;
}
@Test
public void path() {
assertNotNull(this.exampleFolder);
}
@Test
public void compilation() throws Exception {
Assume.assumeTrue(this.exampleFolder != null);
final File projectRoot = createProject();
final List<File> installedFiles = copyFiles(projectRoot);
assertFalse("No installed file in " + projectRoot, installedFiles.isEmpty());
List<String> issues = compileFiles(projectRoot, installedFiles);
assertNoIssue(issues);
}
private void assertNoIssue(List<String> issues) {
if (!issues.isEmpty()) {
throw new ComparisonFailure("Errors in the example code", "", Strings.concat("\n", issues));
}
}
private List<String> compileFiles(File root, List<File> installedFiles) throws Exception {
final List<String> issues = new ArrayList<>();
compiler.setBasePath(root.getAbsolutePath());
compiler.setTempDirectory(getTempPath(root));
compiler.addSourcePath(getSourcePath(root));
compiler.setClassOutputPath(getBinPath(root));
compiler.setOutputPath(getSourceGenPath(root));
compiler.setGenerateGeneratedAnnotation(false);
compiler.setGenerateInlineAnnotation(false);
compiler.setGenerateSyntheticSuppressWarnings(true);
compiler.setDeleteTempDirectory(false);
compiler.setClassPath(getClasspath());
compiler.setJavaSourceVersion(SARLVersion.MINIMAL_JDK_VERSION);
compiler.setAllWarningSeverities(Severity.IGNORE);
compiler.setJavaCompilerVerbose(false);
compiler.getLogger().setLevel(Level.OFF);
compiler.addIssueMessageListener((issue, uri, message) -> {
if (issue.isSyntaxError() || issue.getSeverity().compareTo(Severity.ERROR) >= 0) {
final Integer line = issue.getLineNumber();
final int issueLine = (line == null ? 0 : line.intValue());
issues.add(message + " (line " + issueLine + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
});
if (compiler.compile()) {
return Collections.emptyList();
}
return issues;
}
private List<File> getClasspath() throws Exception {
final List<File> classpath = new ArrayList<>();
final Iterator<URL> iterator = ClasspathUtil.getClasspath();
while (iterator.hasNext()) {
final URL url = iterator.next();
try {
final File file = FileSystem.convertURLToFile(url);
classpath.add(file);
} catch (IllegalArgumentException exception) {
//
}
}
return classpath;
}
private List<File> copyFiles(File root) throws Exception {
final List<File> installedFiles = new ArrayList<>();
final List<File> folders = new ArrayList<>();
folders.add(this.exampleFolder);
while (!folders.isEmpty()) {
final File folder = folders.remove(0);
for (final File file : folder.listFiles()) {
if (file.isDirectory()) {
folders.add(file);
} else if (file.isFile()) {
if (!isIgnorableFile(file)) {
final File relPathFile = FileSystem.makeRelative(file, this.exampleFolder);
final File targetFile = FileSystem.join(root, relPathFile);
targetFile.getParentFile().mkdirs();
FileSystem.copy(file, targetFile);
installedFiles.add(relPathFile);
}
}
}
}
return installedFiles;
}
private static boolean isIgnorableFile(File file) {
final String name = file.getName();
return ".classpath".equals(name) || ".project".equals(name);
}
private File getSourcePath(File rootPath) {
return FileSystem.join(rootPath, "src", "main", "sarl");
}
private File getSourceGenPath(File rootPath) {
return new File(rootPath, "src-gen");
}
private File getBinPath(File rootPath) {
return new File(rootPath, "bin");
}
private File getTempPath(File rootPath) {
return new File(rootPath, "build");
}
private File createProject() throws Exception {
final File rootPath = FileSystem.createTempDirectory("exampletests", ".tmp").getAbsoluteFile();
getSourcePath(rootPath).mkdirs();
getSourceGenPath(rootPath).mkdirs();
getBinPath(rootPath).mkdirs();
getTempPath(rootPath).mkdirs();
FileSystem.deleteOnExit(rootPath);
return rootPath;
}
}