1/*
2 * Copyright 2010 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.google.android.testing.mocking;
17
18import javassist.CannotCompileException;
19import javassist.ClassPool;
20import javassist.CtClass;
21import javassist.NotFoundException;
22
23import junit.framework.TestCase;
24
25import java.io.File;
26import java.io.IOException;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Collection;
30import java.util.List;
31import java.util.Vector;
32import java.util.jar.JarEntry;
33
34/**
35 * @author swoodward@google.com (Stephen Woodward)
36 */
37public class AndroidFrameworkMockGeneratorTest extends TestCase {
38  private void cleanupGeneratedClasses(CtClass... classes) {
39    for (CtClass clazz : classes) {
40      clazz.detach();
41    }
42  }
43
44  private Collection<JarEntry> getMockJarEntries() {
45    JarEntry firstEntry = new JarEntry("java/lang/Object.class");
46    JarEntry secondEntry = new JarEntry(
47        "com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest$Inner.class");
48    List<JarEntry> entryList = new ArrayList<JarEntry>();
49    entryList.add(firstEntry);
50    entryList.add(secondEntry);
51    return entryList;
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> getClassNames(List<GeneratedClassFile> classes) {
76    List<String> classNames = new ArrayList<String>();
77    for (GeneratedClassFile clazz : classes) {
78      classNames.add(clazz.getClassName());
79    }
80    return classNames;
81  }
82
83  private AndroidFrameworkMockGenerator getMockGenerator() {
84    return new AndroidFrameworkMockGenerator();
85  }
86
87  public void testCreateMockForClass() throws ClassNotFoundException, IOException,
88      CannotCompileException {
89    AndroidFrameworkMockGenerator mockGenerator = getMockGenerator();
90    for (SdkVersion version : SdkVersion.getAllVersions()) {
91      List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Object.class, version);
92
93      List<String> expectedNames = new ArrayList<String>();
94      expectedNames.addAll(Arrays.asList(new String[] {
95          version.getPackagePrefix() + "genmocks.java.lang.ObjectDelegateSubclass",
96          version.getPackagePrefix() + "genmocks.java.lang.ObjectDelegateInterface"}));
97      List<String> actualNames = getClassNames(classes);
98      assertUnorderedContentsSame(expectedNames, actualNames);
99    }
100  }
101
102  public void testGetClassList() throws ClassNotFoundException {
103    Collection<JarEntry> jarEntries = getMockJarEntries();
104    List<String> expectedClassNames =
105        new ArrayList<String>(Arrays.asList(new String[] {
106            "java.lang.Object",
107            "com.google.android.testing.mocking.AndroidFrameworkMockGeneratorTest$Inner"}));
108    List<Class<?>> list = getMockGenerator().getClassList(jarEntries);
109    assertEquals(expectedClassNames.size(), list.size());
110    for (Class<?> clazz : list) {
111      assertTrue(clazz.getName(), expectedClassNames.contains(clazz.getName()));
112    }
113  }
114
115  public void testIsClassFile() {
116    assertTrue(getMockGenerator().jarEntryIsClassFile(new JarEntry("something.class")));
117    assertTrue(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.class")));
118    assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.clas")));
119    assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.class ")));
120    assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar")));
121  }
122
123  public void testGetJarFileNameForVersion() {
124    for (SdkVersion version : SdkVersion.getAllVersions()) {
125      getMockGenerator();
126      assertEquals("lib/android/android_" + version.getVersionName() + ".jar",
127          AndroidFrameworkMockGenerator.getJarFileNameForVersion(version)
128              .replace('\\', '/'));
129    }
130  }
131
132  public void testGetMocksForClass() throws ClassNotFoundException, IOException,
133      CannotCompileException, NotFoundException {
134    List<CtClass> createdClasses = new ArrayList<CtClass>();
135    AndroidFrameworkMockGenerator mockGenerator = getMockGenerator();
136    for (SdkVersion version : SdkVersion.getAllVersions()) {
137      List<GeneratedClassFile> createdMocks = mockGenerator.createMocksForClass(
138          Vector.class, version);
139      for (GeneratedClassFile mock : createdMocks) {
140        CtClass ctClass = ClassPool.getDefault().get(mock.getClassName());
141        createdClasses.add(ctClass);
142        ctClass.toClass();
143      }
144    }
145    List<GeneratedClassFile> mocks = mockGenerator.getMocksForClass(Vector.class);
146    String[] expectedClassNames = new String[] {
147        "v15.genmocks.java.util.VectorDelegateSubclass",
148        "v15.genmocks.java.util.VectorDelegateInterface",
149        "v16.genmocks.java.util.VectorDelegateSubclass",
150        "v16.genmocks.java.util.VectorDelegateInterface",
151        "v201.genmocks.java.util.VectorDelegateSubclass",
152        "v201.genmocks.java.util.VectorDelegateInterface",
153        "v21.genmocks.java.util.VectorDelegateSubclass",
154        "v21.genmocks.java.util.VectorDelegateInterface",
155        "v22.genmocks.java.util.VectorDelegateSubclass",
156        "v22.genmocks.java.util.VectorDelegateInterface",
157        "v23.genmocks.java.util.VectorDelegateSubclass",
158        "v23.genmocks.java.util.VectorDelegateInterface"
159    };
160    assertEquals(expectedClassNames.length, mocks.size());
161    for (int i = 0; i < mocks.size(); ++i) {
162      assertEquals(expectedClassNames[i], mocks.get(i).getClassName());
163    }
164    cleanupGeneratedClasses(createdClasses.toArray(new CtClass[0]));
165  }
166
167  class Inner {
168  }
169}
170