blob: 0b8961b8137e8a61db9c81a62e63ea3df9057b2c [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* 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.google.android.testing.mocking;
import javassist.CannotCompileException;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.tools.JavaFileObject;
/**
* @author swoodward@google.com (Stephen Woodward)
*/
public class UsesMocksProcessorTest extends TestCase {
private Set<? extends Element> getAnnotatedElementsSet(Class<?>... classes) {
Set<Element> set = new HashSet<Element>();
for (Class<?> clazz : classes) {
set.add(getMockElement(clazz));
}
return set;
}
@SuppressWarnings("unchecked")
private Element getMockElement(Class<?> clazz) {
Element mockElement = EasyMock.createNiceMock(Element.class);
EasyMock.expect(mockElement.getAnnotationMirrors()).andReturn(getMockAnnotationMirrors(clazz))
.anyTimes();
EasyMock.replay(mockElement);
return mockElement;
}
@SuppressWarnings("unchecked")
private List getMockAnnotationMirrors(Class<?> clazz) {
List<AnnotationMirror> mockMirrorList = new ArrayList<AnnotationMirror>();
AnnotationMirror mockMirror = EasyMock.createNiceMock(AnnotationMirror.class);
EasyMock.expect(mockMirror.getAnnotationType()).andReturn(getMockAnnotationType()).anyTimes();
EasyMock.expect(mockMirror.getElementValues()).andReturn(getMockElementValuesMap(clazz))
.anyTimes();
EasyMock.replay(mockMirror);
mockMirrorList.add(mockMirror);
return mockMirrorList;
}
@SuppressWarnings("unchecked")
private Map getMockElementValuesMap(Class<?> clazz) {
Map mockValuesMap = new HashMap();
mockValuesMap.put(getMockExecutableElement(), getMockAnnotationValue(clazz));
return mockValuesMap;
}
private AnnotationValue getMockAnnotationValue(Class<?> clazz) {
AnnotationValue mockValue = EasyMock.createMock(AnnotationValue.class);
EasyMock.expect(mockValue.getValue()).andReturn(
Arrays.asList(new String[] {clazz.getName() + ".class"})).anyTimes();
EasyMock.replay(mockValue);
return mockValue;
}
private ExecutableElement getMockExecutableElement() {
ExecutableElement mockElement = EasyMock.createNiceMock(ExecutableElement.class);
EasyMock.replay(mockElement);
return mockElement;
}
private DeclaredType getMockAnnotationType() {
return new DeclaredType() {
@Override
public String toString() {
return UsesMocks.class.getName();
}
@Override
public Element asElement() {
return null;
}
@Override
public TypeMirror getEnclosingType() {
return null;
}
@Override
public List<? extends TypeMirror> getTypeArguments() {
return null;
}
@Override
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return null;
}
@Override
public TypeKind getKind() {
return null;
}
};
}
private UsesMocksProcessor getProcessor() {
return getProcessor(getMockProcessingEnvironment());
}
private UsesMocksProcessor getProcessor(ProcessingEnvironment processingEnv) {
UsesMocksProcessor processor = new UsesMocksProcessor();
processor.init(processingEnv);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
processor.logger = new ProcessorLogger(outputStream, processingEnv);
return processor;
}
private ProcessingEnvironment getMockProcessingEnvironment(Filer mockFiler) {
ProcessingEnvironment mockEnvironment = EasyMock.createNiceMock(ProcessingEnvironment.class);
EasyMock.expect(mockEnvironment.getMessager()).andReturn(getMockMessager()).anyTimes();
EasyMock.expect(mockEnvironment.getFiler()).andReturn(mockFiler).anyTimes();
EasyMock.expect(mockEnvironment.getOptions()).andReturn(getMockOptions()).anyTimes();
EasyMock.replay(mockEnvironment);
return mockEnvironment;
}
private Map<String, String> getMockOptions() {
Map<String, String> map = new HashMap<String, String>();
map.put("bin_dir", ".");
map.put("logfile", "logfile");
return map;
}
private ProcessingEnvironment getMockProcessingEnvironment() {
return getMockProcessingEnvironment(getMockFiler());
}
private Messager getMockMessager() {
Messager mockMessager = EasyMock.createNiceMock(Messager.class);
EasyMock.replay(mockMessager);
return mockMessager;
}
private Filer getMockFiler() {
try {
return getMockFiler(getMockFileObject());
} catch (IOException e) {
// Can't happen
throw new RuntimeException(e);
}
}
private Filer getMockFiler(JavaFileObject mockFileObject) {
Filer mockFiler = EasyMock.createNiceMock(Filer.class);
try {
EasyMock.expect(mockFiler.createClassFile((CharSequence) EasyMock.anyObject())).andReturn(
mockFileObject).anyTimes();
} catch (IOException e) {
// Can't happen
throw new RuntimeException(e);
}
EasyMock.replay(mockFiler);
return mockFiler;
}
private JavaFileObject getMockFileObject() throws IOException {
return getMockFileObject(new ByteArrayOutputStream());
}
private JavaFileObject getMockFileObject(OutputStream outStream) throws IOException {
JavaFileObject mockFileObject = EasyMock.createNiceMock(JavaFileObject.class);
EasyMock.expect(mockFileObject.openOutputStream()).andReturn(outStream).anyTimes();
EasyMock.replay(mockFileObject);
return mockFileObject;
}
private RoundEnvironment getMockRoundEnvironment(Set<? extends Element> elementsWithAnnotation) {
return getMockRoundEnvironment(elementsWithAnnotation, false);
}
@SuppressWarnings("unchecked")
private RoundEnvironment getMockRoundEnvironment(Set<? extends Element> elementsWithAnnotation,
boolean finishedProcessing) {
RoundEnvironment mockEnv = EasyMock.createNiceMock(RoundEnvironment.class);
EasyMock.expect(mockEnv.getElementsAnnotatedWith(UsesMocks.class)).andReturn(
(Set) elementsWithAnnotation).anyTimes();
EasyMock.expect(mockEnv.processingOver()).andReturn(finishedProcessing).anyTimes();
EasyMock.replay(mockEnv);
return mockEnv;
}
public void testGetClassMocks() throws IOException, CannotCompileException {
List<Class<?>> classesToMock = new ArrayList<Class<?>>();
classesToMock.add(TestCase.class);
List<String> expectedMocks =
new ArrayList<String>(Arrays.asList(new String[] {
"genmocks." + TestCase.class.getName() + "DelegateInterface",
"genmocks." + TestCase.class.getName() + "DelegateSubclass"}));
Set<GeneratedClassFile> mockedClasses =
getProcessor().getClassMocks(classesToMock, true);
assertEquals(2, mockedClasses.size());
for (GeneratedClassFile clazz : mockedClasses) {
assertTrue(expectedMocks.contains(clazz.getClassName()));
expectedMocks.remove(clazz.getClassName());
}
}
public void testWriteMocks() throws IOException, CannotCompileException {
List<Class<?>> classesToMock = new ArrayList<Class<?>>();
classesToMock.add(TestCase.class);
Set<GeneratedClassFile> mockedClassesSet =
getProcessor().getClassMocks(classesToMock, true);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
getProcessor(getMockProcessingEnvironment(getMockFiler(getMockFileObject(outputStream))))
.writeMocks(mockedClassesSet);
String output = new String(outputStream.toByteArray());
for (GeneratedClassFile mockClass : mockedClassesSet) {
String expected = new String(mockClass.getContents());
assertTrue(output.contains(expected));
output = output.replace(expected, "");
}
assertEquals(0, output.length());
}
public void testProcess() {
assertFalse(getProcessor().process(null,
getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class))));
assertFalse(getProcessor().process(null,
getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class), true)));
}
public void testFindClassesToMock() {
Set<? extends Element> annotatedElements = getAnnotatedElementsSet(Set.class, TestCase.class);
List<Class<?>> classesList = getProcessor().findClassesToMock(annotatedElements);
assertEquals(annotatedElements.size(), classesList.size());
assertTrue(classesList.contains(Set.class));
assertTrue(classesList.contains(TestCase.class));
}
}