blob: 838244f8c410396268b23f66981bbf81c9221283 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.android.jack.error;
import com.google.common.io.Files;
import com.android.jack.JackAbortException;
import com.android.jack.backend.jayce.JayceFileImporter.CollisionPolicy;
import com.android.jack.errorhandling.annotationprocessor.ResourceAnnotationProcessor;
import com.android.jack.errorhandling.annotationprocessor.ResourceAnnotationTest;
import com.android.jack.errorhandling.annotationprocessor.SourceAnnotationProcessor;
import com.android.jack.errorhandling.annotationprocessor.SourceAnnotationTest;
import com.android.jack.errorhandling.annotationprocessor.SourceErrorAnnotationTest;
import com.android.jack.frontend.FrontendCompilationException;
import com.android.jack.resource.ResourceImporter;
import com.android.jack.resource.ResourceReadingException;
import com.android.jack.test.TestsProperties;
import com.android.jack.test.helper.ErrorTestHelper;
import com.android.jack.test.junit.KnownIssue;
import com.android.jack.test.toolchain.AbstractTestTools;
import com.android.jack.test.toolchain.IncrementalToolchain;
import com.android.jack.test.toolchain.JackApiToolchainBase;
import junit.framework.Assert;
import org.jf.dexlib.ClassDefItem;
import org.jf.dexlib.DexFile;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
/**
* JUnit test checking Jack behavior when using annotation processor.
*/
public class AnnotationProcessorErrorTest {
/**
* Checks that compilation succeed when running annotation processor to generate resource file.
*/
@Test
public void testAnnotationProcessorError002() throws Exception {
runAnnotProcBuildingResource(new ErrorTestHelper());
}
/**
* Checks that last compilation failed since the resource created by annotation processor already
* exist.
*/
@Test
public void testAnnotationProcessorError003() throws Exception {
ErrorTestHelper te = new ErrorTestHelper();
runAnnotProcBuildingResource(te);
JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class);
jackApiToolchain.setAnnotationProcessorClasses(
Collections.singletonList(ResourceAnnotationProcessor.class.getName()));
ByteArrayOutputStream errOut = new ByteArrayOutputStream();
jackApiToolchain.setErrorStream(errOut);
jackApiToolchain.addResourceDir(te.getOutputDexFolder());
jackApiToolchain.addProperty(ResourceImporter.RESOURCE_COLLISION_POLICY.getName(),
CollisionPolicy.FAIL.name());
try {
jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath())
.addToClasspath(te.getJackFolder())
.srcToExe(te.getOutputDexFolder(), /* zipFile = */ false, te.getSourceFolder());
Assert.fail();
} catch (JackAbortException e) {
Assert.assertTrue(e.getCause() instanceof ResourceReadingException);
// Failure is ok since created file already exists
}
}
/**
* Checks that compilation failed since the source file generated by the annotation processor
* does not compile.
*/
@Test
public void testAnnotationProcessorError004() throws Exception {
ErrorTestHelper te = new ErrorTestHelper();
buildAnnotationRequiredByAnnotationProc(te, new Class<?>[] {SourceAnnotationTest.class,
SourceErrorAnnotationTest.class});
AbstractTestTools.createFile(te.getSourceFolder(), "jack.incremental", "A.java", "package jack.incremental;\n"
+ "import " + SourceErrorAnnotationTest.class.getName() + ";\n"
+ "@" + SourceErrorAnnotationTest.class.getSimpleName() + "\n"
+ "public class A {}\n");
JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class);
jackApiToolchain.setAnnotationProcessorClasses(
Collections.singletonList(SourceAnnotationProcessor.class.getName()));
ByteArrayOutputStream errOut = new ByteArrayOutputStream();
jackApiToolchain.setErrorStream(errOut);
try {
jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath())
.addToClasspath(te.getJackFolder())
.srcToExe(te.getOutputDexFolder(), /* zipFile = */ false, te.getSourceFolder());
Assert.fail();
} catch (FrontendCompilationException ex) {
// Failure is ok since source generated by annotation processor does not compile.
} finally {
Assert.assertTrue(errOut.toString().contains("Syntax error on tokens, delete these tokens"));
}
}
/**
* Checks that compilation succeed to compile source file generated by the annotation processor.
*/
@Test
public void testAnnotationProcessorError005() throws Exception {
ErrorTestHelper te = new ErrorTestHelper();
buildAnnotationRequiredByAnnotationProc(te, new Class<?>[] {SourceAnnotationTest.class,
SourceErrorAnnotationTest.class});
AbstractTestTools.createFile(te.getSourceFolder(), "jack.incremental", "A.java", "package jack.incremental;\n"
+ "import " + SourceAnnotationTest.class.getName() + ";\n"
+ "@" + SourceAnnotationTest.class.getSimpleName() + "\n"
+ "public class A {}\n");
JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class);
jackApiToolchain.setAnnotationProcessorClasses(
Collections.singletonList(SourceAnnotationProcessor.class.getName()));
File dexOutput = te.getOutputDexFolder();
jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath())
.addToClasspath(te.getJackFolder())
.srcToExe(dexOutput, /* zipFile = */ false, te.getSourceFolder());
DexFile dexFile = new DexFile(new File(dexOutput, jackApiToolchain.getBinaryFileName()));
List<String> sourceFileInDex = new ArrayList<String>();
for (ClassDefItem classDef : dexFile.ClassDefsSection.getItems()) {
sourceFileInDex.add(classDef.getSourceFile().getStringValue());
}
Assert.assertTrue(sourceFileInDex.contains("ADuplicated.java"));
Assert.assertTrue(sourceFileInDex.contains("A.java"));
}
private void runAnnotProcBuildingResource(@Nonnull ErrorTestHelper te) throws Exception {
buildAnnotationRequiredByAnnotationProc(te, new Class<?>[] {ResourceAnnotationTest.class});
AbstractTestTools.createFile(te.getSourceFolder(), "jack.incremental", "A.java", "package jack.incremental;\n"
+ "import " + ResourceAnnotationTest.class.getName() + ";\n"
+ "@" + ResourceAnnotationTest.class.getSimpleName() + "\n"
+ "public class A {}\n");
JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class);
jackApiToolchain.setAnnotationProcessorClasses(
Collections.singletonList(ResourceAnnotationProcessor.class.getName()));
jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath())
.addToClasspath(te.getJackFolder())
.srcToExe(te.getOutputDexFolder(), /* zipFile = */ false, te.getSourceFolder());
File discoverFile = new File(te.getOutputDexFolder(), ResourceAnnotationProcessor.FILENAME);
Assert.assertTrue(discoverFile.exists());
LineNumberReader lnr = new LineNumberReader(new FileReader(discoverFile));
Assert.assertEquals(ResourceAnnotationTest.class.getName(), lnr.readLine());
Assert.assertEquals("jack.incremental.A", lnr.readLine());
Assert.assertNull(lnr.readLine());
lnr.close();
}
private void buildAnnotationRequiredByAnnotationProc(@Nonnull ErrorTestHelper te,
Class<?>[] annotationClasses) throws Exception {
File targetAnnotationFileFolder =
new File(te.getSourceFolder(), "com/android/jack/errorhandling/annotationprocessor/");
if (!targetAnnotationFileFolder.mkdirs()) {
Assert.fail("Fail to create folder " + targetAnnotationFileFolder.getAbsolutePath());
}
for (Class<?> annotationClass : annotationClasses) {
Files.copy(new File(TestsProperties.getJackRootDir(),
"jack/tests/com/android/jack/errorhandling/annotationprocessor/"
+ annotationClass.getSimpleName() + ".java"), new File(
targetAnnotationFileFolder, annotationClass.getSimpleName() + ".java"));
}
// Compile annotation to a jack file
JackApiToolchainBase jackApiToolchain =
AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class);
jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath())
.srcToLib(te.getJackFolder(), false /* zipFiles = */, te.getSourceFolder());
AbstractTestTools.deleteTempDir(te.getSourceFolder());
}
}