• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.google.android.testing.mocking;
17 
18 import javassist.CannotCompileException;
19 
20 import junit.framework.TestCase;
21 
22 import org.easymock.EasyMock;
23 
24 import java.io.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 
35 import javax.annotation.processing.Filer;
36 import javax.annotation.processing.Messager;
37 import javax.annotation.processing.ProcessingEnvironment;
38 import javax.annotation.processing.RoundEnvironment;
39 import javax.lang.model.element.AnnotationMirror;
40 import javax.lang.model.element.AnnotationValue;
41 import javax.lang.model.element.Element;
42 import javax.lang.model.element.ExecutableElement;
43 import javax.lang.model.type.DeclaredType;
44 import javax.lang.model.type.TypeKind;
45 import javax.lang.model.type.TypeMirror;
46 import javax.lang.model.type.TypeVisitor;
47 import javax.tools.JavaFileObject;
48 
49 /**
50  * @author swoodward@google.com (Stephen Woodward)
51  */
52 public class UsesMocksProcessorTest extends TestCase {
53 
getAnnotatedElementsSet(Class<?>.... classes)54   private Set<? extends Element> getAnnotatedElementsSet(Class<?>... classes) {
55     Set<Element> set = new HashSet<Element>();
56     for (Class<?> clazz : classes) {
57       set.add(getMockElement(clazz));
58     }
59     return set;
60   }
61 
62   @SuppressWarnings("unchecked")
getMockElement(Class<?> clazz)63   private Element getMockElement(Class<?> clazz) {
64     Element mockElement = EasyMock.createNiceMock(Element.class);
65     EasyMock.expect(mockElement.getAnnotationMirrors()).andReturn(getMockAnnotationMirrors(clazz))
66         .anyTimes();
67     EasyMock.replay(mockElement);
68     return mockElement;
69   }
70 
71   @SuppressWarnings("unchecked")
getMockAnnotationMirrors(Class<?> clazz)72   private List getMockAnnotationMirrors(Class<?> clazz) {
73     List<AnnotationMirror> mockMirrorList = new ArrayList<AnnotationMirror>();
74     AnnotationMirror mockMirror = EasyMock.createNiceMock(AnnotationMirror.class);
75     EasyMock.expect(mockMirror.getAnnotationType()).andReturn(getMockAnnotationType()).anyTimes();
76     EasyMock.expect(mockMirror.getElementValues()).andReturn(getMockElementValuesMap(clazz))
77         .anyTimes();
78     EasyMock.replay(mockMirror);
79     mockMirrorList.add(mockMirror);
80     return mockMirrorList;
81   }
82 
83   @SuppressWarnings("unchecked")
getMockElementValuesMap(Class<?> clazz)84   private Map getMockElementValuesMap(Class<?> clazz) {
85     Map mockValuesMap = new HashMap();
86     mockValuesMap.put(getMockExecutableElement(), getMockAnnotationValue(clazz));
87     return mockValuesMap;
88   }
89 
getMockAnnotationValue(Class<?> clazz)90   private AnnotationValue getMockAnnotationValue(Class<?> clazz) {
91     AnnotationValue mockValue = EasyMock.createMock(AnnotationValue.class);
92     EasyMock.expect(mockValue.getValue()).andReturn(
93         Arrays.asList(new String[] {clazz.getName() + ".class"})).anyTimes();
94     EasyMock.replay(mockValue);
95     return mockValue;
96   }
97 
getMockExecutableElement()98   private ExecutableElement getMockExecutableElement() {
99     ExecutableElement mockElement = EasyMock.createNiceMock(ExecutableElement.class);
100     EasyMock.replay(mockElement);
101     return mockElement;
102   }
103 
getMockAnnotationType()104   private DeclaredType getMockAnnotationType() {
105     return new DeclaredType() {
106       @Override
107       public String toString() {
108         return UsesMocks.class.getName();
109       }
110 
111       @Override
112       public Element asElement() {
113         return null;
114       }
115 
116       @Override
117       public TypeMirror getEnclosingType() {
118         return null;
119       }
120 
121       @Override
122       public List<? extends TypeMirror> getTypeArguments() {
123         return null;
124       }
125 
126       @Override
127       public <R, P> R accept(TypeVisitor<R, P> v, P p) {
128         return null;
129       }
130 
131       @Override
132       public TypeKind getKind() {
133         return null;
134       }
135     };
136   }
137 
138   private UsesMocksProcessor getProcessor() {
139     return getProcessor(getMockProcessingEnvironment());
140   }
141 
142   private UsesMocksProcessor getProcessor(ProcessingEnvironment processingEnv) {
143     UsesMocksProcessor processor = new UsesMocksProcessor();
144     processor.init(processingEnv);
145     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
146     processor.logger = new ProcessorLogger(outputStream, processingEnv);
147     return processor;
148   }
149 
150   private ProcessingEnvironment getMockProcessingEnvironment(Filer mockFiler) {
151     ProcessingEnvironment mockEnvironment = EasyMock.createNiceMock(ProcessingEnvironment.class);
152     EasyMock.expect(mockEnvironment.getMessager()).andReturn(getMockMessager()).anyTimes();
153     EasyMock.expect(mockEnvironment.getFiler()).andReturn(mockFiler).anyTimes();
154     EasyMock.expect(mockEnvironment.getOptions()).andReturn(getMockOptions()).anyTimes();
155     EasyMock.replay(mockEnvironment);
156     return mockEnvironment;
157   }
158 
159   private Map<String, String> getMockOptions() {
160     Map<String, String> map = new HashMap<String, String>();
161     map.put("bin_dir", ".");
162     map.put("logfile", "logfile");
163     return map;
164   }
165 
166   private ProcessingEnvironment getMockProcessingEnvironment() {
167     return getMockProcessingEnvironment(getMockFiler());
168   }
169 
170   private Messager getMockMessager() {
171     Messager mockMessager = EasyMock.createNiceMock(Messager.class);
172     EasyMock.replay(mockMessager);
173     return mockMessager;
174   }
175 
176   private Filer getMockFiler() {
177     try {
178       return getMockFiler(getMockFileObject());
179     } catch (IOException e) {
180       // Can't happen
181       throw new RuntimeException(e);
182     }
183   }
184 
185   private Filer getMockFiler(JavaFileObject mockFileObject) {
186     Filer mockFiler = EasyMock.createNiceMock(Filer.class);
187     try {
188       EasyMock.expect(mockFiler.createClassFile((CharSequence) EasyMock.anyObject())).andReturn(
189           mockFileObject).anyTimes();
190     } catch (IOException e) {
191       // Can't happen
192       throw new RuntimeException(e);
193     }
194     EasyMock.replay(mockFiler);
195     return mockFiler;
196   }
197 
198   private JavaFileObject getMockFileObject() throws IOException {
199     return getMockFileObject(new ByteArrayOutputStream());
200   }
201 
202   private JavaFileObject getMockFileObject(OutputStream outStream) throws IOException {
203     JavaFileObject mockFileObject = EasyMock.createNiceMock(JavaFileObject.class);
204     EasyMock.expect(mockFileObject.openOutputStream()).andReturn(outStream).anyTimes();
205     EasyMock.replay(mockFileObject);
206     return mockFileObject;
207   }
208 
209   private RoundEnvironment getMockRoundEnvironment(Set<? extends Element> elementsWithAnnotation) {
210     return getMockRoundEnvironment(elementsWithAnnotation, false);
211   }
212 
213   @SuppressWarnings("unchecked")
214   private RoundEnvironment getMockRoundEnvironment(Set<? extends Element> elementsWithAnnotation,
215       boolean finishedProcessing) {
216     RoundEnvironment mockEnv = EasyMock.createNiceMock(RoundEnvironment.class);
217     EasyMock.expect(mockEnv.getElementsAnnotatedWith(UsesMocks.class)).andReturn(
218         (Set) elementsWithAnnotation).anyTimes();
219     EasyMock.expect(mockEnv.processingOver()).andReturn(finishedProcessing).anyTimes();
220     EasyMock.replay(mockEnv);
221     return mockEnv;
222   }
223 
224   public void testGetClassMocks() throws IOException, CannotCompileException {
225     List<Class<?>> classesToMock = new ArrayList<Class<?>>();
226     classesToMock.add(TestCase.class);
227     List<String> expectedMocks =
228         new ArrayList<String>(Arrays.asList(new String[] {
229             "genmocks." + TestCase.class.getName() + "DelegateInterface",
230             "genmocks." + TestCase.class.getName() + "DelegateSubclass"}));
231     Set<GeneratedClassFile> mockedClasses =
232         getProcessor().getClassMocks(classesToMock, true);
233 
234     assertEquals(2, mockedClasses.size());
235     for (GeneratedClassFile clazz : mockedClasses) {
236       assertTrue(expectedMocks.contains(clazz.getClassName()));
237       expectedMocks.remove(clazz.getClassName());
238     }
239   }
240 
241   public void testWriteMocks() throws IOException, CannotCompileException {
242     List<Class<?>> classesToMock = new ArrayList<Class<?>>();
243     classesToMock.add(TestCase.class);
244     Set<GeneratedClassFile> mockedClassesSet =
245         getProcessor().getClassMocks(classesToMock, true);
246     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
247 
248     getProcessor(getMockProcessingEnvironment(getMockFiler(getMockFileObject(outputStream))))
249         .writeMocks(mockedClassesSet);
250 
251     String output = new String(outputStream.toByteArray());
252     for (GeneratedClassFile mockClass : mockedClassesSet) {
253       String expected = new String(mockClass.getContents());
254       assertTrue(output.contains(expected));
255       output = output.replace(expected, "");
256     }
257     assertEquals(0, output.length());
258   }
259 
260   public void testProcess() {
261     assertFalse(getProcessor().process(null,
262         getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class))));
263     assertFalse(getProcessor().process(null,
264         getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class), true)));
265   }
266 
267   public void testFindClassesToMock() {
268     Set<? extends Element> annotatedElements = getAnnotatedElementsSet(Set.class, TestCase.class);
269     List<Class<?>> classesList = getProcessor().findClassesToMock(annotatedElements);
270 
271     assertEquals(annotatedElements.size(), classesList.size());
272     assertTrue(classesList.contains(Set.class));
273     assertTrue(classesList.contains(TestCase.class));
274   }
275 }
276