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 */
16package com.google.android.testing.mocking;
17
18import javassist.CannotCompileException;
19import javassist.ClassPool;
20import javassist.CtClass;
21import javassist.CtMethod;
22import javassist.NotFoundException;
23
24import junit.framework.TestCase;
25
26import java.io.IOException;
27import java.lang.reflect.Method;
28import java.math.BigInteger;
29import java.util.ArrayList;
30import java.util.Arrays;
31import java.util.List;
32
33
34/**
35 * Tests for the AndroidMockGenerator class.
36 *
37 * @author swoodward@google.com (Stephen Woodward)
38 */
39public class AndroidMockGeneratorTest extends TestCase {
40  private AndroidMockGenerator getAndroidMockGenerator() {
41    return new AndroidMockGenerator();
42  }
43
44  private NoFileAndroidMockGenerator getNoFileMockGenerator() {
45    return new NoFileAndroidMockGenerator();
46  }
47
48  private void cleanupGeneratedClasses(CtClass... classes) {
49    for (CtClass clazz : classes) {
50      clazz.detach();
51    }
52  }
53
54  private <T> void assertUnorderedContentsSame(Iterable<T> expected, Iterable<T> actual) {
55    List<T> missingItems = new ArrayList<T>();
56    List<T> extraItems = new ArrayList<T>();
57    for (T item : expected) {
58      missingItems.add(item);
59    }
60    for (T item : actual) {
61      missingItems.remove(item);
62      extraItems.add(item);
63    }
64    for (T item : expected) {
65      extraItems.remove(item);
66    }
67    if (missingItems.size() + extraItems.size() != 0) {
68      String errorMessage =
69          "Contents were different. Missing: " + Arrays.toString(missingItems.toArray())
70              + " Extra: " + Arrays.toString(extraItems.toArray());
71      fail(errorMessage);
72    }
73  }
74
75  private List<String> getExpectedNamesForNumberClass() {
76    return getExpectedNamesForNumberClass(false);
77  }
78
79  private List<String> getExpectedNamesForObjectClass() {
80    List<String> expectedNames = new ArrayList<String>();
81    expectedNames.addAll(Arrays.asList(new String[] {"clone", "finalize"}));
82    return expectedNames;
83  }
84
85  private List<String> getExpectedNamesForNumberClass(boolean includeDelegateMethods) {
86    List<String> expectedNames = getExpectedNamesForObjectClass();
87    expectedNames.addAll(Arrays.asList(new String[] {"byteValue", "doubleValue", "floatValue",
88        "intValue", "longValue", "shortValue"}));
89    if (includeDelegateMethods) {
90      expectedNames.addAll(Arrays.asList(new String[] {"getDelegate___AndroidMock",
91          "setDelegate___AndroidMock"}));
92    }
93    return expectedNames;
94  }
95
96  private List<String> getExpectedNamesForBigIntegerClass() {
97    List<String> expectedNames = getExpectedNamesForNumberClass();
98    expectedNames.addAll(Arrays.asList(new String[] {"abs", "add", "and", "andNot", "bitCount",
99        "bitLength", "clearBit", "compareTo", "divide", "divideAndRemainder", "flipBit", "gcd",
100        "getLowestSetBit", "isProbablePrime", "max", "min", "mod", "modInverse", "modPow",
101        "multiply", "negate", "nextProbablePrime", "not", "or", "pow", "remainder", "setBit",
102        "shiftLeft", "shiftRight", "signum", "subtract", "testBit", "toByteArray", "toString",
103        "xor"}));
104    return expectedNames;
105  }
106
107  private List<String> getMethodNames(CtMethod[] methods) {
108    List<String> methodNames = new ArrayList<String>();
109    for (CtMethod method : methods) {
110      methodNames.add(method.getName());
111    }
112    return methodNames;
113  }
114
115  private List<String> getClassNames(List<GeneratedClassFile> classes) {
116    List<String> classNames = new ArrayList<String>();
117    for (GeneratedClassFile clazz : classes) {
118      classNames.add(clazz.getClassName());
119    }
120    return classNames;
121  }
122
123  private List<String> getExpectedSignaturesForBigIntegerClass() {
124    List<String> expectedNames = new ArrayList<String>();
125    expectedNames.addAll(Arrays.asList(new String[] {
126        "public int java.math.BigInteger.getLowestSetBit()",
127        "public java.math.BigInteger java.math.BigInteger.abs()",
128        "protected void java.lang.Object.finalize() throws java.lang.Throwable",
129        "public java.math.BigInteger java.math.BigInteger.modPow(java.math.BigInteger,"
130            + "java.math.BigInteger)",
131        "protected native java.lang.Object java.lang.Object.clone() throws "
132            + "java.lang.CloneNotSupportedException",
133        "public java.math.BigInteger java.math.BigInteger.setBit(int)",
134        "public java.math.BigInteger java.math.BigInteger.shiftRight(int)",
135        "public int java.math.BigInteger.bitLength()",
136        "public java.math.BigInteger java.math.BigInteger.not()",
137        "public java.math.BigInteger java.math.BigInteger.subtract(java.math.BigInteger)",
138        "public java.math.BigInteger java.math.BigInteger.flipBit(int)",
139        "public boolean java.math.BigInteger.isProbablePrime(int)",
140        "public java.math.BigInteger java.math.BigInteger.add(java.math.BigInteger)",
141        "public java.math.BigInteger java.math.BigInteger.modInverse(java.math.BigInteger)",
142        "public java.math.BigInteger java.math.BigInteger.clearBit(int)",
143        "public java.math.BigInteger java.math.BigInteger.multiply(java.math.BigInteger)",
144        "public byte java.lang.Number.byteValue()",
145        "public java.math.BigInteger java.math.BigInteger.gcd(java.math.BigInteger)",
146        "public float java.math.BigInteger.floatValue()",
147        "public java.lang.String java.math.BigInteger.toString(int)",
148        "public java.math.BigInteger java.math.BigInteger.min(java.math.BigInteger)",
149        "public int java.math.BigInteger.intValue()",
150        "public java.math.BigInteger java.math.BigInteger.or(java.math.BigInteger)",
151        "public java.math.BigInteger java.math.BigInteger.remainder(java.math.BigInteger)",
152        "public java.math.BigInteger java.math.BigInteger.divide(java.math.BigInteger)",
153        "public java.math.BigInteger java.math.BigInteger.xor(java.math.BigInteger)",
154        "public java.math.BigInteger java.math.BigInteger.and(java.math.BigInteger)",
155        "public int java.math.BigInteger.signum()",
156        "public java.math.BigInteger[] java.math.BigInteger.divideAndRemainder("
157            + "java.math.BigInteger)",
158        "public java.math.BigInteger java.math.BigInteger.max(java.math.BigInteger)",
159        "public java.math.BigInteger java.math.BigInteger.shiftLeft(int)",
160        "public double java.math.BigInteger.doubleValue()",
161        "public java.math.BigInteger java.math.BigInteger.pow(int)",
162        "public short java.lang.Number.shortValue()",
163        "public java.math.BigInteger java.math.BigInteger.andNot(java.math.BigInteger)",
164        "public byte[] java.math.BigInteger.toByteArray()",
165        "public java.math.BigInteger java.math.BigInteger.negate()",
166        "public int java.math.BigInteger.compareTo(java.math.BigInteger)",
167        "public boolean java.math.BigInteger.testBit(int)",
168        "public int java.math.BigInteger.bitCount()",
169        "public long java.math.BigInteger.longValue()",
170        "public java.math.BigInteger java.math.BigInteger.mod(java.math.BigInteger)",
171        "public java.math.BigInteger java.math.BigInteger.nextProbablePrime()",
172        }));
173    return expectedNames;
174  }
175
176  private List<String> getMethodSignatures(Method[] methods) {
177    List<String> methodSignatures = new ArrayList<String>();
178    for (Method method : methods) {
179      if (getAndroidMockGenerator().isMockable(method)) {
180        methodSignatures.add(method.toGenericString());
181      }
182    }
183    return methodSignatures;
184  }
185
186  public void testIsSupportedType() {
187    Class<?>[] unsupportedClasses =
188        new Class[] {ClassIsAnnotation.class, ClassIsEnum.class, ClassIsFinal.class,
189            ClassIsInterface.class};
190    Class<?>[] supportedClasses = new Class[] {Object.class};
191
192    for (Class<?> clazz : unsupportedClasses) {
193      assertFalse(getAndroidMockGenerator().classIsSupportedType(clazz));
194    }
195    for (Class<?> clazz : supportedClasses) {
196      assertTrue(getAndroidMockGenerator().classIsSupportedType(clazz));
197    }
198  }
199
200  public void testGetDelegateFieldName() {
201    assertEquals("delegateMockObject", getAndroidMockGenerator().getDelegateFieldName());
202  }
203
204  public void testGetInterfaceMethodSource() throws SecurityException, NoSuchMethodException {
205    Method method = Object.class.getMethod("equals", Object.class);
206    assertEquals("public boolean equals(java.lang.Object arg0);", getAndroidMockGenerator()
207        .getInterfaceMethodSource(method));
208  }
209
210  public void testGetInterfaceMethodSourceMultipleExceptions() throws SecurityException,
211      NoSuchMethodException {
212    Method method = Class.class.getDeclaredMethod("newInstance");
213    assertEquals("public java.lang.Object newInstance() throws java.lang.InstantiationException,"
214        + "java.lang.IllegalAccessException;", getAndroidMockGenerator().getInterfaceMethodSource(
215        method));
216  }
217
218  public void testGetInterfaceMethodSourceProtectedMethod() throws SecurityException,
219      NoSuchMethodException {
220    Method method = Object.class.getDeclaredMethod("finalize");
221    assertEquals("public void finalize() throws java.lang.Throwable;", getAndroidMockGenerator()
222        .getInterfaceMethodSource(method));
223  }
224
225  public void testGetInterfaceMethodSourceNoParams() throws SecurityException,
226      NoSuchMethodException {
227    Method method = Object.class.getMethod("toString");
228    assertEquals("public java.lang.String toString();", getAndroidMockGenerator()
229        .getInterfaceMethodSource(method));
230  }
231
232  public void testGetInterfaceMethodSourceVoidReturn() throws SecurityException,
233      NoSuchMethodException {
234    Method method = Thread.class.getMethod("run");
235    assertEquals("public void run();", getAndroidMockGenerator().getInterfaceMethodSource(method));
236  }
237
238  public void testGetInterfaceMethodSourceFinal() throws SecurityException, NoSuchMethodException {
239    Method method = Object.class.getMethod("notify");
240    try {
241      getAndroidMockGenerator().getInterfaceMethodSource(method);
242      fail("Exception not thrown on a final method");
243    } catch (UnsupportedOperationException e) {
244      // expected
245    }
246  }
247
248  public void testGetInterfaceMethodSourceStatic() throws SecurityException, NoSuchMethodException {
249    Method method = Thread.class.getMethod("currentThread");
250    try {
251      getAndroidMockGenerator().getInterfaceMethodSource(method);
252      fail("Exception not thrown on a static method");
253    } catch (UnsupportedOperationException e) {
254      // expected
255    }
256  }
257
258  public void testGetInterfaceName() {
259    AndroidMockGenerator r = getAndroidMockGenerator();
260    assertEquals("genmocks.java.lang.ObjectDelegateInterface",
261        FileUtils.getInterfaceNameFor(Object.class, SdkVersion.UNKNOWN));
262  }
263
264  public void testGetSubclassName() {
265    AndroidMockGenerator r = getAndroidMockGenerator();
266    assertEquals("genmocks.java.lang.ObjectDelegateSubclass",
267        FileUtils.getSubclassNameFor(Object.class, SdkVersion.UNKNOWN));
268  }
269
270  public void testGetDelegateMethodSource() throws SecurityException, NoSuchMethodException {
271    Method method = Object.class.getMethod("equals", Object.class);
272    assertEquals("public boolean equals(java.lang.Object arg0){if(this.delegateMockObject==null){"
273        + "return false;}return this.delegateMockObject.equals(arg0);}", getAndroidMockGenerator()
274        .getDelegateMethodSource(method));
275  }
276
277  public void testGetDelegateMethodSourceAllTypes() throws SecurityException,
278      NoSuchMethodException {
279    String[] returnTypes =
280        new String[] {"boolean", "byte", "short", "int", "long", "char", "float", "double"};
281    String[] castTypes =
282        new String[] {"false", "(byte)0", "(short)0", "(int)0", "(long)0", "(char)0", "(float)0",
283            "(double)0"};
284    for (int i = 0; i < returnTypes.length; ++i) {
285      Method method = AllTypes.class.getMethod(returnTypes[i] + "Foo");
286      assertEquals("public " + returnTypes[i] + " " + returnTypes[i]
287          + "Foo(){if(this.delegateMockObject==null){return " + castTypes[i]
288          + ";}return this.delegateMockObject." + returnTypes[i] + "Foo();}",
289          getAndroidMockGenerator().getDelegateMethodSource(method));
290    }
291    Method method = AllTypes.class.getMethod("objectFoo");
292    assertEquals("public java.lang.Object objectFoo(){if(this.delegateMockObject==null){return "
293        + "null;}return this.delegateMockObject.objectFoo();}", getAndroidMockGenerator()
294        .getDelegateMethodSource(method));
295    method = AllTypes.class.getMethod("voidFoo");
296    assertEquals("public void voidFoo(){if(this.delegateMockObject==null){return ;"
297        + "}this.delegateMockObject.voidFoo();}", getAndroidMockGenerator()
298        .getDelegateMethodSource(method));
299  }
300
301  private class AllTypes {
302    @SuppressWarnings("unused")
303    public void voidFoo() {
304    }
305
306    @SuppressWarnings("unused")
307    public boolean booleanFoo() {
308      return false;
309    }
310
311    @SuppressWarnings("unused")
312    public byte byteFoo() {
313      return 0;
314    }
315
316    @SuppressWarnings("unused")
317    public short shortFoo() {
318      return 0;
319    }
320
321    @SuppressWarnings("unused")
322    public int intFoo() {
323      return 0;
324    }
325
326    @SuppressWarnings("unused")
327    public long longFoo() {
328      return 0;
329    }
330
331    @SuppressWarnings("unused")
332    public char charFoo() {
333      return 0;
334    }
335
336    @SuppressWarnings("unused")
337    public float floatFoo() {
338      return 0;
339    }
340
341    @SuppressWarnings("unused")
342    public double doubleFoo() {
343      return 0;
344    }
345
346    @SuppressWarnings("unused")
347    public Object objectFoo() {
348      return null;
349    }
350  }
351
352  public void testGetDelegateMethodSourceMultipleExceptions() throws SecurityException,
353      NoSuchMethodException {
354    Method method = Class.class.getDeclaredMethod("newInstance");
355    assertEquals(
356        "public java.lang.Object newInstance() throws java.lang.InstantiationException,"
357            + "java.lang.IllegalAccessException{if(this.delegateMockObject==null){return null;}"
358            + "return this.delegateMockObject.newInstance();}", getAndroidMockGenerator()
359            .getDelegateMethodSource(method));
360  }
361
362  public void testGetDelegateMethodSourceProtectedMethod() throws SecurityException,
363      NoSuchMethodException {
364    Method method = Object.class.getDeclaredMethod("finalize");
365    assertEquals("public void finalize() throws java.lang.Throwable{if(this.delegateMockObject=="
366        + "null){return ;}this.delegateMockObject.finalize();}", getAndroidMockGenerator()
367        .getDelegateMethodSource(method));
368  }
369
370  public void testGetDelegateMethodSourceMultiParams() throws SecurityException,
371      NoSuchMethodException {
372    Method method =
373        String.class.getMethod("getChars", Integer.TYPE, Integer.TYPE, char[].class, Integer.TYPE);
374    assertEquals(
375        "public void getChars(int arg0,int arg1,char[] arg2,int arg3){if(this."
376            + "delegateMockObject==null){return ;}this.delegateMockObject.getChars(arg0,arg1,arg2,"
377            + "arg3);}", getAndroidMockGenerator().getDelegateMethodSource(method));
378  }
379
380  public void testGetDelegateMethodSourceNoParams() throws SecurityException,
381      NoSuchMethodException {
382    Method method = Object.class.getMethod("toString");
383    assertEquals(
384        "public java.lang.String toString(){if(this.delegateMockObject==null){return null;"
385            + "}return this.delegateMockObject.toString();}", getAndroidMockGenerator()
386            .getDelegateMethodSource(method));
387  }
388
389  public void testGetDelegateMethodSourceVoidReturn() throws SecurityException,
390      NoSuchMethodException {
391    Method method = Thread.class.getMethod("run");
392    assertEquals("public void run(){if(this.delegateMockObject==null){return ;}this."
393        + "delegateMockObject.run();}", getAndroidMockGenerator().getDelegateMethodSource(method));
394  }
395
396  public void testGetDelegateMethodSourceFinal() throws SecurityException, NoSuchMethodException {
397    Method method = Object.class.getMethod("notify");
398    try {
399      getAndroidMockGenerator().getDelegateMethodSource(method);
400      fail("Exception not thrown on a final method");
401    } catch (UnsupportedOperationException e) {
402      // expected
403    }
404  }
405
406  public void testGetDelegateMethodSourceStatic() throws SecurityException, NoSuchMethodException {
407    Method method = Thread.class.getMethod("currentThread");
408    try {
409      getAndroidMockGenerator().getDelegateMethodSource(method);
410      fail("Exception not thrown on a static method");
411    } catch (UnsupportedOperationException e) {
412      // expected
413    }
414  }
415
416  public void testGenerateEmptySubclass() throws ClassNotFoundException, NotFoundException {
417    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
418    CtClass generatedInterface = mockGenerator.generateInterface(String.class, SdkVersion.UNKNOWN);
419    CtClass generatedClass = getAndroidMockGenerator().generateSkeletalClass(
420        String.class, generatedInterface, SdkVersion.UNKNOWN);
421
422    assertEquals("genmocks.java.lang", generatedClass.getPackageName());
423    assertEquals("StringDelegateSubclass", generatedClass.getSimpleName());
424    assertEquals("java.lang.String", generatedClass.getSuperclass().getName());
425    cleanupGeneratedClasses(generatedInterface, generatedClass);
426  }
427
428  public void testAddMethods() throws ClassNotFoundException {
429    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
430    CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN);
431    CtClass generatedClass =
432        mockGenerator.generateSkeletalClass(Number.class, generatedInterface, SdkVersion.UNKNOWN);
433
434    mockGenerator.addMethods(Number.class, generatedClass);
435
436    List<String> expectedNames = getExpectedNamesForNumberClass();
437    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
438    assertUnorderedContentsSame(expectedNames, actualNames);
439    cleanupGeneratedClasses(generatedInterface, generatedClass);
440  }
441
442  public void testAddMethodsObjectClass() throws ClassNotFoundException {
443    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
444    CtClass generatedInterface = mockGenerator.generateInterface(Object.class, SdkVersion.UNKNOWN);
445    CtClass generatedClass =
446        mockGenerator.generateSkeletalClass(Object.class, generatedInterface, SdkVersion.UNKNOWN);
447
448    mockGenerator.addMethods(Object.class, generatedClass);
449
450    List<String> expectedNames = getExpectedNamesForObjectClass();
451    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
452    assertUnorderedContentsSame(expectedNames, actualNames);
453    cleanupGeneratedClasses(generatedInterface, generatedClass);
454  }
455
456  public void testAddMethodsUsesSuperclass() throws ClassNotFoundException {
457    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
458    CtClass generatedInterface = mockGenerator.generateInterface(
459        BigInteger.class, SdkVersion.UNKNOWN);
460    CtClass generatedClass = mockGenerator.generateSkeletalClass(
461        BigInteger.class, generatedInterface, SdkVersion.UNKNOWN);
462
463    mockGenerator.addMethods(BigInteger.class, generatedClass);
464
465    List<String> expectedNames = getExpectedNamesForBigIntegerClass();
466    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
467    assertUnorderedContentsSame(expectedNames, actualNames);
468    cleanupGeneratedClasses(generatedInterface, generatedClass);
469  }
470
471  public void testGetAllMethods() throws ClassNotFoundException {
472    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
473    CtClass generatedInterface = mockGenerator.generateInterface(
474        BigInteger.class, SdkVersion.UNKNOWN);
475    CtClass generatedClass = mockGenerator.generateSkeletalClass(
476        BigInteger.class, generatedInterface, SdkVersion.UNKNOWN);
477
478    Method[] methods = mockGenerator.getAllMethods(BigInteger.class);
479
480    List<String> expectedNames = getExpectedSignaturesForBigIntegerClass();
481    List<String> actualNames = getMethodSignatures(methods);
482    assertUnorderedContentsSame(expectedNames, actualNames);
483    cleanupGeneratedClasses(generatedInterface, generatedClass);
484  }
485
486  public void testGenerateInterface() {
487    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
488    CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN);
489
490    List<String> expectedNames = getExpectedNamesForNumberClass();
491    List<String> actualNames = getMethodNames(generatedInterface.getDeclaredMethods());
492    assertUnorderedContentsSame(expectedNames, actualNames);
493    cleanupGeneratedClasses(generatedInterface);
494  }
495
496  public void testAddInterfaceMethods() {
497    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
498    CtClass generatedInterface = AndroidMockGenerator.getClassPool().makeInterface("testInterface");
499
500    mockGenerator.addInterfaceMethods(Number.class, generatedInterface);
501
502    List<String> expectedNames = getExpectedNamesForNumberClass();
503    List<String> actualNames = getMethodNames(generatedInterface.getDeclaredMethods());
504    assertUnorderedContentsSame(expectedNames, actualNames);
505    cleanupGeneratedClasses(generatedInterface);
506  }
507
508  public void testGenerateSubclass() throws ClassNotFoundException {
509    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
510    CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN);
511
512    CtClass generatedClass =
513        mockGenerator.generateSubClass(Number.class, generatedInterface, SdkVersion.UNKNOWN);
514
515    List<String> expectedNames = getExpectedNamesForNumberClass(true);
516    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
517    assertUnorderedContentsSame(expectedNames, actualNames);
518    cleanupGeneratedClasses(generatedInterface, generatedClass);
519  }
520
521  public void testCreateMockForClass() throws ClassNotFoundException, IOException,
522      CannotCompileException, NotFoundException {
523    NoFileAndroidMockGenerator mockGenerator = getNoFileMockGenerator();
524    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Object.class);
525
526    List<String> expectedNames = new ArrayList<String>();
527    String subclassName = "genmocks.java.lang.ObjectDelegateSubclass";
528    String interfaceName = "genmocks.java.lang.ObjectDelegateInterface";
529    expectedNames.addAll(Arrays.asList(new String[] {subclassName,
530        interfaceName}));
531    List<String> actualNames = getClassNames(classes);
532    assertUnorderedContentsSame(expectedNames, actualNames);
533    cleanupGeneratedClasses(
534        ClassPool.getDefault().get(subclassName),
535        ClassPool.getDefault().get(interfaceName));
536  }
537
538  public void testGetSetDelegateMethodSource() {
539    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
540    CtClass generatedInterface = mockGenerator.generateInterface(Object.class, SdkVersion.UNKNOWN);
541    String expectedSource =
542        "public void setDelegate___AndroidMock(genmocks.java.lang.ObjectDelegateInterface obj) {"
543            + " this.delegateMockObject = obj;}";
544
545    assertEquals(expectedSource, mockGenerator.getSetDelegateMethodSource(generatedInterface));
546  }
547
548  public void testIsForbiddenMethod() throws SecurityException, NoSuchMethodException {
549    Method[] forbiddenMethods =
550        new Method[] {Object.class.getMethod("equals", Object.class),
551            Object.class.getMethod("toString"), Object.class.getMethod("hashCode")};
552    Method[] allowedMethods = new Method[] {BigInteger.class.getMethod("toString", Integer.TYPE)};
553    for (Method method : forbiddenMethods) {
554      assertTrue(getAndroidMockGenerator().isForbiddenMethod(method));
555    }
556    for (Method method : allowedMethods) {
557      assertFalse(getAndroidMockGenerator().isForbiddenMethod(method));
558    }
559  }
560
561  /**
562   * Support test class for capturing the names of files that would have been
563   * saved to a jar file.
564   *
565   * @author swoodward@google.com (Stephen Woodward)
566   */
567  class NoFileAndroidMockGenerator extends AndroidMockGenerator {
568    List<CtClass> savedClasses = new ArrayList<CtClass>();
569
570    @Override
571    void saveCtClass(CtClass clazz) {
572      savedClasses.add(clazz);
573    }
574  }
575}
576