/*
* Copyright Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the authors tag. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*
* This particular file is subject to the "Classpath" exception as provided in the
* LICENSE file that accompanied this code.
*
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License,
* along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.redhat.ceylon.compiler.java.test.cmr;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.FileObject;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.common.Versions;
import com.redhat.ceylon.common.config.Repositories;
import com.redhat.ceylon.compiler.java.test.CompilerError;
import com.redhat.ceylon.compiler.java.test.CompilerTests;
import com.redhat.ceylon.compiler.java.test.ErrorCollector;
import com.redhat.ceylon.compiler.java.tools.CeyloncTaskImpl;
import com.redhat.ceylon.compiler.java.tools.JarEntryManifestFileObject.OsgiManifest;
import com.redhat.ceylon.compiler.java.tools.LanguageCompiler;
import com.redhat.ceylon.compiler.java.util.Util;
import com.redhat.ceylon.compiler.typechecker.context.Context;
import com.redhat.ceylon.model.cmr.JDKUtils;
import com.redhat.ceylon.model.typechecker.model.Module;
import com.redhat.ceylon.model.typechecker.model.ModuleImport;
import com.redhat.ceylon.model.typechecker.model.Modules;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
public class CMRTests extends CompilerTests {
//
// Modules
@Test
public void testMdlByName() throws IOException{
List<String> options = new LinkedList<String>();
options.add("-src");
options.add(getPackagePath()+"/modules/byName");
options.addAll(defaultOptions);
CeyloncTaskImpl task = getCompilerTask(options,
null,
Arrays.asList("default", "mod"));
Boolean ret = task.call();
assertTrue(ret);
File carFile = getModuleArchive("default", null);
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry moduleClass = car.getEntry("def/Foo.class");
assertNotNull(moduleClass);
ZipEntry moduleClassDir = car.getEntry("def/");
assertNotNull(moduleClassDir);
assertTrue(moduleClassDir.isDirectory());
car.close();
carFile = getModuleArchive("mod", "1");
assertTrue(carFile.exists());
car = new JarFile(carFile);
moduleClass = car.getEntry("mod/$module_.class");
assertNotNull(moduleClass);
moduleClassDir = car.getEntry("mod/");
assertNotNull(moduleClassDir);
assertTrue(moduleClassDir.isDirectory());
car.close();
}
@Test
public void testMdlEndsWithJava() throws IOException{
List<String> options = new LinkedList<String>();
options.add("-src");
options.add(dir);
options.addAll(defaultOptions);
CeyloncTaskImpl task = getCompilerTask(options,
null,
Arrays.asList("com.redhat.ceylon.compiler.java.test.cmr.modules.java"));
Boolean ret = task.call();
assertTrue(ret);
}
@Test
public void testMdlModuleDefault() throws IOException{
compile("modules/def/CeylonClass.ceylon");
File carFile = getModuleArchive("default", null);
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry moduleClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/def/CeylonClass.class");
assertNotNull(moduleClass);
car.close();
}
@Test
public void testMdlModuleDefaultJavaFile() throws IOException{
compile("modules/def/JavaClass.java");
File carFile = getModuleArchive("default", null);
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry moduleClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/def/JavaClass.class");
assertNotNull(moduleClass);
car.close();
}
@Test
public void testMdlModuleDefaultIncremental() throws IOException{
compile("modules/def/A.ceylon");
compile("modules/def/RequiresA.ceylon");
}
@Test
public void testMdlModuleIncremental() throws IOException{
compile("modules/incremental/A.ceylon", "modules/incremental/BUsesA.ceylon", "modules/incremental/UsesB.ceylon");
compile("modules/incremental/A.ceylon", "modules/incremental/UsesB.ceylon");
}
@Test
public void testMdlModuleDefaultIncrementalNoPackage() throws IOException{
List<String> options = new LinkedList<String>();
options.add("-src");
options.add(getPackagePath()+"/modules/def");
options.addAll(defaultOptions);
CeyloncTaskImpl task = getCompilerTask(options,
null,
Collections.<String>emptyList(),
"modules/def/A.ceylon");
Boolean ret = task.call();
assertTrue(ret);
task = getCompilerTask(options,
null,
Collections.<String>emptyList(),
"modules/def/RequiresA.ceylon");
ret = task.call();
assertTrue(ret);
}
@Test
public void testMdlModuleOnlyInOutputRepo() throws IOException {
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
assertFalse(carFile.exists());
File carFileInCache = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6", cacheDir);
if(carFileInCache.exists())
carFileInCache.delete();
compile("modules/single/module.ceylon");
// make sure it was created in the output repo
assertTrue(carFile.exists());
// make sure it wasn't created in the cache repo
assertFalse(carFileInCache.exists());
}
@Test
public void testMdlModuleNotLoadedFromHomeRepo() throws IOException {
File carFile = getModuleArchive("a", "1.0");
assertFalse(carFile.exists());
// clean up the home repo if required
String homeRepo = FileUtil.getUserDir().getCanonicalPath();
File carFileInHomeRepo = getModuleArchive("a", "1.0", homeRepo);
if(carFileInHomeRepo.exists())
carFileInHomeRepo.delete();
// put a broken one in the home repo
compileModuleFromSourceFolder("a", "home_repo/a_broken", homeRepo);
assertTrue(carFileInHomeRepo.exists());
// the good one in the default output repo
compileModuleFromSourceFolder("a", "home_repo/a_working", null);
assertTrue(carFile.exists());
// now compile the dependent module
compileModuleFromSourceFolder("b", "home_repo/b", null);
// make sure it was created in the output repo
assertTrue(carFile.exists());
}
@Test
public void testMdlModuleNotLoadedFromCache() throws IOException {
File carFile = getModuleArchive("b", "1.0");
assertFalse(carFile.exists());
// clean up the cache repo if required
File carFileInHomeRepo = getModuleArchive("a", "1.0", cacheDir);
if(carFileInHomeRepo.exists())
carFileInHomeRepo.delete();
// clean up the working repo if required
String workingRepo = destDir + "-working";
File carFileInWorkingRepo = getModuleArchive("a", "1.0", workingRepo);
if(carFileInWorkingRepo.exists())
carFileInWorkingRepo.delete();
assertFalse(carFileInWorkingRepo.exists());
// put a broken one in the cache repo
compileModuleFromSourceFolder("a", "home_repo/a_broken", cacheDir);
assertTrue(carFileInHomeRepo.exists());
// the good one in a local repo
compileModuleFromSourceFolder("a", "home_repo/a_working", workingRepo);
assertTrue(carFileInWorkingRepo.exists());
// now compile the dependent module by using that repo
compileModuleFromSourceFolder("b", "home_repo/b", null, workingRepo);
// make sure it was created in the output repo
assertTrue(carFile.exists());
}
private void compileModuleFromSourceFolder(String module, String srcFolder, String outFolder, String... repos) {
List<String> options = new LinkedList<String>();
options.add("-src");
options.add(getPackagePath()+"/modules/"+srcFolder);
if(outFolder != null){
options.add("-out");
options.add(outFolder);
}else{
options.addAll(defaultOptions);
}
for(String repo : repos){
options.add("-rep");
options.add(repo);
}
CeyloncTaskImpl task = getCompilerTask(options,
null,
Arrays.asList(module));
Boolean ret = task.call();
assertTrue(ret);
}
@Test
public void testMdlWithCeylonImport() throws IOException{
compile("modules/ceylon_import/module.ceylon", "modules/ceylon_import/ImportCeylonLanguage.ceylon");
}
@Test
public void testMdlWithCommonPrefix() throws IOException{
compile("modules/depend/prefix/module.ceylon");
// This is heisenbug https://github.com/ceylon/ceylon-compiler/issues/460 and for some
// reason it only happens _sometimes_, hence the repeats
compile("modules/depend/prefix_suffix/module.ceylon");
compile("modules/depend/prefix_suffix/module.ceylon");
compile("modules/depend/prefix_suffix/module.ceylon");
compile("modules/depend/prefix_suffix/module.ceylon");
compile("modules/depend/prefix_suffix/module.ceylon");
}
@Test
public void testMdlModuleFromCompiledModule() throws IOException{
compile("modules/single/module.ceylon");
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
// just to be sure
ZipEntry bogusEntry = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/BOGUS");
assertNull(bogusEntry);
ZipEntry moduleClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/$module_.class");
assertNotNull(moduleClass);
car.close();
compile("modules/single/subpackage/Subpackage.ceylon");
// MUST reopen it
car = new JarFile(carFile);
ZipEntry subpackageClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/subpackage/Subpackage.class");
assertNotNull(subpackageClass);
car.close();
}
@Test
public void testMdlCarWithInvalidSHA1() throws IOException{
compile("modules/single/module.ceylon");
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
// just to be sure
ZipEntry moduleClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/$module_.class");
assertNotNull(moduleClass);
car.close();
// now let's break the SHA1
File shaFile = getArchiveName("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6", destDir, "car.sha1");
Writer w = new FileWriter(shaFile);
w.write("fubar");
w.flush();
w.close();
// now try to compile the subpackage with a broken SHA1
String carName = "/com/redhat/ceylon/compiler/java/test/cmr/modules/single/6.6.6/com.redhat.ceylon.compiler.java.test.cmr.modules.single-6.6.6.car";
carName = carName.replace('/', File.separatorChar);
assertErrors("modules/single/subpackage/Subpackage",
new CompilerError(-1, "Module car " + carName
+ " obtained from repository " + (new File(destDir).getAbsolutePath())
+ " has an invalid SHA1 signature: you need to remove it and rebuild the archive, since it may be corrupted."));
}
@Test
public void testMdlCompilerGeneratesModuleForValidUnits() throws IOException{
CeyloncTaskImpl compilerTask = getCompilerTask("modules/single/module.ceylon", "modules/single/Correct.ceylon", "modules/single/Invalid.ceylon");
Boolean success = compilerTask.call();
assertFalse(success);
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry moduleClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/$module_.class");
assertNotNull(moduleClass);
ZipEntry correctClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/Correct.class");
assertNotNull(correctClass);
ZipEntry invalidClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/Invalid.class");
assertNull(invalidClass);
car.close();
}
@Test
public void testMdlInterdepModule(){
// first compile it all from source
compile("modules/interdep/a/module.ceylon", "modules/interdep/a/package.ceylon", "modules/interdep/a/b.ceylon", "modules/interdep/a/A.ceylon",
"modules/interdep/b/module.ceylon", "modules/interdep/b/package.ceylon", "modules/interdep/b/a.ceylon", "modules/interdep/b/B.ceylon");
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.interdep.a", "6.6.6");
assertTrue(carFile.exists());
carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.interdep.b", "6.6.6");
assertTrue(carFile.exists());
// then try to compile only one module (the other being loaded from its car)
compile("modules/interdep/a/module.ceylon", "modules/interdep/a/b.ceylon", "modules/interdep/a/A.ceylon");
}
@Test
public void testMdlDependentModule(){
// Compile only the first module
compile("modules/depend/a/module.ceylon", "modules/depend/a/package.ceylon", "modules/depend/a/A.ceylon");
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.depend.a", "6.6.6");
assertTrue(carFile.exists());
// then try to compile only one module (the other being loaded from its car)
compile("modules/depend/b/module.ceylon", "modules/depend/b/package.ceylon", "modules/depend/b/a.ceylon", "modules/depend/b/aWildcard.ceylon", "modules/depend/b/B.ceylon");
carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.depend.b", "6.6.6");
assertTrue(carFile.exists());
// and then the last one (the other 2 being loaded from their cars) that uses the first one transitively
compile("modules/depend/c/module.ceylon", "modules/depend/c/a.ceylon", "modules/depend/c/b.ceylon");
carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.depend.c", "6.6.6");
assertTrue(carFile.exists());
}
@Test
public void testMdlImplicitDependentModule(){
// Compile only the first module
compile("modules/implicit/a/module.ceylon", "modules/implicit/a/package.ceylon", "modules/implicit/a/A.ceylon",
"modules/implicit/b/module.ceylon", "modules/implicit/b/package.ceylon", "modules/implicit/b/B.ceylon", "modules/implicit/b/B2.ceylon",
"modules/implicit/c/module.ceylon", "modules/implicit/c/package.ceylon", "modules/implicit/c/c.ceylon");
// Dependencies:
//
// c.ceylon--> B2.ceylon
// |
// '-> B.ceylon --> A.ceylon
// Successfull tests :
compile("modules/implicit/c/c.ceylon");
compile("modules/implicit/b/B.ceylon", "modules/implicit/c/c.ceylon");
compile("modules/implicit/b/B2.ceylon", "modules/implicit/c/c.ceylon");
// Failing tests :
Boolean success1 = getCompilerTask("modules/implicit/c/c.ceylon", "modules/implicit/b/B.ceylon").call();
// => B.ceylon : package not found in dependent modules: com.redhat.ceylon.compiler.java.test.cmr.module.implicit.a
Boolean success2 = getCompilerTask("modules/implicit/c/c.ceylon", "modules/implicit/b/B2.ceylon").call();
// => c.ceylon : TypeVisitor caused an exception visiting Import node: com.sun.tools.javac.code.Symbol$CompletionFailure: class file for com.redhat.ceylon.compiler.test.cmr.module.implicit.a.A not found at unknown
Assert.assertTrue(success1 && success2);
}
private void copy(File source, File dest) throws IOException {
InputStream inputStream = new FileInputStream(source);
OutputStream outputStream = new FileOutputStream(dest);
byte[] buffer = new byte[4096];
int read;
while((read = inputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, read);
}
inputStream.close();
outputStream.close();
}
@Test
public void testMdlSuppressObsoleteClasses() throws IOException{
File sourceFile = new File(getPackagePath(), "modules/single/SuppressClass.ceylon");
copy(new File(getPackagePath(), "modules/single/SuppressClass_1.ceylon"), sourceFile);
CeyloncTaskImpl compilerTask = getCompilerTask("modules/single/module.ceylon", "modules/single/SuppressClass.ceylon");
Boolean success = compilerTask.call();
assertTrue(success);
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
assertTrue(carFile.exists());
ZipFile car = new ZipFile(carFile);
ZipEntry oneClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/One.class");
assertNotNull(oneClass);
ZipEntry twoClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/Two.class");
assertNotNull(twoClass);
car.close();
copy(new File(getPackagePath(), "modules/single/SuppressClass_2.ceylon"), sourceFile);
compilerTask = getCompilerTask("modules/single/module.ceylon", "modules/single/SuppressClass.ceylon");
success = compilerTask.call();
assertTrue(success);
carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
assertTrue(carFile.exists());
car = new ZipFile(carFile);
oneClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/One.class");
assertNotNull(oneClass);
twoClass = car.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/Two.class");
assertNull(twoClass);
car.close();
sourceFile.delete();
}
@Test
public void testMdlMultipleRepos(){
cleanCars("build/ceylon-cars-a");
cleanCars("build/ceylon-cars-b");
cleanCars("build/ceylon-cars-c");
// Compile the first module in its own repo
File repoA = new File("build/ceylon-cars-a");
repoA.mkdirs();
Boolean result = getCompilerTask(Arrays.asList("-out", repoA.getPath()),
"modules/depend/a/module.ceylon", "modules/depend/a/package.ceylon", "modules/depend/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.depend.a", "6.6.6", repoA.getPath());
assertTrue(carFile.exists());
// make another repo for the second module
File repoB = new File("build/ceylon-cars-b");
repoB.mkdirs();
// then try to compile only one module (the other being loaded from its car)
result = getCompilerTask(Arrays.asList("-out", repoB.getPath(), "-rep", repoA.getPath()),
"modules/depend/b/module.ceylon", "modules/depend/b/package.ceylon", "modules/depend/b/a.ceylon", "modules/depend/b/B.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.depend.b", "6.6.6", repoB.getPath());
assertTrue(carFile.exists());
// make another repo for the third module
File repoC = new File("build/ceylon-cars-c");
repoC.mkdirs();
// then try to compile only one module (the others being loaded from their car)
result = getCompilerTask(Arrays.asList("-out", repoC.getPath(),
"-rep", repoA.getPath(), "-rep", repoB.getPath()),
"modules/depend/c/module.ceylon", "modules/depend/c/a.ceylon", "modules/depend/c/b.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.depend.c", "6.6.6", repoC.getPath());
assertTrue(carFile.exists());
}
@Test
public void testMdlJarDependency() throws IOException{
// compile our java class
File classesOutputFolder = new File(destDir+"-jar-classes");
cleanCars(classesOutputFolder.getPath());
classesOutputFolder.mkdirs();
File jarOutputFolder = new File(destDir+"-jar");
cleanCars(jarOutputFolder.getPath());
jarOutputFolder.mkdirs();
compileJavaModule(jarOutputFolder, classesOutputFolder, moduleName+".modules.jarDependency.java", "1.0",
moduleName.replace('.', '/')+"/modules/jarDependency/java/JavaDependency.java");
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-rep", jarOutputFolder.getPath()),
(DiagnosticListener<? super FileObject>)null,
"modules/jarDependency/ceylon/module.ceylon", "modules/jarDependency/ceylon/Foo.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
}
private void compileJavaModule(File jarOutputFolder, File classesOutputFolder,
String moduleName, String moduleVersion, String... sourceFileNames) throws IOException {
compileJavaModule(jarOutputFolder, classesOutputFolder,
moduleName, moduleVersion, new File(dir), new File[0], sourceFileNames);
}
private void compileJavaModule(File jarOutputFolder, File classesOutputFolder,
String moduleName, String moduleVersion,
File sourceFolder,
File[] extraClassPath,
String... sourceFileNames) throws IOException {
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
assertNotNull("Missing Java compiler, this test is probably being run with a JRE instead of a JDK!", javaCompiler);
StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null);
Set<String> sourceDirectories = new HashSet<String>();
File[] javaSourceFiles = new File[sourceFileNames.length];
for (int i = 0; i < javaSourceFiles.length; i++) {
javaSourceFiles[i] = new File(sourceFolder, sourceFileNames[i]);
String sfn = sourceFileNames[i].replace(File.separatorChar, '/');
int p = sfn.lastIndexOf('/');
String sourceDir = sfn.substring(0, p);
sourceDirectories.add(sourceDir);
}
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(javaSourceFiles);
StringBuilder cp = new StringBuilder();
for (int i = 0; i < extraClassPath.length; i++) {
if(i > 0)
cp.append(File.pathSeparator);
cp.append(extraClassPath[i]);
}
CompilationTask task = javaCompiler.getTask(null, null, null, Arrays.asList("-d", classesOutputFolder.getPath(),
"-cp", cp.toString(),
"-sourcepath", sourceFolder.getPath()), null, compilationUnits);
assertEquals(Boolean.TRUE, task.call());
File jarFolder = new File(jarOutputFolder, moduleName.replace('.', File.separatorChar)+File.separatorChar+moduleVersion);
jarFolder.mkdirs();
File jarFile = new File(jarFolder, moduleName+"-"+moduleVersion+".jar");
// now jar it up
JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(jarFile));
for(String sourceFileName : sourceFileNames){
String classFileName = sourceFileName.substring(0, sourceFileName.length()-5)+".class";
ZipEntry entry = new ZipEntry(classFileName);
outputStream.putNextEntry(entry);
File classFile = new File(classesOutputFolder, classFileName);
FileInputStream inputStream = new FileInputStream(classFile);
Util.copy(inputStream, outputStream);
inputStream.close();
outputStream.flush();
}
outputStream.close();
for(String sourceDir : sourceDirectories){
File module = null;
String sourceName = "module.properties";
File properties = new File(sourceFolder, sourceDir + File.separator + sourceName);
if(properties.exists()){
module = properties;
}else{
sourceName = "module.xml";
properties = new File(sourceFolder, sourceDir + File.separator + sourceName);
if(properties.exists()){
module = properties;
}
}
if(module != null){
File moduleFile = new File(sourceFolder, sourceDir + File.separator + sourceName);
FileInputStream inputStream = new FileInputStream(moduleFile);
FileOutputStream moduleOutputStream = new FileOutputStream(new File(jarFolder, sourceName));
Util.copy(inputStream, moduleOutputStream);
inputStream.close();
moduleOutputStream.flush();
moduleOutputStream.close();
}
}
}
@Test
public void testMdlAetherDependencyDefault() throws IOException{
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-rep", "aether", "-verbose:cmr"),
(DiagnosticListener<? super FileObject>)null,
"modules/aetherdefault/module.ceylon", "modules/aetherdefault/foo.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
// We're assuming a standard Maven configuration here!
File camelJar = new File(System.getProperty("user.home"), ".m2/repository/org/apache/camel/camel-core/2.9.2/camel-core-2.9.2.jar");
assertTrue(camelJar.exists());
}
@Test
public void testMdlImplicitAetherDependencyDefault() throws IOException{
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-verbose:cmr"),
(DiagnosticListener<? super FileObject>)null,
"modules/aetherdefault/module.ceylon", "modules/aetherdefault/foo.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
// We're assuming a standard Maven configuration here!
File camelJar = new File(System.getProperty("user.home"), ".m2/repository/org/apache/camel/camel-core/2.9.2/camel-core-2.9.2.jar");
assertTrue(camelJar.exists());
}
@Test
public void testMdlAetherIgnoreRecursiveDependencies() throws IOException{
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-rep", "aether", "-verbose:cmr"),
(DiagnosticListener<? super FileObject>)null,
"modules/aetherIgnoreDependencies/module.ceylon", "modules/aetherIgnoreDependencies/foo.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
// We're assuming a standard Maven configuration here!
File camelJar = new File(System.getProperty("user.home"), ".m2/repository/org/apache/camel/camel-core/2.9.4/camel-core-2.9.4.jar");
assertTrue(camelJar.exists());
File camelJettyJar = new File(System.getProperty("user.home"), ".m2/repository/org/apache/camel/camel-jetty/2.9.4/camel-jetty-2.9.4.jar");
assertTrue(camelJettyJar.exists());
}
@Test
public void testMdlAetherDependencyCustom() throws IOException{
// Try to compile the ceylon module
File settingsFile = new File(getPackagePath(), "modules/aethercustom/settings.xml");
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-rep", "aether:" + settingsFile.getAbsolutePath(), "-verbose:cmr"),
(DiagnosticListener<? super FileObject>)null,
"modules/aethercustom/module.ceylon", "modules/aethercustom/foo.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
File restletJar = new File("build/test-cars/cmr-repository", "org/restlet/org.restlet/1.1.10/org.restlet-1.1.10.jar");
assertTrue(restletJar.exists());
}
@Test
public void testMdlAetherMissingDependencies() throws IOException{
CompilerError[] expectedErrors = new CompilerError[]{
new CompilerError(6, "Error while loading the org.apache.camel:camel-jetty/2.9.4 module:\n"
+" Declaration 'org.apache.camel.component.http.HttpComponent' could not be found in module 'org.apache.camel:camel-jetty' or its imported modules"),
new CompilerError(10, "argument must be assignable to parameter 'arg1' of 'addComponent' in 'DefaultCamelContext': 'JettyHttpComponent' is not assignable to 'Component?': Error while loading the org.apache.camel:camel-jetty/2.9.4 module:\n"+
" Declaration 'org.apache.camel.component.http.HttpComponent' could not be found in module 'org.apache.camel:camel-jetty' or its imported modules"),
};
ErrorCollector collector = new ErrorCollector();
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-rep", "aether"/*, "-verbose:cmr"*/),
collector,
"modules/bug1100/module.ceylon", "modules/bug1100/test.ceylon");
assertEquals("Compilation failed", Boolean.FALSE, ceylonTask.call());
TreeSet<CompilerError> actualErrors = collector.get(Diagnostic.Kind.ERROR);
compareErrors(actualErrors, expectedErrors);
}
@Test
public void testMdlAetherMissingDependenciesOverride() throws IOException{
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir,
"-rep", "aether",
"-overrides", getPackagePath()+"/modules/bug1100/overrides.xml"/*, "-verbose:cmr"*/),
"modules/bug1100/module.ceylon", "modules/bug1100/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
}
@Test
public void testMdlDependenciesNoOverride() throws IOException{
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir/*, "-verbose:cmr"*/),
"modules/overrides/module.ceylon", "modules/overrides/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
}
@Test
public void testMdlDependenciesOverrideRemoveDep() throws IOException{
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir,
"-overrides", getPackagePath()+"/modules/overrides/overridesRemoveJavaBase.xml"/*, "-verbose:cmr"*/),
"modules/overrides/module.ceylon", "modules/overrides/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
}
@Test
public void testMdlAetherMissingDependencies2() throws IOException{
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir,
"-rep", "aether"/*, "-verbose:cmr"*/),
"modules/bug1104/module.ceylon", "modules/bug1104/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
}
@Test
public void testMdlCeylonAetherDuplicateImports() throws IOException{
// Try to compile the ceylon module
ErrorCollector collector = new ErrorCollector();
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-verbose:cmr"),
collector,
"modules/ceylonAetherDuplicateImports/module.ceylon", "modules/ceylonAetherDuplicateImports/foo.ceylon");
assertEquals(Boolean.FALSE, ceylonTask.call());
compareErrors(collector.get(Diagnostic.Kind.ERROR),
new CompilerError(23, "duplicate module import: 'org.apache.httpcomponents.httpclient'"),
new CompilerError(25, "duplicate module import: 'org.apache.httpcomponents:httpclient'")
);
}
@Test
public void testMdlCeylonAetherDependencyConflict() throws IOException{
// Try to compile the ceylon module
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-verbose:cmr"),
(DiagnosticListener<? super FileObject>)null,
"modules/ceylonAetherConflict2/module.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
ErrorCollector collector = new ErrorCollector();
ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-verbose:cmr"),
collector,
"modules/ceylonAetherConflict/module.ceylon", "modules/ceylonAetherConflict/foo.ceylon");
assertEquals(Boolean.TRUE, ceylonTask.call());
compareErrors(collector.get(Diagnostic.Kind.WARNING),
new CompilerError(Diagnostic.Kind.WARNING, null, 21, "source code imports two different versions of similar modules 'org.apache.httpcomponents.httpclient/4.3.2' and 'org.apache.httpcomponents:httpclient/4.3.3'"),
new CompilerError(Diagnostic.Kind.WARNING, null, 21, "module (transitively) imports conflicting versions of similar dependencies 'org.apache.httpcomponents.httpclient/4.3.2' and 'org.apache.httpcomponents:httpclient/4.3.3'")
);
}
@Ignore("It takes ages to download about 200 jars")
@Test
public void testMdlApacheSpark() throws Throwable{
// initially run both without offline, then it's much faster
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir, "-offline"/*, "-verbose:cmr"*/),
"modules/apachespark/module.ceylon", "modules/apachespark/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
runInJBossModules("run", "com.redhat.ceylon.compiler.java.test.cmr.modules.apachespark/1",
Arrays.<String>asList("--flat-classpath", "--offline",
"--maven-overrides", getPackagePath()+"/modules/apachespark/overrides.xml"));
}
@Test(expected = AssertionError.class)
public void testMdlDependenciesFromMavenFail() throws Throwable{
Assume.assumeTrue("Runs on JDK8", JDKUtils.jdk == JDKUtils.JDK.JDK8);
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir/*, "-verbose:cmr"*/),
"modules/sparkframework/module.ceylon", "modules/sparkframework/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
runInJBossModules("run", "com.redhat.ceylon.compiler.java.test.cmr.modules.sparkframework/1");
}
@Test
public void testMdlDependenciesFromMavenAutoExport() throws Throwable{
Assume.assumeTrue("Runs on JDK8", JDKUtils.jdk == JDKUtils.JDK.JDK8);
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir/*, "-verbose:cmr"*/),
"modules/sparkframework/module.ceylon", "modules/sparkframework/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
runInJBossModules("run", "com.redhat.ceylon.compiler.java.test.cmr.modules.sparkframework/1",
Arrays.asList("--auto-export-maven-dependencies"));
}
@Test
public void testMdlDependenciesFromMavenFlatClasspath() throws Throwable{
Assume.assumeTrue("Runs on JDK8", JDKUtils.jdk == JDKUtils.JDK.JDK8);
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir/*, "-verbose:cmr"*/),
"modules/sparkframework/module.ceylon", "modules/sparkframework/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
runInJBossModules("run", "com.redhat.ceylon.compiler.java.test.cmr.modules.sparkframework/1",
Arrays.asList("--flat-classpath", "--overrides", getPackagePath()+"/modules/sparkframework/overrides-log.xml"));
}
@Test
public void testMdlDependenciesFromMavenWithOverrides() throws Throwable{
Assume.assumeTrue("Runs on JDK8", JDKUtils.jdk == JDKUtils.JDK.JDK8);
CeyloncTaskImpl ceylonTask = getCompilerTask(Arrays.asList("-out", destDir/*, "-verbose:cmr"*/),
"modules/sparkframework/module.ceylon", "modules/sparkframework/test.ceylon");
assertEquals("Compilation failed", Boolean.TRUE, ceylonTask.call());
runInJBossModules("run", "com.redhat.ceylon.compiler.java.test.cmr.modules.sparkframework/1",
Arrays.asList("--overrides", getPackagePath()+"/modules/sparkframework/overrides-fix.xml"));
}
@Test
public void testMdlSourceArchive() throws IOException{
File sourceArchiveFile = getSourceArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
sourceArchiveFile.delete();
assertFalse(sourceArchiveFile.exists());
// compile one file
compile("modules/single/module.ceylon");
// make sure it was created
assertTrue(sourceArchiveFile.exists());
JarFile sourceArchive = new JarFile(sourceArchiveFile);
assertEquals(2, countEntries(sourceArchive));
ZipEntry moduleClass = sourceArchive.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/module.ceylon");
assertNotNull(moduleClass);
ZipEntry moduleClassDir = sourceArchive.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/");
assertNotNull(moduleClassDir);
sourceArchive.close();
// now compile another file
compile("modules/single/subpackage/Subpackage.ceylon");
// MUST reopen it
sourceArchive = new JarFile(sourceArchiveFile);
assertEquals(4, countEntries(sourceArchive));
ZipEntry subpackageClass = sourceArchive.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/subpackage/Subpackage.ceylon");
assertNotNull(subpackageClass);
ZipEntry subpackageClassDir = sourceArchive.getEntry("com/redhat/ceylon/compiler/java/test/cmr/modules/single/subpackage/");
assertNotNull(subpackageClassDir);
sourceArchive.close();
}
@Test
public void testMdlMultipleVersionsOnSameCompilation(){
// Compile module A/1
Boolean result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a1"),
"modules/multiversion/a1/a/module.ceylon", "modules/multiversion/a1/a/package.ceylon", "modules/multiversion/a1/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
ErrorCollector collector = new ErrorCollector();
// Compile module A/2 with B importing A/1
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a2"+File.pathSeparator+getPackagePath()+"/modules/multiversion/b"),
collector,
"modules/multiversion/a2/a/module.ceylon", "modules/multiversion/a2/a/package.ceylon", "modules/multiversion/a2/a/A.ceylon",
"modules/multiversion/b/b/module.ceylon", "modules/multiversion/b/b/B.ceylon").call();
Assert.assertEquals(Boolean.FALSE, result);
compareErrors(collector.get(Diagnostic.Kind.ERROR),
new CompilerError(20, "source code imports two different versions of module 'a': version '1' and version '2'"));
}
@Test
public void testMdlMultipleVersionsDuringImport(){
// Compile module A/1
Boolean result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a1"),
"modules/multiversion/a1/a/module.ceylon", "modules/multiversion/a1/a/package.ceylon", "modules/multiversion/a1/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module A/2
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a2"),
"modules/multiversion/a2/a/module.ceylon", "modules/multiversion/a2/a/package.ceylon", "modules/multiversion/a2/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
ErrorCollector collector = new ErrorCollector();
// Compile module cImportsATwice which imports both A/1 and A/2
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/c"),
collector,
"modules/multiversion/c/cImportsATwice/module.ceylon", "modules/multiversion/c/cImportsATwice/C.ceylon").call();
Assert.assertEquals(Boolean.FALSE, result);
compareErrors(collector.get(Diagnostic.Kind.ERROR),
new CompilerError(20, "module (transitively) imports conflicting versions of dependency 'a': version '1' and version '2'"),
new CompilerError(20, "source code imports two different versions of module 'a': version '1' and version '2'"),
new CompilerError(22, "duplicate module import: 'a'")
);
}
@Test
public void testMdlMultipleVersionsDuringDependencyImport(){
// Compile module A/1
Boolean result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a1"),
"modules/multiversion/a1/a/module.ceylon", "modules/multiversion/a1/a/package.ceylon", "modules/multiversion/a1/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module A/2
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a2"),
"modules/multiversion/a2/a/module.ceylon", "modules/multiversion/a2/a/package.ceylon", "modules/multiversion/a2/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module B/1
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/b"),
"modules/multiversion/b/b/module.ceylon", "modules/multiversion/b/b/package.ceylon", "modules/multiversion/b/b/B.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module cImportsABIndirectlyOK which imports both A/1 and A/2
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/c"),
"modules/multiversion/c/cImportsABIndirectlyOK/module.ceylon", "modules/multiversion/c/cImportsABIndirectlyOK/C.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
}
@Test
public void testMdlMultipleVersionsDuringImplicitImport(){
// Compile module A/1
Boolean result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a1"),
"modules/multiversion/a1/a/module.ceylon", "modules/multiversion/a1/a/package.ceylon", "modules/multiversion/a1/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module A/2
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/a2"),
"modules/multiversion/a2/a/module.ceylon", "modules/multiversion/a2/a/package.ceylon", "modules/multiversion/a2/a/A.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module bExportsA1/1
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/b"),
"modules/multiversion/b/bExportsA1/module.ceylon", "modules/multiversion/b/bExportsA1/package.ceylon", "modules/multiversion/b/bExportsA1/B.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
// Compile module cImportsABIndirectlyFail which imports both A/1 and A/2
ErrorCollector collector = new ErrorCollector();
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"/modules/multiversion/c"),
collector,
"modules/multiversion/c/cImportsABIndirectlyFail/module.ceylon", "modules/multiversion/c/cImportsABIndirectlyFail/C.ceylon").call();
Assert.assertEquals(Boolean.FALSE, result);
compareErrors(collector.get(Diagnostic.Kind.ERROR),
new CompilerError(20, "module (transitively) imports conflicting versions of dependency 'a': version '1' and version '2'"),
new CompilerError(20, "source code imports two different versions of module 'a': version '1' and version '2'")
);
}
private int countEntries(JarFile jar) {
int count = 0;
Enumeration<JarEntry> entries = jar.entries();
while(entries.hasMoreElements()){
count++;
entries.nextElement();
}
return count;
}
@Test
public void testMdlSha1Signatures() throws IOException{
File sourceArchiveFile = getSourceArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
File sourceArchiveSignatureFile = new File(sourceArchiveFile.getPath()+".sha1");
File moduleArchiveFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.single", "6.6.6");
File moduleArchiveSignatureFile = new File(moduleArchiveFile.getPath()+".sha1");
// cleanup
sourceArchiveFile.delete();
sourceArchiveSignatureFile.delete();
moduleArchiveFile.delete();
moduleArchiveSignatureFile.delete();
// safety check
assertFalse(sourceArchiveFile.exists());
assertFalse(sourceArchiveSignatureFile.exists());
assertFalse(moduleArchiveFile.exists());
assertFalse(moduleArchiveSignatureFile.exists());
// compile one file
compile("modules/single/module.ceylon");
// make sure everything was created
assertTrue(sourceArchiveFile.exists());
assertTrue(sourceArchiveSignatureFile.exists());
assertTrue(moduleArchiveFile.exists());
assertTrue(moduleArchiveSignatureFile.exists());
// check the signatures vaguely
checkSha1(sourceArchiveSignatureFile);
checkSha1(moduleArchiveSignatureFile);
}
private void checkSha1(File signatureFile) throws IOException {
Assert.assertEquals(40, signatureFile.length());
FileInputStream reader = new FileInputStream(signatureFile);
byte[] bytes = new byte[40];
Assert.assertEquals(40, reader.read(bytes));
reader.close();
char[] sha1 = new String(bytes, "ASCII").toCharArray();
for (int i = 0; i < sha1.length; i++) {
char c = sha1[i];
Assert.assertTrue((c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'f')
|| (c >= 'A' && c <= 'F'));
}
}
@Test
public void testMdlJdkBaseModule() throws IOException{
compile("modules/jdk/appletBroken/Foo.ceylon");
}
@Test
public void testMdlUsesJavaWithoutImportingIt() throws IOException{
assertErrors("modules/jdk/usesJavaWithoutImportingIt/Foo",
new CompilerError(20, "package not found in imported modules: 'java.lang' (add module import to module descriptor of 'com.redhat.ceylon.compiler.java.test.cmr.modules.jdk.usesJavaWithoutImportingIt')"),
new CompilerError(23, "function or value does not exist: 'nanoTime'"));
}
@Test
public void testMdlDefaultUsesJavaWithoutImportingIt() throws IOException{
List<String> options = new LinkedList<String>();
options.add("-src");
options.add(getPackagePath()+"/modules/jdk/defaultUsesJavaWithoutImportingIt");
options.addAll(defaultOptions);
assertErrors("modules/jdk/defaultUsesJavaWithoutImportingIt/Foo",
new CompilerError(20, "package not found in imported modules: 'java.lang' (define a module and add module import to its module descriptor)"),
new CompilerError(23, "function or value does not exist: 'nanoTime'"));
}
@Test
public void testMdlLegacyImport(){
// Compile a module that imports a legacy module that has a shared import of another legacy module
compile("modules/legacyimport/module.ceylon", "modules/legacyimport/package.ceylon", "modules/legacyimport/A.ceylon");
File carFile = getModuleArchive("com.redhat.ceylon.compiler.java.test.cmr.modules.legacyimport", "6.6.6");
assertTrue(carFile.exists());
}
@Test
public void testMdlBug1062IncompatibleMissingImport() throws IOException{
// compile our java class
File classesOutputFolder = new File(destDir+"-jar-classes");
cleanCars(classesOutputFolder.getPath());
classesOutputFolder.mkdirs();
File jarOutputFolder = new File(destDir+"-jar");
cleanCars(jarOutputFolder.getPath());
jarOutputFolder.mkdirs();
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaA", "1",
new File(getPackagePath(), "modules/bug1062/javaA1-src"),
new File[0],
"bug1062/javaA/JavaA.java");
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaA", "2",
new File(getPackagePath(), "modules/bug1062/javaA2-src"),
new File[0],
"bug1062/javaA/JavaA.java");
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaB", "1",
new File(getPackagePath(), "modules/bug1062/javaB-nomodule-src"),
new File[]{new File(jarOutputFolder, "bug1062/javaA/1/bug1062.javaA-1.jar")},
"bug1062/javaB/JavaB.java");
assertErrors("modules/bug1062/ceylon/test",
Arrays.asList("-rep", jarOutputFolder.getPath()), null,
new CompilerError(5, "could not determine type of method or attribute reference: 'method' of 'JavaB': Error while loading the bug1062.javaB/1 module:\n"+
" Declaration 'bug1062.javaA.JavaA' could not be found in module 'bug1062.javaB' or its imported modules but was found in the non-imported module 'bug1062.javaA'"),
new CompilerError(5, "parameter type could not be determined: 'arg0' of 'method' in 'JavaB': Error while loading the bug1062.javaB/1 module:\n" +
" Declaration 'bug1062.javaA.JavaA' could not be found in module 'bug1062.javaB' or its imported modules but was found in the non-imported module 'bug1062.javaA'")
);
}
@Test
public void testMdlBug1062IncompatibleNonSharedImport() throws IOException{
// compile our java class
File classesOutputFolder = new File(destDir+"-jar-classes");
cleanCars(classesOutputFolder.getPath());
classesOutputFolder.mkdirs();
File jarOutputFolder = new File(destDir+"-jar");
cleanCars(jarOutputFolder.getPath());
jarOutputFolder.mkdirs();
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaA", "1",
new File(getPackagePath()+"/modules/bug1062/javaA1-src"),
new File[0],
"bug1062/javaA/JavaA.java");
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaA", "2",
new File(getPackagePath()+"/modules/bug1062/javaA2-src"),
new File[0],
"bug1062/javaA/JavaA.java");
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaB", "1",
new File(getPackagePath()+"/modules/bug1062/javaB-module-src"),
new File[]{new File(jarOutputFolder, "bug1062/javaA/1/bug1062.javaA-1.jar")},
"bug1062/javaB/JavaB.java");
// ceylon module imports JavaA/2 and JavaB/1
// JavaB/1 imports JavaA/1
assertErrors("modules/bug1062/ceylon/test",
Arrays.asList("-rep", jarOutputFolder.getPath(), "-cp", getClassPathAsPath()), null,
new CompilerError(5, "could not determine type of method or attribute reference: 'method' of 'JavaB': Error while loading the bug1062.javaB/1 module:\n"+
" Declaration 'bug1062.javaA.JavaA' could not be found in module 'bug1062.javaB' or its imported modules but was found in the non-imported module 'bug1062.javaA'"),
new CompilerError(5, "parameter type could not be determined: 'arg0' of 'method' in 'JavaB': Error while loading the bug1062.javaB/1 module:\n" +
" Declaration 'bug1062.javaA.JavaA' could not be found in module 'bug1062.javaB' or its imported modules but was found in the non-imported module 'bug1062.javaA'")
);
}
@Test
public void testMdlBug1062IncompatibleSharedImport() throws IOException{
// compile our java class
File classesOutputFolder = new File(destDir+"-jar-classes");
cleanCars(classesOutputFolder.getPath());
classesOutputFolder.mkdirs();
File jarOutputFolder = new File(destDir+"-jar");
cleanCars(jarOutputFolder.getPath());
jarOutputFolder.mkdirs();
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaA", "1",
new File(getPackagePath()+"/modules/bug1062/javaA1-src"),
new File[0],
"bug1062/javaA/JavaA.java");
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaA", "2",
new File(getPackagePath()+"/modules/bug1062/javaA2-src"),
new File[0],
"bug1062/javaA/JavaA.java");
compileJavaModule(jarOutputFolder, classesOutputFolder, "bug1062.javaB", "1",
new File(getPackagePath()+"/modules/bug1062/javaB-module-export-src"),
new File[]{new File(jarOutputFolder, "bug1062/javaA/1/bug1062.javaA-1.jar")},
"bug1062/javaB/JavaB.java");
// ceylon module imports JavaA/2 and JavaB/1
// JavaB/1 shared imports JavaA/1
assertErrors("modules/bug1062/ceylon/test",
Arrays.asList("-rep", jarOutputFolder.getPath()), null,
new CompilerError(2, "module (transitively) imports conflicting versions of dependency 'bug1062.javaA': version '1' and version '2'"),
new CompilerError(2, "source code imports two different versions of module 'bug1062.javaA': version '1' and version '2'")
);
}
@Test
public void testMdlDefaultImportsInexistantPackage() throws IOException{
// we do it twice to make sure existing class files do not confuse it
for(int i=0;i<2;i++){
assertErrors(new String[]{
"modules/defaultImportsInexistantPackage/file.ceylon",
"modules/defaultImportsInexistantPackage/isModule/module.ceylon",
"modules/defaultImportsInexistantPackage/isModule/package.ceylon",
"modules/defaultImportsInexistantPackage/isModule/foo.ceylon",
},
defaultOptions,
null,
new CompilerError( 1, "package not found in imported modules: 'doesnotExist' (define a module and add module import to its module descriptor)"),
new CompilerError( 2, "package not found in imported modules: 'com.redhat.ceylon.compiler.java.test.cmr.modules.defaultImportsInexistantPackage.isModule' (define a module and add module import to its module descriptor)")
);
}
}
@Test
public void testMdlProducesOsgiManifest() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon");
final String moduleName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleName, moduleVersion);
Attributes attr = manifest.getMainAttributes();
assertEquals("2", attr.get(OsgiManifest.Bundle_ManifestVersion));
assertEquals(moduleName, attr.get(OsgiManifest.Bundle_SymbolicName));
String bundleVersion = (String) attr.get(OsgiManifest.Bundle_Version);
int qualifierIndex = bundleVersion.lastIndexOf('.');
String bundleVersionWithoutQualifier = qualifierIndex > 0 ? bundleVersion.substring(0, qualifierIndex) : bundleVersion;
assertEquals(moduleVersion, bundleVersionWithoutQualifier);
}
@Test
public void testMdlDefaultHasNoOsgiManifest() throws IOException {
compile("modules/def/CeylonClass.ceylon");
File carFile = getModuleArchive("default", null);
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry manifest = car.getEntry(OsgiManifest.MANIFEST_FILE_NAME);
assertNull(manifest);
car.close();
}
@Test
public void testMdlOsgiManifestDisabled() throws IOException {
ErrorCollector c = new ErrorCollector();
List<String> options = new ArrayList<String>(defaultOptions.size()+1);
options.addAll(defaultOptions);
options.add("-noosgi");
assertCompilesOk(c, getCompilerTask(options, c, "modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon").call2());
final String moduleName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a";
final String moduleVersion = "1.1.0";
File carFile = getModuleArchive(moduleName, moduleVersion);
JarFile car = new JarFile(carFile);
ZipEntry manifest = car.getEntry(OsgiManifest.MANIFEST_FILE_NAME);
assertNull(manifest);
car.close();
}
@Test
public void testMdlOsgiManifestRequiresCeylonLanguageBundle() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon");
final Manifest manifest = getManifest(
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a", "1.1.0");
assertEquals("ceylon.language;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport" +
",com.redhat.ceylon.dist;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport",
manifest.getMainAttributes().get(OsgiManifest.Require_Bundle));
}
@Test
public void testMdlOsgiManifestExportsSharedPackages() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon", "modules/osgi/a/A.ceylon",
"modules/osgi/a/b/package.ceylon", "modules/osgi/a/b/B.ceylon",
"modules/osgi/a/c/package.ceylon", "modules/osgi/a/c/C.ceylon");
final String moduleName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleName, moduleVersion);
assertNotNull(manifest);
Attributes attr = manifest.getMainAttributes();
String attribute = (String) attr.get(OsgiManifest.Export_Package);
String[] exportPackage = attribute.split(",");
assertEquals(2, exportPackage.length);
assertThat(
Arrays.asList(exportPackage),
CoreMatchers.hasItems(
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a;version="+ moduleVersion,
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a.c;version="+ moduleVersion));
assertThat( Arrays.asList(exportPackage),
CoreMatchers.not(CoreMatchers.hasItem("com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a.b;version=" + moduleVersion)));
}
@Test
public void testMdlOsgiManifestRequresImportedModules() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon");
compile("modules/osgi/b/module.ceylon",
"modules/osgi/b/package.ceylon",
"modules/osgi/b/B.ceylon");
final String moduleBName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.b";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleBName, moduleVersion);
final String[] requireBundle = ((String) manifest.getMainAttributes()
.get(OsgiManifest.Require_Bundle)).split(",");
assertEquals(3, requireBundle.length);
assertThat(Arrays.asList(requireBundle), CoreMatchers.hasItems(
"ceylon.language;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport",
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a;bundle-version=1.1.0",
"com.redhat.ceylon.dist;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport"));
}
@Test
public void testMdlOsgiManifestFiltersProvidedBundles() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon");
ArrayList<String> options = new ArrayList<>(defaultOptions);
options.addAll(Arrays.asList(
"-osgi-provided-bundles",
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a , ceylon.language"));
compilesWithoutWarnings(
options,
"modules/osgi/b/module.ceylon",
"modules/osgi/b/package.ceylon",
"modules/osgi/b/B.ceylon");
final String moduleBName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.b";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleBName, moduleVersion);
final String[] requireBundle = ((String) manifest.getMainAttributes()
.get(OsgiManifest.Require_Bundle)).split(",");
assertEquals(1, requireBundle.length);
assertThat(Arrays.asList(requireBundle), CoreMatchers.hasItems(
"com.redhat.ceylon.dist;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport"));
}
@Test
public void testMdlOsgiManifestFiltersProvidedBundle() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon");
ArrayList<String> options = new ArrayList<>(defaultOptions);
options.addAll(Arrays.asList(
"-osgi-provided-bundles",
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a"));
compilesWithoutWarnings(
options,
"modules/osgi/b/module.ceylon",
"modules/osgi/b/package.ceylon",
"modules/osgi/b/B.ceylon");
final String moduleBName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.b";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleBName, moduleVersion);
final String[] requireBundle = ((String) manifest.getMainAttributes()
.get(OsgiManifest.Require_Bundle)).split(",");
assertEquals(2, requireBundle.length);
assertThat(Arrays.asList(requireBundle), CoreMatchers.hasItems(
"ceylon.language;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport",
"com.redhat.ceylon.dist;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport"));
}
@Test
public void testMdlOsgiManifestReexportsSharedImportedModules() throws IOException {
compile("modules/osgi/a/module.ceylon",
"modules/osgi/a/package.ceylon",
"modules/osgi/a/A.ceylon");
compile("modules/osgi/c/module.ceylon",
"modules/osgi/c/package.ceylon",
"modules/osgi/c/C.ceylon");
final String moduleCName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.c";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleCName, moduleVersion);
final String[] requireBundle = ((String) manifest.getMainAttributes()
.get(OsgiManifest.Require_Bundle)).split(",");
assertEquals(3, requireBundle.length);
assertThat(Arrays.asList(requireBundle), CoreMatchers.hasItems(
"ceylon.language;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport",
"com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.a;bundle-version=1.1.0;visibility:=reexport",
"com.redhat.ceylon.dist;bundle-version="+Versions.CEYLON_VERSION_NUMBER+";visibility:=reexport"));
}
@Test
public void testMdlOsgiManifestWithJavaImportRequiresJavaSECapability() throws IOException {
compile("modules/osgi/java/module.ceylon",
"modules/osgi/java/package.ceylon",
"modules/osgi/java/foo.ceylon");
final String moduleName = "com.redhat.ceylon.compiler.java.test.cmr.modules.osgi.java";
final String moduleVersion = "1.1.0";
final Manifest manifest = getManifest(moduleName, moduleVersion);
assertEquals("osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(version>=1.7))\"",
manifest.getMainAttributes().get(OsgiManifest.Require_Capability));
}
private Manifest getManifest(String moduleName, String moduleVersion) throws IOException {
File carFile = getModuleArchive(moduleName, moduleVersion);
Manifest manifest = null;
try (JarFile car = new JarFile(carFile)) {
manifest = car.getManifest();
}
assertNotNull(manifest);
return manifest;
}
@Test
public void testMdlPomManifest() throws IOException {
compile("modules/pom/a/module.ceylon",
"modules/pom/b/module.ceylon");
final String moduleName = "com.redhat.ceylon.compiler.java.test.cmr.modules.pom.b";
final String moduleVersion = "1";
File carFile = getModuleArchive(moduleName, moduleVersion);
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry pomFile = car.getEntry("META-INF/maven/com.redhat.ceylon.compiler.java.test.cmr.modules.pom/b/pom.xml");
assertNotNull(pomFile);
String pomContents = read(car, pomFile);
assertEquals("<?xml version=\"1.0\" ?>\n"
+"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n"
+" <modelVersion>4.0.0</modelVersion>\n"
+" <groupId>com.redhat.ceylon.compiler.java.test.cmr.modules.pom</groupId>\n"
+" <artifactId>b</artifactId>\n"
+" <version>1</version>\n"
+" <name>com.redhat.ceylon.compiler.java.test.cmr.modules.pom.b</name>\n"
+" <dependencies>\n"
+" <dependency>\n"
+" <groupId>com.redhat.ceylon.compiler.java.test.cmr.modules.pom</groupId>\n"
+" <artifactId>a</artifactId>\n"
+" <version>1</version>\n"
+" </dependency>\n"
+" </dependencies>\n"
+"</project>\n",
pomContents);
ZipEntry propertiesFile = car.getEntry("META-INF/maven/com.redhat.ceylon.compiler.java.test.cmr.modules.pom/b/pom.properties");
assertNotNull(propertiesFile);
String propertiesContents = read(car, propertiesFile);
// remove the date comment
propertiesContents = propertiesContents.replaceFirst("^(#Generated by Ceylon\n)#[^\n]+\n", "$1");
assertEquals("#Generated by Ceylon\n"
+"version=1\n"
+"groupId=com.redhat.ceylon.compiler.java.test.cmr.modules.pom\n"
+"artifactId=b\n", propertiesContents);
car.close();
}
@Test
public void testMdlNoPomManifest() throws IOException {
ErrorCollector c = new ErrorCollector();
assertCompilesOk(c, getCompilerTask(Arrays.asList("-nopom", "-out", destDir), c, "modules/pom/a/module.ceylon",
"modules/pom/b/module.ceylon").call2());
final String moduleName = "com.redhat.ceylon.compiler.java.test.cmr.modules.pom.b";
final String moduleVersion = "1";
File carFile = getModuleArchive(moduleName, moduleVersion);
assertTrue(carFile.exists());
JarFile car = new JarFile(carFile);
ZipEntry pomFile = car.getEntry("META-INF/maven/com.redhat.ceylon.compiler.java.test.cmr.modules.pom/b/pom.xml");
assertNull(pomFile);
ZipEntry propertiesFile = car.getEntry("META-INF/maven/com.redhat.ceylon.compiler.java.test.cmr.modules.pom/b/pom.properties");
assertNull(propertiesFile);
car.close();
}
private String read(JarFile car, ZipEntry entry) throws IOException {
try(InputStream is = car.getInputStream(entry);
Reader r = new InputStreamReader(is);
BufferedReader br = new BufferedReader(r)){
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null)
sb.append(line).append("\n");
return sb.toString();
}
}
private void setupBinaryModulesForOverridesCeylonModuleTests() {
Boolean result = null;
for (String version : Arrays.asList("v1", "v2")) {
// Compile modules and generate archives
result = getCompilerTask(Arrays.asList("-src", getPackagePath()+"modules/overridesCeylonModule/" + version),
"modules/overridesCeylonModule/" + version + "/a/module.ceylon",
"modules/overridesCeylonModule/" + version + "/b/module.ceylon",
"modules/overridesCeylonModule/" + version + "/b/hidden/package.ceylon",
"modules/overridesCeylonModule/" + version + "/b/shared/package.ceylon",
"modules/overridesCeylonModule/" + version + "/c/module.ceylon",
"modules/overridesCeylonModule/" + version + "/c/hidden/package.ceylon",
"modules/overridesCeylonModule/" + version + "/c/shared/package.ceylon").call();
Assert.assertEquals(Boolean.TRUE, result);
}
}
private static class ModulesRetriever implements TaskListener {
private com.sun.tools.javac.util.Context context = null;
HashMap<String, Module> modules = null;
public ModulesRetriever(com.sun.tools.javac.util.Context context) {
this.context = context;
}
@Override
public void started(TaskEvent e) {
}
@Override
public void finished(TaskEvent e) {
if(e.getKind() == TaskEvent.Kind.ENTER){
if(modules == null) {
modules = new HashMap<>();
Context ceylonContext = LanguageCompiler.getCeylonContextInstance(context);
assert(ceylonContext != null);
Modules modules = ceylonContext.getModules();
assert(modules != null);
for (Module m : modules.getListOfModules()) {
String name = m.getNameAsString();
if (name.equals("a") || name.equals("b") || name.equals("c")) {
this.modules.put(name, m);
}
}
}
}
}
}
@Test
public void testOverridesCeylonModuleInSourceImport(){
setupBinaryModulesForOverridesCeylonModuleTests();
ErrorCollector collector = new ErrorCollector();
CeyloncTaskImpl compilerTask = getCompilerTask(
Arrays.asList(
"-continue",
"-src", getPackagePath()+"/modules",
"-overrides", getPackagePath() +"modules/overridesCeylonModule/overrides-a-version.xml"
),
collector,
"modules/overridesCeylonModule/module.ceylon");
ModulesRetriever modulesRetriever = new ModulesRetriever(compilerTask.getContext());
compilerTask.setTaskListener(modulesRetriever);
Boolean result = compilerTask.call();
Assert.assertEquals(Boolean.FALSE, result);
compareErrors(collector.get(Diagnostic.Kind.ERROR),
new CompilerError(2, "The module import should not be overriden, since it is explicitely imported by a project source module"));
assert(modulesRetriever.modules != null);
Module a = modulesRetriever.modules.get("a");
Module b = modulesRetriever.modules.get("b");
Module c = modulesRetriever.modules.get("c");
assert(a != null);
assert(b != null);
assert(c != null);
assertEquals("The version override should not be applied to modules imported in source code", "2", a.getVersion());
assertEquals("The version override should not be applied to modules imported in source code", "2", b.getVersion());
assertEquals("The version override should not be applied to modules imported in source code", "2", c.getVersion());
}
@Test
public void testOverridesCeylonModuleVersionProducesJavaModule(){
setupBinaryModulesForOverridesCeylonModuleTests();
ErrorCollector collector = new ErrorCollector();
CeyloncTaskImpl compilerTask = getCompilerTask(
Arrays.asList(
"-src", getPackagePath()+"/modules",
"-overrides", getPackagePath() +"modules/overridesCeylonModule/overrides-b-version.xml"
),
collector,
"modules/overridesCeylonModule/module.ceylon");
ModulesRetriever modulesRetriever = new ModulesRetriever(compilerTask.getContext());
compilerTask.setTaskListener(modulesRetriever);
Boolean result = compilerTask.call();
Assert.assertEquals(Boolean.TRUE, result);
assert(modulesRetriever.modules != null);
Module b = modulesRetriever.modules.get("b");
assert(b != null);
assertEquals("The Ceylon module 'b' is now seen as a Java module when a version override is applied", false, b.isJava());
}
@Test
public void testOverridesCeylonModuleVersionAlterdPackageSharing(){
setupBinaryModulesForOverridesCeylonModuleTests();
ErrorCollector collector = new ErrorCollector();
CeyloncTaskImpl compilerTask = getCompilerTask(
Arrays.asList(
"-src", getPackagePath()+"/modules",
"-overrides", getPackagePath() +"modules/overridesCeylonModule/overrides-b-version.xml"
),
collector,
"modules/overridesCeylonModule/module.ceylon", "modules/overridesCeylonModule/testImportHiddenPackage.ceylon");
ModulesRetriever modulesRetriever = new ModulesRetriever(compilerTask.getContext());
compilerTask.setTaskListener(modulesRetriever);
Boolean result = compilerTask.call();
Assert.assertEquals(Boolean.FALSE, result);
compareErrors(collector.get(Diagnostic.Kind.ERROR),
new CompilerError(2, "imported package is not shared: 'b.hidden'"));
}
private ModuleImport getModuleImport(Module m, String name) {
for (ModuleImport i : m.getImports()) {
if (i.getModule().getNameAsString().equals(name)) {
return i;
}
}
return null;
}
@Test
public void testOverridesCeylonModuleShareImport() {
setupBinaryModulesForOverridesCeylonModuleTests();
ErrorCollector collector = new ErrorCollector();
CeyloncTaskImpl compilerTask = getCompilerTask(
Arrays.asList(
"-src", getPackagePath()+"/modules",
"-overrides", getPackagePath() +"modules/overridesCeylonModule/overrides-share-c-import.xml"
),
collector,
"modules/overridesCeylonModule/module.ceylon");
ModulesRetriever modulesRetriever = new ModulesRetriever(compilerTask.getContext());
compilerTask.setTaskListener(modulesRetriever);
Boolean result = compilerTask.call();
Assert.assertEquals(Boolean.TRUE, result);
Module a = modulesRetriever.modules.get("a");
assert(a != null);
ModuleImport cImport = getModuleImport(a, "c");
assert(cImport != null);
assertEquals("The 'c' module import should be seen as 'exported' after applying the overrides file", true, cImport.isExport());
}
@Test
public void testCacheFolderCreation() throws IOException{
// move our user cache folder
File userCacheRepo = Repositories.get().getCacheRepoDir();
File tmpCacheRepo = null;
boolean moved = false;
if(userCacheRepo.exists()){
// let's move it
System.out.println("Moving user cache repo away");
tmpCacheRepo = File.createTempFile("moved-", "-out-for-CMRTests", userCacheRepo.getParentFile());
tmpCacheRepo.delete();
assert(userCacheRepo.renameTo(tmpCacheRepo));
moved = true;
}
try{
String cachePath = getCachePath();
File cacheFolder = new File(cachePath);
// cleared
assert(!cacheFolder.exists());
// clear or moved
assert(!userCacheRepo.exists());
compile("modules/def/A.ceylon");
// created
assert(cacheFolder.exists());
// still not there
assert(!userCacheRepo.exists());
}finally{
if(moved){
System.out.println("Moving user cache repo back");
Assert.assertTrue("Moving back your cache repo has failed: it is now at "
+tmpCacheRepo+" so if you want to keep it at "
+userCacheRepo+" you need to move it manually. Sorry.",
tmpCacheRepo.renameTo(userCacheRepo));
}
}
}
@Test
public void testMdlNullVersion() throws IOException{
assertErrors("modules/nullVersion/module",
new CompilerError(21, "missing module version"),
new CompilerError(21, "cannot find module artifact null-null(.car|.jar)\n \t- dependency tree: com.redhat.ceylon.compiler.java.test.cmr.modules.nullVersion/1 -> null/null")
);
}
}