blob: 0b8961b8137e8a61db9c81a62e63ea3df9057b2c [file] [log] [blame]
Luis Sigal8da3e6e2011-02-24 17:22:33 +00001/*
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 */
16package com.google.android.testing.mocking;
17
18import javassist.CannotCompileException;
19
20import junit.framework.TestCase;
21
22import org.easymock.EasyMock;
23
24import java.io.ByteArrayOutputStream;
25import java.io.IOException;
26import java.io.OutputStream;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.HashMap;
30import java.util.HashSet;
31import java.util.List;
32import java.util.Map;
33import java.util.Set;
34
35import javax.annotation.processing.Filer;
36import javax.annotation.processing.Messager;
37import javax.annotation.processing.ProcessingEnvironment;
38import javax.annotation.processing.RoundEnvironment;
39import javax.lang.model.element.AnnotationMirror;
40import javax.lang.model.element.AnnotationValue;
41import javax.lang.model.element.Element;
42import javax.lang.model.element.ExecutableElement;
43import javax.lang.model.type.DeclaredType;
44import javax.lang.model.type.TypeKind;
45import javax.lang.model.type.TypeMirror;
46import javax.lang.model.type.TypeVisitor;
47import javax.tools.JavaFileObject;
48
49/**
50 * @author swoodward@google.com (Stephen Woodward)
51 */
52public class UsesMocksProcessorTest extends TestCase {
53
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")
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")
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")
84 private Map getMockElementValuesMap(Class<?> clazz) {
85 Map mockValuesMap = new HashMap();
86 mockValuesMap.put(getMockExecutableElement(), getMockAnnotationValue(clazz));
87 return mockValuesMap;
88 }
89
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
98 private ExecutableElement getMockExecutableElement() {
99 ExecutableElement mockElement = EasyMock.createNiceMock(ExecutableElement.class);
100 EasyMock.replay(mockElement);
101 return mockElement;
102 }
103
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}